feat(sites): 内置公开 BT 站 Nyaa / 蜜柑 / AniBT / AnimeGarden / 萌番组

- 新专用解析器(spiders/public.ts):RSS / Torznab / JSON API,搜索 + 最新列表 + 按资源 ID 取种子或磁力
- 手写定义(definitions/public.ts,public: true),并入内置定义表;定义视图按 public 标为 public_bt
- 添加站点:公开 BT 站可从内置站一键添加(专用适配器、默认定时抓取、默认不进搜索集合),手填 RSS 保留
- 样例取自 2026-10-02 公开接口,截前两条

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-02 21:19:19 +08:00
1 parent 9cdf492291
commit b8876542b8
16 files changed
+770 -18

No files matched your search

@@ -119,9 +119,36 @@ describe.skipIf(!up)("站点类型:API、调度与 RSS", () => {
expect(pubWrongAdapter.status).toBe(400);
});
it("站点定义都是 PT 站;PT 站带登录与账号数据", async () => {
it("内置公开 BT 站:定义标为 public_bt;按定义添加用专用适配器,定时抓最新,不默认进搜索,不能登录", async () => {
const defs = await json(await h.req("/site-definitions"));
expect(defs.body.data.items.every((d: { kind: string }) => d.kind === "pt")).toBe(true);
const items = defs.body.data.items as { key: string; kind: string; adapter: string }[];
const pub = ["nyaa", "mikan", "anibt", "animegarden", "bangumimoe"];
expect(
items
.filter((d) => d.kind === "public_bt")
.map((d) => d.key)
.sort(),
).toEqual([...pub].sort());
expect(items.filter((d) => !pub.includes(d.key)).every((d) => d.kind === "pt")).toBe(true);
const nyaa = await json(
await h.req("/sites", { body: { key: "nyaa", name: "Nyaa", adapter: "api", baseUrl: "https://nyaa.si/" } }),
);
expect(nyaa.status).toBe(200);
expect(nyaa.body.data).toMatchObject({
kind: "public_bt",
adapter: "api",
snapshotEnabled: true,
searchDefault: false,
});
expect(nyaa.body.data.capabilities).toEqual(expect.arrayContaining(["search", "list"]));
expect(nyaa.body.data.capabilities).not.toContain("login");
const wrong = await h.req("/sites", {
body: { key: "mikan", kind: "public_bt", name: "蜜柑", adapter: "generic_rss", baseUrl: "https://mikanani.me/" },
});
expect(wrong.status).toBe(400);
});
it("PT 站定义带登录与账号数据", async () => {
const pt = await json(
await h.req("/sites", {
body: { key: "audiences", name: "观众", adapter: "nexusphp", baseUrl: "https://audiences.invalid/" },