完成 Ruff 全量清理

This commit is contained in:
yml2213
2026-08-31 10:55:44 +08:00
parent 840af3108e
commit 09ab80e062
68 changed files with 323 additions and 291 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ class CookieEnricher:
self.generate_acf_ccn_cookie()
logger.info("补CK完成")
return
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
last_error = e
logger.warning(f"补CK失败 {attempt}/{max_attempts}: {e}")
if attempt < max_attempts:
+17 -13
View File
@@ -5,7 +5,7 @@ import os
import re
import threading
import time
from datetime import datetime, timedelta
from datetime import UTC, datetime, timedelta
import requests
from loguru import logger
@@ -68,8 +68,8 @@ class EmailVerifier:
f"{self.roundcube_url}?_task=logout",
timeout=5,
)
except Exception:
pass
except Exception as exc: # noqa: BLE001
logger.debug(f"Roundcube logout failed: {exc}")
self._rc_session = None
self._rc_logged_in = False
@@ -176,7 +176,7 @@ class EmailVerifier:
logger.debug(f"Roundcube: {password_name}登录成功 ({self.username})")
return True, False
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.warning(f"Roundcube: 登录异常: {e}")
return False, False
@@ -230,7 +230,7 @@ class EmailVerifier:
return messages
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.warning(f"Roundcube: 获取邮件列表失败: {e}")
return []
@@ -252,7 +252,7 @@ class EmailVerifier:
)
return resp.text
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.warning(f"Roundcube: 读取邮件 {uid} 失败: {e}")
return None
@@ -270,7 +270,7 @@ class EmailVerifier:
- "2026-06-20" → 直接解析
- "06-20" → 今年的该日期
"""
now = datetime.now()
now = datetime.now(UTC)
# 今天
if date_str.startswith("今天"):
@@ -322,32 +322,36 @@ class EmailVerifier:
# 日期格式 2026-06-20
try:
return datetime.strptime(date_str.strip(), "%Y-%m-%d")
return datetime.strptime(date_str.strip(), "%Y-%m-%d").replace(tzinfo=UTC)
except ValueError:
pass
# 日期格式 2026-06-20 14:30
try:
return datetime.strptime(date_str.strip(), "%Y-%m-%d %H:%M")
return datetime.strptime(date_str.strip(), "%Y-%m-%d %H:%M").replace(
tzinfo=UTC
)
except ValueError:
pass
# 日期格式 2026-06-20 14:30:00
try:
return datetime.strptime(date_str.strip(), "%Y-%m-%d %H:%M:%S")
return datetime.strptime(date_str.strip(), "%Y-%m-%d %H:%M:%S").replace(
tzinfo=UTC
)
except ValueError:
pass
# 日期格式 06-20
try:
dt = datetime.strptime(date_str.strip(), "%m-%d")
dt = datetime.strptime(date_str.strip(), "%m-%d").replace(tzinfo=UTC)
return dt.replace(year=now.year)
except ValueError:
pass
# 日期格式 06-20 14:30
try:
dt = datetime.strptime(date_str.strip(), "%m-%d %H:%M")
dt = datetime.strptime(date_str.strip(), "%m-%d %H:%M").replace(tzinfo=UTC)
return dt.replace(year=now.year)
except ValueError:
pass
@@ -395,7 +399,7 @@ class EmailVerifier:
return code
except EmailLoginError:
raise
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
last_error = str(e)
logger.warning(f"Roundcube 读邮件异常: {e}")
+4 -4
View File
@@ -398,7 +398,7 @@ class DouyuLogin:
return LoginResult(
success=False, message=str(e), code="email_login_failed"
)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
elapsed = time.monotonic() - start_time
if self.max_login_retries > 0:
logger.error(
@@ -475,7 +475,7 @@ class DouyuLogin:
return LoginResult(
success=False, message=str(e), code="email_login_failed"
)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
elapsed = time.monotonic() - start_time
if self.max_login_retries > 0:
logger.error(
@@ -901,7 +901,7 @@ class DouyuLogin:
if response2.status_code == 200:
logger.info("WebLogin成功")
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.warning(f"WebLogin请求失败(不影响登录): {e}")
# 登录成功后补齐 Web 侧 Cookie。补 CK 失败只影响完整度,不回滚已成功的登录态。
@@ -915,7 +915,7 @@ class DouyuLogin:
).enrich_with_retry()
except InterruptedError:
raise
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self._cookie_enrich_error = self._truncate_error(str(e), 160)
logger.warning(
f"补CK最终失败,本次仍按登录成功保存基础CK: {self._cookie_enrich_error}"
+5 -3
View File
@@ -137,7 +137,7 @@ class BaseWhitelistAdapter(ABC):
return False, f"白名单添加失败,API响应: {resp}"
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
msg = f"白名单同步失败: {e}"
logger.error(msg)
return False, msg
@@ -165,7 +165,8 @@ def _get_local_exit_ip() -> str | None:
match = re.search(r"(\d{1,3}(?:\.\d{1,3}){3})", text)
if match:
return match.group(1)
except Exception:
except Exception as exc: # noqa: BLE001
logger.debug(f"本机出口 IP 查询失败: {url}: {exc}")
continue
return None
@@ -197,6 +198,7 @@ def get_exit_ip_via_proxy(proxy: str) -> str | None:
match = re.search(r"(\d{1,3}(?:\.\d{1,3}){3})", text)
if match:
return match.group(1)
except Exception:
except Exception as exc: # noqa: BLE001
logger.debug(f"代理出口 IP 查询失败: {url}: {exc}")
continue
return None
+4 -4
View File
@@ -75,7 +75,7 @@ class XiequAdapter(BaseWhitelistAdapter):
if r.get("IP") or r.get("ip")
]
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.error(f"获取白名单失败: {e}")
return []
@@ -120,7 +120,7 @@ class XiequAdapter(BaseWhitelistAdapter):
logger.warning(f"白名单添加结果: {text}")
return False, text
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.error(f"添加白名单失败: {e}")
return False, str(e)
@@ -141,7 +141,7 @@ class XiequAdapter(BaseWhitelistAdapter):
logger.warning(f"白名单删除结果: {text}")
return False, text
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.error(f"删除白名单失败: {e}")
return False, str(e)
@@ -160,7 +160,7 @@ class XiequAdapter(BaseWhitelistAdapter):
logger.info(msg)
return True, msg
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
msg = f"连接失败: {e}"
logger.error(msg)
return False, msg
+3 -3
View File
@@ -115,7 +115,7 @@ class XkdailiAdapter(BaseWhitelistAdapter):
logger.warning(f"星空白名单添加失败: {msg}")
return ok, msg
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.error(f"星空添加白名单失败: {e}")
return False, str(e)
@@ -136,7 +136,7 @@ class XkdailiAdapter(BaseWhitelistAdapter):
logger.warning(f"星空白名单删除失败: {msg}")
return ok, msg
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
logger.error(f"星空删除白名单失败: {e}")
return False, str(e)
@@ -159,5 +159,5 @@ class XkdailiAdapter(BaseWhitelistAdapter):
# 其他错误(如无效IP),说明认证通过了
return True, f"连接成功,API可访问: {msg}"
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
return False, f"连接失败: {e}"
+1 -1
View File
@@ -167,7 +167,7 @@ class ProxyResolver:
f"代理预检 {attempt}/{max_attempts}: {last_error}: {text[:80]}",
)
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
last_error = f"代理API请求失败: {exc}"
self._log("warning", f"代理预检 {attempt}/{max_attempts}: {last_error}")
+5 -3
View File
@@ -27,7 +27,7 @@ def verify_proxy_url(proxy_url: str, timeout: tuple = (3, 5)) -> tuple[bool, str
)
response.raise_for_status()
return True, "代理可用 → 斗鱼可达"
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
err_msg = str(exc)
if "Tunnel connection failed" in err_msg or "503" in err_msg:
detail = "代理拒绝连接(白名单可能未生效)"
@@ -75,7 +75,8 @@ def verify_proxies_concurrent(
ok, _ = future.result()
if ok:
available.append(future_map[future])
except Exception:
except Exception as exc: # noqa: BLE001
logger.debug(f"代理并发验证失败: {future_map[future]}: {exc}")
continue
if available:
logger.success(
@@ -99,7 +100,8 @@ def verify_proxies_concurrent(
if item != future:
item.cancel()
return proxy_url, msg
except Exception:
except Exception as exc: # noqa: BLE001
logger.debug(f"代理并发验证失败: {proxy_url}: {exc}")
continue
return None, f"{len(proxy_urls)} 个代理均不可用"
-1
View File
@@ -1,6 +1,5 @@
"""代理模块使用的白名单适配器。"""
from .proxy_platforms import create_adapter
from .proxy_platforms.base import BaseWhitelistAdapter, _get_local_exit_ip
+7 -7
View File
@@ -73,7 +73,7 @@ def get_challenge_gt_bak() -> tuple[str, str]:
}
params = {
"t": str(int(round(time.time() * 1000))),
"t": str(round(time.time() * 1000)),
}
response = requests.get(
@@ -133,7 +133,7 @@ def get_js_address(gt: str, proxies: Mapping[str, str] | None = None) -> dict:
params = {
"gt": gt,
"callback": "geetest_" + str(int(round(time.time() * 1000))),
"callback": "geetest_" + str(round(time.time() * 1000)),
}
response = _get(
@@ -173,7 +173,7 @@ def get_c_s(
+ "&lang=zh-cn&pt=0&client_type=web&w="
+ w
+ "&callback=geetest_"
+ str(int(round(time.time() * 1000))),
+ str(round(time.time() * 1000)),
headers=headers,
proxies=proxies,
)
@@ -210,7 +210,7 @@ def req_fullpage_validate(
+ "&lang=zh-cn&pt=0&client_type=web&w="
+ w
+ "&callback=geetest_"
+ str(int(round(time.time() * 1000))),
+ str(round(time.time() * 1000)),
headers=headers,
proxies=proxies,
)
@@ -241,7 +241,7 @@ def req_slide(gt: str, challenge: str, w2: str) -> None:
+ "&lang=zh-cn&pt=0&client_type=web&w="
+ w2
+ "&callback=geetest_"
+ str(int(round(time.time() * 1000))),
+ str(round(time.time() * 1000)),
headers=headers,
timeout=REQUEST_TIMEOUT,
)
@@ -277,7 +277,7 @@ def get_picture(gt: str, challenge: str) -> tuple[str, str, list[int], str, str,
"isPC": "true",
"autoReset": "true",
"width": "100%",
"callback": "geetest_" + str(int(round(time.time() * 1000))),
"callback": "geetest_" + str(round(time.time() * 1000)),
}
response = requests.get(
@@ -343,7 +343,7 @@ def req_end(gt: str, challenge: str, w: str) -> dict:
+ "&lang=zh-cn&%24_BCm=0&client_type=web&w="
+ w
+ "&callback=geetest_"
+ str(int(round(time.time() * 1000))),
+ str(round(time.time() * 1000)),
headers=headers,
timeout=REQUEST_TIMEOUT,
)
+1 -1
View File
@@ -592,7 +592,7 @@ def H(t: int, e: str) -> str:
n = 36 * r[0] + r[1]
# 计算目标值
a = round(t) + n
a = (t) + n
# 构建字符池
_ = [[], [], [], [], []]
+2 -2
View File
@@ -85,7 +85,7 @@ def get_w2(gt: str, challenge: str, c: list[int], s: str, str_16: str) -> str:
"u": fake_timing["loadEventEnd"],
}
first_time = int(round(time.time() * 1000)) # 伪造脚本开始运行时间
first_time = round(time.time() * 1000) # 伪造脚本开始运行时间
guiji_yuanshu_shuzu = generate_realistic_trajectory(
start_x=random.randint(400, 600), # 起始位置随机
@@ -99,7 +99,7 @@ def get_w2(gt: str, challenge: str, c: list[int], s: str, str_16: str) -> str:
compressed = compress_trajectory(trajectory)
tt = encrypt_string(compressed, c, s)
passtime = str(int(round(time.time() * 1000)) - first_time)
passtime = str(round(time.time() * 1000) - first_time)
rp = simple_md5(gt + challenge + passtime)
+3 -3
View File
@@ -306,7 +306,7 @@ class UserPrizeRecordItem(TafStruct):
self.exchangeDate = ins.read_int64(21, default=self.exchangeDate)
while True:
pos = ins.buf.tell()
tag, dtype = ins.read_head()
_tag, dtype = ins.read_head()
if dtype == TafType.STRUCT_END:
ins.buf.seek(pos)
return
@@ -406,7 +406,7 @@ class ActTaskPrizeInfo(TafStruct):
self.extra = ins.read_map(12)
while True:
pos = ins.buf.tell()
tag, dtype = ins.read_head()
_tag, dtype = ins.read_head()
if dtype == TafType.STRUCT_END:
ins.buf.seek(pos)
return
@@ -494,7 +494,7 @@ class ActTaskDetailItem(TafStruct):
self.endTime = ins.read_string(26, default=self.endTime)
while True:
pos = ins.buf.tell()
tag, dtype = ins.read_head()
_tag, dtype = ins.read_head()
if dtype == TafType.STRUCT_END:
ins.buf.seek(pos)
return
+6 -6
View File
@@ -232,7 +232,7 @@ def solve_safe_auth(
result = solver.solve(risk_url)
except HuyaQrAuthRequiredError:
raise
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
last_err = exc
logger.warning(f"[safe_auth] 第 {attempt + 1} 次过验异常: {exc}")
time.sleep(1.0)
@@ -425,8 +425,8 @@ class HuyaAppPasswordLogin:
from .device_profile import record_login
record_login(self.username, result.success, result.message)
except Exception: # 元数据记录失败不影响登录结果
pass
except Exception as exc: # noqa: BLE001 # 元数据记录失败不影响登录结果
logger.debug(f"登录元数据记录失败: {exc}")
return result
def _login_impl(self) -> HuyaLoginResult:
@@ -450,7 +450,7 @@ class HuyaAppPasswordLogin:
message=str(exc),
code="QR_AUTH_REQUIRED",
)
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
return HuyaLoginResult(
success=False,
message=f"App 登录凭证获取失败: {exc}",
@@ -478,7 +478,7 @@ class HuyaAppPasswordLogin:
if env.uid != uid:
struct.pack_into(">Q", raw, env.uid_off, uid)
wup = base64.b64encode(bytes(raw)).decode("ascii")
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
return HuyaLoginResult(
success=False,
message=f"证书铸造/信封补丁失败: {exc}",
@@ -603,7 +603,7 @@ class HuyaAppPasswordLogin:
sdid=sdid,
context=pc.context,
)
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
return HuyaLoginResult(
success=False,
message=f"扫码绑定兑换 Cookie 失败: {exc}",
+4 -4
View File
@@ -6,7 +6,7 @@ import threading
import time
from collections.abc import Mapping
from dataclasses import dataclass
from datetime import datetime
from datetime import UTC, datetime
from core.sms_provider import SmsLine, SmsProviderClient
@@ -76,7 +76,7 @@ def register_huya_with_sms_line(
sms_url=item.url,
)
sent_at = datetime.now()
sent_at = datetime.now(UTC)
try:
code_result = send_huya_sms_code(phone=phone, proxies=proxies)
except HuyaLoginError as exc:
@@ -89,7 +89,7 @@ def register_huya_with_sms_line(
normalized_phone=normalized_phone,
sms_url=item.url,
)
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
return HuyaAutoRegisterResult(
phone=phone,
provider=item.provider,
@@ -155,7 +155,7 @@ def register_huya_with_sms_line(
sms_url=item.url,
attempts=attempts,
)
except Exception as exc:
except Exception as exc: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
return HuyaAutoRegisterResult(
phone=phone,
provider=item.provider,
+2 -2
View File
@@ -10,7 +10,7 @@ import time
import uuid
from collections.abc import Mapping
from dataclasses import dataclass
from datetime import datetime
from datetime import UTC, datetime
from urllib.parse import quote, urlsplit, urlunsplit
import requests
@@ -496,7 +496,7 @@ def change_huya_password_with_sms_line(
) -> HuyaChangePasswordResult:
"""使用同一手机号接码链接完成改密短信验证。"""
changer = HuyaPasswordChanger(uid=uid, cookie=cookie, proxies=proxies)
sent_at = datetime.now()
sent_at = datetime.now(UTC)
code_result = changer.send_code()
if not code_result.success or not code_result.session_data:
return HuyaChangePasswordResult(
+8 -6
View File
@@ -22,6 +22,8 @@ import random
from collections.abc import Mapping
from pathlib import Path
from loguru import logger
ROOT = Path(__file__).resolve().parent.parent.parent
DATA_DIR = ROOT / "data"
PRIMARY_PROFILE_DB = DATA_DIR / "huya_device_profiles.json"
@@ -119,13 +121,13 @@ def _load_db() -> dict:
if PRIMARY_PROFILE_DB.exists():
try:
return json.loads(PRIMARY_PROFILE_DB.read_text("utf-8"))
except Exception:
pass
except Exception as exc: # noqa: BLE001
logger.debug(f"读取主设备画像库失败: {exc}")
if FALLBACK_PROFILE_DB.exists():
try:
return json.loads(FALLBACK_PROFILE_DB.read_text("utf-8"))
except Exception:
pass
except Exception as exc: # noqa: BLE001
logger.debug(f"读取备用设备画像库失败: {exc}")
return {}
@@ -135,8 +137,8 @@ def _save_db(db: dict) -> None:
PRIMARY_PROFILE_DB.write_text(
json.dumps(db, indent=2, ensure_ascii=False), encoding="utf-8"
)
except Exception:
pass
except Exception as exc: # noqa: BLE001
logger.debug(f"保存设备画像库失败: {exc}")
def _enrich_profile(profile: dict) -> tuple[dict, bool]:
+4 -2
View File
@@ -10,6 +10,8 @@ import json
import struct
from pathlib import Path
from loguru import logger
INT8, INT16, INT32, INT64 = 0x00, 0x01, 0x02, 0x03
STRING1, STRING4 = 0x06, 0x07
MAP, LIST = 0x08, 0x09
@@ -131,8 +133,8 @@ class Envelope:
if candidate.exists():
try:
return cls._load_from_path(candidate)
except Exception:
pass
except Exception as exc: # noqa: BLE001
logger.debug(f"加载证书信封候选文件失败: {candidate}: {exc}")
return cls(base64.b64decode(DEFAULT_QURL_B64))
@classmethod
+12 -9
View File
@@ -4,6 +4,8 @@ TAF/WUP 帧解码器 — 将二进制帧转为可读摘要,用于日志输出
from typing import Any, cast
from loguru import logger
from .taf_protocol import TafInputStream, TafType
from .wup_protocol import normalize_wup_payload
@@ -101,13 +103,13 @@ def _decode_taf_struct(ins: TafInputStream, depth: int = 0) -> dict:
if depth < 5:
try:
val = _decode_taf_value(ins, dtype, depth)
except Exception:
except Exception: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
val = f"<decode_err:0x{dtype:02x}>"
else:
val = "<...>"
try:
ins.skip_field(dtype)
except Exception:
except Exception: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
break
key = f"tag{tag}"
if key in fields:
@@ -195,19 +197,20 @@ def _decode_wup_body(body: bytes) -> dict:
if v:
try:
tins = TafInputStream(v)
ttag, tdt = tins.peek_head()
_ttag, tdt = tins.peek_head()
if tdt == TafType.STRUCT_BEGIN:
tins.read_head()
result[k] = _decode_taf_struct(tins)
else:
result[k] = f"<{len(v)}B>"
except Exception:
except Exception as exc: # noqa: BLE001
logger.debug(f"TAF 嵌套结构解码失败: {exc}")
result[k] = f"<{len(v)}B>"
else:
result[k] = _decode_taf_value(sins, vt)
except Exception:
pass
except Exception as e:
except Exception as exc: # noqa: BLE001
logger.debug(f"TAF 字段解码失败: {exc}")
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
result["err"] = str(e)
return result
@@ -286,7 +289,7 @@ def format_wss_log(body: bytes, cmd: int, seq: int, direction: str) -> str:
try:
ins = TafInputStream(clean)
# 看第一个 head
tag, dtype = ins.peek_head()
_tag, dtype = ins.peek_head()
if dtype == TafType.STRUCT_BEGIN:
ins.read_head()
fields = _decode_taf_struct(ins)
@@ -314,6 +317,6 @@ def format_wss_log(body: bytes, cmd: int, seq: int, direction: str) -> str:
if fields:
return f"{prefix} {cmd_name} {_fmt_fields(cast(dict[str, Any], _truncate(fields)))}"
return f"{prefix} {cmd_name}"
except Exception:
except Exception: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
cmd_name = CMD_NAMES.get(cmd, f"0x{cmd:02x}")
return f"{prefix} {cmd_name} ({len(body)}B)"
+7 -7
View File
@@ -92,7 +92,7 @@ class WSConnectParaInfo(TafStruct):
def _gen_trace_id() -> str:
"""生成 sTraceId (格式 hex8:hex8:0:0HAR 实证)"""
h = "%016x" % random.getrandbits(64)
h = f"{random.getrandbits(64):016x}"
return f"{h}:{h}:0:0"
@@ -294,7 +294,7 @@ class HuyaHttpClient:
import gzip
resp_data = gzip.decompress(resp_data)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[HTTP] ❌ 请求失败: {type(e).__name__}: {e}")
return None
@@ -611,13 +611,13 @@ class HuyaHttpClient:
or resp.headers.get("Content-Encoding") == "gzip"
):
resp_data = gzip.decompress(resp_data)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[LIVELINK] ❌ 小程序码请求失败: {type(e).__name__}: {e}")
return None
try:
data = json.loads(resp_data.decode("utf-8", "replace"))
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[LIVELINK] ❌ 小程序码响应解析失败: {type(e).__name__}: {e}")
return None
@@ -679,13 +679,13 @@ class HuyaHttpClient:
or resp.headers.get("Content-Encoding") == "gzip"
):
resp_data = gzip.decompress(resp_data)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[LIVELINK] ❌ 二维码状态请求失败: {type(e).__name__}: {e}")
return None
try:
data = json.loads(resp_data.decode("utf-8", "replace"))
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(
f"[LIVELINK] ❌ 二维码状态响应解析失败: {type(e).__name__}: {e}"
)
@@ -972,7 +972,7 @@ class HuyaHttpClient:
import gzip
resp_data = gzip.decompress(resp_data)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[HTTP] ❌ payOrderSubmitV5 失败: {e}")
return None
+3 -4
View File
@@ -380,10 +380,9 @@ class HuyaPasswordLogin:
last_exc: Exception | None = None
for attempt in range(max_ip_retries + 1):
if attempt > 0:
if not self._swap_proxy():
logger.warning("无可用代理可切换,停止换 IP 重试")
break
if attempt > 0 and not self._swap_proxy():
logger.warning("无可用代理可切换,停止换 IP 重试")
break
try:
return self._login_once()
except (HuyaQrAuthRequiredError, HuyaSmsAuthRequiredError) as exc:
+2 -3
View File
@@ -5,7 +5,6 @@
来源:m-shop.yaoguo.com 的 jce/ShopFacade.js、api/orderui.ts、api/mall/PlayMallNewHome.ts
"""
from .taf_protocol import TafInputStream, TafOutputStream, TafStruct, TafType
@@ -68,7 +67,7 @@ def _skip_to_struct_end(ins: TafInputStream):
"""跳过当前结构里未解析的尾部字段,停在 STRUCT_END 前。"""
while True:
pos = ins.buf.tell()
tag, dtype = ins.read_head()
_tag, dtype = ins.read_head()
if dtype == TafType.STRUCT_END:
ins.buf.seek(pos)
return
@@ -427,7 +426,7 @@ class GoodsPriceInfo(TafStruct):
def first_sku_id(self) -> int:
if not self.skuMap:
return 0
return sorted(self.skuMap.keys())[0]
return min(self.skuMap.keys())
@property
def sku_list(self) -> list[dict]:
+3 -3
View File
@@ -255,7 +255,7 @@ class TafInputStream:
def _read_int_len(self) -> int:
"""读 map/list 长度(int32 带优化)"""
tag, dtype = self.read_head()
_tag, dtype = self.read_head()
return self._read_int_value(dtype)
def _read_int_value(self, dtype: int) -> int:
@@ -273,7 +273,7 @@ class TafInputStream:
def _skip_struct(self):
while True:
tag, dtype = self.read_head()
_tag, dtype = self.read_head()
if dtype == TafType.STRUCT_END:
break
self.skip_field(dtype)
@@ -441,7 +441,7 @@ class TafInputStream:
obj = struct_class()
obj.read_from(self)
# 消费 STRUCT_END
t, dt = self.read_head()
_t, dt = self.read_head()
if dt != TafType.STRUCT_END:
raise ValueError(f"期望 STRUCT_END, 实际 0x{dt:02x}")
return obj
+1 -1
View File
@@ -261,7 +261,7 @@ class HuyaCaptchaOcr:
target["cropped_image"],
char["cropped_image"],
)
except Exception:
except Exception: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
score_matrix[target_index][char_index] = 1e6
row_ind, col_ind = linear_sum_assignment(score_matrix)
+3 -3
View File
@@ -137,7 +137,7 @@ class HuyaVerificationSolver:
max_width = max(bg.shape[1], tip.shape[1])
def pad_right(img, target_width):
height, width = img.shape[:2]
_height, width = img.shape[:2]
if width >= target_width:
return img
return cv2.copyMakeBorder(
@@ -299,8 +299,8 @@ class HuyaVerificationSolver:
"虎牙登录风控strategys完整结构: {}",
json.dumps(strategies, ensure_ascii=False)[:1200],
)
except Exception: # noqa: BLE001
pass
except Exception as exc: # noqa: BLE001
logger.debug(f"风控策略日志序列化失败: {exc}")
strategy_url_lower = strategy_url.lower()
# 判定依据是 URL 路径,不是 strategy 数值。
# 实测(2026-08-25): strategy=64 时 pt_auth.html 是滑块、qr_auth.html 才是扫码,
+14 -12
View File
@@ -76,7 +76,7 @@ class WssMessage:
def decode(cls, data: bytes) -> "WssMessage":
if len(data) < 6:
raise ValueError(f"消息太短: {len(data)} bytes")
version, command = struct.unpack(">BB", data[0:2])
_version, command = struct.unpack(">BB", data[0:2])
sequence = struct.unpack(">I", data[2:6])[0]
body = data[6:]
return cls(command=command, sequence=sequence, body=body)
@@ -256,7 +256,7 @@ class HuyaWssClient:
format_wss_log(msg.body, msg.command, msg.sequence, "")
)
await self._handle_message(msg)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(
f"[WSS] 解析消息失败: {e} raw_hex={raw_bytes[:50].hex()}"
)
@@ -264,7 +264,7 @@ class HuyaWssClient:
pass
except websockets.exceptions.ConnectionClosed as e:
self.logger(f"[WSS] 连接关闭: code={e.code} reason={e.reason}")
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[WSS] 接收循环异常: {type(e).__name__}: {e}")
async def _handle_message(self, msg: WssMessage):
@@ -289,7 +289,7 @@ class HuyaWssClient:
await self.send_heartbeat()
except asyncio.CancelledError:
pass
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[WSS] 心跳循环异常: {e}")
async def send_heartbeat(self):
@@ -399,7 +399,7 @@ class HuyaWssClient:
)
return
ins = TafInputStream(treq)
tag, dtype = ins.peek_head()
_tag, dtype = ins.peek_head()
if dtype != 0x0A: # STRUCT_BEGIN
self.logger(f"[RPC] wsLaunch tRsp 非结构体 dtype=0x{dtype:02x}")
return
@@ -432,7 +432,7 @@ class HuyaWssClient:
self.logger(
f"[RPC] wsLaunch 解析: guid={self._launch_guid} ip={self._launch_ip}"
)
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
self.logger(f"[RPC] wsLaunch 响应解析失败: {e}")
@staticmethod
@@ -610,15 +610,17 @@ class HuyaWssClient:
if data and isinstance(data, bytes) and len(data) > 0:
try:
ins = TafInputStream(data)
tag, dtype = ins.peek_head()
_tag, dtype = ins.peek_head()
if dtype == TafType.STRUCT_BEGIN:
ins.read_head()
decoded = _decode_taf_struct(ins)
self.logger(
f"[←] {service}.{method} {key}: {_truncate(decoded)}"
)
except Exception:
pass
except Exception as exc: # noqa: BLE001
self.logger(
f"[debug] WUP 响应字段解码失败: {service}.{method}.{key}: {exc}"
)
if rsp_class is None:
return body
@@ -794,13 +796,13 @@ class HuyaWssClient:
if data and isinstance(data, bytes) and len(data) > 0:
try:
ins = TafInputStream(data)
tag, dtype = ins.peek_head()
_tag, dtype = ins.peek_head()
if dtype == TafType.STRUCT_BEGIN:
ins.read_head()
decoded = _decode_taf_struct(ins)
self.logger(f"[←] payOrderSubmitV5 {key}: {_truncate(decoded)}")
except Exception:
pass
except Exception as exc: # noqa: BLE001
self.logger(f"[debug] WUP 支付响应字段解码失败: {key}: {exc}")
result = wup_resp.readStruct("tRsp", PayOrderRes)
if result is None:
result = wup_resp.readStruct("tResp", PayOrderRes)
+3 -3
View File
@@ -211,7 +211,7 @@ class WupResponse:
_, vt = ins.read_head()
val = _read_bytes_value(ins, vt)
self.newdata[key] = val
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
print(f"[WupResponse] 解析 newdata 失败: {e}")
def readStruct(self, key: str, struct_class=None):
@@ -236,13 +236,13 @@ class WupResponse:
ins = TafInputStream(data)
# newdata 里的结构体以 STRUCT_BEGIN 开头
try:
tag, dtype = ins.peek_head()
_tag, dtype = ins.peek_head()
if dtype == TafType.STRUCT_BEGIN:
ins.read_head() # 消费 STRUCT_BEGIN
obj = struct_class()
obj.read_from(ins)
return obj
except Exception as e:
except Exception as e: # noqa: BLE001 外部接口与任务边界需要保留宽泛异常兜底
print(f"[WupResponse] 解析 {struct_class.__name__} 失败: {e}")
return None
+2 -2
View File
@@ -5,7 +5,7 @@ from __future__ import annotations
import json
import re
from dataclasses import dataclass
from datetime import datetime
from datetime import UTC, datetime
from urllib.parse import urlparse
import requests
@@ -98,7 +98,7 @@ def _parse_sms8_time(value: str) -> datetime | None:
return None
for fmt in ("%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S"):
try:
return datetime.strptime(text, fmt)
return datetime.strptime(text, fmt).replace(tzinfo=UTC)
except ValueError:
continue
return None