mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 16:59:12 +00:00
feat(web): releases list filtering (#136)
This commit is contained in:
parent
279d4ff7a3
commit
246e3ddc26
7 changed files with 459 additions and 48 deletions
|
@ -84,14 +84,14 @@ func (repo *ReleaseRepo) StoreReleaseActionStatus(ctx context.Context, a *domain
|
|||
return nil
|
||||
}
|
||||
|
||||
func (repo *ReleaseRepo) Find(ctx context.Context, params domain.QueryParams) ([]domain.Release, int64, int64, error) {
|
||||
func (repo *ReleaseRepo) Find(ctx context.Context, params domain.ReleaseQueryParams) ([]domain.Release, int64, int64, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
||||
queryBuilder := sq.
|
||||
Select("id", "filter_status", "rejections", "indexer", "filter", "protocol", "title", "torrent_name", "size", "timestamp", "COUNT() OVER() AS total_count").
|
||||
From("release").
|
||||
OrderBy("timestamp DESC")
|
||||
Select("r.id", "r.filter_status", "r.rejections", "r.indexer", "r.filter", "r.protocol", "r.title", "r.torrent_name", "r.size", "r.timestamp", "COUNT() OVER() AS total_count").
|
||||
From("release r").
|
||||
OrderBy("r.timestamp DESC")
|
||||
|
||||
if params.Limit > 0 {
|
||||
queryBuilder = queryBuilder.Limit(params.Limit)
|
||||
|
@ -104,18 +104,22 @@ func (repo *ReleaseRepo) Find(ctx context.Context, params domain.QueryParams) ([
|
|||
}
|
||||
|
||||
if params.Cursor > 0 {
|
||||
queryBuilder = queryBuilder.Where(sq.Lt{"id": params.Cursor})
|
||||
queryBuilder = queryBuilder.Where(sq.Lt{"r.id": params.Cursor})
|
||||
}
|
||||
|
||||
if params.Filter != nil {
|
||||
if params.Filters.Indexers != nil {
|
||||
filter := sq.And{}
|
||||
for k, v := range params.Filter {
|
||||
filter = append(filter, sq.Eq{k: v})
|
||||
for _, v := range params.Filters.Indexers {
|
||||
filter = append(filter, sq.Eq{"r.indexer": v})
|
||||
}
|
||||
|
||||
queryBuilder = queryBuilder.Where(filter)
|
||||
}
|
||||
|
||||
if params.Filters.PushStatus != "" {
|
||||
queryBuilder = queryBuilder.InnerJoin("release_action_status ras ON r.id = ras.release_id").Where(sq.Eq{"ras.status": params.Filters.PushStatus})
|
||||
}
|
||||
|
||||
query, args, err := queryBuilder.ToSql()
|
||||
log.Trace().Str("database", "release.find").Msgf("query: '%v', args: '%v'", query, args)
|
||||
|
||||
|
@ -171,6 +175,46 @@ func (repo *ReleaseRepo) Find(ctx context.Context, params domain.QueryParams) ([
|
|||
return res, nextCursor, countItems, nil
|
||||
}
|
||||
|
||||
func (repo *ReleaseRepo) GetIndexerOptions(ctx context.Context) ([]string, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
||||
query := `
|
||||
SELECT DISTINCT indexer FROM "release"
|
||||
UNION
|
||||
SELECT DISTINCT identifier indexer FROM indexer;`
|
||||
|
||||
log.Trace().Str("database", "release.get_indexers").Msgf("query: '%v'", query)
|
||||
|
||||
res := make([]string, 0)
|
||||
|
||||
rows, err := repo.db.handler.QueryContext(ctx, query)
|
||||
if err != nil {
|
||||
log.Error().Stack().Err(err).Msg("error fetching indexer list")
|
||||
return res, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
log.Error().Stack().Err(err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var indexer string
|
||||
|
||||
if err := rows.Scan(&indexer); err != nil {
|
||||
log.Error().Stack().Err(err).Msg("release.find: error scanning data to struct")
|
||||
return res, err
|
||||
}
|
||||
|
||||
res = append(res, indexer)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (repo *ReleaseRepo) GetActionStatusByReleaseID(ctx context.Context, releaseID int64) ([]domain.ReleaseActionStatus, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
|
|
@ -26,7 +26,8 @@ import (
|
|||
|
||||
type ReleaseRepo interface {
|
||||
Store(ctx context.Context, release *Release) (*Release, error)
|
||||
Find(ctx context.Context, params QueryParams) (res []Release, nextCursor int64, count int64, err error)
|
||||
Find(ctx context.Context, params ReleaseQueryParams) (res []Release, nextCursor int64, count int64, err error)
|
||||
GetIndexerOptions(ctx context.Context) ([]string, error)
|
||||
GetActionStatusByReleaseID(ctx context.Context, releaseID int64) ([]ReleaseActionStatus, error)
|
||||
Stats(ctx context.Context) (*ReleaseStats, error)
|
||||
StoreReleaseActionStatus(ctx context.Context, actionStatus *ReleaseActionStatus) error
|
||||
|
@ -1485,11 +1486,14 @@ const (
|
|||
ReleaseImplementationIRC ReleaseImplementation = "IRC"
|
||||
)
|
||||
|
||||
type QueryParams struct {
|
||||
Limit uint64
|
||||
Offset uint64
|
||||
Cursor uint64
|
||||
Sort map[string]string
|
||||
Filter map[string]string
|
||||
type ReleaseQueryParams struct {
|
||||
Limit uint64
|
||||
Offset uint64
|
||||
Cursor uint64
|
||||
Sort map[string]string
|
||||
Filters struct {
|
||||
Indexers []string
|
||||
PushStatus string
|
||||
}
|
||||
Search string
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package http
|
|||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/autobrr/autobrr/internal/domain"
|
||||
|
@ -10,7 +11,8 @@ import (
|
|||
)
|
||||
|
||||
type releaseService interface {
|
||||
Find(ctx context.Context, query domain.QueryParams) (res []domain.Release, nextCursor int64, count int64, err error)
|
||||
Find(ctx context.Context, query domain.ReleaseQueryParams) (res []domain.Release, nextCursor int64, count int64, err error)
|
||||
GetIndexerOptions(ctx context.Context) ([]string, error)
|
||||
Stats(ctx context.Context) (*domain.ReleaseStats, error)
|
||||
}
|
||||
|
||||
|
@ -29,6 +31,7 @@ func newReleaseHandler(encoder encoder, service releaseService) *releaseHandler
|
|||
func (h releaseHandler) Routes(r chi.Router) {
|
||||
r.Get("/", h.findReleases)
|
||||
r.Get("/stats", h.getStats)
|
||||
r.Get("/indexers", h.getIndexerOptions)
|
||||
}
|
||||
|
||||
func (h releaseHandler) findReleases(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -40,6 +43,7 @@ func (h releaseHandler) findReleases(w http.ResponseWriter, r *http.Request) {
|
|||
"code": "BAD_REQUEST_PARAMS",
|
||||
"message": "limit parameter is invalid",
|
||||
}, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if limit == 0 {
|
||||
limit = 20
|
||||
|
@ -52,23 +56,44 @@ func (h releaseHandler) findReleases(w http.ResponseWriter, r *http.Request) {
|
|||
"code": "BAD_REQUEST_PARAMS",
|
||||
"message": "offset parameter is invalid",
|
||||
}, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
cursorP := r.URL.Query().Get("cursor")
|
||||
cursor, err := strconv.Atoi(cursorP)
|
||||
if err != nil && cursorP != "" {
|
||||
h.encoder.StatusResponse(r.Context(), w, map[string]interface{}{
|
||||
"code": "BAD_REQUEST_PARAMS",
|
||||
"message": "cursor parameter is invalid",
|
||||
}, http.StatusBadRequest)
|
||||
cursor := 0
|
||||
if cursorP != "" {
|
||||
cursor, err = strconv.Atoi(cursorP)
|
||||
if err != nil && cursorP != "" {
|
||||
h.encoder.StatusResponse(r.Context(), w, map[string]interface{}{
|
||||
"code": "BAD_REQUEST_PARAMS",
|
||||
"message": "cursor parameter is invalid",
|
||||
}, http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
query := domain.QueryParams{
|
||||
u, err := url.Parse(r.URL.String())
|
||||
if err != nil {
|
||||
h.encoder.StatusResponse(r.Context(), w, map[string]interface{}{
|
||||
"code": "BAD_REQUEST_PARAMS",
|
||||
"message": "indexer parameter is invalid",
|
||||
}, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
vals := u.Query()
|
||||
indexer := vals["indexer"]
|
||||
|
||||
pushStatus := r.URL.Query().Get("push_status")
|
||||
|
||||
query := domain.ReleaseQueryParams{
|
||||
Limit: uint64(limit),
|
||||
Offset: uint64(offset),
|
||||
Cursor: uint64(cursor),
|
||||
Sort: nil,
|
||||
//Filter: "",
|
||||
Filters: struct {
|
||||
Indexers []string
|
||||
PushStatus string
|
||||
}{Indexers: indexer, PushStatus: pushStatus},
|
||||
}
|
||||
|
||||
releases, nextCursor, count, err := h.service.Find(r.Context(), query)
|
||||
|
@ -90,6 +115,16 @@ func (h releaseHandler) findReleases(w http.ResponseWriter, r *http.Request) {
|
|||
h.encoder.StatusResponse(r.Context(), w, ret, http.StatusOK)
|
||||
}
|
||||
|
||||
func (h releaseHandler) getIndexerOptions(w http.ResponseWriter, r *http.Request) {
|
||||
stats, err := h.service.GetIndexerOptions(r.Context())
|
||||
if err != nil {
|
||||
h.encoder.StatusNotFound(r.Context(), w)
|
||||
return
|
||||
}
|
||||
|
||||
h.encoder.StatusResponse(r.Context(), w, stats, http.StatusOK)
|
||||
}
|
||||
|
||||
func (h releaseHandler) getStats(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
stats, err := h.service.Stats(r.Context())
|
||||
|
|
|
@ -10,7 +10,8 @@ import (
|
|||
)
|
||||
|
||||
type Service interface {
|
||||
Find(ctx context.Context, query domain.QueryParams) (res []domain.Release, nextCursor int64, count int64, err error)
|
||||
Find(ctx context.Context, query domain.ReleaseQueryParams) (res []domain.Release, nextCursor int64, count int64, err error)
|
||||
GetIndexerOptions(ctx context.Context) ([]string, error)
|
||||
Stats(ctx context.Context) (*domain.ReleaseStats, error)
|
||||
Store(ctx context.Context, release *domain.Release) error
|
||||
StoreReleaseActionStatus(ctx context.Context, actionStatus *domain.ReleaseActionStatus) error
|
||||
|
@ -29,7 +30,7 @@ func NewService(repo domain.ReleaseRepo, actionService action.Service) Service {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *service) Find(ctx context.Context, query domain.QueryParams) (res []domain.Release, nextCursor int64, count int64, err error) {
|
||||
func (s *service) Find(ctx context.Context, query domain.ReleaseQueryParams) (res []domain.Release, nextCursor int64, count int64, err error) {
|
||||
res, nextCursor, count, err = s.repo.Find(ctx, query)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -38,6 +39,10 @@ func (s *service) Find(ctx context.Context, query domain.QueryParams) (res []dom
|
|||
return
|
||||
}
|
||||
|
||||
func (s *service) GetIndexerOptions(ctx context.Context) ([]string, error) {
|
||||
return s.repo.GetIndexerOptions(ctx)
|
||||
}
|
||||
|
||||
func (s *service) Stats(ctx context.Context) (*domain.ReleaseStats, error) {
|
||||
stats, err := s.repo.Stats(ctx)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue