docs(plan): on-demand site detail page parsing (HHClub details.php)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
94fd48bff2
commit
ac478673bc
39 files changed
+2446
-339
No files matched your search
@@ -476,25 +476,43 @@ export function registerLibraryRoutes(app: ModuleApp, d: AoDeps) {
|
||||
response: MediaServerInventory,
|
||||
},
|
||||
async (_c, { query }) => {
|
||||
const e = await db()
|
||||
.selectFrom("media_entity")
|
||||
.select(["id", "kind", "title", "year"])
|
||||
.where("id", "=", query.mediaEntityId)
|
||||
.executeTakeFirst();
|
||||
if (!e) notFound("作品");
|
||||
const idents = await db()
|
||||
.selectFrom("external_identity")
|
||||
.select(["provider", "entity_type", "external_id"])
|
||||
.where("media_entity_id", "=", e!.id)
|
||||
.where("status", "=", "accepted")
|
||||
.execute();
|
||||
// 按 TMDB 条目查时:本地已建档(接受了该身份,合并跟到最终作品)就按作品查,否则只用这一个 TMDB ID
|
||||
let entityId = query.mediaEntityId ?? null;
|
||||
if (!entityId && query.tmdbType && query.tmdbId) {
|
||||
const hit = await db()
|
||||
.selectFrom("external_identity as i")
|
||||
.innerJoin("media_entity as m", "m.id", "i.media_entity_id")
|
||||
.select(["m.id", "m.status", "m.merged_into_id"])
|
||||
.where("i.provider", "=", "tmdb")
|
||||
.where("i.entity_type", "=", query.tmdbType)
|
||||
.where("i.external_id", "=", query.tmdbId)
|
||||
.where("i.status", "=", "accepted")
|
||||
.executeTakeFirst();
|
||||
entityId = hit ? (hit.status === "merged" && hit.merged_into_id ? hit.merged_into_id : hit.id) : null;
|
||||
}
|
||||
const e = entityId
|
||||
? await db()
|
||||
.selectFrom("media_entity")
|
||||
.select(["id", "kind", "title", "year"])
|
||||
.where("id", "=", entityId)
|
||||
.executeTakeFirst()
|
||||
: null;
|
||||
if (entityId && !e) notFound("作品");
|
||||
const idents = e
|
||||
? await db()
|
||||
.selectFrom("external_identity")
|
||||
.select(["provider", "entity_type", "external_id"])
|
||||
.where("media_entity_id", "=", e.id)
|
||||
.where("status", "=", "accepted")
|
||||
.execute()
|
||||
: [{ provider: "tmdb", entity_type: query.tmdbType!, external_id: query.tmdbId! }];
|
||||
const insts = await db()
|
||||
.selectFrom("media_server_instance")
|
||||
.selectAll()
|
||||
.where("enabled", "=", true)
|
||||
.orderBy("name")
|
||||
.execute();
|
||||
const type = e!.kind === "movie" ? "Movie" : "Series";
|
||||
const type = (e ? e.kind === "movie" : query.tmdbType === "movie") ? "Movie" : "Series";
|
||||
const usable = idents.filter((i) => MS_PROVIDER_KEY[i.provider]);
|
||||
// 按实例并行(allSettled):单个 Emby 慢/挂只让自己 unknown,不拖住其它实例;每实例内部限并发 + 总超时
|
||||
const settled = await Promise.allSettled(
|
||||
@@ -514,7 +532,7 @@ export function registerLibraryRoutes(app: ModuleApp, d: AoDeps) {
|
||||
);
|
||||
// partial:至少一个实例因查询失败/超时为 unknown(no_external_id 不算失败)
|
||||
const partial = instances.some((x) => x.status === "unknown" && x.reason !== "no_external_id");
|
||||
return { mediaEntityId: e!.id, instances, partial } satisfies MediaServerInventory;
|
||||
return { mediaEntityId: e?.id ?? null, instances, partial } satisfies MediaServerInventory;
|
||||
},
|
||||
{ tag: TAG },
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user