feat(organize,web): sidecars follow selected videos; /console/organize?ids= prefill (FE-4 follow-ups)
- planImport (sourcePaths mode): when a selected source is a video file, same-directory subtitles / external audio whose stem (language tags stripped) matches it join the source list, so the organize wizard, which expands a directory into individual videos, no longer drops them. Unrelated sidecars stay out; pathGuard applies to the added files. - Organize records page honours ?ids= (wizard multi-group redirect): shows just those records via /files/records, refreshes while running, clear chip. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
363f85b1a1
commit
2ae780d2a1
5 files changed
+310
-7
No files matched your search
@@ -176,6 +176,38 @@ describe.skipIf(skip)("files 识别 / 整理 / 探测 / 刮削", () => {
|
||||
await h.db.updateTable("automation_grant").set({ status: "revoked" }).where("id", "=", grant.id).execute();
|
||||
});
|
||||
|
||||
it("organize:选中的视频带上同目录同主干的字幕 / 外挂音轨,无关字幕不带", async () => {
|
||||
const dir = join(h.dl, "Some.Show.S01.1080p.WEB-DL");
|
||||
await writeFile(join(dir, "Some.Show.S01E02.1080p.WEB-DL-GRP.chs.ass"), "sub-ep2");
|
||||
await writeFile(join(dir, "Some.Show.S01E03.1080p.WEB-DL-GRP.mka"), "audio-ep3");
|
||||
await writeFile(join(dir, "unrelated.srt"), "noise");
|
||||
// 整理向导把目录展开成逐个视频后提交
|
||||
const items = ["Some.Show.S01E02.1080p.WEB-DL-GRP.mkv", "Some.Show.S01E03.1080p.WEB-DL-GRP.mkv"].map((n) => ({
|
||||
root: h.dlRoot,
|
||||
path: `Some.Show.S01.1080p.WEB-DL/${n}`,
|
||||
mediaEntityId: show,
|
||||
season: 1,
|
||||
}));
|
||||
const dry = await h.api("POST", "/files/organize", {
|
||||
idempotencyKey: key(),
|
||||
items,
|
||||
action: "copy",
|
||||
dryRun: true,
|
||||
minSizeBytes: 0,
|
||||
});
|
||||
expect(dry.status).toBe(200);
|
||||
const g = dry.body.data.groups[0];
|
||||
expect(g.error).toBeNull();
|
||||
const byKind = (k: string) =>
|
||||
g.files.filter((f: { kind: string }) => f.kind === k).map((f: { source: string; target: string }) => f);
|
||||
expect(byKind("subtitle")).toHaveLength(1);
|
||||
expect(byKind("subtitle")[0].source).toBe(join(dir, "Some.Show.S01E02.1080p.WEB-DL-GRP.chs.ass"));
|
||||
expect(byKind("subtitle")[0].target).toMatch(/S01E02.*\.chi\.zh-cn\.ass$/);
|
||||
expect(byKind("audio")).toHaveLength(1);
|
||||
expect(byKind("audio")[0].target).toMatch(/S01E03.*\.mka$/);
|
||||
expect(JSON.stringify(g)).not.toContain("unrelated.srt");
|
||||
});
|
||||
|
||||
it("organize:路径逃逸同样拒绝", async () => {
|
||||
const r = await h.api("POST", "/files/organize", {
|
||||
idempotencyKey: key(),
|
||||
|
||||
Reference in new issue
Block a user