feat(contracts,server,web): files G6–G8 fields and identify S-7 contract
- G6: FileRoot.pendingCount/pendingPartial for download roots (same rule as the unidentified filter, recursive, cached 5 min, invalidated by files.changed) - G7: FileEntry.parsedHint from parseReleasePath (file + parent dirs); the web subline uses it and no longer parses names itself - G8: FileIdentifyCandidate.posterUrl (TMDB poster_path via adapter and catalog.lookup, local entities from metadata.posterPath); thumbnails in the identify panel - S-7 contract: FilesIdentifyResult.remoteTaskId/remotePending, MediaServerInventory.partial, EventType identify.completed with IdentifyCompletedPayload; identify panel (useIdentifyLive) and organize wizard merge remote results by root + path, buffering events that beat the response Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
fd2f7bc33d
commit
abc69886ea
26 files changed
+510
-134
No files matched your search
@@ -0,0 +1,72 @@
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import { parsedHintOf } from "../../src/modules/file-manager/hint.ts";
|
||||
import { posterUrlOf } from "../../src/modules/file-manager/identify.ts";
|
||||
import { createFmHarness, type FmHarness, pgAvailable, READ_KEY, seedDownload } from "./harness.ts";
|
||||
|
||||
// C1-C 契约收尾:G6 下载目录待识别计数 / G7 列表轻量解析 parsedHint / G8 候选海报 posterUrl。
|
||||
|
||||
describe("G7 parsedHintOf / G8 posterUrlOf(纯函数)", () => {
|
||||
it("剧集:标题 · 季集 · 分辨率;父目录补标题", () => {
|
||||
expect(parsedHintOf("The.Last.of.Us.S01E02.1080p.WEB-DL.mkv")).toBe("The Last of Us · S01E02 · 1080p");
|
||||
expect(parsedHintOf("The.Bear.S01.1080p/The.Bear.S01E01.1080p.WEB-DL-GRP.mkv")).toMatch(
|
||||
/^The Bear · S01E01 · 1080p$/,
|
||||
);
|
||||
});
|
||||
it("电影带年份;解析不出标题为 null", () => {
|
||||
expect(parsedHintOf("Oppenheimer.2023.2160p.BluRay.x265.mkv")).toBe("Oppenheimer (2023) · 2160p");
|
||||
expect(parsedHintOf("")).toBeNull();
|
||||
});
|
||||
it("posterUrl:相对 poster_path 拼 w154,完整 URL 原样,空为 null", () => {
|
||||
expect(posterUrlOf("/abc.jpg")).toBe("https://image.tmdb.org/t/p/w154/abc.jpg");
|
||||
expect(posterUrlOf("https://img.example/x.jpg")).toBe("https://img.example/x.jpg");
|
||||
expect(posterUrlOf(null)).toBeNull();
|
||||
expect(posterUrlOf("")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
const skip = !(await pgAvailable());
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 测试断言直接读响应 JSON
|
||||
type Loose = any;
|
||||
|
||||
describe.skipIf(skip)("files G6/G7(列表与根)", () => {
|
||||
let h: FmHarness;
|
||||
beforeAll(async () => {
|
||||
h = await createFmHarness("g678");
|
||||
await writeFile(join(h.dl, "The.Last.of.Us.S01E02.1080p.WEB-DL.mkv"), "v");
|
||||
await writeFile(join(h.dl, "notes.txt"), "t");
|
||||
await writeFile(join(h.dl, "Half.Done.2024.1080p.mkv.!qB"), "p");
|
||||
await mkdir(join(h.dl, "Show.S02"), { recursive: true });
|
||||
await writeFile(join(h.dl, "Show.S02", "Show.S02E01.720p.mkv"), "v");
|
||||
// 纳管下载任务内容(做种)不算待识别
|
||||
await mkdir(join(h.dl, "Seeding.Film.2020.1080p"), { recursive: true });
|
||||
await writeFile(join(h.dl, "Seeding.Film.2020.1080p", "Seeding.Film.2020.1080p.mkv"), "v");
|
||||
await seedDownload(h.db, h, { name: "Seeding.Film.2020.1080p", status: "completed" });
|
||||
});
|
||||
afterAll(async () => {
|
||||
await h?.close();
|
||||
});
|
||||
|
||||
it("G6:下载目录带 pendingCount(递归、排除临时与做种),库根为 null", async () => {
|
||||
const r = await h.api("GET", "/files/roots", undefined, READ_KEY);
|
||||
expect(r.status).toBe(200);
|
||||
const dl = r.body.data.items.find((x: Loose) => x.id === h.dlRoot);
|
||||
const lib = r.body.data.items.find((x: Loose) => x.id === h.libRoot);
|
||||
expect(dl).toMatchObject({ pendingCount: 2, pendingPartial: false });
|
||||
expect(lib).toMatchObject({ pendingCount: null, pendingPartial: false });
|
||||
});
|
||||
|
||||
it("G7:待识别视频行带 parsedHint,其它行为 null", async () => {
|
||||
const r = await h.api("GET", `/files?root=${encodeURIComponent(h.dlRoot)}`, undefined, READ_KEY);
|
||||
expect(r.status).toBe(200);
|
||||
const by = (n: string) => r.body.data.entries.find((x: Loose) => x.name === n);
|
||||
expect(by("The.Last.of.Us.S01E02.1080p.WEB-DL.mkv")).toMatchObject({
|
||||
status: "unidentified",
|
||||
parsedHint: "The Last of Us · S01E02 · 1080p",
|
||||
});
|
||||
expect(by("notes.txt").parsedHint).toBeNull();
|
||||
expect(by("Show.S02").parsedHint).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user