feat(adapters): port MoviePilot open site framework (7 spiders, 20 user parsers) + MovieClaw v0.27.0 site definitions + mp-sync tools (W1-3c)
- sites/spiders: Haidan/HDDolby/RousiPro/SunnyPT/TNode/TorrentLeech/Yema (+mTorrent wrapper), specialized SiteAdapter, indirect download resolved at download time - sites/user-parsers: SiteParserBase + all 20 MP SiteSchema parsers (lxml XPath via xpath+xmldom), refreshSiteUserData with schema fallback - sites/definitions: zod SiteDefinition schemas, 23 MovieClaw v0.27.0 (MIT) definitions via scripts/mp-sync/movieclaw-import.mjs, registry getSiteDefinition/listSiteDefinitions, NOTICE - scripts/mp-sync: ledger.json (upstream sha256), check.mjs, build-ledger.mjs; docs/porting/mp-sync-ledger.md - license-and-provenance: add copied-mit kind, re-anchor MovieClaw rows to v0.27.0 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
cf85481d95
commit
d9f2af2f3c
166 files changed
+16577
-186
No files matched your search
@@ -40,8 +40,9 @@
|
||||
| 引用事实性常量:协议字段名(qB WebUI API、M-Team API、TMDB API)、站点公开的 HTML 结构、行业通用词表(`WEB-DL`、`REMUX`、`DDP5.1`) | 照搬上游**整理过的数据表**:`RELEASE_GROUPS` 站点到组名的正则表(`app/domain/meta/releasegroup.py:26`)、`StreamingPlatforms` 平台码表(`app/domain/meta/streamingplatform.py`,约 270 条)、`_name_nostring_re` 干扰词表。这类表要**自行编制**,并在 ledger 里写明来源(例如公开的 scene/P2P 命名规范、站点官方规则页) |
|
||||
| 上游测试里的**标题字符串**(事实数据)可以作为输入语料 | 整份拷贝 `tests/cases/meta.py` 这类测试文件;期望值必须由我们自己按 REQ 判定,不是照抄上游的 target |
|
||||
| MovieClaw:阅读 YAML 的**字段结构**,参考其字段设计 | 在没有书面授权时拷贝 MovieClaw main 的配置或代码(附条件许可);把 main 的内容当作 MIT 使用 |
|
||||
| MovieClaw **tag `v0.27.0`(`c79bb1b0`,MIT)** 的资产可以原样复制或转换(`kind=copied-mit`),前提是保留 MIT 全文与 `Copyright (c) 2026 MovieClaw`(`packages/adapters/src/sites/definitions/NOTICE-MovieClaw.md`),每个产物写明来源提交与路径(站点定义 JSON 的 `provenance` 字段),且只经 `git show v0.27.0:<path>` 读取(用户 2026-09-27 确认,依据 `movieclaw-assessment.md` §1) | 复制 `v0.27.0` 之后(`251f1988` 起附条件许可)的任何内容;复制 MC 仓库内自带独立许可的第三方子组件(`skill-creator` Apache-2.0、`liquid-glass`)而不遵守其各自许可 |
|
||||
|
||||
**对每个 PR 的要求**:只要实现参考了上游,PR 描述里就必须写"参考:`docs/porting/<文件>#<节>`",并在 §3 ledger 里补一行,登记状态为 `behavior-ref`。只有真的复制了代码或数据时,才登记为 `copied`;按目前的边界,**不应出现 `copied`**。
|
||||
**对每个 PR 的要求**:只要实现参考了上游,PR 描述里就必须写"参考:`docs/porting/<文件>#<节>`",并在 §3 ledger 里补一行,登记状态为 `behavior-ref`。只有真的复制了代码或数据时,才登记为 `copied`;按目前的边界,**不应出现 `copied`**。例外是 `copied-mit`:复制 MIT 许可的资产(目前仅 MovieClaw v0.27.0),必须 `notice_required=是` 并附 NOTICE。
|
||||
|
||||
### 2.1 分发时的注意事项(首期不分发,先写在这里)
|
||||
|
||||
@@ -59,7 +60,7 @@
|
||||
| --- | --- |
|
||||
| `id` | `CL-<序号>` |
|
||||
| `our_module` | 本项目的文件或函数,例如 `packages/domain/src/title/parse.ts#parseReleaseTitle` |
|
||||
| `kind` | `behavior-ref`(只参考行为)/ `data-ref`(参考了数据结构,内容自行编制)/ `copied`(复制,原则上禁止)/ `dependency`(npm 依赖) |
|
||||
| `kind` | `behavior-ref`(只参考行为)/ `data-ref`(参考了数据结构,内容自行编制)/ `copied`(复制,原则上禁止)/ `copied-mit`(复制 MIT 资产,须保留 NOTICE,见 §2)/ `dependency`(npm 依赖) |
|
||||
| `upstream` | 仓库 URL |
|
||||
| `commit_or_version` | 精确提交或 tag,不能写 `main` |
|
||||
| `upstream_paths` | 文件:函数:行号 |
|
||||
@@ -82,9 +83,11 @@
|
||||
| CL-006 | `packages/domain/src/organize/*`、`packages/adapters/src/fs/*`、`packages/tasks/src/verify-and-import.ts` | behavior-ref | MoviePilot | e6820a8 | 见 `moviepilot-transfer.md` §2 各表 | GPL-3.0 | transfer §2-§4 | 见 transfer §3 的必须偏离表 | 否 | internal-only |
|
||||
| CL-007 | `packages/adapters/src/qbittorrent/*` | behavior-ref | MoviePilot | e6820a8 | `app/modules/qbittorrent/__init__.py`、`qbittorrent.py`(行号见 downloader-and-sites 文档) | GPL-3.0 | downloader-and-sites §qB | 标签接管,删数据前做引用检查 | 否 | internal-only |
|
||||
| CL-008 | `packages/adapters/src/sites/nexusphp/*` | behavior-ref | MoviePilot | e6820a8 | `app/modules/indexer/spider/*`、`app/modules/indexer/parser/nexus_php.py`、`nexus_audiences.py` | GPL-3.0 | downloader-and-sites §站点 | 站点定义自行编制;不使用闭源 SitesHelper | 否 | internal-only |
|
||||
| CL-009 | `packages/adapters/src/sites/nexusphp/configs/audiences.ts` | data-ref | MovieClaw | fc9eb72 | `src/movieclaw_tracker/sites/configs/audiences.yaml` | MovieClaw License(Apache-2.0 加非商业条件) | downloader-and-sites §MovieClaw | **只参考字段结构**;选择器值以我们自己抓取的观众页面为准重新编写 | 否(未复制) | internal-only |
|
||||
| CL-010 | `packages/adapters/src/sites/mteam/*` | behavior-ref + data-ref | MovieClaw + MoviePilot | fc9eb72 / e6820a8 | MC:`sites/configs/mteam.yaml`、`sites/custom/mteam.py`;MP:`app/modules/indexer/parser/mtorrent.py` | MC 附条件 / GPL-3.0 | downloader-and-sites §M-Team | API 字段以 M-Team 公开 API 为准,按 API Key 模式实现 | 否 | internal-only |
|
||||
| CL-009(retired → CL-012) | `packages/adapters/src/sites/nexusphp/configs/audiences.ts` | data-ref | MovieClaw | fc9eb72 | `src/movieclaw_tracker/sites/configs/audiences.yaml` | MovieClaw License(Apache-2.0 加非商业条件) | downloader-and-sites §MovieClaw | **只参考字段结构**;选择器值以我们自己抓取的观众页面为准重新编写 | 否(未复制) | internal-only |
|
||||
| CL-010(retired → CL-013) | `packages/adapters/src/sites/mteam/*` | behavior-ref + data-ref | MovieClaw + MoviePilot | fc9eb72 / e6820a8 | MC:`sites/configs/mteam.yaml`、`sites/custom/mteam.py`;MP:`app/modules/indexer/parser/mtorrent.py` | MC 附条件 / GPL-3.0 | downloader-and-sites §M-Team | API 字段以 M-Team 公开 API 为准,按 API Key 模式实现 | 否 | internal-only |
|
||||
| CL-011 | `packages/testkit/fixtures/title-parity.json` | data-ref | MoviePilot | e6820a8 | 输入语料参考 `tests/cases/meta.py`;**期望值自行判定** | GPL-3.0(原测试文件) | metadata-recognition §9 | 只取标题字符串,必要时脱敏 | 否 | internal-only |
|
||||
| CL-012 | `packages/adapters/src/sites/definitions/*.json`(23 站)、`definitions/manifest.generated.ts`、`spider/mc-selector.ts`、`scripts/mp-sync/movieclaw-import.mjs` | copied-mit | MovieClaw | **v0.27.0**(`c79bb1b0`) | `src/movieclaw_tracker/sites/configs/*.yaml`;`selectors.py` `NexusPHPSelectors` 默认值;`frameworks/nexusphp.py` `_css_text` | MIT | downloader-and-sites §W1-3c | YAML 转为 MP indexer schema + `umt`;观众/馒头/HHClub/CHD 由 `scripts/mp-sync/movieclaw-overrides/*.json` 覆盖;除 4 主力站外 `enabled:false` | 是(`definitions/NOTICE-MovieClaw.md`) | internal-only |
|
||||
| CL-013 | `packages/adapters/src/sites/mteam/*` | behavior-ref + copied-mit | MovieClaw + MoviePilot | **v0.27.0**(`c79bb1b0`)/ e6820a8 | MC:`sites/configs/mteam.yaml`(→ `definitions/mteam.json`)、`sites/custom/mteam.py`(字段对照);MP:`app/modules/indexer/spider/mtorrent.py`、`parser/mtorrent.py` | MIT / GPL-3.0 | downloader-and-sites §M-Team | 定义由 MC 转换 + W1-3b 值覆盖;API 行为按 MP | 是(MC 部分) | internal-only |
|
||||
|
||||
> 新增 npm 依赖(例如 anitopy 的等价实现、`re2`、`fast-xml-parser`)按 `kind=dependency` 登记,填锁定版本和 SPDX。
|
||||
|
||||
@@ -92,7 +95,7 @@
|
||||
|
||||
1. ledger 以本文件 §3.2 为唯一登记处,按 id 追加,不删除旧行;撤销时把行标记为 `retired`。
|
||||
2. 上游提交升级时,**新增一行**,写新的提交号,不覆盖旧行。对照文档里的行号也要按新提交重新核对。
|
||||
3. `copied` 行出现时,CI 必须失败。建议在 `scripts/` 里加一个检查:ledger 中 `kind=copied` 的行数必须为 0。
|
||||
3. `copied` 行出现时,CI 必须失败。建议在 `scripts/` 里加一个检查:ledger 中 `kind=copied` 的行数必须为 0。`copied-mit` 不在此列,但必须有 NOTICE 文件且 `notice=是`。
|
||||
4. 审核人检查三件事:PR 里有没有"参考:"链接;ledger 有没有对应行;diff 中有没有大段和上游高度相似的代码(可以用 `jscpd` 这类工具,把上游目录作为外部语料做一次抽样检查)。
|
||||
|
||||
---
|
||||
|
||||
@@ -662,3 +662,36 @@ MC 注册表 `MC:src/movieclaw_tracker/registry.py:172` `_load_site_yaml` 读取
|
||||
### 10.4 许可提示
|
||||
|
||||
本节模块是对 MP(GPL-3.0)实现的逐函数 TS 移植,性质上比 `behavior-ref` 更接近衍生作品。项目目前为 internal-only 使用;若将来对外分发,需按 `license-and-provenance.md` §2 重新评估(GPL-3.0 同许可与源码提供义务)。
|
||||
|
||||
## 11. W1-3c 实际迁移对照(MP 开源站点框架全量 + MovieClaw 站点定义)
|
||||
|
||||
逐文件对照总表与跟随更新流程见 `mp-sync-ledger.md`(`scripts/mp-sync/ledger.json` 由源码 `@mp-source` 标签生成)。本节只记结构性决定。
|
||||
|
||||
### 11.1 专用 spider(`packages/adapters/src/sites/spiders/`)
|
||||
|
||||
| MP | 本项目 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `IndexerModule.SPIDER_PARSER_CLASSES` / `_SPECIALIZED_SEARCH_ARGUMENTS` | `spiders/index.ts` `SPECIALIZED_SPIDERS`、`SpecializedSpider.search(ctx, {keyword, mtype, cat, page})` | 键名与 MP 相同(Haidan/HDDolby/RousiPro/SunnyPT/TNodeSpider/TorrentLeech/Yema/mTorrent) |
|
||||
| 各 spider `__get_params` / `__parse_result` / `__process_response` / 系数函数 | `spiders/<name>.ts` 同名纯函数 | 常量表逐字保留;结果为 MP 字段(`SpiderTorrent`)+ `category_id`、`site_release_id`、`*_utc` 扩展 |
|
||||
| `(True, [])` 错误返回 | `SiteError` | 401/403 → `auth_invalid`,缺凭据 → `auth_missing`,业务错误按文案分类 |
|
||||
| `[base64 请求配置]url` enclosure + `submission._resolve_indirect_download_url` | `spiders/common.ts` `resolveIndirectDownloadUrl` / `downloadTorrentFile` | 下载时现场换直链,结果约束到可信 API 基址,不带凭据下载并校验 .torrent |
|
||||
| `TNodeSpider.__get_token`(`@cached` 24h)、`SunnyPTSpider._category_cache`(1h) | 适配器实例内 TTL 缓存 | |
|
||||
|
||||
### 11.2 站点用户信息解析器(`packages/adapters/src/sites/user-parsers/`)
|
||||
|
||||
| MP | 本项目 |
|
||||
| --- | --- |
|
||||
| `parser/__init__.py` `SiteSchema` / `SiteParserBase` | `types.ts` `SiteSchema` / `base.ts` `SiteParserBase`(`parse` 流程、`_get_page_content` 请求模式、`_parse_logged_in`、`to_dict`) |
|
||||
| `parser/<name>.py` 20 个类 | `user-parsers/<kebab-name>.ts` 同名类 |
|
||||
| `IndexerModule.refresh_userdata`(schema 回退) | `registry.ts` `refreshSiteUserData` |
|
||||
| `SiteUserData` | `SiteUserInfo`(camelCase,`raw` = `to_dict()`,不含凭据) |
|
||||
| lxml XPath / BeautifulSoup | `dom.ts`(xpath + xmldom)/ cheerio |
|
||||
| `SiteUtils.is_logged_in`、`under_challenge`、`parse_int/parse_float`、`normalize_datetime`、`format_timestamp`、`extract_domain` | `common.ts` 同名函数 |
|
||||
|
||||
偏离:翻页上限 50;网络/HTTP 失败另记 `http_errors`;写操作(标记已读)受 `fetchMessages` 门控;`normalize_datetime` 只处理绝对时间。
|
||||
|
||||
### 11.3 站点定义
|
||||
|
||||
- MP 的站点定义不可得(加密),定义 schema 按 `sites.pyi` 与 spider 读取的键整理为 zod(`definitions/schema.ts`),加载即校验。
|
||||
- 选择器值:用户 2026-09-27 确认复制 MovieClaw **v0.27.0**(MIT)资产,23 个站点经 `scripts/mp-sync/movieclaw-import.mjs` 转换(ledger CL-012/CL-013,`copied-mit`,NOTICE 见 `definitions/NOTICE-MovieClaw.md`)。映射规则按 `movieclaw-assessment.md` §4;`page_offset -1 → browse.start 0`;`promo_*_rules → case` 表(补 `"*": 1`);`X::attr(a) → {selector, attribute}`;分类取 `\d+`;MovieClaw 的 documentary/anime/game/av/other 只进 `categoryNames`(原始 ID 保留)。
|
||||
- 观众/馒头保留 W1-3b 手写值(覆盖层),HHClub/CHD 覆盖层补站点分类名;4 个主力站启用,其余 19 站 `enabled:false`(未实测)。
|
||||
@@ -0,0 +1,99 @@
|
||||
# MoviePilot 跟随移植账本(mp-sync)
|
||||
|
||||
> **许可结论(引自 `license-and-provenance.md`)**:MoviePilot 为 GPLv3;本目录登记的站点框架文件是用户 2026-09-27 明确要求"照抄 MP v3 实现迁移"的数据来源适配部分,每个移植文件头保留 `SPDX-License-Identifier: GPL-3.0-only` 与来源声明;MP 的闭源/加密部分(`sites.*.so`、`user.sites.v3.bin`)**不解密、不参考**,站点定义改由 MovieClaw **v0.27.0(MIT,`copied-mit`,见 `packages/adapters/src/sites/definitions/NOTICE-MovieClaw.md`)** 转换 + 手写覆盖。MovieClaw v0.27.0 之后改为附条件许可,**不跟随其后续提交**。
|
||||
|
||||
## 1. 机制
|
||||
|
||||
- **登记来源**:每个移植文件头写 `@mp-source <上游路径> @ <提交>`(一个文件可多行);sites 目录外或 W1-3a/b 早期文件在 `scripts/mp-sync/ledger.manual.json` 人工登记。
|
||||
- **ledger**:`scripts/mp-sync/ledger.json`(`build-ledger.mjs` 生成)按上游文件聚合:`upstream`、移植时 `commit`、该文件在该提交的内容 `sha256`、本项目文件 `ours[]`。
|
||||
- **监视目录**:`app/modules/indexer/spider/`、`app/modules/indexer/parser/`,出现 ledger 未收录的新文件即提示(MP 新增站点 spider/解析器)。
|
||||
|
||||
## 2. 用法
|
||||
|
||||
MP 本地仓库默认 `/opt/moviepilot-plus/upstream/MoviePilot`(浅克隆,当前 `e6820a8`)。以下命令 Node 24 或 `deno run -A` 均可(不依赖根 package.json / deno.json 任务)。
|
||||
|
||||
```bash
|
||||
# 1) 取上游新提交(浅克隆)
|
||||
git -C /opt/moviepilot-plus/upstream/MoviePilot fetch --depth=1 origin <新提交或 v3>
|
||||
# 2) 查差异:已变更 / 已删除 / 监视目录新增,附逐文件 git diff 命令;有变化退出码 1
|
||||
node scripts/mp-sync/check.mjs --to <新提交> # 或 --mp <路径> --json
|
||||
# 3) 按 diff 增量移植 TS 文件,把文件头 @mp-source 的提交号改为新提交(新文件加标签)
|
||||
# 4) 重建 ledger 与下表
|
||||
node scripts/mp-sync/build-ledger.mjs --commit <新提交>
|
||||
# 5) 跑适配器测试
|
||||
cd packages/adapters && deno run -A npm:vitest run src/sites
|
||||
```
|
||||
|
||||
MovieClaw 站点定义(与 MP 无关,但同属站点框架跟随工具):
|
||||
|
||||
```bash
|
||||
node scripts/mp-sync/movieclaw-import.mjs # 从 v0.27.0 重新转换 23 个站点定义(覆盖层:scripts/mp-sync/movieclaw-overrides/)
|
||||
node scripts/mp-sync/movieclaw-import.mjs --check # 只比较,有差异退出码 1
|
||||
```
|
||||
|
||||
## 3. 当前对照总表
|
||||
|
||||
<!-- mp-sync:table:begin -->
|
||||
共 49 个上游文件(`adapters/` = `packages/adapters/src/`)。
|
||||
|
||||
| 上游文件 | 本项目文件 | 移植提交 | sha256(前 12 位) | 来源 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `app/adapters/network/cloudflare.py` | `adapters/sites/user-parsers/common.ts` | `e6820a8` | `a23a2c44da05` | tag |
|
||||
| `app/application/mediaserver.py` | `adapters/emby/client.ts` | `e6820a8` | `f034f0be8ba6` | manual |
|
||||
| `app/application/rss.py` | `adapters/rss/fetch.ts`<br>`adapters/rss/parse.ts`<br>`adapters/rss/rss-link.ts` | `e6820a8` | `8ea70f712512` | manual |
|
||||
| `app/application/site/sites.pyi` | `adapters/sites/definitions/schema.ts`<br>`adapters/sites/registry.ts`<br>`adapters/sites/spider/schema.ts` | `e6820a8` | `8fea9a239354` | manual |
|
||||
| `app/chain/download/submission.py` | `adapters/sites/mteam/adapter.ts`<br>`adapters/sites/spider/adapter.ts`<br>`adapters/sites/spiders/common.ts` | `e6820a8` | `f7cb870e47d6` | manual+tag |
|
||||
| `app/domain/site.py` | `adapters/sites/user-parsers/common.ts` | `e6820a8` | `650c795a4def` | tag |
|
||||
| `app/foundation/dom.py` | `adapters/sites/user-parsers/dom.ts` | `e6820a8` | `6d6accf2cef1` | tag |
|
||||
| `app/foundation/size.py` | `adapters/sites/spider/spider.ts` | `e6820a8` | `7b0b8f50588c` | manual |
|
||||
| `app/foundation/temporal.py` | `adapters/sites/spiders/common.ts`<br>`adapters/sites/user-parsers/common.ts` | `e6820a8` | `74941f460e40` | tag |
|
||||
| `app/foundation/text.py` | `adapters/sites/user-parsers/common.ts` | `e6820a8` | `a88c75dc8431` | tag |
|
||||
| `app/modules/__init__.py` | `adapters/qbittorrent/paths.ts` | `e6820a8` | `2edada0ea591` | manual |
|
||||
| `app/modules/_base/downloader.py` | `adapters/qbittorrent/torrent.ts` | `e6820a8` | `84bd8946c8b2` | manual |
|
||||
| `app/modules/emby/emby.py` | `adapters/emby/client.ts` | `e6820a8` | `e6468ea34ef2` | manual |
|
||||
| `app/modules/filemanager/storages/local.py` | `adapters/fs/copy.ts`<br>`adapters/fs/move.ts` | `e6820a8` | `806a1970ca8e` | manual |
|
||||
| `app/modules/filemanager/transhandler.py` | `adapters/fs/move.ts` | `e6820a8` | `13e2bba491ac` | manual |
|
||||
| `app/modules/indexer/__init__.py` | `adapters/sites/registry.ts`<br>`adapters/sites/spider/adapter.ts`<br>`adapters/sites/spiders/adapter.ts`<br>`adapters/sites/spiders/index.ts`<br>`adapters/sites/spiders/map.ts`<br>`adapters/sites/spiders/types.ts`<br>`adapters/sites/user-parsers/registry.ts` | `e6820a8` | `e9c5d15fdaa5` | manual+tag |
|
||||
| `app/modules/indexer/parser/__init__.py` | `adapters/sites/user-parsers/base.ts`<br>`adapters/sites/user-parsers/types.ts` | `e6820a8` | `0e6c4215b713` | tag |
|
||||
| `app/modules/indexer/parser/bitpt.py` | `adapters/sites/user-parsers/bitpt.ts` | `e6820a8` | `871d25e570f1` | tag |
|
||||
| `app/modules/indexer/parser/discuz.py` | `adapters/sites/user-parsers/discuz.ts` | `e6820a8` | `12277ba955ce` | tag |
|
||||
| `app/modules/indexer/parser/file_list.py` | `adapters/sites/user-parsers/file-list.ts` | `e6820a8` | `f92e65ed7327` | tag |
|
||||
| `app/modules/indexer/parser/gazelle.py` | `adapters/sites/user-parsers/gazelle.ts` | `e6820a8` | `c10e5246724b` | tag |
|
||||
| `app/modules/indexer/parser/hddolby.py` | `adapters/sites/user-parsers/hddolby.ts` | `e6820a8` | `a4336d92d603` | tag |
|
||||
| `app/modules/indexer/parser/ipt.py` | `adapters/sites/user-parsers/ipt.ts` | `e6820a8` | `2b9d04d76606` | tag |
|
||||
| `app/modules/indexer/parser/mtorrent.py` | `adapters/sites/user-parsers/mtorrent.ts` | `e6820a8` | `c5d5a3c6f9f5` | tag |
|
||||
| `app/modules/indexer/parser/nexus_audiences.py` | `adapters/sites/user-parsers/nexus-audiences.ts` | `e6820a8` | `1a2d104db769` | tag |
|
||||
| `app/modules/indexer/parser/nexus_hhanclub.py` | `adapters/sites/user-parsers/nexus-hhanclub.ts` | `e6820a8` | `8850619069d4` | tag |
|
||||
| `app/modules/indexer/parser/nexus_php.py` | `adapters/sites/user-parsers/nexus-php.ts` | `e6820a8` | `39303ae96d9c` | tag |
|
||||
| `app/modules/indexer/parser/nexus_project.py` | `adapters/sites/user-parsers/nexus-project.ts` | `e6820a8` | `2b5508cfb2f8` | tag |
|
||||
| `app/modules/indexer/parser/nexus_rabbit.py` | `adapters/sites/user-parsers/nexus-rabbit.ts` | `e6820a8` | `09149b89a7c7` | tag |
|
||||
| `app/modules/indexer/parser/rousi.py` | `adapters/sites/user-parsers/rousi.ts` | `e6820a8` | `1b1ea93de084` | tag |
|
||||
| `app/modules/indexer/parser/small_horse.py` | `adapters/sites/user-parsers/small-horse.ts` | `e6820a8` | `b73b5de97737` | tag |
|
||||
| `app/modules/indexer/parser/sunnypt.py` | `adapters/sites/user-parsers/sunnypt.ts` | `e6820a8` | `937f8453fa2b` | tag |
|
||||
| `app/modules/indexer/parser/tnode.py` | `adapters/sites/user-parsers/tnode.ts` | `e6820a8` | `c9cb809fc4bf` | tag |
|
||||
| `app/modules/indexer/parser/torrent_leech.py` | `adapters/sites/user-parsers/torrent-leech.ts` | `e6820a8` | `72d1473a3bba` | tag |
|
||||
| `app/modules/indexer/parser/unit3d.py` | `adapters/sites/user-parsers/unit3d.ts` | `e6820a8` | `9a4d579deca5` | tag |
|
||||
| `app/modules/indexer/parser/yema.py` | `adapters/sites/user-parsers/yema.ts` | `e6820a8` | `0f98fd580bad` | tag |
|
||||
| `app/modules/indexer/parser/zhixing.py` | `adapters/sites/user-parsers/zhixing.ts` | `e6820a8` | `90c8954e7387` | tag |
|
||||
| `app/modules/indexer/spider/__init__.py` | `adapters/sites/spider/map.ts`<br>`adapters/sites/spider/schema.ts`<br>`adapters/sites/spider/spider.ts`<br>`adapters/sites/spider/template.ts` | `e6820a8` | `2513d962fa43` | manual |
|
||||
| `app/modules/indexer/spider/haidan.py` | `adapters/sites/spiders/haidan.ts` | `e6820a8` | `75eb802f19f0` | tag |
|
||||
| `app/modules/indexer/spider/hddolby.py` | `adapters/sites/spiders/hddolby.ts` | `e6820a8` | `46a50bd8d49f` | tag |
|
||||
| `app/modules/indexer/spider/mtorrent.py` | `adapters/sites/mteam/adapter.ts`<br>`adapters/sites/mteam/client.ts`<br>`adapters/sites/mteam/spider.ts`<br>`adapters/sites/spiders/mtorrent.ts` | `e6820a8` | `a8ab2b822cb2` | manual+tag |
|
||||
| `app/modules/indexer/spider/rousi.py` | `adapters/sites/spiders/rousi.ts` | `e6820a8` | `aa13c386a560` | tag |
|
||||
| `app/modules/indexer/spider/sunnypt.py` | `adapters/sites/spiders/sunnypt.ts` | `e6820a8` | `735b0d721e65` | tag |
|
||||
| `app/modules/indexer/spider/tnode.py` | `adapters/sites/spiders/tnode.ts` | `e6820a8` | `a3634a268dba` | tag |
|
||||
| `app/modules/indexer/spider/torrentleech.py` | `adapters/sites/spiders/torrentleech.ts` | `e6820a8` | `c965f2bcaea4` | tag |
|
||||
| `app/modules/indexer/spider/yema.py` | `adapters/sites/spiders/yema.ts` | `e6820a8` | `560b62c1ff10` | tag |
|
||||
| `app/modules/qbittorrent/qbittorrent.py` | `adapters/qbittorrent/client.ts`<br>`adapters/qbittorrent/state.ts` | `e6820a8` | `ab02e97e986f` | manual |
|
||||
| `app/modules/themoviedb/tmdbapi.py` | `adapters/tmdb/client.ts`<br>`adapters/tmdb/match.ts` | `e6820a8` | `787553a6f57d` | manual |
|
||||
| `app/schemas/site.py` | `adapters/sites/user-parsers/types.ts` | `e6820a8` | `e7952ed40b7b` | tag |
|
||||
<!-- mp-sync:table:end -->
|
||||
|
||||
## 4. 移植时的统一偏离(每个文件头另有细节)
|
||||
|
||||
1. **凭据不进候选/结果**:MP 两段式 enclosure(`[base64(含 apikey 的请求配置)]url`)不生成,下载时由 adapter 现场换直链;用户信息 `raw` 不含 cookie/apikey/token。
|
||||
2. **错误显式化**:MP spider 的 `(is_error, [])` 改为抛 `SiteError{kind}`;用户信息解析保留 MP 的 `err_msg` 语义,另记脱敏的 `http_errors`。
|
||||
3. **翻页上限**:做种/消息翻页最多 50 页(MP 无上限)。
|
||||
4. **XPath**:lxml → `xpath` + `@xmldom/xmldom`(经 htmlparser2 解析,不插入 tbody),见 `user-parsers/dom.ts`。
|
||||
5. **dateparser**:只实现绝对时间格式,相对时间原样返回(待核验)。
|
||||
6. **写操作门控**:读取站内信后标记已读(MTorrent/Rousi/NexusRabbit)只在 `fetchMessages=true` 时发生(MP 由全局 `SITE_MESSAGE` 控制)。
|
||||
Reference in new issue
Block a user