fix(organize): 不是视频的文件移入回收站并开待处理,不留在媒体库
- 收尾判定 NOT_VIDEO 后,已拷 / 搬进库的新文件和它的附属文件移入回收站(登记 trash_item),开待处理; - 附属文件结果改为跳过 main_failed(不再写成功却不登记); - 已结束记录重放时补做,可重入;原地入库不动原文件,洗版替换照旧回滚。 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
1c8c5d2fb7
commit
b40716d74f
5 files changed
+219
-2
No files matched your search
@@ -0,0 +1,85 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
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";
|
||||
|
||||
// 收尾时 ffprobe 判定「不是视频」:已拷 / 搬进库的新文件与它的附属文件移入回收站(不留未登记文件),
|
||||
// 附属文件结果改为跳过(main_failed),开待处理;重放不重复处理。
|
||||
|
||||
const hasPg = await pgAvailable();
|
||||
const FAKE = "Fake.2020.1080p.BluRay.x264-GRP.mkv";
|
||||
const SUB = "Fake.2020.1080p.BluRay.x264-GRP.zh.srt";
|
||||
|
||||
describe.skipIf(!hasPg)("整理:不是视频的文件不留在媒体库", () => {
|
||||
let h: Harness;
|
||||
let lib: TempTree;
|
||||
let src: TempTree;
|
||||
|
||||
beforeAll(async () => {
|
||||
lib = await createTempTree({}, { sentinel: true, prefix: "umt-nvlib-" });
|
||||
src = await createTempTree(
|
||||
{ [FAKE]: 200_000, [SUB]: "1\n00:00:01,000 --> 00:00:02,000\n字幕\n" },
|
||||
{ prefix: "umt-nvsrc-" },
|
||||
);
|
||||
h = await createHarness("not_video", {
|
||||
probe: async (p: string) =>
|
||||
p.endsWith(".mkv")
|
||||
? ({ status: "ok", video: [], audio: [], subtitle: [] } as never)
|
||||
: ({ status: "unknown" } as never),
|
||||
});
|
||||
await seedBase(h.db, { libraryPath: lib.root, cachePath: src.root, qbUrl: "http://127.0.0.1:9" });
|
||||
}, 60_000);
|
||||
afterAll(async () => {
|
||||
await h?.close();
|
||||
for (const t of [lib, src]) await t?.cleanup();
|
||||
});
|
||||
|
||||
it("Move:新文件与字幕移入回收站,不登记资产,开待处理;重放不重复", async () => {
|
||||
const entity = await seedEntity(h.db, { kind: "movie", title: "伪装片", year: 2020 });
|
||||
const plan = await planImport(h.d, {
|
||||
sourcePaths: [src.path(FAKE)],
|
||||
mediaEntityId: entity,
|
||||
action: "move",
|
||||
trigger: "manual",
|
||||
actorType: "user",
|
||||
});
|
||||
expect(plan.status).toBe("running");
|
||||
const ex = await executeRecord(h.d, plan.recordId!);
|
||||
expect(ex.status).toBe("failed");
|
||||
|
||||
const files = await h.db
|
||||
.selectFrom("organization_file_result")
|
||||
.select(["role", "status", "skip_reason", "target_path", "error", "media_asset_id"])
|
||||
.where("organization_record_id", "=", plan.recordId!)
|
||||
.orderBy("ordinal")
|
||||
.execute();
|
||||
const main = files.find((f) => f.role === "main")!;
|
||||
const sub = files.find((f) => f.role === "subtitle")!;
|
||||
expect(main).toMatchObject({ status: "failed", media_asset_id: null });
|
||||
expect((main.error as { code: string }).code).toBe("NOT_VIDEO");
|
||||
expect(sub).toMatchObject({ status: "skipped", skip_reason: "main_failed", media_asset_id: null });
|
||||
|
||||
// 库里不留文件,回收站里各一份(Move 时源已删,回收站里是唯一一份)
|
||||
expect(existsSync(join(lib.root, main.target_path!))).toBe(false);
|
||||
expect(existsSync(join(lib.root, sub.target_path!))).toBe(false);
|
||||
expect(existsSync(src.path(FAKE))).toBe(false);
|
||||
const trash = await h.db.selectFrom("trash_item").select(["original_path", "trash_path"]).execute();
|
||||
expect(trash.map((t) => t.original_path).sort()).toEqual([main.target_path, sub.target_path].sort());
|
||||
for (const t of trash) expect(existsSync(t.trash_path)).toBe(true);
|
||||
expect(await h.db.selectFrom("media_asset").select("id").where("media_entity_id", "=", entity).execute()).toEqual(
|
||||
[],
|
||||
);
|
||||
const decisions = await h.db
|
||||
.selectFrom("decision")
|
||||
.select(["title", "status"])
|
||||
.where("dedupe_key", "=", `organize_not_video:${plan.recordId}`)
|
||||
.execute();
|
||||
expect(decisions).toEqual([{ title: "1 个文件不是视频,没有入库", status: "open" }]);
|
||||
|
||||
// 重放:已结束记录不重复移动
|
||||
await executeRecord(h.d, plan.recordId!);
|
||||
expect(await h.db.selectFrom("trash_item").select("id").execute()).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user