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:
rootandClaude Opus 5.5 committed 2026-09-27 18:39:27 +08:00
1 parent cf85481d95
commit d9f2af2f3c
166 files changed
+16577 -186

No files matched your search

@@ -0,0 +1,38 @@
# 第三方声明:MovieClaw(MIT)
本目录下的站点定义 JSON(`provenance.source = "movieclaw"`)由 `scripts/mp-sync/movieclaw-import.mjs`
从 MovieClaw **tag `v0.27.0`(提交 `c79bb1b065c826823fc1c15bcb99b3c282c3fce0`)** 的
`src/movieclaw_tracker/sites/configs/*.yaml` 与 `src/movieclaw_tracker/selectors.py`(`NexusPHPSelectors` 默认值)
转换而来;`packages/adapters/src/sites/spider/mc-selector.ts` 的选择器语义对照 `frameworks/nexusphp.py` `_css_text`。
该版本以 MIT 许可发布(MovieClaw 自 `251f1988` 起改为附条件许可,**新许可下的内容未被使用**)。
- 上游仓库:https://github.com/movieclaw/movieclaw
- 许可类别:`copied-mit`(见 `docs/porting/license-and-provenance.md`)
- 本项目的修改:字段改写为 MoviePilot indexer schema + `umt` 扩展;默认值展开;分类名与观众/馒头定义由
`scripts/mp-sync/movieclaw-overrides/*.json` 覆盖。
以下为 MovieClaw v0.27.0 `LICENSE` 全文(原样):
```
MIT License
Copyright (c) 2026 MovieClaw
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
@@ -0,0 +1,252 @@
{
"id": "agsvpt",
"name": "AGSVPT",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/agsvpt.yaml"
},
"domain": "https://www.agsvpt.com/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
},
{
"id": "407",
"desc": "剧集"
},
{
"id": "419",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
},
{
"id": "411",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > span"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "AGSVPT",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "剧集",
"408": "音乐",
"411": "音乐",
"413": "游戏",
"415": "其他",
"419": "剧集"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='User_Name']::attr(href)",
"username_css": "a[class*='User_Name']",
"class_css": "a[class*='User_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding']::next_sibling_text",
"leeching_css": "img[alt='Torrents leeching']::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -1,7 +1,16 @@
{
"_provenance": "按 MoviePilot SiteSpider indexer schema 手写;字段结构参考 MovieClaw audiences.yaml(data-ref,未复制);选择器值按 NexusPHP 公开页面惯例编写,仅对 testkit mock 验证,待真实页面核验。见 ../README.md",
"id": "audiences",
"name": "观众",
"enabled": true,
"schema": "NexusAudiences",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/audiences.yaml",
"overrides": "scripts/mp-sync/movieclaw-overrides/audiences.json"
},
"domain": "https://audiences.me/",
"encoding": "UTF-8",
"public": false,
@@ -10,14 +19,45 @@
"result_num": 100,
"timeout": 30,
"search": {
"paths": [{ "path": "torrents.php", "type": "all" }],
"params": { "search": "{keyword}", "search_area": 4 }
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}",
"search_area": 4
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"batch": { "delimiter": " ", "space_replace": "_" },
"browse": { "path": "torrents.php?page={page}", "start": 0 },
"category": {
"movie": [{ "id": "401", "cat": "Movies", "desc": "电影" }],
"tv": [{ "id": "402", "cat": "TV Series", "desc": "剧集" }, { "id": "403", "cat": "TV Shows", "desc": "综艺" }],
"movie": [
{
"id": "401",
"cat": "Movies",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"cat": "TV Series",
"desc": "剧集"
},
{
"id": "403",
"cat": "TV Shows",
"desc": "综艺"
}
],
"music": []
},
"torrents": {
@@ -25,28 +65,62 @@
"selector": "table.torrents > tbody > tr:has(table.torrentname), table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": { "selector": "a[href*=\"details.php?id=\"]" },
"title_optional": { "selector": "a[title][href*=\"details.php?id=\"]", "attribute": "title" },
"title_default": {
"selector": "a[href*=\"details.php?id=\"]"
},
"title_optional": {
"selector": "a[title][href*=\"details.php?id=\"]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": { "selector": "a[href*=\"details.php?id=\"]", "attribute": "href" },
"download": { "selector": "a[href*=\"download.php?id=\"]", "attribute": "href" },
"details": {
"selector": "a[href*=\"details.php?id=\"]",
"attribute": "href"
},
"download": {
"selector": "a[href*=\"download.php?id=\"]",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [{ "name": "re_search", "args": ["tt\\d+", 0] }]
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4) > span"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date_elapsed": { "selector": "td:nth-child(4) > span" },
"date_added": { "selector": "td:nth-child(4) > span", "attribute": "title" },
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [{ "name": "dateparse", "args": "%Y-%m-%d %H:%M:%S" }]
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"size": { "selector": "td:nth-child(5)" },
"seeders": { "selector": "td:nth-child(6)" },
"leechers": { "selector": "td:nth-child(7)" },
"grabs": { "selector": "td:nth-child(8)" },
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
@@ -65,17 +139,31 @@
"*": 1
}
},
"freedate": {
"selector": "img[class^=\"pro_\"]",
"attribute": "title",
"filters": [{ "name": "re_search", "args": ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", 0] }]
"description": {
"selector": "span.torrent-subtitle-line"
},
"description": { "selector": "span.torrent-subtitle-line" },
"labels": { "selector": "span.tags" },
"category": {
"selector": "a[href*=\"?cat=\"]",
"attribute": "href",
"filters": [{ "name": "querystring", "args": "cat" }]
"filters": [
{
"name": "querystring",
"args": "cat"
}
]
},
"freedate": {
"selector": "img[class^=\"pro_\"]",
"attribute": "title",
"filters": [
{
"name": "re_search",
"args": ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", 0]
}
]
},
"labels": {
"selector": "span.tags"
}
}
},
@@ -84,14 +172,47 @@
"kind": "nexusphp",
"displayName": "观众",
"timezone": "+08:00",
"rateLimit": { "minIntervalMs": 3000, "burst": 1 },
"capabilities": { "list": true, "search": true, "detail": true, "download": true, "rss": true },
"categoryNames": { "401": "电影", "402": "剧集", "403": "综艺", "406": "纪录片" },
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": true
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "综艺",
"406": "纪录片"
},
"loginSuccess": "a[href*=\"logout\"]",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "td.rowhead:contains('等级') + td::text",
"uploaded_css": "span.site-userbar__compact-metric--uploaded",
"downloaded_css": "span.site-userbar__compact-metric--downloaded",
"ratio_css": "td.rowhead:contains('分享率') + td::text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "td.rowhead:contains('当前做种') + td::text",
"leeching_css": "td.rowhead:contains('当前下载') + td::text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
@@ -0,0 +1,252 @@
{
"id": "chdbits",
"name": "彩虹岛",
"enabled": true,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/chdbits.yaml",
"overrides": "scripts/mp-sync/movieclaw-overrides/chdbits.json"
},
"domain": "https://ptchdbits.co/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "综艺"
},
{
"id": "407",
"desc": "体育"
}
],
"music": [
{
"id": "406",
"desc": "MV"
},
{
"id": "408",
"desc": "HQ Audio"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "font.subtitle"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"freedate": {
"selector": "td.embedded > span[title]",
"attribute": "title",
"filters": [
{
"name": "re_search",
"args": ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "彩虹岛",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "综艺",
"404": "纪录片",
"405": "动漫",
"406": "MV",
"407": "体育",
"408": "HQ Audio",
"409": "其他"
},
"loginSuccess": "a[href='logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"username_css": "a[href^='userdetails.php?id=']",
"class_css": "td.rowhead:contains('等级') + td::text",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding']::next_sibling_text",
"leeching_css": "img[alt='Torrents leeching']::next_sibling_text",
"vip_css": "a[class^='VIP']"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,156 @@
import { CHDBITS_LIST_PAGE, CHDBITS_LOGIN_PAGE, HHANCLUB_DETAIL_PAGE, HHANCLUB_LIST_PAGE } from "@umt/testkit";
import { describe, expect, it } from "vitest";
import { getSiteDefinition, listSiteDefinitions } from "../registry.ts";
import { parseDetailPage } from "../spider/detail.ts";
import { spiderTorrentToRelease } from "../spider/map.ts";
import type { IndexerDefinition } from "../spider/schema.ts";
import { SiteSpider } from "../spider/spider.ts";
import {
BUILTIN_SITE_DEFINITIONS,
chdbitsDefinition,
hhanclubDefinition,
loadSiteDefinition,
parseIndexerDefinition,
} from "./index.ts";
import { MOVIECLAW_DEFINITION_JSON } from "./manifest.generated.ts";
const OBSERVED = "2026-09-27T00:00:00.000Z";
const PRIMARY = ["audiences", "chdbits", "hhanclub", "mteam"];
describe("站点定义:加载时 zod 校验", () => {
const ids = Object.keys(MOVIECLAW_DEFINITION_JSON).sort();
it("MovieClaw v0.27.0 全部 23 站转换结果均在注册表中", () => {
expect(ids).toHaveLength(23);
expect(listSiteDefinitions().map((d) => d.id)).toEqual(ids);
});
it.each(ids)("%s:schema 校验通过,provenance 指向 MovieClaw v0.27.0 MIT", (id) => {
const def = loadSiteDefinition(MOVIECLAW_DEFINITION_JSON[id]);
expect(def.id).toBe(id);
expect(def.provenance).toMatchObject({ source: "movieclaw", ref: "v0.27.0", commit: "c79bb1b0", license: "MIT" });
expect(def.provenance?.file).toBe(`src/movieclaw_tracker/sites/configs/${id}.yaml`);
expect(def.enabled).toBe(PRIMARY.includes(id));
expect(getSiteDefinition(id)).toBe(BUILTIN_SITE_DEFINITIONS[id]);
});
it("enabledOnly 只列 4 个主力站", () => {
expect(listSiteDefinitions({ enabledOnly: true }).map((d) => d.id)).toEqual(PRIMARY);
});
it("非法定义被拒绝并指出字段路径", () => {
const bad = structuredClone(MOVIECLAW_DEFINITION_JSON.chdbits) as Record<string, unknown>;
(bad as { domain: string }).domain = "https://ptchdbits.co"; // 缺结尾 /
delete (bad as { umt: Record<string, unknown> }).umt.timezone;
expect(() => parseIndexerDefinition(bad)).toThrow(/chdbits.*domain.*umt\.timezone|chdbits.*umt\.timezone.*domain/);
expect(() => loadSiteDefinition({ id: "x", umt: { kind: "gopher" } })).toThrow(/umt\.kind 未知/);
const typo = structuredClone(MOVIECLAW_DEFINITION_JSON.hhanclub) as {
torrents: { fields: Record<string, unknown> };
};
typo.torrents.fields.size = { selectr: "div" };
expect(() => parseIndexerDefinition(typo)).toThrow(/torrents\.fields\.size/);
});
it("观众:W1-3b 手写值优先(覆盖层),MovieClaw 值补空", () => {
const a = getSiteDefinition("audiences") as IndexerDefinition;
expect(a.search?.params).toEqual({ search: "{keyword}", search_area: 4 }); // W1-3b
expect(a.torrents.fields.category?.filters).toEqual([{ name: "querystring", args: "cat" }]); // W1-3b
expect(a.umt.profile?.uploaded_css).toBe("span.site-userbar__compact-metric--uploaded"); // MovieClaw 补空
expect(a.schema).toBe("NexusAudiences");
expect(a.provenance?.overrides).toBe("scripts/mp-sync/movieclaw-overrides/audiences.json");
});
it("OurBits 的 cat[] 分类参数由定义表达;TTG 需自定义适配器 → 禁用", () => {
const ob = getSiteDefinition("ourbits") as IndexerDefinition;
expect(ob.category?.param).toBe("cat[]");
const url = new URL(new SiteSpider(ob, { keyword: "x", mtype: "movie" }).getSearchUrl());
expect(url.searchParams.getAll("cat[]").length).toBeGreaterThan(0);
const ttg = getSiteDefinition("ttg") as IndexerDefinition;
expect(ttg.umt.customClass).toContain("TTGSite");
expect(ttg.enabled).toBe(false);
});
});
describe("HHClub 定义(div 卡片模板)", () => {
const parse = (html: string) => {
const r = new SiteSpider(hhanclubDefinition, {}).parse(html);
return r.torrents.map((t) => spiderTorrentToRelease(t, hhanclubDefinition, OBSERVED)!);
};
it("列表:标题/副标题/综艺原始分类 403/大小/人数/发布时间/免费 + H&R", () => {
const [a, b] = parse(HHANCLUB_LIST_PAGE);
expect(a).toMatchObject({
siteId: "hhanclub",
siteReleaseId: "90001",
title: "Go.Fighting.S10E01.2026.2160p.WEB-DL.H265.AAC-HHWEB",
subtitle: "极限挑战 第十季 第1期",
category: { id: "403", name: "综艺" },
sizeBytes: Math.round(6.12 * 1024 ** 3),
seeders: 88,
leechers: 5,
snatched: 1024,
promotion: { type: "free", downloadFactor: 0, uploadFactor: 1 },
hr: true,
uploadedAt: "2026-09-20T12:30:00.000Z",
detailUrl: "https://hhanclub.net/details.php?id=90001&hit=1",
});
expect(b).toMatchObject({
siteReleaseId: "90002",
category: { id: "401", name: "电影" },
promotion: { type: "2x50%", downloadFactor: 0.5, uploadFactor: 2 },
hr: false,
});
});
it("浏览从 page=0 起(MovieClaw page_offset -1);mtype=tv 选 402/403/407/412", () => {
expect(new SiteSpider(hhanclubDefinition, { page: 0 }).getSearchUrl()).toBe(
"https://hhanclub.net/torrents.php?page=0",
);
const u = new URL(new SiteSpider(hhanclubDefinition, { keyword: "极限挑战", mtype: "tv" }).getSearchUrl());
expect(["cat402", "cat403", "cat407", "cat412"].every((k) => u.searchParams.get(k) === "1")).toBe(true);
expect(u.searchParams.get("search")).toBe("极限挑战");
});
it("详情页:逐字段选择器(Tailwind div 结构)取标题/副标题/大小/IMDb/豆瓣", () => {
const { kind, detail } = parseDetailPage(HHANCLUB_DETAIL_PAGE, hhanclubDefinition, "90002", OBSERVED);
expect(kind).toBe("ok");
expect(detail).toMatchObject({
title: "Dune.Part.Two.2024.2160p.UHD.BluRay.REMUX-HHWEB",
subtitle: "沙丘2 | 中字",
sizeBytes: Math.round(78.3 * 1024 ** 3),
imdbId: "tt15239678",
doubanId: "35575567",
});
});
});
describe("CHDBits 定义(标准 NexusPHP)", () => {
it("列表:title 属性全名、font.subtitle、2x 免费 + 截止时间、cat 链接分类", () => {
const r = new SiteSpider(chdbitsDefinition, {}).parse(CHDBITS_LIST_PAGE);
const [a, b] = r.torrents.map((t) => spiderTorrentToRelease(t, chdbitsDefinition, OBSERVED)!);
expect(a).toMatchObject({
siteReleaseId: "555001",
title: "The.Last.of.Us.S02.2025.1080p.BluRay.x264.DTS-HD.MA.5.1-CHD",
category: { id: "402", name: "剧集" },
sizeBytes: Math.round(45.2 * 1024 ** 3),
seeders: 42,
leechers: 3,
snatched: 100,
promotion: { type: "2xfree", downloadFactor: 0, uploadFactor: 2, expiresAt: "2026-09-30T04:00:00.000Z" },
hr: "unknown",
uploadedAt: "2026-09-25T00:00:00.000Z",
});
expect(a!.subtitle).toContain("最后生还者 第二季");
expect(b).toMatchObject({
siteReleaseId: "555002",
category: { id: "401", name: "电影" },
promotion: { type: "none", downloadFactor: 1, uploadFactor: 1, expiresAt: null },
});
});
it("登录页识别为登录/权限页,不产生结果", () => {
const r = new SiteSpider(chdbitsDefinition, {}).parse(CHDBITS_LOGIN_PAGE);
expect(r.loginPage).toBe(true);
expect(r.torrents).toEqual([]);
});
});
@@ -0,0 +1,279 @@
{
"id": "hdarea",
"name": "高清视界 HDArea",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hdarea.yaml"
},
"domain": "https://www.hdarea.club/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "300",
"desc": "电影"
},
{
"id": "401",
"desc": "电影"
},
{
"id": "410",
"desc": "电影"
},
{
"id": "411",
"desc": "电影"
},
{
"id": "412",
"desc": "电影"
},
{
"id": "413",
"desc": "电影"
},
{
"id": "414",
"desc": "电影"
},
{
"id": "415",
"desc": "电影"
},
{
"id": "416",
"desc": "电影"
},
{
"id": "417",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(5)"
},
"date_added": {
"selector": "td:nth-child(5) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(6)"
},
"seeders": {
"selector": "td:nth-child(7)"
},
"leechers": {
"selector": "td:nth-child(8)"
},
"grabs": {
"selector": "td:nth-child(9)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > div[title]",
"attribute": "title"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "高清视界 HDArea",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 60000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"300": "电影",
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "其他",
"408": "音乐",
"409": "其他",
"410": "电影",
"411": "电影",
"412": "电影",
"413": "电影",
"414": "电影",
"415": "电影",
"416": "电影",
"417": "电影"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,236 @@
{
"id": "hddolby",
"name": "高清杜比 HDDolby",
"enabled": false,
"schema": "HDDolby",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hddolby.yaml"
},
"domain": "https://www.hddolby.com/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded span[style*='float:left']"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "高清杜比 HDDolby",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "其他",
"408": "音乐",
"409": "其他",
"410": "游戏",
"411": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,245 @@
{
"id": "hdfans",
"name": "HDFans",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hdfans.yaml"
},
"domain": "https://hdfans.org/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "416",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "407",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded br"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "HDFans",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "纪录片",
"404": "其他",
"405": "其他",
"406": "音乐",
"407": "音乐",
"408": "音乐",
"409": "其他",
"410": "其他",
"416": "剧集",
"417": "动漫",
"418": "其他",
"419": "其他",
"421": "游戏",
"423": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,434 @@
{
"id": "hdhome",
"name": "高清家园",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hdhome.yaml"
},
"domain": "https://hdhome.org/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "411",
"desc": "电影"
},
{
"id": "412",
"desc": "电影"
},
{
"id": "413",
"desc": "电影"
},
{
"id": "414",
"desc": "电影"
},
{
"id": "415",
"desc": "电影"
},
{
"id": "416",
"desc": "电影"
},
{
"id": "450",
"desc": "电影"
},
{
"id": "499",
"desc": "电影"
},
{
"id": "505",
"desc": "电影"
},
{
"id": "506",
"desc": "电影"
},
{
"id": "518",
"desc": "电影"
}
],
"tv": [
{
"id": "425",
"desc": "剧集"
},
{
"id": "426",
"desc": "剧集"
},
{
"id": "427",
"desc": "剧集"
},
{
"id": "428",
"desc": "剧集"
},
{
"id": "429",
"desc": "剧集"
},
{
"id": "430",
"desc": "剧集"
},
{
"id": "431",
"desc": "剧集"
},
{
"id": "432",
"desc": "剧集"
},
{
"id": "433",
"desc": "剧集"
},
{
"id": "434",
"desc": "剧集"
},
{
"id": "435",
"desc": "剧集"
},
{
"id": "436",
"desc": "剧集"
},
{
"id": "437",
"desc": "剧集"
},
{
"id": "438",
"desc": "剧集"
},
{
"id": "442",
"desc": "剧集"
},
{
"id": "443",
"desc": "剧集"
},
{
"id": "452",
"desc": "剧集"
},
{
"id": "453",
"desc": "剧集"
},
{
"id": "502",
"desc": "剧集"
},
{
"id": "504",
"desc": "剧集"
},
{
"id": "511",
"desc": "剧集"
},
{
"id": "523",
"desc": "剧集"
},
{
"id": "526",
"desc": "剧集"
}
],
"music": [
{
"id": "439",
"desc": "音乐"
},
{
"id": "440",
"desc": "音乐"
},
{
"id": "441",
"desc": "音乐"
},
{
"id": "503",
"desc": "音乐"
},
{
"id": "423",
"desc": "音乐"
},
{
"id": "424",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > span:not([class])"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"hr": {
"selector": "img.hitandrun"
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "高清家园",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"409": "其他",
"411": "电影",
"412": "电影",
"413": "电影",
"414": "电影",
"415": "电影",
"416": "电影",
"417": "纪录片",
"418": "纪录片",
"419": "纪录片",
"420": "纪录片",
"421": "纪录片",
"422": "纪录片",
"423": "音乐",
"424": "音乐",
"425": "剧集",
"426": "剧集",
"427": "剧集",
"428": "剧集",
"429": "剧集",
"430": "剧集",
"431": "剧集",
"432": "剧集",
"433": "剧集",
"434": "剧集",
"435": "剧集",
"436": "剧集",
"437": "剧集",
"438": "剧集",
"439": "音乐",
"440": "音乐",
"441": "音乐",
"442": "剧集",
"443": "剧集",
"444": "动漫",
"445": "动漫",
"446": "动漫",
"447": "动漫",
"448": "动漫",
"449": "动漫",
"450": "电影",
"451": "纪录片",
"452": "剧集",
"453": "剧集",
"454": "动漫",
"499": "电影",
"500": "纪录片",
"501": "动漫",
"502": "剧集",
"503": "音乐",
"504": "剧集",
"505": "电影",
"506": "电影",
"507": "纪录片",
"508": "纪录片",
"509": "动漫",
"510": "动漫",
"511": "剧集",
"518": "电影",
"523": "剧集",
"526": "剧集",
"529": "纪录片",
"531": "动漫"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "a[href*='userdetails.php?id=']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus::next_sibling_text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding'] + *",
"leeching_css": "img[alt='Torrents leeching'] + *"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,276 @@
{
"id": "hdsky",
"name": "HDSky",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hdsky.yaml"
},
"domain": "https://hdsky.me/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
},
{
"id": "410",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
},
{
"id": "407",
"desc": "剧集"
},
{
"id": "411",
"desc": "剧集"
},
{
"id": "412",
"desc": "剧集"
},
{
"id": "413",
"desc": "剧集"
},
{
"id": "414",
"desc": "剧集"
},
{
"id": "415",
"desc": "剧集"
},
{
"id": "416",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents.progresstable tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a[href*='details.php'] b span"
},
"title_optional": {
"selector": "table.torrentname a[href*='details.php'] b span[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "table.torrentname a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "form[action*='download.php']",
"attribute": "action"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "a[href*='dllist=1#seeders']"
},
"leechers": {
"selector": "a[href*='dllist=1#leechers']"
},
"grabs": {
"selector": "a[href*='viewsnatches.php'] b, td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_2up": 2,
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"*": 1
}
},
"description": {
"selector": "table.torrentname br + span"
},
"category": {
"selector": "td:first-child a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "HDSky",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "剧集",
"408": "音乐",
"409": "其他",
"410": "电影",
"411": "剧集",
"412": "剧集",
"413": "剧集",
"414": "剧集",
"415": "剧集",
"416": "剧集"
},
"loginSuccess": "a[href='logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td.rowfollow",
"size": "td.rowhead:contains('基本信息') + td.rowfollow",
"description": "#kdescr",
"download": "form[action*='download.php']::attr(action)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,239 @@
{
"id": "hdtime",
"name": "HDTime",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hdtime.yaml"
},
"domain": "https://hdtime.org/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
},
{
"id": "424",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"*": 1
}
},
"description": {
"selector": "td.embedded br"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "HDTime",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "其他",
"408": "音乐",
"409": "其他",
"410": "游戏",
"411": "其他",
"414": "其他",
"424": "电影"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,240 @@
{
"id": "hdvideo",
"name": "HDVIDEO",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hdvideo.yaml"
},
"domain": "https://hdvideo.top/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
},
{
"id": "407",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents tr"
},
"fields": {
"title_default": {
"selector": "span.tt-name a b"
},
"title_optional": {
"selector": "span.tt-name a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "span.tt-name a",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(5)"
},
"date_added": {
"selector": "td:nth-child(5) span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(6)"
},
"seeders": {
"selector": "a[href*='dllist=1#seeders']"
},
"leechers": {
"selector": "a[href*='dllist=1#leechers'], td:nth-child(8)"
},
"grabs": {
"selector": "a[href*='viewsnatches.php'] b"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_2up": 2,
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"*": 1
}
},
"description": {
"selector": "span.tt-sub"
},
"category": {
"selector": "td:nth-child(2) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "HDVIDEO",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "剧集",
"408": "音乐"
},
"loginSuccess": "a[href='logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td.rowfollow",
"size": "td.rowhead:contains('基本信息') + td.rowfollow",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,254 @@
{
"id": "hhanclub",
"name": "憨憨",
"enabled": true,
"schema": "NexusHhanclub",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/hhanclub.yaml",
"overrides": "scripts/mp-sync/movieclaw-overrides/hhanclub.json"
},
"domain": "https://hhanclub.net/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "电视剧"
},
{
"id": "403",
"desc": "综艺"
},
{
"id": "407",
"desc": "体育"
},
{
"id": "412",
"desc": "短剧"
}
],
"music": [
{
"id": "410",
"desc": "音乐"
},
{
"id": "411",
"desc": "MV"
}
]
},
"torrents": {
"list": {
"selector": "div.torrent-table-sub-info"
},
"fields": {
"title_default": {
"selector": "div.torrent-title a.torrent-info-text-name"
},
"title_optional": {
"selector": "div.torrent-title a.torrent-info-text-name[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "div.torrent-title a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "div.torrent-manage a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "div.torrent-info-text-added"
},
"date_added": {
"selector": "div.torrent-info-text-added > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "div.torrent-info-text-size"
},
"seeders": {
"selector": "div.torrent-info-text-seeders"
},
"leechers": {
"selector": "div.torrent-info-text-leechers"
},
"grabs": {
"selector": "div.torrent-info-text-finished"
},
"downloadvolumefactor": {
"case": {
"span.promotion-tag-free": 0,
"span.promotion-tag-free2up": 0,
"span.promotion-tag-2xfree": 0,
"span.promotion-tag-50": 0.5,
"span.promotion-tag-50pctdown": 0.5,
"span.promotion-tag-50pctdown2up": 0.5,
"span.promotion-tag-30": 0.3,
"span.promotion-tag-30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"span.promotion-tag-free2up": 2,
"span.promotion-tag-50pctdown2up": 2,
"span.promotion-tag-2up": 2,
"span.promotion-tag-2xfree": 2,
"*": 1
}
},
"description": {
"selector": "div.torrent-info-text-small_name"
},
"category": {
"selector": "div.torrent-cat a",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"hr": {
"selector": "div.torrent-info-hr"
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "憨憨",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "电视剧",
"403": "综艺",
"404": "纪录片",
"405": "动漫",
"407": "体育",
"409": "其他",
"410": "音乐",
"411": "MV",
"412": "短剧"
},
"loginSuccess": "a[href='logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name']",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "img[alt='上传']::next_sibling_text",
"downloaded_css": "img[alt='下载']::next_sibling_text",
"ratio_css": "img[alt='分享率'] + div",
"bonus_css": "img[alt='憨豆'] + a div",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='做种数']::next_sibling_text",
"leeching_css": "img[alt='下载数']::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "div.font-bold.leading-6:contains('标题'):not(:contains('副标题')) + div.font-bold.leading-6",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "div.font-bold.leading-6:contains('标题'):not(:contains('副标题')) + div.font-bold.leading-6",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "div.font-bold.leading-6:contains('标题'):not(:contains('副标题')) + div.font-bold.leading-6",
"subtitle": "div.font-bold.leading-6:contains('副标题') + div.font-bold.leading-6",
"size": "span.font-bold:contains('大小') + span",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -1,16 +1,48 @@
import type { IndexerDefinition } from "../spider/schema";
import audiencesJson from "./audiences.json";
/**
* 站点定义加载与校验。
* - `*.json`:由 scripts/mp-sync/movieclaw-import.mjs 从 MovieClaw v0.27.0(MIT,见 NOTICE-MovieClaw.md)转换,
* 手工覆盖层在 scripts/mp-sync/movieclaw-overrides/;不要直接手改 JSON(重跑脚本会覆盖)。
* - 加载时一律经 zod schema(./schema.ts)校验,失败即抛错。
*/
import type { MteamDefinition } from "../mteam/definition.ts";
import type { IndexerDefinition } from "../spider/schema.ts";
import type { SpecializedSiteDefinition } from "../spiders/types.ts";
import { MOVIECLAW_DEFINITION_JSON } from "./manifest.generated.ts";
import { parseIndexerDefinition, parseMteamDefinition, parseSpecializedSiteDefinition } from "./schema.ts";
/** 站点定义最小校验(随产品发布的定义文件;加站只需新增 JSON 并在此登记)。 */
export function loadIndexerDefinition(json: unknown): IndexerDefinition {
const d = json as Partial<IndexerDefinition>;
if (!d || typeof d !== "object") throw new Error("站点定义必须是对象");
for (const k of ["id", "name", "domain"] as const) {
if (typeof d[k] !== "string" || !d[k]) throw new Error(`站点定义缺少 ${k}`);
}
if (!d.torrents?.list?.selector || !d.torrents.fields) throw new Error(`站点定义 ${d.id} 缺少 torrents.list/fields`);
if (!d.umt?.version || !d.umt.timezone || !d.umt.rateLimit) throw new Error(`站点定义 ${d.id} 缺少 umt 扩展`);
return d as IndexerDefinition;
export type SiteDefinition = IndexerDefinition | MteamDefinition | SpecializedSiteDefinition;
/** 按 `umt.kind` 分派校验 */
export function loadSiteDefinition(json: unknown): SiteDefinition {
const kind = (json as { umt?: { kind?: unknown } } | null)?.umt?.kind;
if (kind === "mteam") return parseMteamDefinition(json);
if (kind === "nexusphp") return parseIndexerDefinition(json);
if (kind === "api") return parseSpecializedSiteDefinition(json);
throw new Error(`站点定义 ${(json as { id?: unknown })?.id ?? "<unknown>"} 的 umt.kind 未知:${String(kind)}`);
}
export const audiencesDefinition: IndexerDefinition = loadIndexerDefinition(audiencesJson);
/** 兼容 W1-3b 导出名:NexusPHP 定义校验 */
export function loadIndexerDefinition(json: unknown): IndexerDefinition {
return parseIndexerDefinition(json);
}
/** 随产品发布的全部定义(已校验),键为站点 id */
export const BUILTIN_SITE_DEFINITIONS: Readonly<Record<string, SiteDefinition>> = Object.freeze(
Object.fromEntries(Object.entries(MOVIECLAW_DEFINITION_JSON).map(([id, json]) => [id, loadSiteDefinition(json)])),
);
export const audiencesDefinition = BUILTIN_SITE_DEFINITIONS.audiences as IndexerDefinition;
export const hhanclubDefinition = BUILTIN_SITE_DEFINITIONS.hhanclub as IndexerDefinition;
export const chdbitsDefinition = BUILTIN_SITE_DEFINITIONS.chdbits as IndexerDefinition;
export {
DefinitionProvenanceSchema,
IndexerDefinitionSchema,
MteamDefinitionSchema,
parseIndexerDefinition,
parseMteamDefinition,
parseSpecializedSiteDefinition,
SpecializedSiteDefinitionSchema,
SpiderFieldSelectorSchema,
SpiderFilterSchema,
} from "./schema.ts";
@@ -0,0 +1,261 @@
{
"id": "keepfrds",
"name": "朋友",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/keepfrds.yaml"
},
"domain": "https://pt.keepfrds.com/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
},
{
"id": "407",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
},
{
"id": "420",
"desc": "音乐"
},
{
"id": "421",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_nl": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_nl": 0,
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > br"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "朋友",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"300": "其他",
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "剧集",
"408": "音乐",
"409": "其他",
"414": "其他",
"415": "其他",
"419": "成人",
"420": "音乐",
"421": "音乐",
"422": "其他",
"423": "游戏",
"424": "其他",
"425": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "a[href*='userdetails.php?id=']::attr(class)",
"uploaded_css": "span.uploaded",
"downloaded_css": "span.downloaded",
"ratio_css": "td.rowhead:contains('分享率') + td::text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "td.rowhead:contains('当前做种') + td::text",
"leeching_css": "td.rowhead:contains('当前下载') + td::text"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,51 @@
// 由 scripts/mp-sync/movieclaw-import.mjs 生成,请勿手改(MovieClaw v0.27.0 c79bb1b0,MIT)
import agsvptJson from "./agsvpt.json" with { type: "json" };
import audiencesJson from "./audiences.json" with { type: "json" };
import chdbitsJson from "./chdbits.json" with { type: "json" };
import hdareaJson from "./hdarea.json" with { type: "json" };
import hddolbyJson from "./hddolby.json" with { type: "json" };
import hdfansJson from "./hdfans.json" with { type: "json" };
import hdhomeJson from "./hdhome.json" with { type: "json" };
import hdskyJson from "./hdsky.json" with { type: "json" };
import hdtimeJson from "./hdtime.json" with { type: "json" };
import hdvideoJson from "./hdvideo.json" with { type: "json" };
import hhanclubJson from "./hhanclub.json" with { type: "json" };
import keepfrdsJson from "./keepfrds.json" with { type: "json" };
import mteamJson from "./mteam.json" with { type: "json" };
import niceptJson from "./nicept.json" with { type: "json" };
import ourbitsJson from "./ourbits.json" with { type: "json" };
import piggoJson from "./piggo.json" with { type: "json" };
import pterJson from "./pter.json" with { type: "json" };
import pthomeJson from "./pthome.json" with { type: "json" };
import pttimeJson from "./pttime.json" with { type: "json" };
import soulvoiceJson from "./soulvoice.json" with { type: "json" };
import ssdJson from "./ssd.json" with { type: "json" };
import tjuptJson from "./tjupt.json" with { type: "json" };
import ttgJson from "./ttg.json" with { type: "json" };
/** MovieClaw 转换来的站点定义原始 JSON(未校验;经 loadSiteDefinition 校验后使用) */
export const MOVIECLAW_DEFINITION_JSON: Record<string, unknown> = {
agsvpt: agsvptJson,
audiences: audiencesJson,
chdbits: chdbitsJson,
hdarea: hdareaJson,
hddolby: hddolbyJson,
hdfans: hdfansJson,
hdhome: hdhomeJson,
hdsky: hdskyJson,
hdtime: hdtimeJson,
hdvideo: hdvideoJson,
hhanclub: hhanclubJson,
keepfrds: keepfrdsJson,
mteam: mteamJson,
nicept: niceptJson,
ourbits: ourbitsJson,
piggo: piggoJson,
pter: pterJson,
pthome: pthomeJson,
pttime: pttimeJson,
soulvoice: soulvoiceJson,
ssd: ssdJson,
tjupt: tjuptJson,
ttg: ttgJson,
};
@@ -0,0 +1,72 @@
{
"id": "mteam",
"name": "馒头",
"enabled": true,
"schema": "MTorrent",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/mteam.yaml",
"overrides": "scripts/mp-sync/movieclaw-overrides/mteam.json"
},
"domain": "https://tp.m-team.cc/",
"parser": "mTorrent",
"timeout": 15,
"umt": {
"version": "[email protected]",
"kind": "mteam",
"displayName": "馒头",
"apiBaseUrl": "https://api.m-team.cc",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 1000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "综艺",
"404": "纪录",
"405": "动画",
"406": "音乐",
"407": "体育",
"408": "音乐",
"409": "其他",
"410": "成人",
"411": "成人",
"412": "成人",
"413": "成人",
"419": "电影",
"420": "电影",
"421": "电影",
"422": "其他",
"423": "游戏",
"424": "成人",
"425": "成人",
"426": "成人",
"427": "其他",
"429": "成人",
"430": "成人",
"431": "成人",
"432": "成人",
"433": "成人",
"434": "音乐",
"435": "剧集",
"436": "成人",
"437": "成人",
"438": "剧集",
"439": "电影"
},
"authSupported": ["apikey"],
"customClass": "movieclaw_tracker.sites.custom.mteam.MTeamSite"
}
}
@@ -0,0 +1,215 @@
{
"id": "nicept",
"name": "NicePT",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/nicept.yaml"
},
"domain": "https://www.nicept.net/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [],
"tv": [],
"music": []
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded br"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"hr": {
"selector": "img.hitandrun"
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "NicePT",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "成人",
"402": "成人",
"403": "成人",
"404": "成人",
"500": "成人",
"501": "成人",
"503": "成人",
"504": "成人"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副標題') + td::text",
"size": "td.rowhead:contains('基本資訊') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,261 @@
{
"id": "ourbits",
"name": "OurBits",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/ourbits.yaml"
},
"domain": "https://ourbits.club/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
},
{
"id": "402",
"desc": "电影"
}
],
"tv": [
{
"id": "405",
"desc": "剧集"
},
{
"id": "412",
"desc": "剧集"
},
{
"id": "413",
"desc": "剧集"
},
{
"id": "415",
"desc": "剧集"
}
],
"music": [
{
"id": "416",
"desc": "音乐"
},
{
"id": "414",
"desc": "音乐"
},
{
"id": "419",
"desc": "音乐"
}
],
"param": "cat[]"
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > div"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"hr": {
"selector": "img.hitandrun"
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "OurBits",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "电影",
"405": "剧集",
"410": "纪录片",
"411": "动漫",
"412": "剧集",
"413": "剧集",
"414": "音乐",
"415": "剧集",
"416": "音乐",
"419": "音乐"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "a[href*='userdetails.php?id=']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "td.rowhead:contains('分享率') + td::text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding'] + *",
"leeching_css": "img[alt='Torrents leeching'] + *"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
},
"customClass": "movieclaw_tracker.sites.custom.ourbits.OurBitsSite"
}
}
@@ -0,0 +1,233 @@
{
"id": "piggo",
"name": "猪猪网 Piggo",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/piggo.yaml"
},
"domain": "https://piggo.me/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_50pctdown": 0.5,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"*": 1
}
},
"description": {
"selector": "td.embedded br"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "猪猪网 Piggo",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 8000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "其他",
"408": "音乐",
"409": "其他",
"912": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,233 @@
{
"id": "pter",
"name": "猫站",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/pter.yaml"
},
"domain": "https://pterclub.net/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "404",
"desc": "剧集"
},
{
"id": "405",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "418",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "猫站",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "纪录片",
"403": "动漫",
"404": "剧集",
"405": "剧集",
"406": "音乐",
"409": "游戏",
"418": "音乐"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "a[href*='userdetails.php?id=']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding'] + *",
"leeching_css": "img[alt='Torrents leeching'] + *"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,239 @@
{
"id": "pthome",
"name": "铂金家",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/pthome.yaml"
},
"domain": "https://pthome.net/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
},
{
"id": "407",
"desc": "剧集"
}
],
"music": [
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > span:not([class])"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "铂金家",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"407": "剧集",
"408": "音乐",
"409": "其他",
"410": "游戏",
"411": "其他",
"412": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "a[href*='userdetails.php?id=']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus::next_sibling_text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding'] + *",
"leeching_css": "img[alt='Torrents leeching'] + *"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,240 @@
{
"id": "pttime",
"name": "PTTime",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/pttime.yaml"
},
"domain": "https://www.pttime.org/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
}
],
"music": [
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(5)"
},
"date_added": {
"selector": "td:nth-child(5) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(6)"
},
"seeders": {
"selector": "td:nth-child(7)"
},
"leechers": {
"selector": "td:nth-child(8)"
},
"grabs": {
"selector": "td:nth-child(9)"
},
"downloadvolumefactor": {
"case": {
"font.promotion.free": 0,
"font.promotion.twoupfree": 0,
"font.promotion.halfdown": 0.5,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"font.promotion.twoupfree": 2,
"font.promotion.twoup": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded font[title]",
"attribute": "title"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "PTTime",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"100": "其他",
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "其他",
"406": "动漫",
"407": "其他",
"408": "音乐",
"409": "其他",
"411": "其他",
"412": "其他",
"420": "其他",
"421": "游戏",
"422": "其他",
"423": "其他",
"430": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "#info_block span.medium a[href*='userdetails.php']::attr(href)",
"username_css": "#info_block span.medium a[href*='userdetails.php'] b",
"class_css": "td.rowhead:contains('用户等级') + td b::text",
"uploaded_css": "#info_block font:contains('上传:')::next_sibling_text",
"downloaded_css": "#info_block font:contains('下载:')::next_sibling_text",
"ratio_css": "#info_block font:contains('分享率:')::next_sibling_text",
"bonus_css": "#info_block a[href='mybonus.php']::next_sibling_text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "#info_block font[title='当前做种']::next_sibling_text",
"leeching_css": "#info_block font[title='当前下载']::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,248 @@
/**
* 站点定义 zod schema(加载时校验)。
*
* 键名按 MoviePilot e6820a8 `app/application/site/sites.pyi` `SitesHelper.get_indexer(domain) -> dict` 与
* `app/modules/indexer/spider/__init__.py` `SiteSpider` / 专用 spider 读取的 indexer dict 键整理
* (id、name、domain、encoding、public、proxy、language、parser、result_num、timeout、media_type、search、batch、
* browse、category、torrents),MP 的真实定义在加密 user.sites.v3.bin 中不可读;
* `enabled` / `schema`(MP 用户信息解析器 SiteSchema)/ `provenance` / `umt` 为本项目扩展。
* TS 类型仍以 spider/schema.ts `IndexerDefinition`、mteam/definition.ts `MteamDefinition` 为准,
* 本文件保证 JSON 与之一致(见 schema.test.ts)。
*/
import { z } from "zod";
import type { MteamDefinition } from "../mteam/definition.ts";
import type { IndexerDefinition } from "../spider/schema.ts";
import type { SpecializedSiteDefinition } from "../spiders/types.ts";
import { SiteSchema } from "../user-parsers/types.ts";
const SITE_SCHEMA_VALUES = Object.values(SiteSchema) as [string, ...string[]];
export const DefinitionProvenanceSchema = z.strictObject({
source: z.enum(["movieclaw", "handwritten"]),
ref: z.string().optional(),
commit: z.string().optional(),
license: z.string().optional(),
file: z.string().optional(),
overrides: z.string().optional(),
note: z.string().optional(),
});
export const SpiderFilterSchema = z.discriminatedUnion("name", [
z.strictObject({ name: z.literal("re_search"), args: z.tuple([z.string(), z.number().int()]) }),
z.strictObject({ name: z.literal("split"), args: z.tuple([z.string(), z.number().int()]) }),
z.strictObject({ name: z.literal("replace"), args: z.tuple([z.string(), z.string()]) }),
z.strictObject({ name: z.literal("dateparse"), args: z.string() }),
z.strictObject({ name: z.literal("strip"), args: z.unknown().optional() }),
z.strictObject({ name: z.literal("appendleft"), args: z.string() }),
z.strictObject({ name: z.literal("querystring"), args: z.string() }),
]);
export const SpiderFieldSelectorSchema = z.strictObject({
selector: z.string().min(1).optional(),
selectors: z.string().min(1).optional(),
attribute: z.string().min(1).optional(),
index: z.number().int().optional(),
contents: z.number().int().optional(),
remove: z.string().optional(),
filters: z.array(SpiderFilterSchema).optional(),
text: z.string().optional(),
case: z.record(z.string(), z.number()).optional(),
});
const CategoryItemSchema = z.strictObject({
id: z.union([z.string(), z.number()]),
cat: z.string().optional(),
desc: z.string().optional(),
param: z.string().optional(),
value: z.union([z.string(), z.number()]).optional(),
params: z.record(z.string(), z.union([z.string(), z.number()])).optional(),
});
const CategoryConfigSchema = z.strictObject({
movie: z.array(CategoryItemSchema).optional(),
tv: z.array(CategoryItemSchema).optional(),
music: z.array(CategoryItemSchema).optional(),
field: z.string().optional(),
delimiter: z.string().optional(),
param: z.string().optional(),
});
const CapabilitiesSchema = z.strictObject({
list: z.boolean(),
search: z.boolean(),
detail: z.boolean(),
download: z.boolean(),
rss: z.boolean(),
});
const RateLimitSchema = z.strictObject({ minIntervalMs: z.number().int().min(0), burst: z.number().int().min(1) });
const TimezoneSchema = z.string().regex(/^[+-]\d{2}:\d{2}$/, "时区须为 ±HH:MM 偏移");
const PairSchema = z.tuple([z.string(), z.string()]);
const UmtNexusSchema = z.strictObject({
version: z.string().min(1),
kind: z.literal("nexusphp"),
displayName: z.string().optional(),
customClass: z.string().optional(),
hrSeedHours: z.number().positive().optional(),
authSupported: z.array(z.enum(["cookie", "credential", "apikey"])).optional(),
timezone: TimezoneSchema,
rateLimit: RateLimitSchema,
capabilities: CapabilitiesSchema,
categoryNames: z.record(z.string(), z.string()).optional(),
loginSuccess: z.string().optional(),
emptyMarkers: z.array(z.string()).optional(),
pagination: z.string().optional(),
login: z
.strictObject({
path: z.string(),
usernameField: z.string(),
passwordField: z.string(),
errorCss: z.string(),
extraFormData: z.array(PairSchema).optional(),
selectDefaults: z.array(PairSchema).optional(),
})
.optional(),
profile: z.record(z.string(), z.string()).optional(),
detail: z
.strictObject({
path: z.string(),
title: z.string(),
rowLabel: z.string(),
rowValue: z.string(),
labels: z.strictObject({
subtitle: z.array(z.string()),
basicInfo: z.array(z.string()),
peers: z.array(z.string()),
}),
description: z.string(),
headerScope: z.string(),
notFoundMarkers: z.array(z.string()),
fields: z
.strictObject({
title: z.string().optional(),
subtitle: z.string().optional(),
size: z.string().optional(),
description: z.string().optional(),
download: z.string().optional(),
imdb: z.string().optional(),
douban: z.string().optional(),
fileList: z.string().optional(),
})
.optional(),
})
.optional(),
downloadPath: z.string().min(1),
detailPath: z.string().min(1),
});
const BaseDefinitionShape = {
id: z.string().regex(/^[a-z0-9_]+$/, "id 只能是小写字母/数字/下划线"),
name: z.string().min(1),
enabled: z.boolean().optional(),
schema: z.enum(SITE_SCHEMA_VALUES).optional(),
provenance: DefinitionProvenanceSchema.optional(),
domain: z
.string()
.url()
.refine((s) => s.endsWith("/"), "domain 须以 / 结尾"),
timeout: z.number().positive().optional(),
proxy: z.boolean().optional(),
};
const FieldsSchema = z.record(z.string(), SpiderFieldSelectorSchema);
export const IndexerDefinitionSchema = z.strictObject({
...BaseDefinitionShape,
encoding: z.string().optional(),
public: z.boolean().optional(),
language: z.string().optional(),
parser: z.string().optional(),
result_num: z.number().int().positive().optional(),
media_type: z.string().optional(),
search: z
.strictObject({
paths: z.array(z.strictObject({ path: z.string(), type: z.enum(["all", "movie", "tv", "music"]).optional() })),
params: z.record(z.string(), z.union([z.string(), z.number()])).optional(),
imdbid_format: z.string().optional(),
result_media_type: z.literal("requested").optional(),
})
.optional(),
batch: z.strictObject({ delimiter: z.string().optional(), space_replace: z.string().optional() }).optional(),
browse: z
.strictObject({
path: z.string(),
start: z.number().int().optional(),
list: z.strictObject({ selector: z.string() }).optional(),
fields: FieldsSchema.optional(),
})
.optional(),
category: CategoryConfigSchema.optional(),
torrents: z.strictObject({
list: z.strictObject({ selector: z.string().min(1) }),
fields: FieldsSchema.refine((f) => Boolean(f.title || f.title_default), "torrents.fields 缺少 title"),
}),
umt: UmtNexusSchema,
});
export const MteamDefinitionSchema = z.strictObject({
...BaseDefinitionShape,
parser: z.literal("mTorrent"),
timeout: z.number().positive(),
umt: z.strictObject({
version: z.string().min(1),
kind: z.literal("mteam"),
displayName: z.string(),
apiBaseUrl: z.string().url().optional(),
timezone: TimezoneSchema,
rateLimit: RateLimitSchema,
capabilities: CapabilitiesSchema,
categoryNames: z.record(z.string(), z.string()),
authSupported: z.array(z.enum(["cookie", "credential", "apikey"])).optional(),
customClass: z.string().optional(),
}),
});
/** MP 专用 spider(`SPIDER_PARSER_CLASSES` 中除 mTorrent 外的 7 个)站点定义 */
export const SpecializedSiteDefinitionSchema = z.strictObject({
...BaseDefinitionShape,
parser: z.enum(["Haidan", "HDDolby", "RousiPro", "SunnyPT", "TNodeSpider", "TorrentLeech", "Yema"]),
public: z.boolean().optional(),
category: CategoryConfigSchema.optional(),
api_url: z.string().url().optional(),
umt: z.strictObject({
version: z.string().min(1),
kind: z.literal("api"),
displayName: z.string(),
timezone: TimezoneSchema,
rateLimit: RateLimitSchema,
capabilities: CapabilitiesSchema,
categoryNames: z.record(z.string(), z.string()).optional(),
apiBaseUrl: z.string().url().optional(),
}),
});
function formatIssues(id: unknown, e: z.ZodError): string {
const issues = e.issues.map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`).join("; ");
return `站点定义 ${typeof id === "string" ? id : "<unknown>"} 校验失败:${issues}`;
}
/** NexusPHP(通用 SiteSpider)定义校验 */
export function parseIndexerDefinition(json: unknown): IndexerDefinition {
const r = IndexerDefinitionSchema.safeParse(json);
if (!r.success) throw new Error(formatIssues((json as { id?: unknown })?.id, r.error));
return r.data as IndexerDefinition;
}
/** 馒头(M-Team API)定义校验 */
export function parseMteamDefinition(json: unknown): MteamDefinition {
const r = MteamDefinitionSchema.safeParse(json);
if (!r.success) throw new Error(formatIssues((json as { id?: unknown })?.id, r.error));
return r.data as MteamDefinition;
}
/** 专用 API spider 定义校验 */
export function parseSpecializedSiteDefinition(json: unknown): SpecializedSiteDefinition {
const r = SpecializedSiteDefinitionSchema.safeParse(json);
if (!r.success) throw new Error(formatIssues((json as { id?: unknown })?.id, r.error));
return r.data as SpecializedSiteDefinition;
}
@@ -0,0 +1,238 @@
{
"id": "soulvoice",
"name": "聆音",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/soulvoice.yaml"
},
"domain": "https://pt.soulvoice.club/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "401",
"desc": "电影"
},
{
"id": "424",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"desc": "剧集"
},
{
"id": "403",
"desc": "剧集"
}
],
"music": [
{
"id": "406",
"desc": "音乐"
},
{
"id": "408",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr, table.torrents > tbody > tr"
},
"fields": {
"title_default": {
"selector": "table.torrentname a b"
},
"title_optional": {
"selector": "table.torrentname a b[title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4)"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"*": 1
}
},
"description": {
"selector": "td.embedded br"
},
"category": {
"selector": "td:nth-child(1) a[href*='cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "聆音",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "剧集",
"404": "纪录片",
"405": "动漫",
"406": "音乐",
"407": "其他",
"408": "音乐",
"409": "其他",
"424": "电影",
"499": "其他",
"500": "其他"
},
"loginSuccess": "a[href*='logout']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[class*='_Name']::attr(href)",
"username_css": "a[class*='_Name'] b",
"class_css": "a[class*='_Name']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "font.color_bonus",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img.arrowup::next_sibling_text",
"leeching_css": "img.arrowdown::next_sibling_text"
},
"detail": {
"path": "details.php",
"title": "h1#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "h1#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "h1#top",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('基本信息') + td.rowfollow > b::next_sibling_text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,252 @@
{
"id": "ssd",
"name": "不可说",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/ssd.yaml"
},
"domain": "https://springsunday.net/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"category": {
"movie": [
{
"id": "501",
"desc": "电影"
}
],
"tv": [
{
"id": "502",
"desc": "剧集"
},
{
"id": "505",
"desc": "剧集"
},
{
"id": "506",
"desc": "剧集"
}
],
"music": [
{
"id": "507",
"desc": "音乐"
},
{
"id": "508",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td.rowfollow:nth-last-child(6)"
},
"date_added": {
"selector": "td.rowfollow:nth-last-child(6) > span[title]",
"attribute": "title"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td.rowfollow:nth-last-child(5)"
},
"seeders": {
"selector": "td.rowfollow:nth-last-child(4)"
},
"leechers": {
"selector": "td.rowfollow:nth-last-child(3)"
},
"grabs": {
"selector": "td.rowfollow:nth-last-child(2)"
},
"downloadvolumefactor": {
"case": {
"span.torrent-pro-free": 0,
"span.torrent-pro-free2up": 0,
"span.torrent-pro-50pctdown": 0.5,
"span.torrent-pro-50pctdown2up": 0.5,
"span.torrent-pro-30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"span.torrent-pro-free2up": 2,
"span.torrent-pro-50pctdown2up": 2,
"span.torrent-pro-2up": 2,
"*": 1
}
},
"description": {
"selector": "div.torrent-smalldescr > span:not([class])"
},
"category": {
"selector": "a[href^='?cat=']",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"freedate": {
"selector": "span.torrent-pro-free ~ span > span[title]",
"attribute": "title",
"filters": [
{
"name": "re_search",
"args": ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "不可说",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"501": "电影",
"502": "剧集",
"503": "纪录片",
"504": "动漫",
"505": "剧集",
"506": "剧集",
"507": "音乐",
"508": "音乐",
"509": "其他"
},
"loginSuccess": "a[href^='logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href^='userdetails.php?id=']::attr(href)",
"username_css": "a[href^='userdetails.php?id=']",
"class_css": "a[href^='userdetails.php?id=']::attr(class)",
"uploaded_css": "font.color_uploaded::next_sibling_text",
"downloaded_css": "font.color_downloaded::next_sibling_text",
"ratio_css": "font.color_ratio::next_sibling_text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "img[alt='Torrents seeding'] + *",
"leeching_css": "img[alt='Torrents leeching'] + *",
"vip_css": "a[class^='VIP']"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,198 @@
{
"id": "tjupt",
"name": "北洋园",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/tjupt.yaml"
},
"domain": "https://tjupt.org/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 1
},
"category": {
"movie": [],
"tv": [],
"music": []
},
"torrents": {
"list": {
"selector": "table.torrents > tr:not(:first-child)"
},
"fields": {
"title_default": {
"selector": ":scope > td:nth-child(2) a[href*='details.php']"
},
"title_optional": {
"selector": ":scope > td:nth-child(2) a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_added": {
"selector": ":scope > td:nth-child(4)"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": ":scope > td:nth-child(5)"
},
"seeders": {
"selector": ":scope > td:nth-child(6)"
},
"leechers": {
"selector": ":scope > td:nth-child(7)"
},
"grabs": {
"selector": ":scope > td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
"img.pro_free2up": 0,
"img.pro_50pctdown": 0.5,
"img.pro_50pctdown2up": 0.5,
"img.pro_30pctdown": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img.pro_free2up": 2,
"img.pro_50pctdown2up": 2,
"img.pro_2up": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > span"
},
"category": {
"selector": ":scope > td:nth-child(1) a",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "北洋园",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 5000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {},
"loginSuccess": "a[href*='logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"authSupported": ["cookie", "credential"],
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text",
"selectDefaults": [["logout", "7"]]
},
"profile": {
"path": "userdetails.php",
"uid_css": "a.User_Name::attr(href)",
"username_css": "a.User_Name b",
"class_css": "td.rowhead:contains('等级') + td img::attr(title)",
"uploaded_css": "td.rowhead:contains('上传量') + td::text",
"bonus_css": "td.rowhead:contains('魔力值') + td",
"join_date_css": "td.rowhead:contains('加入日期') + td::text"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
}
}
}
@@ -0,0 +1,340 @@
{
"id": "ttg",
"name": "听听歌",
"enabled": false,
"schema": "NexusPhp",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/ttg.yaml"
},
"domain": "https://totheglory.im/",
"encoding": "UTF-8",
"public": false,
"proxy": false,
"language": "zh",
"result_num": 100,
"timeout": 30,
"search": {
"paths": [
{
"path": "browse.php",
"type": "all"
}
],
"params": {
"search": "{keyword}"
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "browse.php?page={page}",
"start": 1
},
"category": {
"movie": [
{
"id": "电影DVDRip",
"desc": "电影"
},
{
"id": "电影720p",
"desc": "电影"
},
{
"id": "电影1080i/p",
"desc": "电影"
},
{
"id": "BluRay原盘",
"desc": "电影"
},
{
"id": "影视2160p",
"desc": "电影"
},
{
"id": "UHD原盘",
"desc": "电影"
},
{
"id": "iPhone/iPad视频",
"desc": "电影"
}
],
"tv": [
{
"id": "欧美剧720p",
"desc": "剧集"
},
{
"id": "欧美剧1080i/p",
"desc": "剧集"
},
{
"id": "高清日剧",
"desc": "剧集"
},
{
"id": "大陆港台剧720p",
"desc": "剧集"
},
{
"id": "高清韩剧",
"desc": "剧集"
},
{
"id": "大陆港台剧1080i/p",
"desc": "剧集"
},
{
"id": "欧美剧包",
"desc": "剧集"
},
{
"id": "日剧包",
"desc": "剧集"
},
{
"id": "华语剧包",
"desc": "剧集"
},
{
"id": "韩剧包",
"desc": "剧集"
},
{
"id": "高清体育节目",
"desc": "剧集"
},
{
"id": "韩国综艺",
"desc": "剧集"
},
{
"id": "日本综艺",
"desc": "剧集"
},
{
"id": "高清综艺",
"desc": "剧集"
}
],
"music": [
{
"id": "(电影原声&Game)OST",
"desc": "音乐"
},
{
"id": "无损音乐FLAC&APE",
"desc": "音乐"
},
{
"id": "MV&演唱会",
"desc": "音乐"
},
{
"id": "补充音轨",
"desc": "音乐"
}
]
},
"torrents": {
"list": {
"selector": "table#torrent_table > tr[id]"
},
"fields": {
"title_default": {
"selector": "a[href*='details.php']"
},
"title_optional": {
"selector": "a[href*='details.php'][title]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": {
"selector": "a[href*='details.php']",
"attribute": "href"
},
"download": {
"selector": "a[href*='download.php']",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_added": {
"selector": "td:nth-child(5)"
},
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"downloadvolumefactor": {
"case": {
"img[alt=\"free\"]": 0,
"img[alt=\"50%\"]": 0.5,
"img[alt=\"30%\"]": 0.3,
"*": 1
}
},
"uploadvolumefactor": {
"case": {
"img[alt=\"200%\"]": 2,
"*": 1
}
},
"description": {
"selector": "td.embedded > span"
},
"category": {
"selector": "td:nth-child(1) img",
"attribute": "class",
"filters": [
{
"name": "re_search",
"args": ["\\d+", 0]
}
]
},
"freedate": {
"selector": "span[onclick]",
"attribute": "onclick",
"filters": [
{
"name": "re_search",
"args": ["\\d+年\\d+月\\d+日\\d+点\\d+分", 0]
}
]
}
}
},
"umt": {
"version": "[email protected]",
"kind": "nexusphp",
"displayName": "听听歌",
"timezone": "+08:00",
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": false
},
"categoryNames": {
"电影DVDRip": "电影",
"电影720p": "电影",
"电影1080i/p": "电影",
"BluRay原盘": "电影",
"影视2160p": "电影",
"UHD原盘": "电影",
"iPhone/iPad视频": "电影",
"纪录片720p": "纪录片",
"纪录片1080i/p": "纪录片",
"纪录片BluRay原盘": "纪录片",
"欧美剧720p": "剧集",
"欧美剧1080i/p": "剧集",
"高清日剧": "剧集",
"大陆港台剧720p": "剧集",
"高清韩剧": "剧集",
"大陆港台剧1080i/p": "剧集",
"欧美剧包": "剧集",
"日剧包": "剧集",
"华语剧包": "剧集",
"韩剧包": "剧集",
"高清体育节目": "剧集",
"韩国综艺": "剧集",
"日本综艺": "剧集",
"高清综艺": "剧集",
"(电影原声&Game)OST": "音乐",
"无损音乐FLAC&APE": "音乐",
"MV&演唱会": "音乐",
"补充音轨": "音乐",
"高清动漫": "动漫",
"MiniVideo": "其他"
},
"loginSuccess": "a[href='/logout.php']",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"username_css": "h1::text",
"class_css": "td.rowhead:contains('等级') + td::text",
"uploaded_css": "td.rowhead:contains('上传量') + td::text",
"downloaded_css": "td.rowhead:contains('下载量') + td::text",
"ratio_css": "td.rowhead:contains('分享率') + td::text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "td.rowhead:contains('当前做种') + td::text",
"leeching_css": "td.rowhead:contains('当前下载') + td::text"
},
"detail": {
"path": "details.php",
"title": "#top",
"rowLabel": "td.rowhead",
"rowValue": "td.rowfollow",
"labels": {
"subtitle": ["副标题", "Small Description"],
"basicInfo": ["基本信息", "Basic Info"],
"peers": ["同伴", "Peers"]
},
"description": "#kdescr",
"headerScope": "#top",
"notFoundMarkers": ["没有该ID的种子", "No torrent with ID"],
"fields": {
"title": "#top::text",
"subtitle": "td.rowhead:contains('副标题') + td::text",
"size": "td.rowhead:contains('大小') + td::text",
"description": "#kdescr",
"download": "a[href*='download.php']::attr(href)",
"imdb": "a[href*='imdb.com']::attr(href)",
"douban": "a[href*='douban.com']::attr(href)",
"fileList": "td.rowfollow > ul > li::text"
}
},
"customClass": "movieclaw_tracker.sites.custom.ttg.TTGSite"
}
}