Fix auto-rename raw episode folder selection

This commit is contained in:
Sucukdeluxe 2026-03-11 14:17:51 +01:00
parent f9530e015f
commit 99455eca94
2 changed files with 75 additions and 41 deletions

View File

@ -731,10 +731,10 @@ const SCENE_RP_TOKEN_RE = /(?:^|[._\-\s])rp(?:[._\-\s]|$)/i;
const SCENE_REPACK_TOKEN_RE = /(?:^|[._\-\s])repack(?:[._\-\s]|$)/i; const SCENE_REPACK_TOKEN_RE = /(?:^|[._\-\s])repack(?:[._\-\s]|$)/i;
const SCENE_QUALITY_TOKEN_RE = /([._\-\s])((?:4320|2160|1440|1080|720|576|540|480|360)p)(?=[._\-\s]|$)/i; const SCENE_QUALITY_TOKEN_RE = /([._\-\s])((?:4320|2160|1440|1080|720|576|540|480|360)p)(?=[._\-\s]|$)/i;
const SCENE_GROUP_SUFFIX_FALLBACK_RE = /-([A-Za-z0-9]{2,})$/; const SCENE_GROUP_SUFFIX_FALLBACK_RE = /-([A-Za-z0-9]{2,})$/;
const SCENE_NON_GROUP_SUFFIXES = new Set([ const SCENE_NON_GROUP_SUFFIXES = new Set([
"x264", "x264",
"x265", "x265",
"h264", "h264",
"h265", "h265",
"avc", "avc",
"hevc", "hevc",
@ -745,40 +745,49 @@ const SCENE_NON_GROUP_SUFFIXES = new Set([
"bdrip", "bdrip",
"hdtv", "hdtv",
"dvdrip", "dvdrip",
"remux" "remux"
]); ]);
function hasSceneGroupSuffix(fileName: string): boolean { function isValidSceneGroupSuffix(suffix: string): boolean {
const text = String(fileName || "").trim(); const normalizedSuffix = String(suffix || "").trim();
if (!text) { if (!normalizedSuffix) {
return false; return false;
} }
if (SCENE_GROUP_SUFFIX_RE.test(text)) { const lower = normalizedSuffix.toLowerCase();
return true; if (SCENE_NON_GROUP_SUFFIXES.has(lower)) {
} return false;
}
const fallbackMatch = text.match(SCENE_GROUP_SUFFIX_FALLBACK_RE); if (/^s\d{1,2}e\d{1,3}(?:e\d{1,3})?$/i.test(normalizedSuffix) || /^s\d{1,2}$/i.test(normalizedSuffix) || /^e\d{1,3}$/i.test(normalizedSuffix)) {
const suffix = String(fallbackMatch?.[1] || "").trim(); return false;
if (!suffix) { }
return false; if (/^\d+p$/.test(lower) || /^\d+$/.test(lower)) {
} return false;
}
const lower = suffix.toLowerCase(); if (/^\d/.test(normalizedSuffix)) {
if (SCENE_NON_GROUP_SUFFIXES.has(lower)) { return false;
return false; }
} if (/4s(?:f|j)/i.test(normalizedSuffix) && !/^(?:4sf|4sj)$/i.test(normalizedSuffix)) {
if (/^\d+p$/.test(lower) || /^\d+$/.test(lower)) { return false;
return false; }
} return /[a-z]/i.test(normalizedSuffix);
if (/^\d/.test(suffix)) { }
return false;
} function hasSceneGroupSuffix(fileName: string): boolean {
if (/4s(?:f|j)/i.test(suffix) && !/^(?:4sf|4sj)$/i.test(suffix)) { const text = String(fileName || "").trim();
return false; if (!text) {
} return false;
return /[a-z]/i.test(suffix); }
}
if (SCENE_GROUP_SUFFIX_RE.test(text)) {
const directMatch = text.match(SCENE_GROUP_SUFFIX_FALLBACK_RE);
return isValidSceneGroupSuffix(String(directMatch?.[1] || ""));
}
const fallbackMatch = text.match(SCENE_GROUP_SUFFIX_FALLBACK_RE);
const suffix = String(fallbackMatch?.[1] || "").trim();
return isValidSceneGroupSuffix(suffix);
}
export function extractEpisodeToken(fileName: string): string | null { export function extractEpisodeToken(fileName: string): string | null {
const text = String(fileName || ""); const text = String(fileName || "");

View File

@ -6,7 +6,7 @@ import crypto from "node:crypto";
import { EventEmitter, once } from "node:events"; import { EventEmitter, once } from "node:events";
import AdmZip from "adm-zip"; import AdmZip from "adm-zip";
import { afterEach, describe, expect, it, vi } from "vitest"; import { afterEach, describe, expect, it, vi } from "vitest";
import { DownloadManager, extractArchiveNameFromExtractorLogMessage, getAuthoritativeRealDebridTotal, resolveArchiveItemsFromList } from "../src/main/download-manager"; import { DownloadManager, buildAutoRenameBaseNameFromFoldersWithOptions, extractArchiveNameFromExtractorLogMessage, getAuthoritativeRealDebridTotal, resolveArchiveItemsFromList } from "../src/main/download-manager";
import { planDownloadCompletion, validateDownloadedFileCompletion } from "../src/main/download-completion"; import { planDownloadCompletion, validateDownloadedFileCompletion } from "../src/main/download-completion";
import { defaultSettings } from "../src/main/constants"; import { defaultSettings } from "../src/main/constants";
import { parseDebridLinkApiKeys } from "../src/shared/debrid-link-keys"; import { parseDebridLinkApiKeys } from "../src/shared/debrid-link-keys";
@ -77,8 +77,33 @@ describe("download completion planning", () => {
}); });
}); });
}); });
async function waitFor(predicate: () => boolean, timeoutMs = 15000): Promise<void> { describe("auto rename base selection", () => {
it("ignores raw episode-suffix folders like 4sf-amilllt...-s03e10 as scene targets", () => {
expect(buildAutoRenameBaseNameFromFoldersWithOptions(
[
"4sf-amilllt.de.dl.web.7p-s03e10",
"A.Million.Little.Things.S03.GERMAN.DL.720p.WEB.H264-RWP",
"amilllt.de.dl.web.7p-s03e10"
],
"A.Million.Little.Things.S03E10.Vertraue.mir.GERMAN.DL.720p.WEB.H264-4SF",
{ forceEpisodeForSeasonFolder: true }
)).toBe("A.Million.Little.Things.S03E10.GERMAN.DL.720p.WEB.H264-RWP");
});
it("ignores compact archive folder stems like scn-alco7-S03E18 as scene targets", () => {
expect(buildAutoRenameBaseNameFromFoldersWithOptions(
[
"scn-alco7-S03E18",
"Alex.und.Co.S03.GERMAN.DL.720p.WEB.H264-SunDry"
],
"alex.und.co.s03e18.720p.web.h264-sundry",
{ forceEpisodeForSeasonFolder: true }
)).toBe("Alex.und.Co.S03E18.GERMAN.DL.720p.WEB.H264-SunDry");
});
});
async function waitFor(predicate: () => boolean, timeoutMs = 15000): Promise<void> {
const started = Date.now(); const started = Date.now();
while (!predicate()) { while (!predicate()) {
if (Date.now() - started > timeoutMs) { if (Date.now() - started > timeoutMs) {