feat(organize): 文件级标题粗核,混合包里明显不是本作品的视频降为待确认
- 同一批视频里文件名标题与作品标题 / 原名 / 别名明显不符(没有足够共同词)的排除为 title_mismatch,不按本作品命名入库; - 只在同批至少一个文件对得上作品时才判断,剧集只看带 SxxEyy 的文件,用户逐文件指定过的不核; - title_mismatch 算「本该入库却被排除」:记录部分完成、开待处理、Move 不移除下载任务。 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
b40716d74f
commit
c532060c83
10 files changed
+283
-10
No files matched your search
@@ -0,0 +1,84 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import { createTempTree, type TempTree } from "@umt/testkit";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import { executeRecord, planImport } from "../../src/modules/acquisition-organize/services/organize.ts";
|
||||
import { createHarness, type Harness, pgAvailable, seedBase, seedEntity } from "./harness.ts";
|
||||
|
||||
// 文件级标题粗核:合集 / 混合包里标题明显不是本作品的视频不按本作品命名入库,
|
||||
// 降为待确认(排除原因 title_mismatch),记录部分完成并开待处理;用户逐文件指定过的不核。
|
||||
|
||||
const hasPg = await pgAvailable();
|
||||
const SIZE = 200_000;
|
||||
const PACK = "Nolan.Pack";
|
||||
|
||||
describe.skipIf(!hasPg)("整理:文件标题明显不是本作品时降为待确认", () => {
|
||||
let h: Harness;
|
||||
let lib: TempTree;
|
||||
let src: TempTree;
|
||||
let entity = "";
|
||||
|
||||
beforeAll(async () => {
|
||||
lib = await createTempTree({}, { sentinel: true, prefix: "umt-tclib-" });
|
||||
src = await createTempTree(
|
||||
{
|
||||
[`${PACK}/Inception.2010.1080p.BluRay.x264-GRP.mkv`]: SIZE,
|
||||
[`${PACK}/Interstellar.2014.1080p.BluRay.x264-GRP.mkv`]: SIZE,
|
||||
},
|
||||
{ prefix: "umt-tcsrc-" },
|
||||
);
|
||||
h = await createHarness("title_check");
|
||||
await seedBase(h.db, { libraryPath: lib.root, cachePath: src.root, qbUrl: "http://127.0.0.1:9" });
|
||||
await h.setSettings("organize", { scrapeAfterImport: false });
|
||||
entity = await seedEntity(h.db, { kind: "movie", title: "盗梦空间", year: 2010 });
|
||||
await h.db.updateTable("media_entity").set({ original_title: "Inception" }).where("id", "=", entity).execute();
|
||||
}, 60_000);
|
||||
afterAll(async () => {
|
||||
await h?.close();
|
||||
for (const t of [lib, src]) await t?.cleanup();
|
||||
});
|
||||
|
||||
it("合集里的别的电影:排除 title_mismatch,不入库,记录部分完成并开待处理", async () => {
|
||||
const plan = await planImport(h.d, {
|
||||
sourcePaths: [src.path(PACK)],
|
||||
mediaEntityId: entity,
|
||||
action: "copy",
|
||||
trigger: "auto",
|
||||
actorType: "system",
|
||||
});
|
||||
expect(plan.status).toBe("running");
|
||||
const ex = await executeRecord(h.d, plan.recordId!);
|
||||
expect(ex.status).toBe("partial");
|
||||
const files = await h.db
|
||||
.selectFrom("organization_file_result")
|
||||
.select(["source_path", "status", "skip_reason", "target_path"])
|
||||
.where("organization_record_id", "=", plan.recordId!)
|
||||
.execute();
|
||||
const other = files.find((f) => f.source_path.includes("Interstellar"))!;
|
||||
expect(other).toMatchObject({ status: "skipped", skip_reason: "excluded:title_mismatch", target_path: null });
|
||||
const mine = files.find((f) => f.source_path.includes("Inception"))!;
|
||||
expect(mine.status).toBe("succeeded");
|
||||
expect(existsSync(src.path(`${PACK}/Interstellar.2014.1080p.BluRay.x264-GRP.mkv`))).toBe(true);
|
||||
const decision = await h.db
|
||||
.selectFrom("decision")
|
||||
.select(["summary", "status"])
|
||||
.where("dedupe_key", "=", `organize_excluded:${plan.recordId}`)
|
||||
.executeTakeFirstOrThrow();
|
||||
expect(decision.status).toBe("open");
|
||||
expect(decision.summary).toContain("标题不是本作品");
|
||||
});
|
||||
|
||||
it("用户逐文件指定过的不核", async () => {
|
||||
const plan = await planImport(h.d, {
|
||||
sourcePaths: [src.path(PACK)],
|
||||
mediaEntityId: entity,
|
||||
action: "copy",
|
||||
trigger: "manual",
|
||||
actorType: "user",
|
||||
dryRun: true,
|
||||
fileOverrides: {
|
||||
[src.path(`${PACK}/Interstellar.2014.1080p.BluRay.x264-GRP.mkv`)]: { contentUnitIds: [] },
|
||||
},
|
||||
});
|
||||
expect(plan.plan!.organize.excluded.some((x) => x.reason === "title_mismatch")).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user