* fix(scanner): skip misplaced TV episodes in movie libraries
A movie-type library containing a TV show laid out as
"Show/Season NN/SxxExx.mkv" (e.g. a fan "supercuts" pack) created one
bogus movie item per episode, all titled after the season folder
("Season 01"). They surfaced on Recently Added and never matched.
Add naming.IsMisplacedSeriesFile, which detects a file with an SxxExx
name inside an explicit "Season NN"/"Specials" directory, and guard
createOrFindSkeleton so such files in a strict movie library are recorded
as a skipped root (reason series_in_movie_library) instead of becoming
items. The movie match-queue worker now dequeues files the skeleton step
deliberately skips instead of erroring on the empty content id.
The guard fires on the structural signal alone, regardless of any parsed
provider id, because a "Season NN" folder otherwise yields a bogus tmdb
id (the season number). Movies whose release filename merely contains an
SxxExx substring but live in a proper "Title (Year)/" folder are
unaffected (covered by the new test).
* fix(metadata): durably exclude misplaced-series files from movie queue
Address review findings on the misplaced-TV skip:
- The skipped file's content_id is never set, so every library sync
re-enqueued it just for the worker to skip and dequeue it again.
Exclude files beneath a series_in_movie_library skipped root in the
movie match queue predicates; deleting the skipped root row makes the
files eligible again. The worker drain remains to flush rows claimed
before the root was recorded.
- Extract the eligibility predicate (previously duplicated verbatim in
eight queries) into movieQueueFileEligibleCond.
- Derive skipped-root file_count from media_files under the root via a
new UpsertObservedFile instead of hardcoding 1: a 34-episode pack now
reports 34 instead of each per-file upsert overwriting the count.
This also fixes the pre-existing missing_folder_ids undercount.
- Fold the two near-identical Upsert+log blocks in createOrFindSkeleton
into a recordSkippedRoot helper, normalize libraryType once, and name
the reason strings as constants.
- Drop a no-op filepath.Base on already-split path segments in
IsMisplacedSeriesFile.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Quick <31828688+Quick104@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
36 lines
1.8 KiB
Go
36 lines
1.8 KiB
Go
package naming
|
|
|
|
import "testing"
|
|
|
|
func TestIsMisplacedSeriesFile(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
path string
|
|
want bool
|
|
}{
|
|
// Misplaced TV show in a movie library: Season dir + SxxExx file.
|
|
{"bleach supercut", `/mnt/unionfs/movies/anime-dub/Bleach Supercuts/Season 01/Bleach Supercuts S01E01 - Ichigo.mkv`, true},
|
|
{"bleach last ep", `/mnt/unionfs/movies/anime-dub/Bleach Supercuts/Season 01/Bleach Supercuts S01E34- Goodbye.mkv`, true},
|
|
{"specials dir", `/mnt/unionfs/movies/anime/Some Show/Specials/Some Show S00E02 - OVA.mkv`, true},
|
|
{"extras dir", `/mnt/unionfs/movies/anime/Some Show/Extras/Some Show S00E03 - Bonus.mkv`, true},
|
|
{"lowercase season", `/x/movies/Show/season 2/Show s02e05.mkv`, true},
|
|
|
|
// Legit movies whose release filenames merely contain an SxxExx substring
|
|
// but sit in a proper "Title (Year)/" folder — must NOT be flagged.
|
|
{"fired up", `/mnt/unionfs/movies/alt-cuts/1080p/Fired Up! (2009)/101.Dalmatian.Street.S01E09-E10.Perfect.Match.1080p.mkv`, false},
|
|
{"puppet master", `/mnt/unionfs/movies/alt-cuts/1080p/Puppet Master (1989)/Transformers.Armada.S01E43.Puppet.1080p.mkv`, false},
|
|
{"k seven", `/mnt/unionfs/movies/anime/K Seven Stories Movie 1 RB Blaze (2018) {tmdb-483452}/K (2012) - S00E05 - R-B Blaze.mkv`, false},
|
|
|
|
// Ordinary movie, no episode pattern at all.
|
|
{"plain movie", `/mnt/unionfs/movies/00s/Heat (1995) {tmdb-949}/Heat (1995).mkv`, false},
|
|
// Episode pattern but no season/specials directory (loose dump) — not our
|
|
// case here; left to the existing ambiguity heuristic, so NOT flagged.
|
|
{"loose episode no season dir", `/mnt/unionfs/movies/anime/Whatever S01E02.mkv`, false},
|
|
}
|
|
for _, tc := range cases {
|
|
if got := IsMisplacedSeriesFile(tc.path); got != tc.want {
|
|
t.Errorf("%s: IsMisplacedSeriesFile(%q) = %v, want %v", tc.name, tc.path, got, tc.want)
|
|
}
|
|
}
|
|
}
|