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:
1 parent
9cdf492291
commit
b8876542b8
16 files changed
+770
-18
No files matched your search
@@ -148,10 +148,34 @@ export function SiteAddDialog({ onClose, initialKind }: { onClose: () => void; i
|
||||
!needle || d.name.toLowerCase().includes(needle) || d.key.includes(needle) || d.baseUrl.includes(needle);
|
||||
return GROUP_ORDER.map((a) => ({
|
||||
adapter: a,
|
||||
items: items.filter((d) => d.adapter === a && hit(d)).sort((x, y) => x.name.localeCompare(y.name, "zh-CN")),
|
||||
items: items
|
||||
.filter((d) => d.kind === "pt" && d.adapter === a && hit(d))
|
||||
.sort((x, y) => x.name.localeCompare(y.name, "zh-CN")),
|
||||
})).filter((g) => g.items.length);
|
||||
}, [items, q]);
|
||||
|
||||
const publicDefs = items.filter((d) => d.kind === "public_bt");
|
||||
/** 内置公开 BT 站:一步建好(专用适配器、定时抓最新),进站点页 */
|
||||
const addPublic = async (d: SiteDefinitionView) => {
|
||||
try {
|
||||
setPhase("保存中…");
|
||||
const site = await create.mutateAsync({
|
||||
kind: "public_bt",
|
||||
key: d.key,
|
||||
adapter: d.adapter,
|
||||
name: d.name,
|
||||
baseUrl: d.baseUrl,
|
||||
});
|
||||
toast.success(`已添加「${site.name}」`);
|
||||
onClose();
|
||||
navigate(consolePath("sites", site.id));
|
||||
} catch (err) {
|
||||
toast.error(errorMessage(err, "保存失败"));
|
||||
} finally {
|
||||
setPhase(null);
|
||||
}
|
||||
};
|
||||
|
||||
const pick = (key: string) => {
|
||||
const d = items.find((x) => x.key === key);
|
||||
setDefKey(key);
|
||||
@@ -197,6 +221,32 @@ export function SiteAddDialog({ onClose, initialKind }: { onClose: () => void; i
|
||||
}}
|
||||
className="min-w-0"
|
||||
>
|
||||
{kind === "public_bt" && publicDefs.length ? (
|
||||
<div className="mb-4">
|
||||
<p className="mb-2 text-caption font-medium text-foreground">内置站点</p>
|
||||
<ul className="grid gap-2 sm:grid-cols-2">
|
||||
{publicDefs.map((d) => (
|
||||
<li key={d.key}>
|
||||
<button
|
||||
type="button"
|
||||
disabled={busy || !!d.siteId}
|
||||
onClick={() => void addPublic(d)}
|
||||
className="flex w-full min-w-0 items-center justify-between gap-2 rounded-lg border border-border/70 px-3 py-2 text-left transition-colors hover:border-foreground/40 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent"
|
||||
>
|
||||
<span className="min-w-0">
|
||||
<span className="block truncate text-caption font-medium text-foreground">{d.name}</span>
|
||||
<span className="block truncate text-meta text-muted-foreground">{hostOf(d.baseUrl)}</span>
|
||||
</span>
|
||||
{d.siteId ? <StatusBadge className="shrink-0">已添加</StatusBadge> : null}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="mt-3 mb-2 text-meta text-muted-foreground">
|
||||
内置站点支持搜索和定时抓取最新资源,不需要账号。其他公开站可以在下面手动填 RSS 地址。
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
<FormField label="名称" htmlFor="add-feed-name" required error={errors.name}>
|
||||
<Input
|
||||
id="add-feed-name"
|
||||
|
||||
Reference in new issue
Block a user