mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-06 15:22:05 +08:00
fix(indexer): paginate M-Team seeding statistics
This commit is contained in:
@@ -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]:
|
||||
|
||||
@@ -1702,7 +1702,6 @@
|
||||
"app/modules/indexer/parser/mtorrent.py": {
|
||||
"assignment": 11,
|
||||
"empty-body": 1,
|
||||
"index": 2,
|
||||
"no-untyped-def": 6,
|
||||
"type-arg": 1
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user