feat(adapters): RSS and PT site adapters ported from MoviePilot v3 + mocks (W1-3b)
- rss: port of MP RssHelper._parse_impl/get_rss_link semantics with safe XML (entities off, DTD/ENTITY rejected, size/item caps), ETag/Last-Modified, backoff + Retry-After, circuit breaker with manual reset, passkey redaction, overlap-window GUID+digest dedupe - sites/spider: TS port of MP SiteSpider (indexer schema, search URL builder, field DSL, filters, Jinja templates via nunjucks, login-page detection); audiences definition hand-written as JSON; raw category id preserved; shared per-site token bucket - sites/mteam: port of MP MTorrentSpider (params, result mapping, promo factors, genDlToken flow) without embedding the API key in enclosures; business code/message checks - testkit: mock RSS server, mock NexusPHP site, mock M-Team API - docs: W1-3b migration mapping appended to porting ledger Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
ef2e504a94
commit
a6d049db81
47 files changed
+5414
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import type { SiteCapabilities } from "../types";
|
||||
|
||||
/**
|
||||
* 馒头站点定义:键名沿用 MP indexer dict(id/name/domain/parser/timeout),
|
||||
* `umt` 为本项目扩展。API Key 不在定义里,经 SecretResolver 注入(MP 放在 indexer['apikey'])。
|
||||
*/
|
||||
export interface MteamDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
/** 网页域(MP `_url`,详情页 = `${domain}detail/${id}`) */
|
||||
domain: string;
|
||||
parser: "mTorrent";
|
||||
timeout: number;
|
||||
umt: {
|
||||
version: string;
|
||||
kind: "mteam";
|
||||
displayName: string;
|
||||
/** API 基址;缺省为 `https://api.<根域>`(MP `_searchurl % _domain`) */
|
||||
apiBaseUrl?: string;
|
||||
timezone: string;
|
||||
rateLimit: { minIntervalMs: number; burst: number };
|
||||
capabilities: SiteCapabilities;
|
||||
/** 原始分类 ID → 名称(自行编制,待核验) */
|
||||
categoryNames: Record<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
export const mteamDefinition: MteamDefinition = {
|
||||
id: "mteam",
|
||||
name: "馒头",
|
||||
domain: "https://tp.m-team.cc/",
|
||||
parser: "mTorrent",
|
||||
timeout: 15,
|
||||
umt: {
|
||||
version: "[email protected]",
|
||||
kind: "mteam",
|
||||
displayName: "馒头",
|
||||
timezone: "+08:00",
|
||||
rateLimit: { minIntervalMs: 1000, burst: 1 },
|
||||
capabilities: { list: true, search: true, detail: true, download: true, rss: false },
|
||||
categoryNames: {
|
||||
"401": "电影",
|
||||
"419": "电影",
|
||||
"420": "电影",
|
||||
"421": "电影",
|
||||
"439": "电影",
|
||||
"402": "剧集",
|
||||
"403": "综艺",
|
||||
"435": "剧集",
|
||||
"438": "剧集",
|
||||
"404": "纪录",
|
||||
"405": "动画",
|
||||
"407": "体育",
|
||||
"406": "音乐",
|
||||
"408": "音乐",
|
||||
"434": "音乐",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/** MP `site_rules.extract_domain` 的简化:取主机名最后两级。 */
|
||||
export function rootDomain(url: string): string {
|
||||
const host = new URL(url).hostname;
|
||||
const parts = host.split(".");
|
||||
return parts.length >= 2 ? parts.slice(-2).join(".") : host;
|
||||
}
|
||||
|
||||
export function mteamApiBase(def: MteamDefinition): string {
|
||||
return (def.umt.apiBaseUrl ?? `https://api.${rootDomain(def.domain)}`).replace(/\/$/, "");
|
||||
}
|
||||
Reference in new issue
Block a user