feat(media): the operator's map gives a folder the id its name cannot reach
Tvdb titles a record in the show's own language and keeps the English name in aliases the name search never reads, so the rule that accepts only tvdb's own spelling of a query can never resolve them: ブラッククローバー (331753) holds no alias at all, and the bare alias "One Piece" belongs to 392276, the 2023 live action, not to the 1999 record (81797) that 1,072-file pack is. Seventeen pack folders on the array — 3,507 files — are in that class. media-shows.py now reads scripts/media-shows-tvdb-ids.tsv by default: one line per pack folder, folder <TAB> tvdb id <TAB> note, every id read from tvdb's own record. The map outranks a provider id, because a box set's provider id is the server's own guess at a folder name, and it merges the release folders that are one show. Everything it touched goes to the exceptions: every folder it named, every row that matched no folder, every disagreement with a provider id, every id tvdb never answered. The file is read fail-closed — an id that is not a number, or one folder named twice, stops the plan, because a typo there renames a pack of 1,268 files to the wrong show. scripts/media-shows-tvdb.py is the sheet the map was built from, promoted out of /tmp so the next run is reproducible: it reads a plan's mkdir rows, asks tvdb about every destination folder carrying no [tvdbid-], and grades the answer EXACT / PUNCT / NEAR / NONE by how much was guessed to reach it. Acceptance is unchanged from the passes it replaces — bare-form equality plus the year-span guard — and that gate is what rejected three confident picks: Fairy Tail's 2024 sequel (410031), the 2026 Hokuto no Ken remake (465216) and Mugyutto! Black Clover (378762) offered for Black Clover. The sheet is for the operator; the map is what the planner reads, and only after he approves the rows. Tests: seven for the map's behaviour — rename to the record it names, two release folders becoming one series, precedence over a provider id and the line stating the disagreement, an id tvdb never answered, a row whose folder is gone, a malformed id refusing the run, a folder named twice refusing the run — plus one that the shipped file parses and never stops a plan.
This commit is contained in:
1 parent
576c3421b8
commit
7aa32d1b64
5 files changed
+609
-16
No files matched your search
@@ -566,3 +566,132 @@ PY
|
||||
run grep -i "numbering tvdb contradicts" "$EXC"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------- the operator map
|
||||
# Most of this library carries no tvdb id anywhere: the authority titles anime by
|
||||
# its own record — in the show's language — and the English name rides in aliases
|
||||
# the planner's name search never reads, so a search that demands tvdb's own
|
||||
# spelling cannot reach it. The operator's map is the other door: one line per
|
||||
# folder, `folder <TAB> tvdb id <TAB> note`, each id checked by hand against the
|
||||
# record it names. It outranks a provider id, it merges the release folders that
|
||||
# are one show, and every folder it touched is named in the exceptions: one wrong
|
||||
# row there is 1,268 renames to the wrong show, so nothing about it is silent.
|
||||
|
||||
plan_map() { # the plan, with the operator's map in hand
|
||||
run python3 "$PLAN" --root "$LIB" --enum "$ENUM" --titles "$TITLES" \
|
||||
--probed "$PROBED" --tmdb-cache "$CACHE" --movies "$MOVIES" \
|
||||
--tvdb-ids "$1" --out "$OUT" --exceptions "$EXC"
|
||||
}
|
||||
|
||||
@test "a folder the operator mapped to a tvdb id renames to that record" {
|
||||
printf '{"tvdb:series:331753": %s}\n' \
|
||||
'{"name": "Black Clover", "year": "2017"}' > "$CACHE"
|
||||
{
|
||||
printf '# the note column carries why the name search cannot reach it\n'
|
||||
printf 'Black Clover 001\t331753\tthe record holds no alias\n'
|
||||
} > "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
file "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" 5000
|
||||
title_row "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" \
|
||||
"Black Clover 001" "" 1 1
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
want="$LIB/Black Clover (2017) [tvdbid-331753]/Season 01"
|
||||
want+="/Black Clover (2017) - S01E01.mkv"
|
||||
[ "$(dst "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv")" = "$want" ]
|
||||
}
|
||||
|
||||
@test "release folders one id maps are ONE series folder" {
|
||||
printf '{"tvdb:series:81797": %s}\n' \
|
||||
'{"name": "One Piece", "year": "1999"}' > "$CACHE"
|
||||
{
|
||||
printf '[Anime Time] One Piece (0001-1071)\t81797\tbare "One Piece" is the 2023 live action\n'
|
||||
printf 'One Piece Ship Collection\t81797\tthe same record, split by release\n'
|
||||
} > "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
file "$LIB/[Anime Time] One Piece (0001-1071)/One.Piece.0001.mkv" 5000
|
||||
file "$LIB/One Piece Ship Collection/One.Piece.0002.mkv" 6000
|
||||
title_row "$LIB/[Anime Time] One Piece (0001-1071)/One.Piece.0001.mkv" \
|
||||
"One Piece" 1999 1 1
|
||||
title_row "$LIB/One Piece Ship Collection/One.Piece.0002.mkv" \
|
||||
"One Piece Ship Collection" "" 1 2
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
want="$LIB/One Piece (1999) [tvdbid-81797]/Season 01"
|
||||
want+="/One Piece (1999) - S01E01.mkv"
|
||||
[ "$(dst "$LIB/[Anime Time] One Piece (0001-1071)/One.Piece.0001.mkv")" \
|
||||
= "$want" ]
|
||||
want="$LIB/One Piece (1999) [tvdbid-81797]/Season 01"
|
||||
want+="/One Piece (1999) - S01E02.mkv"
|
||||
[ "$(dst "$LIB/One Piece Ship Collection/One.Piece.0002.mkv")" = "$want" ]
|
||||
}
|
||||
|
||||
@test "the map outranks a provider id and says which two disagreed" {
|
||||
printf '{"tvdb:series:4242": %s, "tvdb:series:78850": %s}\n' \
|
||||
'{"name": "Real Ship", "year": "1999"}' \
|
||||
'{"name": "Box Junk", "year": "2016"}' > "$CACHE"
|
||||
printf '%s\t4242\thand-verified against the record\n' \
|
||||
"Show Box (2016) Season 1 S01 (1080p WEB-DL)" > "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
dst "$BOX/Show.Box.S01E01.1080p.WEB-DL.mkv" \
|
||||
| grep -q "^$LIB/Real Ship (1999) \[tvdbid-4242\]/Season 01/"
|
||||
run grep -E '78850.*4242|4242.*78850' "$EXC"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "a map id the authority never answered keeps the provider's name and is named" {
|
||||
printf 'Black Clover 001\t331753\ttvdb never answered\n' \
|
||||
> "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
file "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" 5000
|
||||
title_row "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" \
|
||||
"Black Clover 001" "" 1 1
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
dst "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" \
|
||||
| grep -q "^$LIB/Black Clover 001 \[tvdbid-331753\]/Season 01/"
|
||||
run grep -q "331753" "$EXC"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "a map row for a folder the array no longer holds is reported" {
|
||||
printf 'Gone Pack\t4242\tmoved away\n' > "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
run grep "Gone Pack" "$EXC"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "a map line whose id is not a number stops the plan" {
|
||||
printf 'Black Clover 001\tnotanid\ttypo\n' > "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
file "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" 5000
|
||||
title_row "$LIB/Black Clover 001/Season 01/Black.Clover.001.mkv" \
|
||||
"Black Clover 001" "" 1 1
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "$output" == *"notanid"* ]]
|
||||
}
|
||||
|
||||
# The map the fleet ships is scripts/media-shows-tvdb-ids.tsv, and the planner
|
||||
# reads it by default: an unusable line there stops every plan the operator runs
|
||||
# from the checkout, so the seam validates the real file, not a fixture copy.
|
||||
@test "the shipped operator map parses and never stops a plan" {
|
||||
MAPS="$REPO_ROOT/scripts/media-shows-tvdb-ids.tsv"
|
||||
run awk -F '\t' '!/^#/ && NF {
|
||||
if (NF < 2 || $2 !~ /^[0-9]+$/) { print "unusable row: " $0; bad = 1 }
|
||||
} END { exit bad }' "$MAPS"
|
||||
[ "$status" -eq 0 ]
|
||||
dup=$(awk -F '\t' '!/^#/ && NF {print $1}' "$MAPS" | sort | uniq -d)
|
||||
[ -z "$dup" ]
|
||||
plan_map "$MAPS"
|
||||
[ "$status" -eq 0 ]
|
||||
grep -qi "operator's map" "$EXC"
|
||||
}
|
||||
|
||||
@test "a map that names one folder twice stops the plan" {
|
||||
printf '{"tvdb:series:78850": %s}\n' \
|
||||
'{"name": "Naruto", "year": "2002"}' > "$CACHE"
|
||||
{
|
||||
printf 'Naruto Complete Series\t78850\tthe dub pack\n'
|
||||
printf 'Naruto Complete Series\t331753\ta paste of another row\n'
|
||||
} > "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
file "$LIB/Naruto Complete Series/Season 01/naruto 01.mkv" 5000
|
||||
title_row "$LIB/Naruto Complete Series/Season 01/naruto 01.mkv" \
|
||||
"Naruto Complete Series" "" 1 1
|
||||
plan_map "$BATS_TEST_TMPDIR/ids.tsv"
|
||||
[ "$status" -eq 2 ]
|
||||
[[ "$output" == *"named twice"* ]]
|
||||
}
|
||||
Reference in new issue
Block a user