mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
fix(filters): store and update with no external filters (#1049)
* fix(filters): store and update * fix(filters): bad fmt var * fix(filters): store expect status * fix(filters): store expect status * fix(filters): external filter always rejected
This commit is contained in:
parent
0fa53b0b2e
commit
3e244fac10
14 changed files with 151 additions and 125 deletions
|
@ -186,10 +186,11 @@ func (r *ActionRepo) attachDownloadClient(ctx context.Context, tx *Tx, clientID
|
||||||
var settingsJsonStr string
|
var settingsJsonStr string
|
||||||
|
|
||||||
if err := row.Scan(&client.ID, &client.Name, &client.Type, &client.Enabled, &client.Host, &client.Port, &client.TLS, &client.TLSSkipVerify, &client.Username, &client.Password, &settingsJsonStr); err != nil {
|
if err := row.Scan(&client.ID, &client.Name, &client.Type, &client.Enabled, &client.Host, &client.Port, &client.TLS, &client.TLSSkipVerify, &client.Username, &client.Password, &settingsJsonStr); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
r.log.Warn().Msgf("no download client with id %d", clientID)
|
r.log.Warn().Msgf("no download client with id %d", clientID)
|
||||||
return nil, nil
|
return nil, domain.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "error scanning row")
|
return nil, errors.Wrap(err, "error scanning row")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,8 +347,8 @@ func (r *ActionRepo) Get(ctx context.Context, req *domain.GetActionRequest) (*do
|
||||||
var paused, ignoreRules sql.NullBool
|
var paused, ignoreRules sql.NullBool
|
||||||
|
|
||||||
if err := row.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &clientID, &filterID); err != nil {
|
if err := row.Scan(&a.ID, &a.Name, &a.Type, &a.Enabled, &execCmd, &execArgs, &watchFolder, &category, &tags, &label, &savePath, &paused, &ignoreRules, &limitDl, &limitUl, &limitRatio, &limitSeedTime, &a.ReAnnounceSkip, &a.ReAnnounceDelete, &a.ReAnnounceInterval, &a.ReAnnounceMaxAttempts, &webhookHost, &webhookType, &webhookMethod, &webhookData, &clientID, &filterID); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, nil
|
return nil, domain.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "error scanning row")
|
return nil, errors.Wrap(err, "error scanning row")
|
||||||
|
@ -506,14 +507,14 @@ func (r *ActionRepo) Store(ctx context.Context, action domain.Action) (*domain.A
|
||||||
// return values
|
// return values
|
||||||
var retID int64
|
var retID int64
|
||||||
|
|
||||||
err := queryBuilder.QueryRowContext(ctx).Scan(&retID)
|
if err := queryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "error executing query")
|
return nil, errors.Wrap(err, "error executing query")
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Debug().Msgf("action.store: added new %v", retID)
|
|
||||||
action.ID = int(retID)
|
action.ID = int(retID)
|
||||||
|
|
||||||
|
r.log.Debug().Msgf("action.store: added new %d", retID)
|
||||||
|
|
||||||
return &action, nil
|
return &action, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,7 +589,7 @@ func (r *ActionRepo) Update(ctx context.Context, action domain.Action) (*domain.
|
||||||
return &action, nil
|
return &action, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ActionRepo) StoreFilterActions(ctx context.Context, actions []*domain.Action, filterID int64) ([]*domain.Action, error) {
|
func (r *ActionRepo) StoreFilterActions(ctx context.Context, filterID int64, actions []*domain.Action) ([]*domain.Action, error) {
|
||||||
tx, err := r.db.handler.BeginTx(ctx, nil)
|
tx, err := r.db.handler.BeginTx(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error begin transaction")
|
return nil, errors.Wrap(err, "error begin transaction")
|
||||||
|
|
|
@ -156,7 +156,7 @@ func (r *DownloadClientRepo) FindByID(ctx context.Context, id int32) (*domain.Do
|
||||||
var settingsJsonStr string
|
var settingsJsonStr string
|
||||||
|
|
||||||
if err := row.Scan(&client.ID, &client.Name, &client.Type, &client.Enabled, &client.Host, &client.Port, &client.TLS, &client.TLSSkipVerify, &client.Username, &client.Password, &settingsJsonStr); err != nil {
|
if err := row.Scan(&client.ID, &client.Name, &client.Type, &client.Enabled, &client.Host, &client.Port, &client.TLS, &client.TLSSkipVerify, &client.Username, &client.Password, &settingsJsonStr); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, errors.New("no client configured")
|
return nil, errors.New("no client configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,11 @@ func (r *FeedCacheRepo) Get(bucket string, key string) ([]byte, error) {
|
||||||
var value []byte
|
var value []byte
|
||||||
var ttl time.Duration
|
var ttl time.Duration
|
||||||
|
|
||||||
if err := row.Scan(&value, &ttl); err != nil && err != sql.ErrNoRows {
|
if err := row.Scan(&value, &ttl); err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "error scanning row")
|
return nil, errors.Wrap(err, "error scanning row")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +147,11 @@ func (r *FeedCacheRepo) Exists(bucket string, key string) (bool, error) {
|
||||||
|
|
||||||
var exists bool
|
var exists bool
|
||||||
err = r.db.handler.QueryRow(query, args...).Scan(&exists)
|
err = r.db.handler.QueryRow(query, args...).Scan(&exists)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return false, domain.ErrRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
return false, errors.Wrap(err, "error query")
|
return false, errors.Wrap(err, "error query")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -769,7 +769,7 @@ func (r *FilterRepo) FindExternalFiltersByID(ctx context.Context, filterId int)
|
||||||
return externalFilters, nil
|
return externalFilters, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FilterRepo) Store(ctx context.Context, filter domain.Filter) (*domain.Filter, error) {
|
func (r *FilterRepo) Store(ctx context.Context, filter *domain.Filter) error {
|
||||||
queryBuilder := r.db.squirrel.
|
queryBuilder := r.db.squirrel.
|
||||||
Insert("filter").
|
Insert("filter").
|
||||||
Columns(
|
Columns(
|
||||||
|
@ -896,15 +896,15 @@ func (r *FilterRepo) Store(ctx context.Context, filter domain.Filter) (*domain.F
|
||||||
var retID int
|
var retID int
|
||||||
|
|
||||||
if err := queryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil {
|
if err := queryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil {
|
||||||
return nil, errors.Wrap(err, "error executing query")
|
return errors.Wrap(err, "error executing query")
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.ID = retID
|
filter.ID = retID
|
||||||
|
|
||||||
return &filter, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FilterRepo) Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error) {
|
func (r *FilterRepo) Update(ctx context.Context, filter *domain.Filter) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
queryBuilder := r.db.squirrel.
|
queryBuilder := r.db.squirrel.
|
||||||
|
@ -971,15 +971,15 @@ func (r *FilterRepo) Update(ctx context.Context, filter domain.Filter) (*domain.
|
||||||
|
|
||||||
query, args, err := queryBuilder.ToSql()
|
query, args, err := queryBuilder.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error building query")
|
return errors.Wrap(err, "error building query")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = r.db.handler.ExecContext(ctx, query, args...)
|
_, err = r.db.handler.ExecContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error executing query")
|
return errors.Wrap(err, "error executing query")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &filter, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FilterRepo) UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error {
|
func (r *FilterRepo) UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error {
|
||||||
|
@ -1245,13 +1245,23 @@ func (r *FilterRepo) StoreIndexerConnections(ctx context.Context, filterID int,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error building query")
|
return errors.Wrap(err, "error building query")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = tx.ExecContext(ctx, deleteQuery, deleteArgs...)
|
_, err = tx.ExecContext(ctx, deleteQuery, deleteArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error executing query")
|
return errors.Wrap(err, "error executing query")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(indexers) == 0 {
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return errors.Wrap(err, "error store indexers for filter: %d", filterID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
queryBuilder := r.db.squirrel.
|
queryBuilder := r.db.squirrel.
|
||||||
Insert("filter_indexer").Columns("filter_id", "indexer_id")
|
Insert("filter_indexer").
|
||||||
|
Columns("filter_id", "indexer_id")
|
||||||
|
|
||||||
for _, indexer := range indexers {
|
for _, indexer := range indexers {
|
||||||
queryBuilder = queryBuilder.Values(filterID, indexer.ID)
|
queryBuilder = queryBuilder.Values(filterID, indexer.ID)
|
||||||
|
@ -1311,6 +1321,24 @@ func (r *FilterRepo) DeleteIndexerConnections(ctx context.Context, filterID int)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *FilterRepo) DeleteFilterExternal(ctx context.Context, filterID int) error {
|
||||||
|
queryBuilder := r.db.squirrel.
|
||||||
|
Delete("filter_external").
|
||||||
|
Where(sq.Eq{"filter_id": filterID})
|
||||||
|
|
||||||
|
query, args, err := queryBuilder.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error building query")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.db.handler.ExecContext(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error executing query")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *FilterRepo) Delete(ctx context.Context, filterID int) error {
|
func (r *FilterRepo) Delete(ctx context.Context, filterID int) error {
|
||||||
queryBuilder := r.db.squirrel.
|
queryBuilder := r.db.squirrel.
|
||||||
Delete("filter").
|
Delete("filter").
|
||||||
|
@ -1411,6 +1439,14 @@ func (r *FilterRepo) StoreFilterExternal(ctx context.Context, filterID int, exte
|
||||||
return errors.Wrap(err, "error executing query")
|
return errors.Wrap(err, "error executing query")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(externalFilters) == 0 {
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return errors.Wrap(err, "error delete external filters for filter: %d", filterID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
qb := r.db.squirrel.
|
qb := r.db.squirrel.
|
||||||
Insert("filter_external").
|
Insert("filter_external").
|
||||||
Columns(
|
Columns(
|
||||||
|
|
|
@ -260,12 +260,12 @@ func (r *IrcRepo) CheckExistingNetwork(ctx context.Context, network *domain.IrcN
|
||||||
var tls sql.NullBool
|
var tls sql.NullBool
|
||||||
|
|
||||||
if err = row.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer); err != nil {
|
if err = row.Scan(&net.ID, &net.Enabled, &net.Name, &net.Server, &net.Port, &tls, &pass, &nick, &net.Auth.Mechanism, &account, &password, &inviteCmd, &bouncerAddr, &net.UseBouncer); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
// no result is not an error in our case
|
// no result is not an error in our case
|
||||||
return nil, nil
|
return nil, nil
|
||||||
} else {
|
|
||||||
return nil, errors.Wrap(err, "error scanning row")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, errors.Wrap(err, "error scanning row")
|
||||||
}
|
}
|
||||||
|
|
||||||
net.TLS = tls.Bool
|
net.TLS = tls.Bool
|
||||||
|
|
|
@ -425,7 +425,7 @@ func (repo *ReleaseRepo) Get(ctx context.Context, req *domain.GetReleaseRequest)
|
||||||
var filterId sql.NullInt64
|
var filterId sql.NullInt64
|
||||||
|
|
||||||
if err := row.Scan(&rls.ID, &rls.FilterStatus, pq.Array(&rls.Rejections), &indexerName, &filterName, &filterId, &rls.Protocol, &infoUrl, &downloadUrl, &rls.Title, &rls.TorrentName, &rls.Size, &rls.Timestamp); err != nil {
|
if err := row.Scan(&rls.ID, &rls.FilterStatus, pq.Array(&rls.Rejections), &indexerName, &filterName, &filterId, &rls.Protocol, &infoUrl, &downloadUrl, &rls.Title, &rls.TorrentName, &rls.Size, &rls.Timestamp); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "error scanning row")
|
return nil, errors.Wrap(err, "error scanning row")
|
||||||
|
@ -468,7 +468,7 @@ func (repo *ReleaseRepo) GetActionStatus(ctx context.Context, req *domain.GetRel
|
||||||
var actionId, filterId sql.NullInt64
|
var actionId, filterId sql.NullInt64
|
||||||
|
|
||||||
if err := row.Scan(&rls.ID, &rls.Status, &rls.Action, &actionId, &rls.Type, &client, &filter, &filterId, &rls.ReleaseID, pq.Array(&rls.Rejections), &rls.Timestamp); err != nil {
|
if err := row.Scan(&rls.ID, &rls.Status, &rls.Action, &actionId, &rls.Type, &client, &filter, &filterId, &rls.ReleaseID, pq.Array(&rls.Rejections), &rls.Timestamp); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,8 @@ func (r *UserRepo) FindByUsername(ctx context.Context, username string) (*domain
|
||||||
var user domain.User
|
var user domain.User
|
||||||
|
|
||||||
if err := row.Scan(&user.ID, &user.Username, &user.Password); err != nil {
|
if err := row.Scan(&user.ID, &user.Username, &user.Password); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, nil
|
return nil, domain.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "error scanning row")
|
return nil, errors.Wrap(err, "error scanning row")
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
type ActionRepo interface {
|
type ActionRepo interface {
|
||||||
Store(ctx context.Context, action Action) (*Action, error)
|
Store(ctx context.Context, action Action) (*Action, error)
|
||||||
StoreFilterActions(ctx context.Context, actions []*Action, filterID int64) ([]*Action, error)
|
StoreFilterActions(ctx context.Context, filterID int64, actions []*Action) ([]*Action, error)
|
||||||
FindByFilterID(ctx context.Context, filterID int) ([]*Action, error)
|
FindByFilterID(ctx context.Context, filterID int) ([]*Action, error)
|
||||||
List(ctx context.Context) ([]Action, error)
|
List(ctx context.Context) ([]Action, error)
|
||||||
Get(ctx context.Context, req *GetActionRequest) (*Action, error)
|
Get(ctx context.Context, req *GetActionRequest) (*Action, error)
|
||||||
|
|
|
@ -26,8 +26,8 @@ type FilterRepo interface {
|
||||||
FindByID(ctx context.Context, filterID int) (*Filter, error)
|
FindByID(ctx context.Context, filterID int) (*Filter, error)
|
||||||
FindByIndexerIdentifier(ctx context.Context, indexer string) ([]Filter, error)
|
FindByIndexerIdentifier(ctx context.Context, indexer string) ([]Filter, error)
|
||||||
FindExternalFiltersByID(ctx context.Context, filterId int) ([]FilterExternal, error)
|
FindExternalFiltersByID(ctx context.Context, filterId int) ([]FilterExternal, error)
|
||||||
Store(ctx context.Context, filter Filter) (*Filter, error)
|
Store(ctx context.Context, filter *Filter) error
|
||||||
Update(ctx context.Context, filter Filter) (*Filter, error)
|
Update(ctx context.Context, filter *Filter) error
|
||||||
UpdatePartial(ctx context.Context, filter FilterUpdate) error
|
UpdatePartial(ctx context.Context, filter FilterUpdate) error
|
||||||
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
||||||
Delete(ctx context.Context, filterID int) error
|
Delete(ctx context.Context, filterID int) error
|
||||||
|
@ -35,6 +35,7 @@ type FilterRepo interface {
|
||||||
StoreIndexerConnections(ctx context.Context, filterID int, indexers []Indexer) error
|
StoreIndexerConnections(ctx context.Context, filterID int, indexers []Indexer) error
|
||||||
StoreFilterExternal(ctx context.Context, filterID int, externalFilters []FilterExternal) error
|
StoreFilterExternal(ctx context.Context, filterID int, externalFilters []FilterExternal) error
|
||||||
DeleteIndexerConnections(ctx context.Context, filterID int) error
|
DeleteIndexerConnections(ctx context.Context, filterID int) error
|
||||||
|
DeleteFilterExternal(ctx context.Context, filterID int) error
|
||||||
GetDownloadsByFilterId(ctx context.Context, filterID int) (*FilterDownloads, error)
|
GetDownloadsByFilterId(ctx context.Context, filterID int) (*FilterDownloads, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,14 +130,6 @@ type Filter struct {
|
||||||
MatchDescription string `json:"match_description,omitempty"`
|
MatchDescription string `json:"match_description,omitempty"`
|
||||||
ExceptDescription string `json:"except_description,omitempty"`
|
ExceptDescription string `json:"except_description,omitempty"`
|
||||||
UseRegexDescription bool `json:"use_regex_description,omitempty"`
|
UseRegexDescription bool `json:"use_regex_description,omitempty"`
|
||||||
//ExternalScriptEnabled bool `json:"external_script_enabled,omitempty"`
|
|
||||||
//ExternalScriptCmd string `json:"external_script_cmd,omitempty"`
|
|
||||||
//ExternalScriptArgs string `json:"external_script_args,omitempty"`
|
|
||||||
//ExternalScriptExpectStatus int `json:"external_script_expect_status,omitempty"`
|
|
||||||
//ExternalWebhookEnabled bool `json:"external_webhook_enabled,omitempty"`
|
|
||||||
//ExternalWebhookHost string `json:"external_webhook_host,omitempty"`
|
|
||||||
//ExternalWebhookData string `json:"external_webhook_data,omitempty"`
|
|
||||||
//ExternalWebhookExpectStatus int `json:"external_webhook_expect_status,omitempty"`
|
|
||||||
ActionsCount int `json:"actions_count"`
|
ActionsCount int `json:"actions_count"`
|
||||||
Actions []*Action `json:"actions,omitempty"`
|
Actions []*Action `json:"actions,omitempty"`
|
||||||
External []FilterExternal `json:"external,omitempty"`
|
External []FilterExternal `json:"external,omitempty"`
|
||||||
|
@ -240,6 +233,7 @@ type FilterUpdate struct {
|
||||||
ExternalWebhookData *string `json:"external_webhook_data,omitempty"`
|
ExternalWebhookData *string `json:"external_webhook_data,omitempty"`
|
||||||
ExternalWebhookExpectStatus *int `json:"external_webhook_expect_status,omitempty"`
|
ExternalWebhookExpectStatus *int `json:"external_webhook_expect_status,omitempty"`
|
||||||
Actions []*Action `json:"actions,omitempty"`
|
Actions []*Action `json:"actions,omitempty"`
|
||||||
|
External []FilterExternal `json:"external,omitempty"`
|
||||||
Indexers []Indexer `json:"indexers,omitempty"`
|
Indexers []Indexer `json:"indexers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ type Service interface {
|
||||||
Find(ctx context.Context, params domain.FilterQueryParams) ([]domain.Filter, error)
|
Find(ctx context.Context, params domain.FilterQueryParams) ([]domain.Filter, error)
|
||||||
CheckFilter(ctx context.Context, f domain.Filter, release *domain.Release) (bool, error)
|
CheckFilter(ctx context.Context, f domain.Filter, release *domain.Release) (bool, error)
|
||||||
ListFilters(ctx context.Context) ([]domain.Filter, error)
|
ListFilters(ctx context.Context) ([]domain.Filter, error)
|
||||||
Store(ctx context.Context, filter domain.Filter) (*domain.Filter, error)
|
Store(ctx context.Context, filter *domain.Filter) error
|
||||||
Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error)
|
Update(ctx context.Context, filter *domain.Filter) error
|
||||||
UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error
|
UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error
|
||||||
Duplicate(ctx context.Context, filterID int) (*domain.Filter, error)
|
Duplicate(ctx context.Context, filterID int) (*domain.Filter, error)
|
||||||
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
||||||
|
@ -145,54 +145,53 @@ func (s *service) GetDownloadsByFilterId(ctx context.Context, filterID int) (*do
|
||||||
return s.GetDownloadsByFilterId(ctx, filterID)
|
return s.GetDownloadsByFilterId(ctx, filterID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Store(ctx context.Context, filter domain.Filter) (*domain.Filter, error) {
|
func (s *service) Store(ctx context.Context, filter *domain.Filter) error {
|
||||||
// validate data
|
// validate data
|
||||||
|
|
||||||
// store
|
// store
|
||||||
f, err := s.repo.Store(ctx, filter)
|
err := s.repo.Store(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not store filter: %v", filter)
|
s.log.Error().Err(err).Msgf("could not store filter: %v", filter)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return f, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error) {
|
func (s *service) Update(ctx context.Context, filter *domain.Filter) error {
|
||||||
// validate data
|
// validate data
|
||||||
if filter.Name == "" {
|
if filter.Name == "" {
|
||||||
return nil, errors.New("validation: name can't be empty")
|
return errors.New("validation: name can't be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
f, err := s.repo.Update(ctx, filter)
|
if err := s.repo.Update(ctx, filter); err != nil {
|
||||||
if err != nil {
|
|
||||||
s.log.Error().Err(err).Msgf("could not update filter: %s", filter.Name)
|
s.log.Error().Err(err).Msgf("could not update filter: %s", filter.Name)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care of connected indexers
|
// take care of connected indexers
|
||||||
if err = s.repo.StoreIndexerConnections(ctx, f.ID, filter.Indexers); err != nil {
|
if err := s.repo.StoreIndexerConnections(ctx, filter.ID, filter.Indexers); err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not store filter indexer connections: %s", filter.Name)
|
s.log.Error().Err(err).Msgf("could not store filter indexer connections: %s", filter.Name)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care of connected external filters
|
// take care of connected external filters
|
||||||
if err = s.repo.StoreFilterExternal(ctx, f.ID, filter.External); err != nil {
|
if err := s.repo.StoreFilterExternal(ctx, filter.ID, filter.External); err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not store external filters: %s", filter.Name)
|
s.log.Error().Err(err).Msgf("could not store external filters: %s", filter.Name)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care of filter actions
|
// take care of filter actions
|
||||||
actions, err := s.actionRepo.StoreFilterActions(ctx, filter.Actions, int64(filter.ID))
|
actions, err := s.actionRepo.StoreFilterActions(ctx, int64(filter.ID), filter.Actions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not store filter actions: %s", filter.Name)
|
s.log.Error().Err(err).Msgf("could not store filter actions: %s", filter.Name)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Actions = actions
|
filter.Actions = actions
|
||||||
|
|
||||||
return f, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error {
|
func (s *service) UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error {
|
||||||
|
@ -211,9 +210,17 @@ func (s *service) UpdatePartial(ctx context.Context, filter domain.FilterUpdate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if filter.External != nil {
|
||||||
|
// take care of connected external filters
|
||||||
|
if err := s.repo.StoreFilterExternal(ctx, filter.ID, filter.External); err != nil {
|
||||||
|
s.log.Error().Err(err).Msgf("could not store external filters: %v", filter.Name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if filter.Actions != nil {
|
if filter.Actions != nil {
|
||||||
// take care of filter actions
|
// take care of filter actions
|
||||||
if _, err := s.actionRepo.StoreFilterActions(ctx, filter.Actions, int64(filter.ID)); err != nil {
|
if _, err := s.actionRepo.StoreFilterActions(ctx, int64(filter.ID), filter.Actions); err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not store filter actions: %v", filter.ID)
|
s.log.Error().Err(err).Msgf("could not store filter actions: %v", filter.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -223,57 +230,48 @@ func (s *service) UpdatePartial(ctx context.Context, filter domain.FilterUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Duplicate(ctx context.Context, filterID int) (*domain.Filter, error) {
|
func (s *service) Duplicate(ctx context.Context, filterID int) (*domain.Filter, error) {
|
||||||
// find filter
|
// find filter with actions, indexers and external filters
|
||||||
baseFilter, err := s.repo.FindByID(ctx, filterID)
|
filter, err := s.FindByID(ctx, filterID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
baseFilter.ID = 0
|
|
||||||
baseFilter.Name = fmt.Sprintf("%v Copy", baseFilter.Name)
|
|
||||||
baseFilter.Enabled = false
|
|
||||||
|
|
||||||
// find actions and attach
|
// reset id and name
|
||||||
filterActions, err := s.actionRepo.FindByFilterID(ctx, filterID)
|
filter.ID = 0
|
||||||
if err != nil {
|
filter.Name = fmt.Sprintf("%s Copy", filter.Name)
|
||||||
s.log.Error().Msgf("could not find filter actions: %+v", &filterID)
|
filter.Enabled = false
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// find indexers and attach
|
// store new filter
|
||||||
filterIndexers, err := s.indexerSvc.FindByFilterID(ctx, filterID)
|
if err := s.repo.Store(ctx, filter); err != nil {
|
||||||
if err != nil {
|
s.log.Error().Err(err).Msgf("could not update filter: %s", filter.Name)
|
||||||
s.log.Error().Err(err).Msgf("could not find indexers for filter: %+v", &baseFilter.Name)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// update
|
|
||||||
filter, err := s.repo.Store(ctx, *baseFilter)
|
|
||||||
if err != nil {
|
|
||||||
s.log.Error().Err(err).Msgf("could not update filter: %v", baseFilter.Name)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care of connected indexers
|
// take care of connected indexers
|
||||||
if err = s.repo.StoreIndexerConnections(ctx, filter.ID, filterIndexers); err != nil {
|
if err := s.repo.StoreIndexerConnections(ctx, filter.ID, filter.Indexers); err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not store filter indexer connections: %v", filter.Name)
|
s.log.Error().Err(err).Msgf("could not store filter indexer connections: %s", filter.Name)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
filter.Indexers = filterIndexers
|
|
||||||
|
|
||||||
// reset action id to 0
|
// reset action id to 0
|
||||||
for i, a := range filterActions {
|
for i, a := range filter.Actions {
|
||||||
|
a := a
|
||||||
a.ID = 0
|
a.ID = 0
|
||||||
filterActions[i] = a
|
filter.Actions[i] = a
|
||||||
}
|
}
|
||||||
|
|
||||||
// take care of filter actions
|
// take care of filter actions
|
||||||
actions, err := s.actionRepo.StoreFilterActions(ctx, filterActions, int64(filter.ID))
|
if _, err := s.actionRepo.StoreFilterActions(ctx, int64(filter.ID), filter.Actions); err != nil {
|
||||||
if err != nil {
|
s.log.Error().Err(err).Msgf("could not store filter actions: %s", filter.Name)
|
||||||
s.log.Error().Err(err).Msgf("could not store filter actions: %v", filter.Name)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.Actions = actions
|
// take care of connected external filters
|
||||||
|
// the external filters are fetched with FindByID
|
||||||
|
if err := s.repo.StoreFilterExternal(ctx, filter.ID, filter.External); err != nil {
|
||||||
|
s.log.Error().Err(err).Msgf("could not store external filters: %s", filter.Name)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return filter, nil
|
return filter, nil
|
||||||
}
|
}
|
||||||
|
@ -306,6 +304,12 @@ func (s *service) Delete(ctx context.Context, filterID int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete filter external
|
||||||
|
if err := s.repo.DeleteFilterExternal(ctx, filterID); err != nil {
|
||||||
|
s.log.Error().Err(err).Msgf("could not delete filter external: %v", filterID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// delete filter
|
// delete filter
|
||||||
if err := s.repo.Delete(ctx, filterID); err != nil {
|
if err := s.repo.Delete(ctx, filterID); err != nil {
|
||||||
s.log.Error().Err(err).Msgf("could not delete filter: %v", filterID)
|
s.log.Error().Err(err).Msgf("could not delete filter: %v", filterID)
|
||||||
|
@ -537,7 +541,7 @@ func (s *service) RunExternalFilters(ctx context.Context, externalFilters []doma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) execCmd(ctx context.Context, external domain.FilterExternal, release *domain.Release) (int, error) {
|
func (s *service) execCmd(ctx context.Context, external domain.FilterExternal, release *domain.Release) (int, error) {
|
||||||
|
|
|
@ -21,9 +21,9 @@ type filterService interface {
|
||||||
ListFilters(ctx context.Context) ([]domain.Filter, error)
|
ListFilters(ctx context.Context) ([]domain.Filter, error)
|
||||||
FindByID(ctx context.Context, filterID int) (*domain.Filter, error)
|
FindByID(ctx context.Context, filterID int) (*domain.Filter, error)
|
||||||
Find(ctx context.Context, params domain.FilterQueryParams) ([]domain.Filter, error)
|
Find(ctx context.Context, params domain.FilterQueryParams) ([]domain.Filter, error)
|
||||||
Store(ctx context.Context, filter domain.Filter) (*domain.Filter, error)
|
Store(ctx context.Context, filter *domain.Filter) error
|
||||||
Delete(ctx context.Context, filterID int) error
|
Delete(ctx context.Context, filterID int) error
|
||||||
Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error)
|
Update(ctx context.Context, filter *domain.Filter) error
|
||||||
UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error
|
UpdatePartial(ctx context.Context, filter domain.FilterUpdate) error
|
||||||
Duplicate(ctx context.Context, filterID int) (*domain.Filter, error)
|
Duplicate(ctx context.Context, filterID int) (*domain.Filter, error)
|
||||||
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
||||||
|
@ -144,7 +144,7 @@ func (h filterHandler) duplicate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
filter, err := h.service.Duplicate(ctx, id)
|
filter, err := h.service.Duplicate(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.encoder.StatusNotFound(w)
|
h.encoder.StatusInternalError(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ func (h filterHandler) duplicate(w http.ResponseWriter, r *http.Request) {
|
||||||
func (h filterHandler) store(w http.ResponseWriter, r *http.Request) {
|
func (h filterHandler) store(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
ctx = r.Context()
|
ctx = r.Context()
|
||||||
data domain.Filter
|
data *domain.Filter
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
||||||
|
@ -162,19 +162,18 @@ func (h filterHandler) store(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filter, err := h.service.Store(ctx, data)
|
if err := h.service.Store(ctx, data); err != nil {
|
||||||
if err != nil {
|
|
||||||
h.encoder.Error(w, err)
|
h.encoder.Error(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.encoder.StatusCreatedData(w, filter)
|
h.encoder.StatusCreatedData(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h filterHandler) update(w http.ResponseWriter, r *http.Request) {
|
func (h filterHandler) update(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
ctx = r.Context()
|
ctx = r.Context()
|
||||||
data domain.Filter
|
data *domain.Filter
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
||||||
|
@ -182,13 +181,12 @@ func (h filterHandler) update(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filter, err := h.service.Update(ctx, data)
|
if err := h.service.Update(ctx, data); err != nil {
|
||||||
if err != nil {
|
|
||||||
h.encoder.Error(w, err)
|
h.encoder.Error(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.encoder.StatusResponse(w, http.StatusOK, filter)
|
h.encoder.StatusResponse(w, http.StatusOK, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h filterHandler) updatePartial(w http.ResponseWriter, r *http.Request) {
|
func (h filterHandler) updatePartial(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -226,7 +226,7 @@ const schema = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
indexers: z.array(indexerSchema).min(1, { message: "Must select at least one indexer" }),
|
indexers: z.array(indexerSchema).min(1, { message: "Must select at least one indexer" }),
|
||||||
actions: z.array(actionSchema),
|
actions: z.array(actionSchema),
|
||||||
external: z.array(externalFilterSchema)
|
external: z.array(externalFilterSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function FilterDetails() {
|
export function FilterDetails() {
|
||||||
|
@ -398,14 +398,6 @@ export function FilterDetails() {
|
||||||
indexers: filter.indexers || [],
|
indexers: filter.indexers || [],
|
||||||
actions: filter.actions || [],
|
actions: filter.actions || [],
|
||||||
external: filter.external || [],
|
external: filter.external || [],
|
||||||
external_script_enabled: filter.external_script_enabled || false,
|
|
||||||
external_script_cmd: filter.external_script_cmd || "",
|
|
||||||
external_script_args: filter.external_script_args || "",
|
|
||||||
external_script_expect_status: filter.external_script_expect_status || 0,
|
|
||||||
external_webhook_enabled: filter.external_webhook_enabled || false,
|
|
||||||
external_webhook_host: filter.external_webhook_host || "",
|
|
||||||
external_webhook_data: filter.external_webhook_data ||"",
|
|
||||||
external_webhook_expect_status: filter.external_webhook_expect_status || 0
|
|
||||||
} as Filter}
|
} as Filter}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
enableReinitialize={true}
|
enableReinitialize={true}
|
||||||
|
|
|
@ -280,10 +280,9 @@ const TypeForm = ({external, idx}: TypeFormProps) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<NumberField
|
<NumberField
|
||||||
name={`external.${idx}.script_expected_status`}
|
name={`external.${idx}.exec_expect_status`}
|
||||||
label="Expected exit status"
|
label="Expected exit status"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -320,7 +319,7 @@ const TypeForm = ({external, idx}: TypeFormProps) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<NumberField
|
<NumberField
|
||||||
name={`external.${idx}.webhook_expected_status`}
|
name={`external.${idx}.webhook_expect_status`}
|
||||||
label="Expected http status"
|
label="Expected http status"
|
||||||
placeholder="200"
|
placeholder="200"
|
||||||
/>
|
/>
|
||||||
|
|
10
web/src/types/Filter.d.ts
vendored
10
web/src/types/Filter.d.ts
vendored
|
@ -71,14 +71,6 @@ interface Filter {
|
||||||
actions: Action[];
|
actions: Action[];
|
||||||
indexers: Indexer[];
|
indexers: Indexer[];
|
||||||
external: ExternalFilter[];
|
external: ExternalFilter[];
|
||||||
external_script_enabled: boolean;
|
|
||||||
external_script_cmd: string;
|
|
||||||
external_script_args: string;
|
|
||||||
external_script_expect_status: number;
|
|
||||||
external_webhook_enabled: boolean;
|
|
||||||
external_webhook_host: string;
|
|
||||||
external_webhook_data: string;
|
|
||||||
external_webhook_expect_status: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Action {
|
interface Action {
|
||||||
|
@ -130,10 +122,12 @@ interface ExternalFilter {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
exec_cmd?: string;
|
exec_cmd?: string;
|
||||||
exec_args?: string;
|
exec_args?: string;
|
||||||
|
exec_expect_status?: number;
|
||||||
webhook_host?: string,
|
webhook_host?: string,
|
||||||
webhook_type?: string;
|
webhook_type?: string;
|
||||||
webhook_method?: WebhookMethod;
|
webhook_method?: WebhookMethod;
|
||||||
webhook_data?: string,
|
webhook_data?: string,
|
||||||
webhook_headers?: string;
|
webhook_headers?: string;
|
||||||
|
webhook_expect_status?: number;
|
||||||
filter_id?: number;
|
filter_id?: number;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue