fix(indexer): paginate M-Team seeding statistics

This commit is contained in:
jxxghp
2026-09-23 15:45:52 +08:00
parent 4f72b77ef0
commit 1422f41c6c
3 changed files with 99 additions and 26 deletions

View File

@@ -1,14 +1,15 @@
# -*- coding: utf-8 -*-
import json
from typing import Optional, Tuple
from typing import Any, Optional, Tuple, cast
from urllib.parse import urljoin
from app.runtime.log import logger
from app.modules.indexer.parser import SiteParserBase, SiteSchema
from app.domain import site as site_rules
class MTorrentSiteUserInfo(SiteParserBase):
"""使用 M-Team API 解析用户信息和当前做种数据。"""
schema = SiteSchema.MTorrent
request_mode = "apikey"
@@ -113,7 +114,7 @@ class MTorrentSiteUserInfo(SiteParserBase):
def _parse_user_torrent_seeding_info(self, html_text: str, multi_page: Optional[bool] = False) -> Optional[str]:
"""
解析用户做种信息
累加当前页的做种数和体积,并根据列表分页元数据继续读取。
"""
if not html_text:
return None
@@ -144,24 +145,30 @@ class MTorrentSiteUserInfo(SiteParserBase):
self.seeding_size += page_seeding_size
self.seeding_info.extend(page_seeding_info)
# 查询总做种数
seeder_count = 0
# 用户信息解析成功后已初始化分页参数,后续页数从做种列表响应中读取。
torrent_params = cast(dict[str, Any], self._torrent_seeding_params)
page_number = int(torrent_params["pageNumber"])
page_size = int(torrent_params["pageSize"])
try:
result = self._get_page_content(
url=urljoin(self._base_url, "api/tracker/myPeerStatus"),
params={"uid": self.userid},
)
if result:
seeder_info = json.loads(result)
seeder_count = int(seeder_info.get("data", {}).get("seeder") or 0)
except Exception as e:
logger.error(f"获取做种数失败: {str(e)}")
if not seeder_count:
total_pages = int(seeding_data.get("totalPages") or 0)
except (TypeError, ValueError):
total_pages = 0
try:
total_torrents = int(seeding_data.get("total") or 0)
except (TypeError, ValueError):
total_torrents = 0
if total_pages:
has_next_page = page_number < total_pages
elif total_torrents:
has_next_page = page_number * page_size < total_torrents
else:
# 旧版响应未提供总量时,满页后再请求一次确认是否结束。
has_next_page = len(torrents) >= page_size
if not has_next_page:
return None
if self.seeding >= seeder_count:
return None
# 还有下一页
self._torrent_seeding_params["pageNumber"] += 1
torrent_params["pageNumber"] = page_number + 1
return ""
def _parse_message_unread_links(self, html_text: str, msg_links: list) -> Optional[str]:

View File

@@ -1702,7 +1702,6 @@
"app/modules/indexer/parser/mtorrent.py": {
"assignment": 11,
"empty-body": 1,
"index": 2,
"no-untyped-def": 6,
"type-arg": 1
},

View File

@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
import json
import pytest
from app.modules.indexer.parser.mtorrent import MTorrentSiteUserInfo
@@ -17,7 +19,7 @@ def _build_parser() -> MTorrentSiteUserInfo:
)
def test_mtorrent_seeding_skips_invalid_torrent_items(monkeypatch):
def test_mtorrent_seeding_skips_invalid_torrent_items():
"""
MTorrent 返回空种子对象时应跳过异常条目并只统计有效做种。
"""
@@ -30,11 +32,6 @@ def test_mtorrent_seeding_skips_invalid_torrent_items(monkeypatch):
"userid": parser.userid,
}
monkeypatch.setattr(
parser,
"_get_page_content",
lambda **_: json.dumps({"data": {"seeder": 1}}),
)
html_text = json.dumps(
{
"code": "0",
@@ -55,3 +52,73 @@ def test_mtorrent_seeding_skips_invalid_torrent_items(monkeypatch):
assert parser.seeding == 1
assert parser.seeding_size == 1024
assert parser.seeding_info == [[3, 1024]]
def test_mtorrent_seeding_paginates_from_list_metadata(monkeypatch):
"""应按做种列表的分页元数据读取全部种子,不依赖 tracker 私有接口。"""
parser = _build_parser()
parser.userid = "1"
parser._torrent_seeding_params = {
"pageNumber": 1,
"pageSize": 2,
"type": "SEEDING",
"userid": parser.userid,
}
monkeypatch.setattr(
parser,
"_get_page_content",
lambda **_: pytest.fail("解析做种列表时不应请求 tracker 私有接口"),
)
first_page = json.dumps(
{
"code": "0",
"data": {
"total": 3,
"totalPages": 2,
"data": [
{"torrent": {"size": "1024", "source": "3"}},
{"torrent": {"size": "2048", "source": "4"}},
],
},
}
)
second_page = json.dumps(
{
"code": "0",
"data": {
"total": 3,
"totalPages": 2,
"data": [{"torrent": {"size": "4096", "source": "5"}}],
},
}
)
assert parser._parse_user_torrent_seeding_info(first_page) == ""
assert parser._torrent_seeding_params["pageNumber"] == 2
assert parser._parse_user_torrent_seeding_info(second_page) is None
assert parser.seeding == 3
assert parser.seeding_size == 7168
assert parser.seeding_info == [[3, 1024], [4, 2048], [5, 4096]]
def test_mtorrent_seeding_uses_page_size_when_totals_are_missing():
"""接口未返回总页数时,满页后继续读取并在空页结束。"""
parser = _build_parser()
parser._torrent_seeding_params = {"pageNumber": 1, "pageSize": 2}
full_page = json.dumps(
{
"code": "0",
"data": {
"data": [
{"torrent": {"size": "1024", "source": "3"}},
{"torrent": {"size": "2048", "source": "4"}},
]
},
}
)
empty_page = json.dumps({"code": "0", "data": {"data": []}})
assert parser._parse_user_torrent_seeding_info(full_page) == ""
assert parser._torrent_seeding_params["pageNumber"] == 2
assert parser._parse_user_torrent_seeding_info(empty_page) is None