From 9cdf492291890b175463f057f8a94714779ae5a6 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 2 Oct 2026 20:59:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(sites):=20OurBits=20=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E9=A1=B5=E6=8C=89=20BBCode=20=E8=A7=A3=E6=9E=90=E7=AE=80?= =?UTF-8?q?=E4=BB=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OurBits 的简介在 div.ubbcode 里是未渲染的 BBCode(站点前端脚本渲染),按 HTML 取文本后 [quote] / [img] / [url] 原样留下、换行全被合并。extractDetailPage 遇到 ubbcode 容器且内容带 BBCode 标记时, 改用 pageFromBbcode 取简介 / 截图 / MediaInfo(换行保留),发布者、文件、标签与页面上的外部 ID 照旧。 覆盖层补 fileListPath(viewfilelist.php),与憨憨一样按需取文件列表。脱敏样例 OURBITS_DETAIL_PAGE + 测试。 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 3 +++ .../src/sites/definitions/definitions.test.ts | 14 ++++++++++ .../src/sites/definitions/ourbits.json | 3 +++ .../adapters/src/sites/spider/detail-page.ts | 18 +++++++++++++ .../sites/fixtures/definitions/sites-2026.ts | 26 +++++++++++++++++++ .../mp-sync/movieclaw-overrides/ourbits.json | 9 ++++++- 6 files changed, 72 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 799f656a..74017362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ## [Unreleased] +### 修复 +- OurBits 详情页:简介是页面里未渲染的 BBCode(站点靠前端脚本渲染),之前原样显示 `[quote]`、`[img]` 且换行全丢;改为按 BBCode 解析,保留换行、去掉标记,图片进截图,引用块里的 MediaInfo 单独取;文件列表按需取 `viewfilelist.php`。已缓存的详情在过期或手动刷新后生效。 + ### 新增 - 下载器可以单独设水位(硬阈值 / 恢复水位 / 清理目标)和保种天数,不填用全局;多个下载器共用一块缓存盘时取最严格的。公网 BT 专用的 qB 可设保种 0 天(站点 H&R 仍遵守)。 diff --git a/packages/adapters/src/sites/definitions/definitions.test.ts b/packages/adapters/src/sites/definitions/definitions.test.ts index 16fc0149..4ae53713 100644 --- a/packages/adapters/src/sites/definitions/definitions.test.ts +++ b/packages/adapters/src/sites/definitions/definitions.test.ts @@ -6,6 +6,7 @@ import { HHANCLUB_LIST_PAGE, HHANCLUB_LIST_PAGE_2026, HHANCLUB_LIST_PAGE_TAGS, + OURBITS_DETAIL_PAGE, OURBITS_LIST_PAGE, } from "@umt/testkit"; import { describe, expect, it } from "vitest"; @@ -234,6 +235,19 @@ describe("2026-10 真实列表页结构(脱敏样例)", () => { expect(a!.tags).toEqual(["官方", "中字"]); }); + it("OurBits 详情:ubbcode 里的 BBCode 简介保留换行、去掉标记,图片进截图,引用块里的 MediaInfo 单独取", () => { + const def = BUILTIN_SITE_DEFINITIONS.ourbits as IndexerDefinition; + const page = parseDetailPage(OURBITS_DETAIL_PAGE, def, "900001", OBSERVED).detail!.page!; + expect(page.descriptionText).toContain("官组作品,感谢原制作者发布。\n"); + expect(page.descriptionText).toContain("◎片  名 示例剧\n◎年  代 2025"); + expect(page.descriptionText).not.toMatch(/\[(img|url|quote|b|color)/); + expect(page.descriptionText).not.toContain("Complete name"); + expect(page.mediaInfo).toMatch(/^General\nComplete name/); + expect(page.screenshots).toEqual(["https://img.example.test/poster.jpg", "https://img.example.test/shot1.jpg"]); + expect(page.doubanId).toBe("36000001"); + expect(def.umt.detail?.page?.fileListPath).toBe("viewfilelist.php?id={id}"); + }); + it("IMDb ID 规范化:纯数字补 tt + 7 位,0 与非法值丢弃", () => { expect(imdbIdOf("299977")).toBe("tt0299977"); expect(imdbIdOf("35522483")).toBe("tt35522483"); diff --git a/packages/adapters/src/sites/definitions/ourbits.json b/packages/adapters/src/sites/definitions/ourbits.json index ad9d2c5e..445f113b 100644 --- a/packages/adapters/src/sites/definitions/ourbits.json +++ b/packages/adapters/src/sites/definitions/ourbits.json @@ -269,6 +269,9 @@ "imdb": "a[href*='imdb.com']::attr(href)", "douban": "a[href*='douban.com']::attr(href)", "fileList": "td.rowfollow > ul > li::text" + }, + "page": { + "fileListPath": "viewfilelist.php?id={id}" } }, "customClass": "movieclaw_tracker.sites.custom.ourbits.OurBitsSite" diff --git a/packages/adapters/src/sites/spider/detail-page.ts b/packages/adapters/src/sites/spider/detail-page.ts index 821c20ca..78aeaa73 100644 --- a/packages/adapters/src/sites/spider/detail-page.ts +++ b/packages/adapters/src/sites/spider/detail-page.ts @@ -11,6 +11,7 @@ import { looksLikeMediaInfo, MAX_FILES, MAX_SCREENSHOTS, + pageFromBbcode, screenshotUrl, tidyText, } from "../detail-text.ts"; @@ -284,5 +285,22 @@ export function extractDetailPage($: CheerioAPI, conf: DetailConf, base: string) } } } + + // 简介是未渲染的 BBCode 原文(OurBits:div.ubbcode,站点靠前端脚本渲染):按 BBCode 取简介 / 截图 / MediaInfo, + // 换行保留;发布者、文件、标签与 HTML 上的外部 ID 照旧 + const ubb = desc?.length ? (desc.is(".ubbcode") ? desc : desc.find(".ubbcode").first()) : null; + const raw = ubb?.length ? ubb.text() : ""; + if (/\[(?:img|url|quote|b|color|size|code)\b[^\]]*\]/i.test(raw)) { + const b = pageFromBbcode(raw, base, { mediaInfo: page.mediaInfo }); + page.descriptionText = b.descriptionText; + page.mediaInfo = b.mediaInfo; + if (b.screenshots.length) { + page.screenshots = b.screenshots; + page.probe.imageCount = b.probe.imageCount; + } + page.imdbId ??= b.imdbId; + page.doubanId ??= b.doubanId; + page.tmdb ??= b.tmdb; + } return page; } diff --git a/packages/testkit/src/sites/fixtures/definitions/sites-2026.ts b/packages/testkit/src/sites/fixtures/definitions/sites-2026.ts index 70a29369..e6cb3f5a 100644 --- a/packages/testkit/src/sites/fixtures/definitions/sites-2026.ts +++ b/packages/testkit/src/sites/fixtures/definitions/sites-2026.ts @@ -68,3 +68,29 @@ export const HHANCLUB_LIST_PAGE_TAGS = `HHCLUB <div class="torrent-manage"><a href="download.php?id=900201">下载</a></div> </div> </body></html>`; + +/** OurBits 详情页:简介是 div.ubbcode 里未渲染的 BBCode(站点靠前端脚本渲染),文件列表要另取 viewfilelist.php */ +export const OURBITS_DETAIL_PAGE = `<!DOCTYPE html><html><head><title>OurBits :: 种子详情 +退出 +

Sample Show 2025 S01 2160p WEB-DL H265 AAC-UBWEB

+ + + + + +
副标题示例剧 | 全40集
基本信息大小:185.04 GB
简介
[quote][b][color=blue]官组作品,感谢原制作者发布。[/color][/b][/quote] + +[img]https://img.example.test/poster.jpg[/img] +◎片  名 示例剧 +◎年  代 2025 +◎豆瓣链接 [url=https://movie.douban.com/subject/36000001/]https://movie.douban.com/subject/36000001/[/url] + +[quote]General +Complete name : Sample.Show.S01E01.2160p.WEB-DL.mp4 +Format : MPEG-4 +Video +Format : HEVC +Width : 3 840 pixels +Audio +Format : AAC[/quote] +[img]https://img.example.test/shot1.jpg[/img]
种子文件文件数:40个文件
`; diff --git a/scripts/mp-sync/movieclaw-overrides/ourbits.json b/scripts/mp-sync/movieclaw-overrides/ourbits.json index 190d97fe..d0fa97c0 100644 --- a/scripts/mp-sync/movieclaw-overrides/ourbits.json +++ b/scripts/mp-sync/movieclaw-overrides/ourbits.json @@ -1,5 +1,5 @@ { - "$comment": "2026-10-02 真实账号核对列表页 1 次(.local/site-samples/ourbits-torrents.html):标题列嵌套的 table.torrentname 有 5 个 td,MovieClaw 的 td:nth-child(n) 会先命中嵌套格子(大小 0、时间 N/A),改为只匹配行的直接子单元格;副标题在 td.embedded 里标签 div 之后,原定义取到的是标签;标签在 span.tag;列表页有 IMDb / 豆瓣 ID(label.imdb_rate / label.douban_rate 的 data 属性,IMDb 为纯数字,映射时补 tt + 7 位)。", + "$comment": "2026-10-02 真实账号核对列表页 1 次(.local/site-samples/ourbits-torrents.html):标题列嵌套的 table.torrentname 有 5 个 td,MovieClaw 的 td:nth-child(n) 会先命中嵌套格子(大小 0、时间 N/A),改为只匹配行的直接子单元格;副标题在 td.embedded 里标签 div 之后,原定义取到的是标签;标签在 span.tag;列表页有 IMDb / 豆瓣 ID(label.imdb_rate / label.douban_rate 的 data 属性,IMDb 为纯数字,映射时补 tt + 7 位)。 详情页(2026-10-02 核对 1 次):简介是 div.ubbcode 里未渲染的 BBCode,由详情解析按 BBCode 处理;文件列表按需取 viewfilelist.php。", "torrents": { "fields": { "date_elapsed": { @@ -49,5 +49,12 @@ ] } } + }, + "umt": { + "detail": { + "page": { + "fileListPath": "viewfilelist.php?id={id}" + } + } } }