Renaming: vollstaendigen Episoden-Ordner als Namen nutzen, wenn Quelle keinen SxxExx-Token hat
User-Report (Desktop-Log): "Kreuzfahrt ins Glück" — 25 Folgen "bet_kig_01_hdt.mkv" (obfuskiert, KEIN SxxExx-Token) landeten roh in der Library, obwohl der Episoden-Ordner "Kreuzfahrt.ins.Glueck.01.Hochzeitsreise.nach.Burma.2007.German.720p.HDTV.x264-BET" bereits der saubere Name ist (Episode als "01" statt S01E01). Ursache (vorbestehend, nicht v1.7.178/179): buildAutoRenameBaseName gibt null zurueck, sobald die QUELLE keinen SxxExx-Token hat — das "Folge 01"-Nummernformat wurde nie unterstuetzt. Fix: Fallback in decideAutoRenameBaseName — fehlt der Quell-Episode-Token und kann normal kein Name abgeleitet werden, aber ein folderCandidate ist ein VOLLSTAENDIGER Scene-Release-Ordner (Scene-Gruppe UND Aufloesung ODER Codec, kein reiner Season-Ordner), wird dieser Ordnername direkt verwendet (note "folder-as-is"). Greift NUR ohne Quell-Episode-Token -> Mega-Direct (mit Quell-Token) bleibt no-target. Aufloesung ODER Codec (nicht nur Aufloesung) deckt DVDRip/XviD ohne 720p ab (Advisor-Punkt). Bonus/Sample werden vorher gefiltert. Verifiziert: tsc 6, 682 Tests gruen (+3: Kreuzfahrt real, DVDRip-nur-Codec, Mega-Direct-bleibt- no-target), Build gruen. Advisor + reproduzierter Diagnose-Test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e9c6a6bcae
commit
dc271e08ff
@ -1422,7 +1422,7 @@ export function buildAutoRenameBaseNameFromFoldersWithOptions(
|
|||||||
* clean target base name to rename to, or a skip with the reason (the caller
|
* clean target base name to rename to, or a skip with the reason (the caller
|
||||||
* logs and falls back to KEEPING the current name — raw-keep is the floor). */
|
* logs and falls back to KEEPING the current name — raw-keep is the floor). */
|
||||||
export type AutoRenameNameDecision =
|
export type AutoRenameNameDecision =
|
||||||
| { kind: "rename"; baseName: string; note?: "token-inserted" | "token-applyToken" | "folder-override"; sourceEpisodeToken?: string; targetEpisodeToken?: string }
|
| { kind: "rename"; baseName: string; note?: "token-inserted" | "token-applyToken" | "folder-override" | "folder-as-is"; sourceEpisodeToken?: string; targetEpisodeToken?: string }
|
||||||
| { kind: "skip"; reason: "no-target" | "source-better" | "token-loss" | "token-mismatch"; targetBaseName?: string; sourceEpisodeToken?: string; targetEpisodeToken?: string };
|
| { kind: "skip"; reason: "no-target" | "source-better" | "token-loss" | "token-mismatch"; targetBaseName?: string; sourceEpisodeToken?: string; targetEpisodeToken?: string };
|
||||||
|
|
||||||
export function decideAutoRenameBaseName(
|
export function decideAutoRenameBaseName(
|
||||||
@ -1510,6 +1510,27 @@ export function decideAutoRenameBaseName(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!targetBaseName) {
|
if (!targetBaseName) {
|
||||||
|
// Fallback "Junk-Quellname + sauberer Release-Ordner": hat die QUELLE keinen Episode-Token
|
||||||
|
// (z.B. obfuskiertes "bet_kig_01_hdt") und kann normal kein Name abgeleitet werden, aber EIN
|
||||||
|
// folderCandidate IST bereits ein VOLLSTAENDIGER Scene-Release-Ordner (Scene-Gruppe UND
|
||||||
|
// Aufloesung ODER Codec, KEIN reiner Season-Ordner), dann diesen Ordnernamen direkt verwenden.
|
||||||
|
// Deckt das "Folge 01"-Nummern-Format ab (Episode als "01" statt S01E01), z.B.
|
||||||
|
// "Kreuzfahrt.ins.Glueck.01.Hochzeitsreise.nach.Burma.2007.German.720p.HDTV.x264-BET".
|
||||||
|
// Greift NUR ohne Quell-Episode-Token → schliesst sich mit dem Fabrikations-Guard oben aus
|
||||||
|
// (Mega-Direct hat einen Quell-Token und kommt nie hierher).
|
||||||
|
if (!extractEpisodeToken(sourceBaseName)) {
|
||||||
|
const RESOLUTION_RE = /\b(?:480|540|576|720|1080|1440|2160|4320)[pi]\b/i;
|
||||||
|
const CODEC_RE = /\b(?:x264|x265|x266|h\.?264|h\.?265|h\.?266|hevc|avc|vvc|av1|xvid|divx)\b/i;
|
||||||
|
for (const folderName of folderCandidates) {
|
||||||
|
const f = sanitizeFilename(String(folderName || "").trim());
|
||||||
|
if (!f) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (hasSceneGroupSuffix(f) && (RESOLUTION_RE.test(f) || CODEC_RE.test(f)) && !SCENE_SEASON_ONLY_RE.test(f)) {
|
||||||
|
return { kind: "rename", baseName: f, note: "folder-as-is" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return { kind: "skip", reason: "no-target" };
|
return { kind: "skip", reason: "no-target" };
|
||||||
}
|
}
|
||||||
return { kind: "rename", baseName: targetBaseName, note };
|
return { kind: "rename", baseName: targetBaseName, note };
|
||||||
|
|||||||
@ -219,3 +219,32 @@ einbinden → Unterstrich-Gruppen erkannt → sauberer Ordner gewinnt → ideale
|
|||||||
VOLLSTAENDIGEN Quellnamen (Serie+Episode+Aufloesung+Codec) durch einen, der die Serien-Identitaet
|
VOLLSTAENDIGEN Quellnamen (Serie+Episode+Aufloesung+Codec) durch einen, der die Serien-Identitaet
|
||||||
verliert" wuerde KUENFTIGE unbekannte Gruppen-Formate abfangen — riskanter Eingriff in Guard A,
|
verliert" wuerde KUENFTIGE unbekannte Gruppen-Formate abfangen — riskanter Eingriff in Guard A,
|
||||||
nur mit Tests + auf User-Wunsch.
|
nur mit Tests + auf User-Wunsch.
|
||||||
|
|
||||||
|
## 2026-06-03 (3) — Renaming-Klasse „Junk-Quellname + sauberer Release-Ordner" (Folge-Nummer statt SxxExx)
|
||||||
|
|
||||||
|
**Symptom (Log 18-18):** „Kreuzfahrt ins Glück" — 25 Folgen `bet_kig_01_hdt.mkv` (obfuskiert, KEIN
|
||||||
|
SxxExx-Token) im sauberen Episoden-Ordner `Kreuzfahrt.ins.Glueck.01.Hochzeitsreise.nach.Burma.2007.
|
||||||
|
German.720p.HDTV.x264-BET` (Episode als bloße „01"). Auto-Rename: „kein Zielname" → 25× roh in die
|
||||||
|
Library. Diesmal SICHTBAR als 25 [WARN] (vorher 0 WARN) — das Log zeigt die Klasse direkt.
|
||||||
|
|
||||||
|
**Ursache (reproduziert):** `buildAutoRenameBaseName` gibt null zurück, sobald die QUELLE keinen
|
||||||
|
SxxExx-Token hat (Z.1288) — egal wie sauber der Ordner ist. Das „Folge 01"-Nummernformat (kein
|
||||||
|
S01E01) wurde nie unterstuetzt. VORBESTEHEND, nicht meine v1.7.178/179.
|
||||||
|
|
||||||
|
**Fix:** Fallback in decideAutoRenameBaseName — wenn kein Zielname UND Quelle hat keinen
|
||||||
|
Episode-Token, den ersten folderCandidate nehmen, der ein VOLLSTAENDIGER Scene-Release-Ordner ist:
|
||||||
|
`hasSceneGroupSuffix(f) && (RESOLUTION_RE.test(f) || CODEC_RE.test(f)) && !SCENE_SEASON_ONLY_RE.test(f)`.
|
||||||
|
Greift NUR ohne Quell-Episode-Token → schliesst sich mit dem Fabrikations-Guard aus (Mega-Direct hat
|
||||||
|
Quell-Token → unerreicht). note:"folder-as-is".
|
||||||
|
|
||||||
|
**Advisor-Punkt (wichtig):** NICHT nur Aufloesung pruefen — alte deutsche TV-Serien gibt es als
|
||||||
|
DVDRip/XviD OHNE 720p-Token. `RESOLUTION_RE ODER CODEC_RE` → sonst die naechste Runde. Pin-Test:
|
||||||
|
DVDRip-Variante (kein 720p, nur x264).
|
||||||
|
|
||||||
|
**Edge (Advisor):** Bonus/Sample muss VOR diesem Fallback gefiltert werden (sonst kriegt ein
|
||||||
|
Featurette/Sample im Episoden-Ordner den Episodennamen). Bestaetigt: Auto-Rename-Loop (Sample-Size +
|
||||||
|
BONUS_FILENAME_RE) und Collect filtern beide vor der Namensherleitung → gedeckt.
|
||||||
|
|
||||||
|
**Meta:** 3. „anderes Format" in Folge — diese Klasse (Junk-Quelle + sauberer Ordner) ist die
|
||||||
|
groesste verbleibende. Scene-Naming hat aber einen langen Schwanz: ehrlich „diese Klasse ist
|
||||||
|
abgedeckt", nicht „jetzt 100%". Das Desktop-Log liefert jede neue Klasse sofort.
|
||||||
|
|||||||
@ -128,6 +128,41 @@ describe("decideAutoRenameBaseName (shared naming decision — used by auto-rena
|
|||||||
expect(decision.kind).toBe("rename");
|
expect(decision.kind).toBe("rename");
|
||||||
expect(decision.kind === "rename" && decision.baseName).toBe(epFolder);
|
expect(decision.kind === "rename" && decision.baseName).toBe(epFolder);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses the complete per-episode folder when the SOURCE has no SxxExx token (bare 'Folge 01' format)", () => {
|
||||||
|
// User-Report: "Kreuzfahrt ins Glück" — Datei "bet_kig_01_hdt.mkv" (kein SxxExx-Token),
|
||||||
|
// Episoden-Ordner nummeriert mit "01" statt S01E01. Frueher "kein Zielname" -> roh in die
|
||||||
|
// Library. Jetzt: der vollstaendige Release-Ordnername wird direkt verwendet.
|
||||||
|
const folders = [
|
||||||
|
"Kreuzfahrt.ins.Glueck.01.Hochzeitsreise.nach.Burma.2007.German.720p.HDTV.x264-BET",
|
||||||
|
"kig.hdtv.7p-001",
|
||||||
|
"Kreuzfahrt ins Glück S01"
|
||||||
|
];
|
||||||
|
const decision = decideAutoRenameBaseName(folders, "bet_kig_01_hdt.mkv", "bet_kig_01_hdt", folders[0], folders[2]);
|
||||||
|
expect(decision.kind).toBe("rename");
|
||||||
|
expect(decision.kind === "rename" && decision.baseName).toBe(folders[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("complete-folder fallback fires on CODEC alone (no resolution token — DVDRip/XviD class)", () => {
|
||||||
|
const folders = [
|
||||||
|
"Kreuzfahrt.ins.Glueck.01.Hochzeitsreise.nach.Burma.2007.German.DVDRip.x264-BET",
|
||||||
|
"Kreuzfahrt ins Glück S01"
|
||||||
|
];
|
||||||
|
const decision = decideAutoRenameBaseName(folders, "bet_kig_01.mkv", "bet_kig_01", folders[0], folders[1]);
|
||||||
|
expect(decision.kind).toBe("rename");
|
||||||
|
expect(decision.kind === "rename" && decision.baseName).toBe(folders[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("complete-folder fallback does NOT fire when the source HAS an episode token (generic pack stays no-target)", () => {
|
||||||
|
const decision = decideAutoRenameBaseName(
|
||||||
|
["Mega-Direct-Pack"],
|
||||||
|
"Direct.Show.S01E01.German.1080p.WEB.x264-DIRECT.mkv",
|
||||||
|
"Direct.Show.S01E01.German.1080p.WEB.x264-DIRECT",
|
||||||
|
"Mega-Direct-Pack",
|
||||||
|
"Mega-Direct-Pack"
|
||||||
|
);
|
||||||
|
expect(decision.kind).toBe("skip");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("hasMeaningfulSeriesPrefix", () => {
|
describe("hasMeaningfulSeriesPrefix", () => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user