From e1d1de1ee731ab1a2c7d4a962da1f32a88cd3814 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Fri, 2 Oct 2026 17:00:41 +0800 Subject: [PATCH] fix(parser): keep Unit3D username as user id --- app/modules/indexer/parser/unit3d.py | 10 +++++++- tests/test_unit3d_parser.py | 36 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/test_unit3d_parser.py diff --git a/app/modules/indexer/parser/unit3d.py b/app/modules/indexer/parser/unit3d.py index af7b2cef5..db1b4ed10 100644 --- a/app/modules/indexer/parser/unit3d.py +++ b/app/modules/indexer/parser/unit3d.py @@ -4,17 +4,20 @@ from typing import Optional from lxml import etree -from app.modules.indexer.parser import SiteParserBase, SiteSchema from app.foundation import size as size_tools from app.foundation import temporal as time_tools from app.foundation import text as text_tools from app.foundation.dom import DomUtils +from app.modules.indexer.parser import SiteParserBase, SiteSchema class Unit3dSiteUserInfo(SiteParserBase): + """Unit3D 架构站点的用户信息解析器。""" + schema = SiteSchema.Unit3d def _parse_user_base_info(self, html_text: str): + """解析用户名并将 Unit3D 的用户名作为用户标识供后续请求使用。""" html_text = self._prepare_html_text(html_text) html = etree.HTML(html_text) try: @@ -23,6 +26,7 @@ class Unit3dSiteUserInfo(SiteParserBase): user_name_match = re.search(r"/users/(.+)/settings", tmps[0]) if user_name_match and user_name_match.group().strip(): self.username = user_name_match.group(1) + self.userid = self.username self._torrent_seeding_page = f"/users/{self.username}/active?perPage=100&client=&seeding=include" self._user_detail_page = f"/users/{self.username}" @@ -37,6 +41,7 @@ class Unit3dSiteUserInfo(SiteParserBase): del html def _parse_site_page(self, html_text: str): + """Unit3D 不需要从站点首页解析额外的站点级数据。""" pass def _parse_user_detail_info(self, html_text: str): @@ -120,6 +125,7 @@ class Unit3dSiteUserInfo(SiteParserBase): return next_page def _parse_user_traffic_info(self, html_text: str): + """解析用户上传量、下载量和分享率。""" html_text = self._prepare_html_text(html_text) upload_match = re.search(r"[^总]上[传傳]量?[::_<>/a-zA-Z-=\"'\s#;]+([\d,.\s]+[KMGTPI]*B)", html_text, re.IGNORECASE) @@ -132,7 +138,9 @@ class Unit3dSiteUserInfo(SiteParserBase): ratio_match and ratio_match.group(1).strip()) else 0.0 def _parse_message_unread_links(self, html_text: str, msg_links: list) -> Optional[str]: + """Unit3D 没有兼容的未读消息列表解析。""" return None def _parse_message_content(self, html_text): + """Unit3D 没有兼容的未读消息正文解析。""" return None, None, None diff --git a/tests/test_unit3d_parser.py b/tests/test_unit3d_parser.py new file mode 100644 index 000000000..4a6382d27 --- /dev/null +++ b/tests/test_unit3d_parser.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from app.modules.indexer.parser.unit3d import Unit3dSiteUserInfo + +USER_BASE_HTML = """ + + + 设置 + 积分 1,234.5 + + +""" + + +def _build_parser() -> Unit3dSiteUserInfo: + """构造一个用于测试的 Unit3D 解析器。""" + return Unit3dSiteUserInfo( + site_name="莫妮卡", + url="https://udm.example/", + site_cookie="test-cookie", + apikey=None, + token=None, + ) + + +def test_unit3d_user_name_is_used_as_valid_userid() -> None: + """解析用户设置链接后,应允许详情页和做种页继续请求。""" + parser = _build_parser() + + parser._parse_user_base_info(USER_BASE_HTML) + + assert parser.username == "monica" + assert parser.userid == "monica" + assert parser._has_valid_userid() + assert parser._user_detail_page == "/users/monica" + assert parser._torrent_seeding_page.startswith("/users/monica/active?") + assert parser.bonus == 1234.5