mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-09 23:30:13 +08:00
Run `ruff check app tests scripts --fix` with the configured rule set (E4/E7/E9/F/I): import sorting (I001), f-strings without placeholders (F541), lambda/variable/unused-import cleanups that ruff marks safe. Nine files whose only ruff debt sits next to pre-existing pylint import-resolution errors (lazy exports, sys.path script imports) or whose "unused" imports are reached through attribute access by tests are left untouched so the changed-file pylint gate and the benchmark tests stay green; their diagnostics remain in the baseline. app/startup/lifecycle/__init__.py and app/main.py import business modules after cache composition, import-path and stdio setup on purpose (the source comments document the contract), so declare E402 per-file-ignores for them instead of adding per-line noqa. Ruff ratchet watermark drops from 498 to 100; sync the baseline fixture and the optimization checklist figure. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
121 lines
4.4 KiB
Python
121 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
import json
|
||
import re
|
||
from typing import Optional
|
||
|
||
from app.foundation import temporal as time_tools
|
||
from app.modules.indexer.parser import SiteParserBase, SiteSchema
|
||
from app.runtime.log import logger
|
||
|
||
|
||
class TNodeSiteUserInfo(SiteParserBase):
|
||
"""通过当前会话 API 获取 TNode 站点用户资料与做种信息。"""
|
||
|
||
schema = SiteSchema.TNode
|
||
|
||
def _parse_site_page(self, html_text: str):
|
||
"""提取 CSRF 令牌,并配置用于取得用户 ID 的当前会话接口。"""
|
||
html_text = self._prepare_html_text(html_text)
|
||
|
||
# <meta name="x-csrf-token" content="fd169876a7b4846f3a7a16fcd5cccf8d">
|
||
csrf_token = re.search(r'<meta name="x-csrf-token" content="(.+?)">', html_text)
|
||
if csrf_token:
|
||
self._addition_headers = {'X-CSRF-TOKEN': csrf_token.group(1)}
|
||
# 当前用户接口依赖 Cookie 会话,不需要预先知道用户 ID。
|
||
self._user_detail_page = "api/user/getMainInfo"
|
||
self._user_detail_requires_userid = False
|
||
self._torrent_seeding_page = "api/user/listTorrentActivity?id=&type=seeding&page=1&size=20000"
|
||
|
||
def _parse_logged_in(self, html_text):
|
||
"""
|
||
判断是否登录成功, 通过判断是否存在用户信息
|
||
暂时跳过检测,待后续优化
|
||
:param html_text:
|
||
:return:
|
||
"""
|
||
return True
|
||
|
||
def _parse_user_base_info(self, html_text: str):
|
||
"""首页不提供用户 ID,身份信息需在详情接口返回后补齐。"""
|
||
self.username = self.userid
|
||
|
||
def _parse_user_traffic_info(self, html_text: str):
|
||
"""流量信息已由当前用户接口返回,无需单独解析。"""
|
||
pass
|
||
|
||
def _parse_user_detail_info(self, html_text: str):
|
||
"""从当前用户接口一次解析身份、资料、流量及未读消息数量。"""
|
||
try:
|
||
detail = json.loads(html_text)
|
||
except json.JSONDecodeError:
|
||
return
|
||
if detail.get("status") != 200:
|
||
return
|
||
|
||
user_info = detail.get("data", {})
|
||
self.userid = user_info.get("id")
|
||
self.username = user_info.get("username")
|
||
self.user_level = user_info.get("class", {}).get("name")
|
||
self.join_at = user_info.get("regTime", 0)
|
||
self.join_at = time_tools.normalize_datetime(str(self.join_at))
|
||
|
||
self.upload = user_info.get("upload")
|
||
self.download = user_info.get("download")
|
||
self.ratio = 0 if self.download <= 0 else round(self.upload / self.download, 3)
|
||
self.bonus = user_info.get("bonus")
|
||
|
||
self.message_unread = user_info.get("unreadAdmin", 0) + user_info.get("unreadInbox", 0) + user_info.get(
|
||
"unreadSystem", 0)
|
||
pass
|
||
|
||
def _parse_user_torrent_seeding_info(self, html_text: str, multi_page: Optional[bool] = False) -> Optional[str]:
|
||
"""
|
||
解析用户做种信息
|
||
"""
|
||
try:
|
||
seeding_info = json.loads(html_text)
|
||
except json.JSONDecodeError as e:
|
||
logger.warning(f"{self._site_name}: Failed to decode seeding info JSON: {e}")
|
||
return None
|
||
|
||
if not isinstance(seeding_info, dict):
|
||
logger.warning(f"{self._site_name}: Seeding info payload is not a dictionary")
|
||
return None
|
||
|
||
if seeding_info.get("status") != 200:
|
||
return None
|
||
|
||
torrents = seeding_info.get("data", {}).get("torrents", [])
|
||
|
||
page_seeding_size = 0
|
||
page_seeding_info = []
|
||
for torrent in torrents:
|
||
size = torrent.get("size", 0)
|
||
seeders = torrent.get("seeding", 0)
|
||
|
||
page_seeding_size += size
|
||
page_seeding_info.append([seeders, size])
|
||
|
||
self.seeding += len(torrents)
|
||
self.seeding_size += page_seeding_size
|
||
self.seeding_info.extend(page_seeding_info)
|
||
|
||
# 是否存在下页数据
|
||
next_page = None
|
||
|
||
return next_page
|
||
|
||
def _parse_message_unread_links(self, html_text: str, msg_links: list) -> Optional[str]:
|
||
"""当前仅支持 API 返回的未读数量,不解析消息链接。"""
|
||
return None
|
||
|
||
def _parse_message_content(self, html_text):
|
||
"""
|
||
系统信息 api/message/listSystem?page=1&size=20
|
||
收件箱信息 api/message/listInbox?page=1&size=20
|
||
管理员信息 api/message/listAdmin?page=1&size=20
|
||
:param html_text:
|
||
:return:
|
||
"""
|
||
return None, None, None
|