feat(subtitles): 字幕站(SubHD、字幕库)在线搜索与下载;rar / 7z 解压;验证码与页面解析在沙箱里
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
92d456d123
commit
59b3680f35
32 files changed
+1704
-166
No files matched your search
@@ -1,6 +1,9 @@
|
||||
import { Api, type SubtitleApplyRequest } from "@umt/contracts";
|
||||
import { Api, type SubtitleApplyRequest, type SubtitleFetchRequest, type SubtitleSource } from "@umt/contracts";
|
||||
import { ApiException } from "../../http/errors.ts";
|
||||
import { route } from "../agent/http.ts";
|
||||
import { sourcesIdentityModule } from "../sources-identity/index.ts";
|
||||
import type { ServerModule } from "../types.ts";
|
||||
import { downloadOnline, SubtitleSiteError, searchOnline, subtitleSearchQuery } from "./online/index.ts";
|
||||
import { applySubtitles, parseSubtitles, subtitleTargets, subtitleWrites, undoSubtitleWrite } from "./service.ts";
|
||||
|
||||
/** 补字幕(docs/plan/subtitles.md):上传 / 在线下载的字幕解析、配对、写入、历史与撤销 */
|
||||
@@ -9,8 +12,39 @@ export function createSubtitlesModule(): ServerModule {
|
||||
name: "subtitles",
|
||||
registerRoutes(app, ctx) {
|
||||
const tag = { tag: "subtitles" };
|
||||
const rt = () => sourcesIdentityModule.runtime(ctx);
|
||||
const siteErr = async <T>(fn: () => Promise<T>): Promise<T> => {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (e) {
|
||||
if (e instanceof SubtitleSiteError) throw new ApiException("upstream_unavailable", e.message);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
route(app, Api.subtitles.targets, ({ query }) => subtitleTargets(ctx, query.entityId), tag);
|
||||
route(app, Api.subtitles.parse, ({ body }) => parseSubtitles(ctx, body.files, body.entityId), tag);
|
||||
route(
|
||||
app,
|
||||
Api.subtitles.search,
|
||||
({ body }) => siteErr(async () => searchOnline(ctx, rt(), await subtitleSearchQuery(ctx, body.entityId, body))),
|
||||
tag,
|
||||
);
|
||||
route(
|
||||
app,
|
||||
Api.subtitles.fetch,
|
||||
({ body }) =>
|
||||
siteErr(async () => {
|
||||
const b = body as SubtitleFetchRequest;
|
||||
const f = await downloadOnline(ctx, rt(), b.siteId, b.ref);
|
||||
const parsed = await parseSubtitles(ctx, [{ name: f.name, base64: f.base64 }], b.entityId);
|
||||
// 在线来源:每项带上字幕站与条目地址,写入时记进历史
|
||||
return {
|
||||
...parsed,
|
||||
items: parsed.items.map((it) => ({ ...it, source: f.siteKey as SubtitleSource, sourceRef: f.pageUrl })),
|
||||
};
|
||||
}),
|
||||
tag,
|
||||
);
|
||||
route(
|
||||
app,
|
||||
Api.subtitles.apply,
|
||||
|
||||
Reference in new issue
Block a user