/** * 站点定义加载与校验。 * - `*.json`:由 scripts/mp-sync/movieclaw-import.mjs 从 MovieClaw v0.27.0(MIT,见 NOTICE-MovieClaw.md)转换, * 手工覆盖层在 scripts/mp-sync/movieclaw-overrides/;不要直接手改 JSON(重跑脚本会覆盖)。 * - 加载时一律经 zod schema(./schema.ts)校验,失败即抛错。 */ import type { MteamDefinition } from "../mteam/definition.ts"; import type { IndexerDefinition } from "../spider/schema.ts"; import type { SpecializedSiteDefinition } from "../spiders/types.ts"; import { MOVIECLAW_DEFINITION_JSON } from "./manifest.generated.ts"; import { parseIndexerDefinition, parseMteamDefinition, parseSpecializedSiteDefinition } from "./schema.ts"; export type SiteDefinition = IndexerDefinition | MteamDefinition | SpecializedSiteDefinition; /** 按 `umt.kind` 分派校验 */ export function loadSiteDefinition(json: unknown): SiteDefinition { const kind = (json as { umt?: { kind?: unknown } } | null)?.umt?.kind; if (kind === "mteam") return parseMteamDefinition(json); if (kind === "nexusphp") return parseIndexerDefinition(json); if (kind === "api") return parseSpecializedSiteDefinition(json); throw new Error(`站点定义 ${(json as { id?: unknown })?.id ?? ""} 的 umt.kind 未知:${String(kind)}`); } /** 兼容 W1-3b 导出名:NexusPHP 定义校验 */ export function loadIndexerDefinition(json: unknown): IndexerDefinition { return parseIndexerDefinition(json); } /** 随产品发布的全部定义(已校验),键为站点 id */ export const BUILTIN_SITE_DEFINITIONS: Readonly> = Object.freeze( Object.fromEntries(Object.entries(MOVIECLAW_DEFINITION_JSON).map(([id, json]) => [id, loadSiteDefinition(json)])), ); export const audiencesDefinition = BUILTIN_SITE_DEFINITIONS.audiences as IndexerDefinition; export const hhanclubDefinition = BUILTIN_SITE_DEFINITIONS.hhanclub as IndexerDefinition; export const chdbitsDefinition = BUILTIN_SITE_DEFINITIONS.chdbits as IndexerDefinition; export { DefinitionProvenanceSchema, IndexerDefinitionSchema, MteamDefinitionSchema, parseIndexerDefinition, parseMteamDefinition, parseSpecializedSiteDefinition, SpecializedSiteDefinitionSchema, SpiderFieldSelectorSchema, SpiderFilterSchema, } from "./schema.ts";