feat(feeds): torznab parse category and freeleech (#492)

* feat(feeds): torznab parse freeleech

* feat(feeds): torznab parse categories
This commit is contained in:
ze0s 2022-10-14 18:01:04 +02:00 committed by GitHub
parent 924899d9f3
commit b7d2161fdb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 478 additions and 57 deletions

View file

@ -309,12 +309,26 @@ func (f Filter) CheckFilter(r *Release) ([]string, bool) {
r.addRejectionF("year not matching. got: %d want: %v", r.Year, f.Years)
}
if f.MatchCategories != "" && !contains(r.Category, f.MatchCategories) {
r.addRejectionF("category not matching. got: %v want: %v", r.Category, f.MatchCategories)
if f.MatchCategories != "" {
var categories []string
categories = append(categories, r.Categories...)
if r.Category != "" {
categories = append(categories, r.Category)
}
if !contains(r.Category, f.MatchCategories) && !containsAny(r.Categories, f.MatchCategories) {
r.addRejectionF("category not matching. got: %v want: %v", strings.Join(categories, ","), f.MatchCategories)
}
}
if f.ExceptCategories != "" && contains(r.Category, f.ExceptCategories) {
r.addRejectionF("category unwanted. got: %v want: %v", r.Category, f.ExceptCategories)
if f.ExceptCategories != "" {
var categories []string
categories = append(categories, r.Categories...)
if r.Category != "" {
categories = append(categories, r.Category)
}
if !contains(r.Category, f.ExceptCategories) && !containsAny(r.Categories, f.ExceptCategories) {
r.addRejectionF("category unwanted. got: %v want: %v", strings.Join(categories, ","), f.ExceptCategories)
}
}
if len(f.MatchReleaseTypes) > 0 && !containsSlice(r.Category, f.MatchReleaseTypes) {
@ -566,15 +580,25 @@ func containsAny(tags []string, filter string) bool {
return containsMatch(tags, strings.Split(filter, ","))
}
func containsAnyOther(filter string, tags ...string) bool {
return containsMatch(tags, strings.Split(filter, ","))
}
func sliceContainsSlice(tags []string, filters []string) bool {
return containsMatchBasic(tags, filters)
}
func containsMatchFuzzy(tags []string, filters []string) bool {
for _, tag := range tags {
if tag == "" {
continue
}
tag = strings.ToLower(tag)
for _, filter := range filters {
if filter == "" {
continue
}
filter = strings.ToLower(filter)
filter = strings.Trim(filter, " ")
// check if line contains * or ?, if so try wildcard match, otherwise try substring match

View file

@ -252,6 +252,111 @@ func TestFilter_CheckFilter(t *testing.T) {
},
want: false,
},
{
name: "movie_bad_category_2",
fields: &Release{
TorrentName: "That Movie 2020 2160p BluRay DD5.1 x264-GROUP1",
//Category: "Movies",
Categories: []string{"Movies/HD", "2040"},
Freeleech: true,
Size: uint64(30000000001), // 30GB
},
args: args{
filter: Filter{
Enabled: true,
MatchCategories: "*tv*",
Freeleech: true,
MinSize: "10 GB",
MaxSize: "40GB",
Resolutions: []string{"1080p", "2160p"},
Sources: []string{"BluRay"},
Codecs: []string{"x264"},
Years: "2015,2018-2022",
MatchReleaseGroups: "GROUP1,BADGROUP",
Shows: "*Movie*, good story, bad movie",
},
rejections: []string{"category not matching. got: Movies/HD,2040 want: *tv*"},
},
want: false,
},
{
name: "movie_category_2",
fields: &Release{
TorrentName: "That Movie 2020 2160p BluRay DD5.1 x264-GROUP1",
//Category: "Movies",
Categories: []string{"Movies/HD", "2040"},
Freeleech: true,
Size: uint64(30000000001), // 30GB
},
args: args{
filter: Filter{
Enabled: true,
MatchCategories: "*Movies*",
Freeleech: true,
MinSize: "10 GB",
MaxSize: "40GB",
Resolutions: []string{"1080p", "2160p"},
Sources: []string{"BluRay"},
Codecs: []string{"x264"},
Years: "2015,2018-2022",
MatchReleaseGroups: "GROUP1,BADGROUP",
Shows: "*Movie*, good story, bad movie",
},
},
want: true,
},
{
name: "movie_category_3",
fields: &Release{
TorrentName: "That Movie 2020 2160p BluRay DD5.1 x264-GROUP1",
//Category: "Movies",
Categories: []string{"Movies/HD", "2040"},
Freeleech: true,
Size: uint64(30000000001), // 30GB
},
args: args{
filter: Filter{
Enabled: true,
MatchCategories: "2040",
Freeleech: true,
MinSize: "10 GB",
MaxSize: "40GB",
Resolutions: []string{"1080p", "2160p"},
Sources: []string{"BluRay"},
Codecs: []string{"x264"},
Years: "2015,2018-2022",
MatchReleaseGroups: "GROUP1,BADGROUP",
Shows: "*Movie*, good story, bad movie",
},
},
want: true,
},
{
name: "movie_category_4",
fields: &Release{
TorrentName: "That Movie 2020 2160p BluRay DD5.1 x264-GROUP1",
//Category: "Movies",
Categories: []string{"Movies/HD", "2040"},
Freeleech: true,
Size: uint64(30000000001), // 30GB
},
args: args{
filter: Filter{
Enabled: true,
MatchCategories: "*HD*",
Freeleech: true,
MinSize: "10 GB",
MaxSize: "40GB",
Resolutions: []string{"1080p", "2160p"},
Sources: []string{"BluRay"},
Codecs: []string{"x264"},
Years: "2015,2018-2022",
MatchReleaseGroups: "GROUP1,BADGROUP",
Shows: "*Movie*, good story, bad movie",
},
},
want: true,
},
{
name: "tv_match_season_episode",
fields: &Release{

View file

@ -52,6 +52,7 @@ type Release struct {
Size uint64 `json:"size"`
Title string `json:"title"` // Parsed title
Category string `json:"category"`
Categories []string `json:"categories,omitempty"`
Season int `json:"season"`
Episode int `json:"episode"`
Year int `json:"year"`

View file

@ -226,15 +226,10 @@ func (s *service) Test(ctx context.Context, feed *domain.Feed) error {
if feed.Type == string(domain.FeedTypeTorznab) {
// setup torznab Client
c := torznab.NewClient(torznab.Config{Host: feed.URL, ApiKey: feed.ApiKey, Log: subLogger})
caps, err := c.GetCaps()
if err != nil {
s.log.Error().Err(err).Msg("error testing feed")
return err
}
if caps == nil {
s.log.Error().Msg("could not test feed and get caps")
return errors.New("could not test feed and get caps")
if _, err := c.FetchFeed(); err != nil {
s.log.Error().Err(err).Msg("error getting torznab feed")
return err
}
}

View file

@ -2,6 +2,7 @@ package feed
import (
"sort"
"strconv"
"time"
"github.com/autobrr/autobrr/internal/domain"
@ -79,6 +80,17 @@ func (j *TorznabJob) process() error {
rls.ParseString(item.Title)
if parseFreeleech(item) {
rls.Freeleech = true
rls.Bonus = []string{"Freeleech"}
}
// map torznab categories ID and Name into rls.Categories
// so we can filter on both ID and Name
for _, category := range item.Categories {
rls.Categories = append(rls.Categories, []string{category.Name, strconv.Itoa(category.ID)}...)
}
releases = append(releases, rls)
}
@ -88,9 +100,21 @@ func (j *TorznabJob) process() error {
return nil
}
func parseFreeleech(item torznab.FeedItem) bool {
for _, attr := range item.Attributes {
if attr.Name == "downloadvolumefactor" {
if attr.Value == "0" {
return true
}
}
}
return false
}
func (j *TorznabJob) getFeed() ([]torznab.FeedItem, error) {
// get feed
feedItems, err := j.Client.GetFeed()
feedItems, err := j.Client.FetchFeed()
if err != nil {
j.Log.Error().Err(err).Msgf("error fetching feed items")
return nil, errors.Wrap(err, "error fetching feed items")