diff --git a/internal/naming/folderid.go b/internal/naming/folderid.go index e9cc064c..473308ba 100644 --- a/internal/naming/folderid.go +++ b/internal/naming/folderid.go @@ -13,6 +13,11 @@ var folderIDPattern = regexp.MustCompile(`[{\[](tmdb|tmdbid|imdb|imdbid|tvdb|tvd var trailingImdbIDPattern = regexp.MustCompile(`(?i)(?:^|\s)(tt\d{7,8})$`) var trailingNumericIDPattern = regexp.MustCompile(`(?:^|\s)(\d+)$`) +// bracketedBareImdbPattern matches a bare IMDb id wrapped in brackets without a +// provider prefix, e.g. [tt10011226] or {tt0095016} (Plex/Kodi-style tags). A +// tt-prefixed number is unambiguously IMDb. +var bracketedBareImdbPattern = regexp.MustCompile(`(?i)[{\[](tt\d{7,8})[}\]]`) + // ParseStructuredFolderIDs extracts only explicit structured provider IDs from // a folder or file name, such as {tmdb-27205} or [imdbid-tt1375666}. It does // not consider trailing bare IDs or folderType-based heuristics. @@ -52,6 +57,10 @@ func ParseFolderIDs(folderName string, folderType string) *FolderIDHints { return hints } + if m := bracketedBareImdbPattern.FindStringSubmatch(folderName); m != nil { + return &FolderIDHints{ImdbID: strings.ToLower(m[1])} + } + trimmed := strings.TrimSpace(folderName) if m := trailingImdbIDPattern.FindStringSubmatch(trimmed); m != nil { return &FolderIDHints{ImdbID: strings.ToLower(m[1])} diff --git a/internal/naming/folderid_test.go b/internal/naming/folderid_test.go new file mode 100644 index 00000000..471e9417 --- /dev/null +++ b/internal/naming/folderid_test.go @@ -0,0 +1,29 @@ +package naming + +import "testing" + +func TestParseFolderIDs_BracketedBareImdb(t *testing.T) { + cases := []struct { + name, folder, wantImdb string + }{ + {"square brackets", "17 Blocks (2021) [tt10011226]", "tt10011226"}, + {"curly braces", "Some Show {tt1234567}", "tt1234567"}, + {"8-digit tt", "Movie (2024) [tt12345678]", "tt12345678"}, + } + for _, c := range cases { + got := ParseFolderIDs(c.folder, "movie") + if got == nil || got.ImdbID != c.wantImdb { + t.Errorf("%s: ParseFolderIDs(%q) = %+v, want ImdbID=%q", c.name, c.folder, got, c.wantImdb) + } + } + // must NOT change existing behavior: + if got := ParseFolderIDs("Movie [imdb-tt1375666]", "movie"); got == nil || got.ImdbID != "tt1375666" { + t.Errorf("structured imdb regressed: %+v", got) + } + if got := ParseFolderIDs("Some Movie (2020) [BB]", "movie"); got != nil { + t.Errorf("non-tt bracket tag must not parse as id, got %+v", got) + } + if got := ParseFolderIDs("17 Blocks (2021)", "movie"); got != nil { + t.Errorf("no-id folder must return nil, got %+v", got) + } +}