Skip to content

Commit c560bfb

Browse files
committed
fix batch of part of a season getting downloaded even with later episodes in the qBittorrent
1 parent bebaf69 commit c560bfb

File tree

6 files changed

+94
-7
lines changed

6 files changed

+94
-7
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.21.6
55
require (
66
github.com/rs/zerolog v1.32.0
77
github.com/stretchr/testify v1.8.4
8+
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3
89
golang.org/x/time v0.5.0
910
gopkg.in/yaml.v3 v3.0.1
1011
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
1515
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
1616
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
1717
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
18+
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo=
19+
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
1820
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1921
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2022
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=

internal/discovery/discovery.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@ func (c *Controller) DigestMALEntry(ctx context.Context, entry myanimelist.Anime
9595
nyaaEntries, err := c.dep.NYAA.List(ctx, titleQuery, sourceQuery, qualityQuery)
9696
log.Debug().Str("entry", entry.GetTitle()).Msgf("found %d torrents", len(nyaaEntries))
9797
if err != nil {
98-
return 0, fmt.Errorf("getting nyaa list: %w", err)
98+
return count, fmt.Errorf("getting nyaa list: %w", err)
9999
}
100100
// There should always be torrents for entries, if there aren't we can just exit the routine.
101101
if len(nyaaEntries) == 0 {
102102
log.Error().Msgf("no torrents found for entry '%s'", entry.GetTitle())
103-
return 0, nil
103+
return count, nil
104104
}
105105
latestTag, err := c.GetLatestTag(ctx, entry)
106106
if err != nil {

internal/discovery/torrent.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import (
1111
"github.com/sonalys/animeman/integrations/qbittorrent"
1212
"github.com/sonalys/animeman/internal/parser"
1313
"github.com/sonalys/animeman/internal/utils"
14+
"golang.org/x/exp/constraints"
1415
)
1516

1617
var numberExpr = regexp.MustCompile(`\d+`)
18+
var batchReplaceExpr = regexp.MustCompile(`(\d+)~(\d+)`)
1719

1820
func strSliceToInt(from []string) []int64 {
1921
out := make([]int64, 0, len(from))
@@ -23,11 +25,42 @@ func strSliceToInt(from []string) []int64 {
2325
return out
2426
}
2527

26-
func min(a, b int) int {
27-
if a < b {
28-
return a
28+
func min[T constraints.Ordered](values ...T) (min T) {
29+
if len(values) == 0 {
30+
return
2931
}
30-
return b
32+
min = values[0]
33+
for i := range values {
34+
if values[i] < min {
35+
min = values[i]
36+
}
37+
}
38+
return min
39+
}
40+
41+
func max[T constraints.Ordered](values ...T) (max T) {
42+
if len(values) == 0 {
43+
return
44+
}
45+
max = values[0]
46+
for i := range values {
47+
if values[i] > max {
48+
max = values[i]
49+
}
50+
}
51+
return max
52+
}
53+
54+
func mergeBatchEpisodes(tag string) string {
55+
matches := batchReplaceExpr.FindAllStringSubmatch(tag, -1)
56+
if len(matches) == 0 {
57+
return tag
58+
}
59+
values := matches[0][1:]
60+
return batchReplaceExpr.ReplaceAllString(
61+
tag,
62+
fmt.Sprint(max(strSliceToInt(values)...)),
63+
)
3164
}
3265

3366
func compareTags(a, b string) int {
@@ -37,6 +70,8 @@ func compareTags(a, b string) int {
3770
if a != "" && b == "" {
3871
return 1
3972
}
73+
a = mergeBatchEpisodes(a)
74+
b = mergeBatchEpisodes(b)
4075
aNums := strSliceToInt(numberExpr.FindAllString(a, -1))
4176
bNums := strSliceToInt(numberExpr.FindAllString(b, -1))
4277
lenA, lenB := len(aNums), len(bNums)

internal/discovery/torrent_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ func Test_getLatestTag(t *testing.T) {
7171
},
7272
want: "S3",
7373
},
74+
{
75+
name: "batch and season",
76+
args: args{
77+
torrents: []qbittorrent.Torrent{
78+
{Tags: "S1E1~13"},
79+
{Tags: "S1E2"},
80+
{Tags: "S1E3"},
81+
},
82+
},
83+
want: "S1E1~13",
84+
},
7485
}
7586
for _, tt := range tests {
7687
t.Run(tt.name, func(t *testing.T) {
@@ -80,3 +91,41 @@ func Test_getLatestTag(t *testing.T) {
8091
})
8192
}
8293
}
94+
95+
func Test_mergeBatchEpisodes(t *testing.T) {
96+
type args struct {
97+
tag string
98+
}
99+
tests := []struct {
100+
name string
101+
args args
102+
want string
103+
}{
104+
{
105+
name: "empty",
106+
args: args{},
107+
want: "",
108+
},
109+
{
110+
name: "ok",
111+
args: args{
112+
tag: "S03E1~12",
113+
},
114+
want: "S03E12",
115+
},
116+
{
117+
name: "no batch",
118+
args: args{
119+
tag: "S03E1",
120+
},
121+
want: "S03E1",
122+
},
123+
}
124+
for _, tt := range tests {
125+
t.Run(tt.name, func(t *testing.T) {
126+
if got := mergeBatchEpisodes(tt.args.tag); got != tt.want {
127+
t.Errorf("mergeBatchEpisodes() = %v, want %v", got, tt.want)
128+
}
129+
})
130+
}
131+
}

internal/parser/title.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func ParseTitle(title string) ParsedTitle {
6161

6262
func (t ParsedTitle) BuildSeasonEpisodeTag() string {
6363
resp := fmt.Sprintf("%s S%s", t.Title, t.Season)
64-
if !t.IsMultiEpisode {
64+
if t.Episode != "" {
6565
resp = resp + fmt.Sprintf("E%s", t.Episode)
6666
}
6767
return resp

0 commit comments

Comments
 (0)