From 17d156a7ca9891e2f1b2cae04baefb884acdf9c8 Mon Sep 17 00:00:00 2001 From: Silo Server Developer Date: Thu, 28 May 2026 03:18:03 +0200 Subject: [PATCH] fix(naming): parse bare bracketed IMDb IDs ([tt10011226]/{tt...}) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Folders tagged with a bare IMDb id in brackets (Plex/Kodi style, e.g. '17 Blocks (2021) [tt10011226]') had the id silently dropped — folderIDPattern needs an 'imdb-' prefix and trailingImdbIDPattern needs an un-bracketed trailing tt-id. Recognize bracketed bare tt-ids so these items get the trusted-ID match path instead of falling to title+year scoring. --- internal/naming/folderid.go | 9 +++++++++ internal/naming/folderid_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 internal/naming/folderid_test.go 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) + } +}