refactor(filters): move rejections from release to filter (#1272)

* refactor: size check

* refactor(filters): checkfilter rejections from release to filter

---------

Co-authored-by: ze0s <ze0s@riseup.net>
This commit is contained in:
Frederick Robinson 2023-12-01 12:04:23 -05:00 committed by GitHub
parent df5fb37c9c
commit 365055fbe1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 186 additions and 161 deletions

View file

@ -30,9 +30,9 @@ import (
type Service interface {
FindByID(ctx context.Context, filterID int) (*domain.Filter, error)
FindByIndexerIdentifier(ctx context.Context, indexer string) ([]domain.Filter, error)
FindByIndexerIdentifier(ctx context.Context, indexer string) ([]*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)
Store(ctx context.Context, filter *domain.Filter) error
Update(ctx context.Context, filter *domain.Filter) error
@ -40,7 +40,7 @@ type Service interface {
Duplicate(ctx context.Context, filterID int) (*domain.Filter, error)
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
Delete(ctx context.Context, filterID int) error
AdditionalSizeCheck(ctx context.Context, f domain.Filter, release *domain.Release) (bool, error)
AdditionalSizeCheck(ctx context.Context, f *domain.Filter, release *domain.Release) (bool, error)
CanDownloadShow(ctx context.Context, release *domain.Release) (bool, error)
GetDownloadsByFilterId(ctx context.Context, filterID int) (*domain.FilterDownloads, error)
}
@ -134,7 +134,7 @@ func (s *service) FindByID(ctx context.Context, filterID int) (*domain.Filter, e
return filter, nil
}
func (s *service) FindByIndexerIdentifier(ctx context.Context, indexer string) ([]domain.Filter, error) {
func (s *service) FindByIndexerIdentifier(ctx context.Context, indexer string) ([]*domain.Filter, error) {
// get filters for indexer
// we do not load actions here since we do not need it at this stage
// only load those after filter has matched
@ -332,16 +332,17 @@ func (s *service) Delete(ctx context.Context, filterID int) error {
return nil
}
func (s *service) CheckFilter(ctx context.Context, f domain.Filter, release *domain.Release) (bool, error) {
func (s *service) CheckFilter(ctx context.Context, f *domain.Filter, release *domain.Release) (bool, error) {
l := s.log.With().Str("method", "CheckFilter").Logger()
s.log.Trace().Msgf("filter.Service.CheckFilter: checking filter: %s %+v", f.Name, f)
s.log.Trace().Msgf("filter.Service.CheckFilter: checking filter: %s for release: %+v", f.Name, release)
l.Trace().Msgf("checking filter: %s %+v", f.Name, f)
l.Trace().Msgf("checking filter: %s for release: %+v", f.Name, release)
// do additional fetch to get download counts for filter
if f.MaxDownloads > 0 {
downloadCounts, err := s.repo.GetDownloadsByFilterId(ctx, f.ID)
if err != nil {
s.log.Error().Err(err).Msg("filter.Service.CheckFilter: error getting download counters for filter")
l.Error().Err(err).Msg("error getting download counters for filter")
return false, nil
}
f.Downloads = downloadCounts
@ -349,7 +350,7 @@ func (s *service) CheckFilter(ctx context.Context, f domain.Filter, release *dom
rejections, matchedFilter := f.CheckFilter(release)
if len(rejections) > 0 {
s.log.Debug().Msgf("filter.Service.CheckFilter: (%s) for release: %v rejections: (%s)", f.Name, release.TorrentName, release.RejectionsString(true))
l.Debug().Msgf("(%s) for release: %v rejections: (%s)", f.Name, release.TorrentName, f.RejectionsString(true))
return false, nil
}
@ -358,12 +359,12 @@ func (s *service) CheckFilter(ctx context.Context, f domain.Filter, release *dom
if f.SmartEpisode {
canDownloadShow, err := s.CanDownloadShow(ctx, release)
if err != nil {
s.log.Trace().Msgf("filter.Service.CheckFilter: failed smart episode check: %s", f.Name)
l.Trace().Msgf("failed smart episode check: %s", f.Name)
return false, nil
}
if !canDownloadShow {
s.log.Trace().Msgf("filter.Service.CheckFilter: failed smart episode check: %s", f.Name)
l.Trace().Msgf("failed smart episode check: %s", f.Name)
release.AddRejectionF("smart episode check: not new: (%s) season: %d ep: %d", release.Title, release.Season, release.Episode)
return false, nil
}
@ -371,36 +372,36 @@ func (s *service) CheckFilter(ctx context.Context, f domain.Filter, release *dom
// if matched, do additional size check if needed, attach actions and return the filter
s.log.Debug().Msgf("filter.Service.CheckFilter: found and matched filter: %s", f.Name)
l.Debug().Msgf("found and matched filter: %s", f.Name)
// If size constraints are set in a filter and the indexer did not
// announce the size, we need to do an additional out of band size
// check.
if release.AdditionalSizeCheckRequired {
s.log.Debug().Msgf("filter.Service.CheckFilter: (%s) additional size check required", f.Name)
l.Debug().Msgf("(%s) additional size check required", f.Name)
ok, err := s.AdditionalSizeCheck(ctx, f, release)
if err != nil {
s.log.Error().Err(err).Msgf("filter.Service.CheckFilter: (%s) additional size check error", f.Name)
l.Error().Err(err).Msgf("(%s) additional size check error", f.Name)
return false, err
}
if !ok {
s.log.Trace().Msgf("filter.Service.CheckFilter: (%s) additional size check not matching what filter wanted", f.Name)
l.Trace().Msgf("(%s) additional size check not matching what filter wanted", f.Name)
return false, nil
}
}
// run external filters
if f.External != nil {
externalOk, err := s.RunExternalFilters(ctx, f.External, release)
externalOk, err := s.RunExternalFilters(ctx, f, f.External, release)
if err != nil {
s.log.Error().Err(err).Msgf("filter.Service.CheckFilter: (%s) external filter check error", f.Name)
l.Error().Err(err).Msgf("(%s) external filter check error", f.Name)
return false, err
}
if !externalOk {
s.log.Trace().Msgf("filter.Service.CheckFilter: (%s) additional size check not matching what filter wanted", f.Name)
l.Debug().Msgf("(%s) external filter check not matching what filter wanted", f.Name)
return false, nil
}
}
@ -419,7 +420,7 @@ func (s *service) CheckFilter(ctx context.Context, f domain.Filter, release *dom
// it is necessary to download the torrent file and parse it to make the size
// check. We use the API where available to minimize the number of torrents we
// need to download.
func (s *service) AdditionalSizeCheck(ctx context.Context, f domain.Filter, release *domain.Release) (bool, error) {
func (s *service) AdditionalSizeCheck(ctx context.Context, f *domain.Filter, release *domain.Release) (bool, error) {
var err error
defer func() {
// try recover panic if anything went wrong with API or size checks
@ -427,44 +428,45 @@ func (s *service) AdditionalSizeCheck(ctx context.Context, f domain.Filter, rele
}()
// do additional size check against indexer api or torrent for size
s.log.Debug().Msgf("filter.Service.AdditionalSizeCheck: (%s) additional size check required", f.Name)
l := s.log.With().Str("method", "AdditionalSizeCheck").Logger()
l.Debug().Msgf("(%s) additional size check required", f.Name)
switch release.Indexer {
case "ptp", "btn", "ggn", "redacted", "ops", "mock":
if release.Size == 0 {
s.log.Trace().Msgf("filter.Service.AdditionalSizeCheck: (%s) preparing to check via api", f.Name)
l.Trace().Msgf("(%s) preparing to check via api", f.Name)
torrentInfo, err := s.apiService.GetTorrentByID(ctx, release.Indexer, release.TorrentID)
if err != nil || torrentInfo == nil {
s.log.Error().Stack().Err(err).Msgf("filter.Service.AdditionalSizeCheck: (%s) could not get torrent info from api: '%s' from: %s", f.Name, release.TorrentID, release.Indexer)
l.Error().Err(err).Msgf("(%s) could not get torrent info from api: '%s' from: %s", f.Name, release.TorrentID, release.Indexer)
return false, err
}
s.log.Debug().Msgf("filter.Service.AdditionalSizeCheck: (%s) got torrent info from api: %+v", f.Name, torrentInfo)
l.Debug().Msgf("(%s) got torrent info from api: %+v", f.Name, torrentInfo)
release.Size = torrentInfo.ReleaseSizeBytes()
}
default:
s.log.Trace().Msgf("filter.Service.AdditionalSizeCheck: (%s) preparing to download torrent metafile", f.Name)
l.Trace().Msgf("(%s) preparing to download torrent metafile", f.Name)
// if indexer doesn't have api, download torrent and add to tmpPath
if err := release.DownloadTorrentFileCtx(ctx); err != nil {
s.log.Error().Stack().Err(err).Msgf("filter.Service.AdditionalSizeCheck: (%s) could not download torrent file with id: '%s' from: %s", f.Name, release.TorrentID, release.Indexer)
l.Error().Err(err).Msgf("(%s) could not download torrent file with id: '%s' from: %s", f.Name, release.TorrentID, release.Indexer)
return false, err
}
}
// compare size against filter
sizeErr, err := f.CheckReleaseSize(release.Size)
sizeOk, err := f.CheckReleaseSize(release.Size)
if err != nil {
s.log.Error().Stack().Err(err).Msgf("filter.Service.AdditionalSizeCheck: (%s) error checking extra size filter", f.Name)
l.Error().Err(err).Msgf("(%s) error comparing release and filter size", f.Name)
return false, err
}
//no match, lets continue to next filter
if sizeErr != nil {
s.log.Debug().Msgf("filter.Service.AdditionalSizeCheck: (%s) filter did not match after additional size check, trying next", f.Name)
return false, nil
if !sizeOk {
l.Debug().Msgf("(%s) filter did not match after additional size check, trying next", f.Name)
return false, err
}
return true, nil
@ -474,7 +476,7 @@ func (s *service) CanDownloadShow(ctx context.Context, release *domain.Release)
return s.releaseRepo.CanDownloadShow(ctx, release.Title, release.Season, release.Episode)
}
func (s *service) RunExternalFilters(ctx context.Context, externalFilters []domain.FilterExternal, release *domain.Release) (bool, error) {
func (s *service) RunExternalFilters(ctx context.Context, f *domain.Filter, externalFilters []domain.FilterExternal, release *domain.Release) (bool, error) {
var err error
defer func() {
@ -504,7 +506,7 @@ func (s *service) RunExternalFilters(ctx context.Context, externalFilters []doma
if exitCode != external.ExecExpectStatus {
s.log.Trace().Msgf("filter.Service.CheckFilter: external script unexpected exit code. got: %d want: %d", exitCode, external.ExecExpectStatus)
release.AddRejectionF("external script unexpected exit code. got: %d want: %d", exitCode, external.ExecExpectStatus)
f.AddRejectionF("external script unexpected exit code. got: %d want: %d", exitCode, external.ExecExpectStatus)
return false, nil
}
@ -517,7 +519,7 @@ func (s *service) RunExternalFilters(ctx context.Context, externalFilters []doma
if statusCode != external.WebhookExpectStatus {
s.log.Trace().Msgf("filter.Service.CheckFilter: external webhook unexpected status code. got: %d want: %d", statusCode, external.WebhookExpectStatus)
release.AddRejectionF("external webhook unexpected status code. got: %d want: %d", statusCode, external.WebhookExpectStatus)
f.AddRejectionF("external webhook unexpected status code. got: %d want: %d", statusCode, external.WebhookExpectStatus)
return false, nil
}
}