mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 16:59:12 +00:00
feat(feeds): torznab parse category and freeleech (#492)
* feat(feeds): torznab parse freeleech * feat(feeds): torznab parse categories
This commit is contained in:
parent
924899d9f3
commit
b7d2161fdb
10 changed files with 478 additions and 57 deletions
|
@ -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
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue