Fix: Folgen in vollstaendigem Episoden-Ordner OHNE -GROUP-Suffix werden umbenannt

Alte deutsche Dokus/Serien-Ordner ohne Gruppen-Suffix (Ordner endet auf bare Codec
".XviD", kein "-GROUP") wurden vom Auto-Rename als "kein Zielname" verworfen — die
Folge landete dann ROH in der Library (z.B. "safari-fm-s04e08a.avi" statt
"Fluss-Monster.S04E08a.Am.Essequibo.Teil.1.German.DOKU.SATRiP.XviD.avi").

buildAutoRenameBaseName akzeptiert jetzt zusaetzlich einen vollstaendigen Episoden-
Ordner: echter SxxExx-Token IM Ordnernamen UND ein Codec-/Aufloesungs-Marker
(SCENE_RESOLUTION_MARKER_RE / SCENE_CODEC_MARKER_RE, inkl. xvid/divx). Der Part-
Buchstabe a/b bleibt erhalten (Ordnername dient unveraendert als Zielname), sodass
Teil 1 und Teil 2 nicht kollidieren. Konservativ: ein nackter "Show.S01E01"-Ordner
ohne Qualitaets-/Codec-Marker wird weiterhin nicht abgeleitet. Greift in Auto-Rename
und Collect. 5 Unit- + 1 Collect-Integrationstest; v1.7.180-Fallback nutzt jetzt
dieselben Module-Konstanten (DRY).
This commit is contained in:
Sucukdeluxe
2026-06-05 17:54:02 +02:00
parent 74aec6f056
commit 339c46bdd2
4 changed files with 142 additions and 5 deletions
+42
View File
@@ -1061,3 +1061,45 @@ describe("isBonusContent (numbered episodes are never bonus)", () => {
expect(isBonusContent(fp, pkgDir, "Making.Of")).toBe(true);
});
});
describe("complete episode folder WITHOUT group suffix (codec/resolution only)", () => {
const hash = "c284d9d9072eaf3ac314d05f951dd115";
it("uses the clean folder name when it has an episode token + codec but no -GROUP (safari S04E08a)", () => {
// Echter Bug (rename-session 2026-06-04): alte deutsche Doku ohne Gruppen-Suffix.
// Ordner endet auf ".XviD" (kein "-GROUP") -> buildAutoRenameBaseName lieferte null ->
// "kein Zielname" -> Datei landete roh als "safari-fm-s04e08a.avi" in der Library.
const folder = "Fluss-Monster.S04E08a.Am.Essequibo.Teil.1.German.DOKU.SATRiP.XviD";
const decision = decideAutoRenameBaseName([folder, hash], "safari-fm-s04e08a.avi", "safari-fm-s04e08a", hash, hash);
expect(decision).toEqual({ kind: "rename", baseName: folder });
});
it("keeps multi-part letters a/b distinct (Teil.1 vs Teil.2 do NOT collide)", () => {
const fa = "Fluss-Monster.S04E08a.Am.Essequibo.Teil.1.German.DOKU.SATRiP.XviD";
const fb = "Fluss-Monster.S04E08b.Am.Essequibo.Teil.2.German.DOKU.SATRiP.XviD";
const da = decideAutoRenameBaseName([fa, hash], "safari-fm-s04e08a.avi", "safari-fm-s04e08a", hash, hash);
const db = decideAutoRenameBaseName([fb, hash], "safari-fm-s04e08b.avi", "safari-fm-s04e08b", hash, hash);
expect(da).toEqual({ kind: "rename", baseName: fa });
expect(db).toEqual({ kind: "rename", baseName: fb });
// Verschiedene Zielnamen -> keine "(2)"-Kollision beim Sammeln.
expect((da as any).baseName).not.toBe((db as any).baseName);
});
it("the previously-working group-suffix folder still works (no regression)", () => {
const folder = "Fluss-Monster.S01E02.Auf.der.Suche.nach.dem.Killer-Wels.German.DOKU.SATRiP.XviD-SAFARi";
const decision = decideAutoRenameBaseName([folder, hash], "safari-fm-s01e02.avi", "safari-fm-s01e02", hash, hash);
expect(decision).toEqual({ kind: "rename", baseName: folder });
});
it("does NOT use a bare episode folder WITHOUT any codec/resolution marker (stays conservative)", () => {
// "Show.S01E01" allein (keine Qualitaets-/Codec-Info, kein -GROUP) ist mehrdeutig ->
// weiterhin kein Ableiten (kein Over-Firing auf generische Ordner).
const decision = decideAutoRenameBaseName(["Show.S01E01", hash], "abc-s01e01.avi", "abc-s01e01", hash, hash);
expect(decision.kind).toBe("skip");
});
it("does NOT fabricate a name from a token-LESS folder (Mega-Direct guard intact)", () => {
const decision = decideAutoRenameBaseName(["Mega-Direct-Pack", hash], "Direct.Show.S01E01.DIRECT.mkv", "Direct.Show.S01E01.DIRECT", hash, hash);
expect(decision.kind).toBe("skip");
});
});
+66
View File
@@ -9686,6 +9686,72 @@ describe("download manager", () => {
void manager;
}, 20000);
it("collect CLEANS a raw .avi whose folder is a complete episode name WITHOUT a -GROUP suffix (safari S04E08a)", async () => {
// Echter Bug (rename-session 2026-06-04): alte deutsche Doku ohne Gruppen-Suffix
// (Ordner endet ".XviD", kein "-GROUP"). buildAutoRenameBaseName lieferte null -> die
// Folge landete ROH als "safari-fm-s04e08a.avi" in der Library. Der Part-Buchstabe a/b
// muss erhalten bleiben (Teil 1 vs Teil 2 duerfen nicht kollidieren).
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
tempDirs.push(root);
const packageName = "c284d9d9072eaf3ac314d05f951dd115";
const outputDir = path.join(root, "downloads", packageName);
const extractDir = path.join(root, "extract", packageName);
const mk = (folder: string, raw: string) => {
const epDir = path.join(extractDir, folder);
fs.mkdirSync(epDir, { recursive: true });
fs.writeFileSync(path.join(epDir, raw), Buffer.alloc(4096, 8));
};
const folderA = "Fluss-Monster.S04E08a.Am.Essequibo.Teil.1.German.DOKU.SATRiP.XviD";
const folderB = "Fluss-Monster.S04E08b.Am.Essequibo.Teil.2.German.DOKU.SATRiP.XviD";
mk(folderA, "safari-fm-s04e08a.avi");
mk(folderB, "safari-fm-s04e08b.avi");
const session = emptySession();
const packageId = `${packageName}-pkg`;
const createdAt = Date.now() - 60_000;
session.packageOrder = [packageId];
session.packages[packageId] = {
id: packageId,
name: packageName,
outputDir,
extractDir,
status: "completed",
itemIds: [],
cancelled: false,
enabled: true,
createdAt,
updatedAt: createdAt
};
const mkvLibraryDir = path.join(root, "mkv-library");
const manager = new DownloadManager(
{
...defaultSettings(),
outputDir: path.join(root, "downloads"),
extractDir: path.join(root, "extract"),
autoExtract: true,
autoRename4sf4sj: true,
collectMkvToLibrary: true,
mkvLibraryDir,
enableIntegrityCheck: false,
cleanupMode: "none"
},
session,
createStoragePaths(path.join(root, "state"))
);
await (manager as any).collectMkvFilesToLibrary(packageId, session.packages[packageId], undefined, false);
// Beide Folgen sauber benannt in der Library, Part a/b distinkt, KEINE rohen Namen.
expect(fs.existsSync(path.join(mkvLibraryDir, `${folderA}.avi`))).toBe(true);
expect(fs.existsSync(path.join(mkvLibraryDir, `${folderB}.avi`))).toBe(true);
expect(fs.existsSync(path.join(mkvLibraryDir, "safari-fm-s04e08a.avi"))).toBe(false);
expect(fs.existsSync(path.join(mkvLibraryDir, "safari-fm-s04e08b.avi"))).toBe(false);
void manager;
}, 20000);
it("deferred final pass renames fresh files before collecting them (no scene names in library)", async () => {
// Folge-Fund zu 18eada9 (verifiziert via Advisor-Gate): 18eada9 schloss den
// "frische Datei landet unbenannt"-Bug nur fuer den HYBRID-Pfad (deferFreshFiles=true