feat(filters): add except origins (#396)

* feat(filters): add except origins

* feat(filters): add user origin
This commit is contained in:
ze0s 2022-08-03 12:47:32 +02:00 committed by GitHub
parent bd8db18a0e
commit 5d80e48b54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 49 additions and 5 deletions

View file

@ -122,6 +122,7 @@ func (r *FilterRepo) FindByID(ctx context.Context, filterID int) (*domain.Filter
"tags", "tags",
"except_tags", "except_tags",
"origins", "origins",
"except_origins",
"external_script_enabled", "external_script_enabled",
"external_script_cmd", "external_script_cmd",
"external_script_args", "external_script_args",
@ -151,7 +152,7 @@ func (r *FilterRepo) FindByID(ctx context.Context, filterID int) (*domain.Filter
var useRegex, scene, freeleech, hasLog, hasCue, perfectFlac, extScriptEnabled, extWebhookEnabled sql.NullBool var useRegex, scene, freeleech, hasLog, hasCue, perfectFlac, extScriptEnabled, extWebhookEnabled sql.NullBool
var delay, maxDownloads, logScore, extWebhookStatus, extScriptStatus sql.NullInt32 var delay, maxDownloads, logScore, extWebhookStatus, extScriptStatus sql.NullInt32
if err := row.Scan(&f.ID, &f.Enabled, &f.Name, &minSize, &maxSize, &delay, &f.Priority, &maxDownloads, &maxDownloadsUnit, &matchReleases, &exceptReleases, &useRegex, &matchReleaseGroups, &exceptReleaseGroups, &scene, &freeleech, &freeleechPercent, &shows, &seasons, &episodes, pq.Array(&f.Resolutions), pq.Array(&f.Codecs), pq.Array(&f.Sources), pq.Array(&f.Containers), pq.Array(&f.MatchHDR), pq.Array(&f.ExceptHDR), pq.Array(&f.MatchOther), pq.Array(&f.ExceptOther), &years, &artists, &albums, pq.Array(&f.MatchReleaseTypes), pq.Array(&f.Formats), pq.Array(&f.Quality), pq.Array(&f.Media), &logScore, &hasLog, &hasCue, &perfectFlac, &matchCategories, &exceptCategories, &matchUploaders, &exceptUploaders, &tags, &exceptTags, pq.Array(&f.Origins), &extScriptEnabled, &extScriptCmd, &extScriptArgs, &extScriptStatus, &extWebhookEnabled, &extWebhookHost, &extWebhookData, &extWebhookStatus, &f.CreatedAt, &f.UpdatedAt); err != nil { if err := row.Scan(&f.ID, &f.Enabled, &f.Name, &minSize, &maxSize, &delay, &f.Priority, &maxDownloads, &maxDownloadsUnit, &matchReleases, &exceptReleases, &useRegex, &matchReleaseGroups, &exceptReleaseGroups, &scene, &freeleech, &freeleechPercent, &shows, &seasons, &episodes, pq.Array(&f.Resolutions), pq.Array(&f.Codecs), pq.Array(&f.Sources), pq.Array(&f.Containers), pq.Array(&f.MatchHDR), pq.Array(&f.ExceptHDR), pq.Array(&f.MatchOther), pq.Array(&f.ExceptOther), &years, &artists, &albums, pq.Array(&f.MatchReleaseTypes), pq.Array(&f.Formats), pq.Array(&f.Quality), pq.Array(&f.Media), &logScore, &hasLog, &hasCue, &perfectFlac, &matchCategories, &exceptCategories, &matchUploaders, &exceptUploaders, &tags, &exceptTags, pq.Array(&f.Origins), pq.Array(&f.ExceptOrigins), &extScriptEnabled, &extScriptCmd, &extScriptArgs, &extScriptStatus, &extWebhookEnabled, &extWebhookHost, &extWebhookData, &extWebhookStatus, &f.CreatedAt, &f.UpdatedAt); err != nil {
return nil, errors.Wrap(err, "error scanning row") return nil, errors.Wrap(err, "error scanning row")
} }
@ -272,6 +273,7 @@ func (r *FilterRepo) findByIndexerIdentifier(ctx context.Context, tx *Tx, indexe
"f.tags", "f.tags",
"f.except_tags", "f.except_tags",
"f.origins", "f.origins",
"f.except_origins",
"f.external_script_enabled", "f.external_script_enabled",
"f.external_script_cmd", "f.external_script_cmd",
"f.external_script_args", "f.external_script_args",
@ -311,7 +313,7 @@ func (r *FilterRepo) findByIndexerIdentifier(ctx context.Context, tx *Tx, indexe
var useRegex, scene, freeleech, hasLog, hasCue, perfectFlac, extScriptEnabled, extWebhookEnabled sql.NullBool var useRegex, scene, freeleech, hasLog, hasCue, perfectFlac, extScriptEnabled, extWebhookEnabled sql.NullBool
var delay, maxDownloads, logScore, extWebhookStatus, extScriptStatus sql.NullInt32 var delay, maxDownloads, logScore, extWebhookStatus, extScriptStatus sql.NullInt32
if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &minSize, &maxSize, &delay, &f.Priority, &maxDownloads, &maxDownloadsUnit, &matchReleases, &exceptReleases, &useRegex, &matchReleaseGroups, &exceptReleaseGroups, &scene, &freeleech, &freeleechPercent, &shows, &seasons, &episodes, pq.Array(&f.Resolutions), pq.Array(&f.Codecs), pq.Array(&f.Sources), pq.Array(&f.Containers), pq.Array(&f.MatchHDR), pq.Array(&f.ExceptHDR), pq.Array(&f.MatchOther), pq.Array(&f.ExceptOther), &years, &artists, &albums, pq.Array(&f.MatchReleaseTypes), pq.Array(&f.Formats), pq.Array(&f.Quality), pq.Array(&f.Media), &logScore, &hasLog, &hasCue, &perfectFlac, &matchCategories, &exceptCategories, &matchUploaders, &exceptUploaders, &tags, &exceptTags, pq.Array(&f.Origins), &extScriptEnabled, &extScriptCmd, &extScriptArgs, &extScriptStatus, &extWebhookEnabled, &extWebhookHost, &extWebhookData, &extWebhookStatus, &f.CreatedAt, &f.UpdatedAt); err != nil { if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &minSize, &maxSize, &delay, &f.Priority, &maxDownloads, &maxDownloadsUnit, &matchReleases, &exceptReleases, &useRegex, &matchReleaseGroups, &exceptReleaseGroups, &scene, &freeleech, &freeleechPercent, &shows, &seasons, &episodes, pq.Array(&f.Resolutions), pq.Array(&f.Codecs), pq.Array(&f.Sources), pq.Array(&f.Containers), pq.Array(&f.MatchHDR), pq.Array(&f.ExceptHDR), pq.Array(&f.MatchOther), pq.Array(&f.ExceptOther), &years, &artists, &albums, pq.Array(&f.MatchReleaseTypes), pq.Array(&f.Formats), pq.Array(&f.Quality), pq.Array(&f.Media), &logScore, &hasLog, &hasCue, &perfectFlac, &matchCategories, &exceptCategories, &matchUploaders, &exceptUploaders, &tags, &exceptTags, pq.Array(&f.Origins), pq.Array(&f.ExceptOrigins), &extScriptEnabled, &extScriptCmd, &extScriptArgs, &extScriptStatus, &extWebhookEnabled, &extWebhookHost, &extWebhookData, &extWebhookStatus, &f.CreatedAt, &f.UpdatedAt); err != nil {
return nil, errors.Wrap(err, "error scanning row") return nil, errors.Wrap(err, "error scanning row")
} }
@ -410,6 +412,7 @@ func (r *FilterRepo) Store(ctx context.Context, filter domain.Filter) (*domain.F
"has_cue", "has_cue",
"perfect_flac", "perfect_flac",
"origins", "origins",
"except_origins",
"external_script_enabled", "external_script_enabled",
"external_script_cmd", "external_script_cmd",
"external_script_args", "external_script_args",
@ -465,6 +468,7 @@ func (r *FilterRepo) Store(ctx context.Context, filter domain.Filter) (*domain.F
filter.Cue, filter.Cue,
filter.PerfectFlac, filter.PerfectFlac,
pq.Array(filter.Origins), pq.Array(filter.Origins),
pq.Array(filter.ExceptOrigins),
filter.ExternalScriptEnabled, filter.ExternalScriptEnabled,
filter.ExternalScriptCmd, filter.ExternalScriptCmd,
filter.ExternalScriptArgs, filter.ExternalScriptArgs,
@ -539,6 +543,7 @@ func (r *FilterRepo) Update(ctx context.Context, filter domain.Filter) (*domain.
Set("has_cue", filter.Cue). Set("has_cue", filter.Cue).
Set("perfect_flac", filter.PerfectFlac). Set("perfect_flac", filter.PerfectFlac).
Set("origins", pq.Array(filter.Origins)). Set("origins", pq.Array(filter.Origins)).
Set("except_origins", pq.Array(filter.ExceptOrigins)).
Set("external_script_enabled", filter.ExternalScriptEnabled). Set("external_script_enabled", filter.ExternalScriptEnabled).
Set("external_script_cmd", filter.ExternalScriptCmd). Set("external_script_cmd", filter.ExternalScriptCmd).
Set("external_script_args", filter.ExternalScriptArgs). Set("external_script_args", filter.ExternalScriptArgs).

View file

@ -107,6 +107,7 @@ CREATE TABLE filter
tags TEXT, tags TEXT,
except_tags TEXT, except_tags TEXT,
origins TEXT [] DEFAULT '{}', origins TEXT [] DEFAULT '{}',
except_origins TEXT [] DEFAULT '{}',
external_script_enabled BOOLEAN DEFAULT FALSE, external_script_enabled BOOLEAN DEFAULT FALSE,
external_script_cmd TEXT, external_script_cmd TEXT,
external_script_args TEXT, external_script_args TEXT,
@ -536,4 +537,8 @@ CREATE INDEX indexer_identifier_index
ALTER TABLE action ALTER TABLE action
ADD COLUMN content_layout TEXT; ADD COLUMN content_layout TEXT;
`, `,
`
ALTER TABLE filter
ADD COLUMN except_origins TEXT [] DEFAULT '{}';
`,
} }

View file

@ -107,6 +107,7 @@ CREATE TABLE filter
tags TEXT, tags TEXT,
except_tags TEXT, except_tags TEXT,
origins TEXT [] DEFAULT '{}', origins TEXT [] DEFAULT '{}',
except_origins TEXT [] DEFAULT '{}',
external_script_enabled BOOLEAN DEFAULT FALSE, external_script_enabled BOOLEAN DEFAULT FALSE,
external_script_cmd TEXT, external_script_cmd TEXT,
external_script_args TEXT, external_script_args TEXT,
@ -856,4 +857,8 @@ CREATE INDEX indexer_identifier_index
ALTER TABLE action ALTER TABLE action
ADD COLUMN content_layout TEXT; ADD COLUMN content_layout TEXT;
`, `,
`
ALTER TABLE filter
ADD COLUMN except_origins TEXT [] DEFAULT '{}';
`,
} }

View file

@ -67,6 +67,7 @@ type Filter struct {
ExceptReleaseGroups string `json:"except_release_groups,omitempty"` ExceptReleaseGroups string `json:"except_release_groups,omitempty"`
Scene bool `json:"scene,omitempty"` Scene bool `json:"scene,omitempty"`
Origins []string `json:"origins,omitempty"` Origins []string `json:"origins,omitempty"`
ExceptOrigins []string `json:"except_origins,omitempty"`
Bonus []string `json:"bonus,omitempty"` Bonus []string `json:"bonus,omitempty"`
Freeleech bool `json:"freeleech,omitempty"` Freeleech bool `json:"freeleech,omitempty"`
FreeleechPercent string `json:"freeleech_percent,omitempty"` FreeleechPercent string `json:"freeleech_percent,omitempty"`
@ -140,6 +141,9 @@ func (f Filter) CheckFilter(r *Release) ([]string, bool) {
if len(f.Origins) > 0 && !containsSlice(r.Origin, f.Origins) { if len(f.Origins) > 0 && !containsSlice(r.Origin, f.Origins) {
r.addRejectionF("origin not matching. got: %v want: %v", r.Origin, f.Origins) r.addRejectionF("origin not matching. got: %v want: %v", r.Origin, f.Origins)
} }
if len(f.ExceptOrigins) > 0 && containsSlice(r.Origin, f.ExceptOrigins) {
r.addRejectionF("except origin not matching. got: %v unwanted: %v", r.Origin, f.ExceptOrigins)
}
// title is the parsed title // title is the parsed title
if f.Shows != "" && !contains(r.Title, f.Shows) { if f.Shows != "" && !contains(r.Title, f.Shows) {

View file

@ -1017,6 +1017,7 @@ func TestFilter_CheckFilter1(t *testing.T) {
ExceptReleaseGroups string ExceptReleaseGroups string
Scene bool Scene bool
Origins []string Origins []string
ExceptOrigins []string
Freeleech bool Freeleech bool
FreeleechPercent string FreeleechPercent string
Shows string Shows string
@ -1510,6 +1511,24 @@ func TestFilter_CheckFilter1(t *testing.T) {
wantRejections: nil, wantRejections: nil,
wantMatch: true, wantMatch: true,
}, },
{
name: "test_37",
fields: fields{
ExceptOrigins: []string{"Internal"},
},
args: args{&Release{TorrentName: "Gillan - Future Shock", Origin: "Internal"}},
wantRejections: []string{"except origin not matching. got: Internal unwanted: [Internal]"},
wantMatch: false,
},
{
name: "test_38",
fields: fields{
ExceptOrigins: []string{"Internal"},
},
args: args{&Release{TorrentName: "Gillan - Future Shock", Origin: "Scene"}},
wantRejections: nil,
wantMatch: true,
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@ -1532,6 +1551,7 @@ func TestFilter_CheckFilter1(t *testing.T) {
ExceptReleaseGroups: tt.fields.ExceptReleaseGroups, ExceptReleaseGroups: tt.fields.ExceptReleaseGroups,
Scene: tt.fields.Scene, Scene: tt.fields.Scene,
Origins: tt.fields.Origins, Origins: tt.fields.Origins,
ExceptOrigins: tt.fields.ExceptOrigins,
Freeleech: tt.fields.Freeleech, Freeleech: tt.fields.Freeleech,
FreeleechPercent: tt.fields.FreeleechPercent, FreeleechPercent: tt.fields.FreeleechPercent,
Shows: tt.fields.Shows, Shows: tt.fields.Shows,

View file

@ -133,6 +133,7 @@ func init() {
{tag: "Scene", title: "Scene", regexp: "", re: nil}, {tag: "Scene", title: "Scene", regexp: "", re: nil},
{tag: "O-Scene", title: "O-Scene", regexp: "", re: nil}, {tag: "O-Scene", title: "O-Scene", regexp: "", re: nil},
{tag: "Internal", title: "Internal", regexp: "", re: nil}, {tag: "Internal", title: "Internal", regexp: "", re: nil},
{tag: "User", title: "User", regexp: "", re: nil},
} }
types["origin"] = origin types["origin"] = origin

View file

@ -282,6 +282,7 @@ export default function FilterDetails() {
artists: filter.artists, artists: filter.artists,
albums: filter.albums, albums: filter.albums,
origins: filter.origins || [], origins: filter.origins || [],
except_origins: filter.except_origins || [],
indexers: filter.indexers || [], indexers: filter.indexers || [],
actions: filter.actions || [], actions: filter.actions || [],
external_script_enabled: filter.external_script_enabled || false, external_script_enabled: filter.external_script_enabled || false,
@ -491,7 +492,8 @@ export function Advanced() {
</CollapsableSection> </CollapsableSection>
<CollapsableSection title="Origins" subtitle="Match Internals, scene, p2p etc if announced"> <CollapsableSection title="Origins" subtitle="Match Internals, scene, p2p etc if announced">
<MultiSelect name="origins" options={ORIGIN_OPTIONS} label="Origins" columns={6} /> <MultiSelect name="origins" options={ORIGIN_OPTIONS} label="Match Origins" columns={6} creatable={true} />
<MultiSelect name="except_origins" options={ORIGIN_OPTIONS} label="Except Origins" columns={6} creatable={true} />
</CollapsableSection> </CollapsableSection>
<CollapsableSection title="Freeleech" subtitle="Match only freeleech and freeleech percent"> <CollapsableSection title="Freeleech" subtitle="Match only freeleech and freeleech percent">
@ -509,10 +511,11 @@ interface CollapsableSectionProps {
title: string; title: string;
subtitle: string; subtitle: string;
children: React.ReactNode; children: React.ReactNode;
defaultOpen?: boolean;
} }
function CollapsableSection({ title, subtitle, children }: CollapsableSectionProps) { function CollapsableSection({ title, subtitle, children, defaultOpen }: CollapsableSectionProps) {
const [isOpen, toggleOpen] = useToggle(false); const [isOpen, toggleOpen] = useToggle(defaultOpen ?? false);
return ( return (
<div className="mt-6 lg:pb-6 border-b border-gray-200 dark:border-gray-700"> <div className="mt-6 lg:pb-6 border-b border-gray-200 dark:border-gray-700">

View file

@ -17,6 +17,7 @@ interface Filter {
except_release_groups: string; except_release_groups: string;
scene: boolean; scene: boolean;
origins: string[]; origins: string[];
except_origins: string[];
freeleech: boolean; freeleech: boolean;
freeleech_percent: string; freeleech_percent: string;
shows: string; shows: string;