diff --git a/main.go b/main.go
index 82b7eba..037971f 100644
--- a/main.go
+++ b/main.go
@@ -133,6 +133,11 @@ func Main(ctx context.Context) error {
)
}
+const (
+ PatternGroupTitleHyphenSE = `^(\[[^\]]*\] )?(?P
.*?)( -)?[ \.](S(?P[0-9]{2})E)?(?P[0-9]{2})[^0-9].*`
+ PatternTitleSE = `^(?P.*) S(?P[0-9]+)E(?P[0-9]+).*`
+)
+
func Run(ctx context.Context, outd, ind string, patterns []string, overrides Fields, dry bool) error {
mvNLn := RealMvNLn
if dry {
@@ -141,10 +146,7 @@ func Run(ctx context.Context, outd, ind string, patterns []string, overrides Fie
return RunWith(ctx,
outd,
ind,
- append(patterns,
- `^\[[^\]]*\] (?P.*) - (?P[0-9]+).*`,
- `^(?P.*) S(?P[0-9]+)E(?P[0-9]+).*`,
- ),
+ append(patterns, PatternGroupTitleHyphenSE, PatternTitleSE),
overrides,
mvNLn,
)
@@ -171,28 +173,11 @@ func RunWith(ctx context.Context, outd, ind string, patterns []string, overrides
func one(ctx context.Context, outd, inf string, patterns []string, overrides Fields, mvNLn MvNLn) error {
f := path.Base(inf)
for _, pattern := range patterns {
- re := regexp.MustCompile(pattern)
- if !re.MatchString(f) {
+ found, match := Parse(f, pattern)
+ if !match {
continue
}
- var found Fields
- groupNames := re.SubexpNames()
- groups := re.FindStringSubmatch(f)
- for i := 1; i < len(groupNames); i++ {
- v := groups[i]
- switch groupNames[i] {
- case "title":
- found.Title = v
- case "season":
- found.Season = v
- case "episode":
- found.Episode = v
- default:
- return fmt.Errorf("unexpected capture group %q", groupNames[i])
- }
- }
-
for _, wr := range [][2]*string{
[2]*string{&found.Title, &overrides.Title},
[2]*string{&found.Season, &overrides.Season},
@@ -213,6 +198,31 @@ func one(ctx context.Context, outd, inf string, patterns []string, overrides Fie
return nil
}
+func Parse(f string, pattern string) (Fields, bool) {
+ re := regexp.MustCompile(pattern)
+ if !re.MatchString(f) {
+ return Fields{}, false
+ }
+
+ var found Fields
+ groupNames := re.SubexpNames()
+ groups := re.FindStringSubmatch(f)
+ for i := 1; i < len(groupNames); i++ {
+ v := groups[i]
+ switch groupNames[i] {
+ case "title":
+ found.Title = v
+ case "season":
+ found.Season = v
+ case "episode":
+ found.Episode = v
+ default:
+ //return fmt.Errorf("unexpected capture group %q", groupNames[i])
+ }
+ }
+ return found, true
+}
+
func foundOne(ctx context.Context, outd, inf string, fields Fields, mvNLn MvNLn) error {
tmpl, err := template.New(inf).Parse(outd)
if err != nil {
diff --git a/main_test.go b/main_test.go
index 893a663..4f3c0aa 100644
--- a/main_test.go
+++ b/main_test.go
@@ -242,3 +242,101 @@ func ls(d string) []string {
slices.Sort(result)
return result
}
+
+func TestParse(t *testing.T) {
+ cases := map[string]struct {
+ pattern string
+ want main.Fields
+ }{
+ "[SubsPlease] Tokidoki Bosotto Russia-go de Dereru Tonari no Alya-san - 01 (720p) [A12844D5].mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "Tokidoki Bosotto Russia-go de Dereru Tonari no Alya-san",
+ Season: "",
+ Episode: "01",
+ },
+ },
+ "Survivor.AU.S12E11.1080p.HEVC.x265-MeGusta[EZTVx.to].mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "Survivor.AU",
+ Season: "12",
+ Episode: "11",
+ },
+ },
+ "DAN DA DAN (2024) S01E01v2 (1080p WEB-DL H264 AAC DDP 2.0 Dual-Audio) [MALD].mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "DAN DA DAN (2024)",
+ Season: "01",
+ Episode: "01",
+ },
+ },
+ "ZENSHU.S01E01.1080p.AMZN.WEB-DL.MULTi.DDP2.0.H.264.MSubs-ToonsHub.mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "ZENSHU",
+ Season: "01",
+ Episode: "01",
+ },
+ },
+ "[Yameii] My Hero Academia - S07E08 [English Dub] [CR WEB-DL 720p] [DE5FFC3E].mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "My Hero Academia",
+ Season: "07",
+ Episode: "08",
+ },
+ },
+ "Ranma1-2.2024.S01E03.Because.Theres.Someone.He.Likes.1080p.NF.WEB-DL.AAC2.0.H.264-VARYG.mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "Ranma1-2.2024",
+ Season: "01",
+ Episode: "03",
+ },
+ },
+ "[Yameii] The Apothecary Diaries - S02E03 [English Dub] [CR WEB-DL 720p] [FD3E7434].mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "The Apothecary Diaries",
+ Season: "02",
+ Episode: "03",
+ },
+ },
+ "The.Dinner.Table.Detective.S01E01.Welcome.to.the.murderous.party.File.1.1080p.AMZN.WEB-DL.DDP2.0.H.264-VARYG.mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "The.Dinner.Table.Detective",
+ Season: "01",
+ Episode: "01",
+ },
+ },
+ "[Reza] Wistoria Wand and Sword - S01E01.mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "Wistoria Wand and Sword",
+ Season: "01",
+ Episode: "01",
+ },
+ },
+ "[EMBER] Ao no Hako - 01.mkv": {
+ pattern: main.PatternGroupTitleHyphenSE,
+ want: main.Fields{
+ Title: "Ao no Hako",
+ Season: "",
+ Episode: "01",
+ },
+ },
+ }
+
+ for f, d := range cases {
+ c := d
+ t.Run(f, func(t *testing.T) {
+ got, _ := main.Parse(f, c.pattern)
+ if got != c.want {
+ t.Errorf("expected \n\t%+v but got \n\t%+v", c.want, got)
+ }
+ })
+ }
+}