Fix: Folgen mit Bonus-Wort im Titel bleiben nicht mehr in "Downloader Fertig" liegen

Eine Folge mit gueltigem SxxExx-Token ist eine echte Episode, niemals Bonus/Extras —
auch wenn ihr Titel oder der Episoden-Ordnername ein Bonus-Wort enthaelt
(Interview/Outtakes/Special/Featurette/Making-Of/...). Bisher stufte der Library-
Collect (und Auto-Rename) solche Folgen als Extras ein und verschob sie NIE in die
Bibliothek — extrahiert und korrekt benannt, aber stumm liegengelassen (Skip nur via
logger.info, im Paket-Log unsichtbar). Betraf u.a. Revenge S04E19 "Interview".

Neue isBonusContent()-Guard an beiden Call-Sites: erst SxxExx pruefen (extractEpisodeToken),
nur ohne Token greift der Bonus-Filter (isInsideBonusDir / BONUS_FILENAME_RE). Echte Extras
ohne Token bleiben gefiltert. 2 Integrationstests + 5 Unit-Tests.
This commit is contained in:
Sucukdeluxe
2026-06-04 23:05:50 +02:00
parent 95a951ccc3
commit afba79cdfd
4 changed files with 227 additions and 3 deletions
+20 -2
View File
@@ -180,6 +180,24 @@ function isInsideBonusDir(filePath: string, packageDir: string): boolean {
return false;
}
/** True if a file is bonus/extras content (Making-Of, Featurette, Interview, )
* that must NOT be collected into the flat episode library.
*
* CRITICAL GUARD: a file carrying a real SxxExx episode token is a NUMBERED
* EPISODE, never extras even when its TITLE (or per-episode folder name)
* happens to contain a bonus keyword, e.g. "Revenge.2011.S04E19.Interview".
* Without this guard, episodes titled Interview/Outtakes/Special/Featurette/
* (and entire series whose name is such a word) were silently dropped from the
* library extracted + correctly renamed but never moved, no error (rd-support
* bundle 2026-06-04). Genuine extras lack an SxxExx token (or live in an
* Extras/Bonus subdir) and are still excluded. */
export function isBonusContent(filePath: string, packageDir: string, nameWithoutExt: string): boolean {
if (extractEpisodeToken(nameWithoutExt)) {
return false;
}
return isInsideBonusDir(filePath, packageDir) || BONUS_FILENAME_RE.test(nameWithoutExt);
}
function expectedMinBytes(totalBytes: number | null | undefined, strict: boolean): number {
if (!totalBytes || totalBytes <= 0) {
return 10240;
@@ -4291,7 +4309,7 @@ export class DownloadManager extends EventEmitter {
// Skip bonus/extras content (Featurettes, Making-Of, Behind-The-Scenes, etc.)
// These have generic descriptive names and would get renamed to misleading
// episode names if matched against the package's SxxExx pattern.
if (isInsideBonusDir(sourcePath, extractDir) || BONUS_FILENAME_RE.test(sourceBaseName)) {
if (isBonusContent(sourcePath, extractDir, sourceBaseName)) {
continue;
}
const folderCandidates: string[] = [];
@@ -5033,7 +5051,7 @@ export class DownloadManager extends EventEmitter {
sampleSkipped += 1;
continue;
}
if (isInsideBonusDir(filePath, sourceRoot) || BONUS_FILENAME_RE.test(stem)) {
if (isBonusContent(filePath, sourceRoot, stem)) {
bonusSkipped += 1;
logger.info(`MKV-Sammelordner: Bonus-Datei uebersprungen: ${path.basename(filePath)} (Pfad: ${path.relative(sourceRoot, filePath)})`);
continue;