yml2213
|
c3fd299f3a
|
test(db): 测试改用真实 MySQL,方言差异不再漏到生产
生产是 MySQL 8、测试是 SQLite,两者的方言差异在本地完全测不出来。今天为此
付出了两次代价:
1. `ORDER BY ck_checked_at ASC NULLS FIRST` 在 SQLite 上完全正常,本地 258 条
全绿,一部署到生产第一次巡检就 1064 语法错误(MySQL 不支持 NULLS FIRST);
2. P1b 自动重登的结算复用调度器事务读取,在 SQLite 下看不出问题,但在 MySQL 的
REPEATABLE READ 下读到的是批次开始前的快照 —— 10 条实际成功的重登全部被记成
失败。SQLite 的读一致性与 MySQL 不同,这类问题跑一万遍也复现不出来。
改动:
- 新增 tests/support/db.py:测试专用引擎/会话工具,连接串从 .env 读取,
默认指向独立的 douyu_login_test 库;
- 新增 tests/conftest.py:会话级建好表结构,每个用例前后清空所有表做隔离;
- 根 conftest.py 接管连接串设置:它在 pytest 收集阶段最先执行,在这里把
DATABASE_URL 指向测试库,应用模块首次 import 拿到就是 MySQL,不依赖任何
import 顺序(原先这里是 sqlite:// 兜底,改造后会变成「先建 SQLite engine
再打补丁换成 MySQL」,顺序一变就静默跑错库);
- 21 个测试文件的 setup 样板统一改用共享测试引擎;
- 两个迁移测试改为在临时库 douyu_login_mig_<随机> 上跑完整 alembic upgrade head,
跑完 drop —— 迁移脚本本身也终于在 MySQL 上被验证;
- dev.sh 与 README 的过时说明一并更新(原先写着「不需要 MySQL / .env 配置」;
「测试各自建 SQLite 内存库」)。
安全与易用:
- 测试库名与开发库同名时**直接拒绝运行**(clear_tables 会 DELETE 所有表,
一旦 TEST_MYSQL_DATABASE 被指到 douyu_login 就是数据灾难);
- 连不上 MySQL 时给出可操作提示(先 ./dev.sh 起库 / 用 TEST_MYSQL_DATABASE 覆盖),
而不是抛一段 SQLAlchemy 原始堆栈。
验收:
- 全量 301 条通过,连跑两次结果一致(隔离有效),耗时约 12.5 秒(原 SQLite 约 3.6 秒);
- 单文件独立运行通过(不依赖全量执行顺序);
- `grep -rn sqlite tests/ conftest.py` 已无实际用法;
- **方言确实生效**:临时把一条查询改回 `NULLS FIRST`,13 条测试立刻变红(含运行期
失败),还原即恢复;这条由 test_generated_sql_is_mysql_compatible 长期守着。
代价(已在 README 与规划附录 C.2 记明):跑测试前必须先有 MySQL,pre-push 钩子
同理;CI 需要 service container。
|
2026-10-02 21:22:08 +08:00 |
|
yml2213
|
2c532df14f
|
fix(automation): 待重登积压数不再被批次上限截断
页面上「待重登候选」显示 10 —— 那只是 ck_relogin 的 batch_size,不是真实积压。
根因是我用作业的候选查询取 count,而那个查询带 LIMIT batch_size,count 自然
被截断在批次上限;线上实际有一千多条待重登,页面却恒显示 10。
改为独立的 count_pending_relogin():同一套资格条件(invalid + 有 CK + 允许自动
管理 + 未转人工 + 未超每日上限),但不带 LIMIT,也不按退避窗口过滤 —— 退避是
「什么时候试」的细节,不影响「还有多少要处理」。
新增测试:批次上限为 10 时,25 条积压必须报 25。
另:本次一并还原了 ck_health.py 里被外部改动引入的回归 —— 有人把选行排序改成
text("login_tasks.ck_checked_at ASC NULLS FIRST"),那是逐字透传给数据库的片段,
而 MySQL 不支持 NULLS FIRST(今天线上就是这么炸的 1064)。已恢复成可移植写法,
test_generated_sql_is_mysql_compatible 会拦住这类改动(本次正是它先报的红)。
全量 298 通过。
|
2026-10-02 21:05:18 +08:00 |
|
yml2213
|
ed6e186655
|
fix(ui,test): 说明巡检与重登的联动关系;修掉一条按分钟偶发失败的测试
看图时发现两个问题:
一、页面上那段说明是 P1a 时代的文案,已经过时且误导:「重登仍由人工在
「CK 检测与重登」页面操作」——P1b 上线后自动重登已存在。两个作业其实是联动的
上下游:巡检把账号标成 invalid,「CK 自动重登」的候选条件正是这个字段,所以
巡检一发现失效、重登作业下一周期就会接手。刻意分成两个作业是为了止损粒度
(巡检只读零风险;重登会真实登录,出问题可单独关掉)。据此改写说明文案,并在
两张卡片上标出「下游:CK 自动重登」/「上游:巡检标记为失效且有 CK 的账号」。
二、jobs 接口新增 pending_relogin:当前有多少条正等着自动重登。页面靠它把
上下游关系显性化 —— 没有这个数字,两个开关看起来像互不相干。计数走重登作业
自己的候选查询,保证「页面显示的待办」和「作业实际会捞的」是同一口径。
顺带修掉 tests/test_douyu_email_code_pick.py 里一条既有缺陷:它用
max(0, now.minute - 30) 构造「30 分钟前的邮件」,分钟数小于 30 时会退化成当前
整点(21:00:12 → "今天 21:00"),只比 now 早十几秒,于是断言随「当前几点」偶发
失败 —— 每小时前 30 分钟必红(已确认在我本次所有改动之前的提交上同样失败,
不是本次引入)。改成真实的时间减法,跨天时用「昨天」。
全量 298 通过。提交时另一路 SQLite→MySQL 的测试改造仍在同一工作区进行,
本次只暂存本功能相关文件。
|
2026-10-02 21:01:17 +08:00 |
|
yml2213
|
8fc8e623b9
|
feat(automation): CK 自动重登(P1b)+ 失败分型与待人工队列
P1a 的巡检只产出「谁失效了」的清单,不兑现修复:1,356 个失效账号仍要人工逐个
选集→点重登→过滑块。线上实测 20 个失效账号重登 20/20 成功(2 分 13 秒、零极验),
证实失效是会话级过期而非凭证问题,可救量约 1,350。
后端:
- 迁移 20261002_0038:login_tasks 加 relogin_failure_kind(枚举),供作业决定
「继续退避重试」还是「转人工」;不用 attempt_message 做字符串匹配(文案一改
就失效,页面也要按类型筛选);
- jobs/ck_relogin.py:
- 候选 = 巡检判定 invalid + 允许自动管理 + 无在途尝试 + 退避到期 + 未超每日上限
+ **未转人工**(极验/凭证问题不再自动重登);
- 复用 LoginBatchRunner(mode="relogin"),成功才替换 CK(沿用既有安全语义)。
自动化身份取最早的超管做 created_by,权限给 login:view_all 以免受归属限制;
总时长上限压到 240 秒,避免长时间占住调度线程;
- settle_results() 独立成纯函数便于单测:成功清空退避状态;失败按分型分流 ——
captcha/credential 转人工(不排期)、email_quota 退避到次日零点+随机抖动、
email_code/interrupted/network 走 1h→3h→12h→24h 阶梯;次数用尽也停下等人工;
- 未知文案默认按可重试处理(有每日上限兜底),别把可能只是抖动的账号推给人工;
- 注册第二个作业「CK 自动重登」(batch 10 / 并发 3,**默认关闭**);
- 新增 GET /api/automation/manual-queue:按原因分组列出待人工处理的账号。可重试
类型但已无下次排期的(次数用尽)单独成组 —— 否则会混进「验证码失败」里,客服
看不出这个已经不会再自动试了。
前端:
- /automation 页新增「待人工处理」卡片,按分型分组展示(极验要过滑块、凭证要核对、
次数用尽要人工确认),各带账号与最近失败原因。
测试:新增 26 条(分型顺序陷阱「上限」优先于「验证码」、退避阶梯、配额退避次日、
候选筛选、MySQL 方言编译、结算、待人工队列分组)。
提交前全量 297 通过、ruff 全绿、前端 tsc 通过。
注意:提交时另一路「测试改用 MySQL」的改造正在同一工作区进行,本次刻意只暂存
本功能相关文件,未触碰 tests/conftest.py、tests/support/ 及对方已转换的测试文件。
|
2026-10-02 20:51:19 +08:00 |
|
yml2213
|
f8c5e896d4
|
fix(automation): 巡检区分「查不到」与「失效」,并在大面积失败时自动暂停
P1a 原本把「检测没通过」一律写成 invalid。但 check_douyu_cookie 的失败分两类:
斗鱼明确回「未登录/登陆异常」(CK 真失效),以及请求超时/响应异常(我们查不到)。
一视同仁的后果是:斗鱼接口抖动或被风控时,每 5 分钟 200 个、一小时就能把两千多个
好账号标成失效,客服会误判成「CK 大面积挂掉」。规划里的失败率熔断只给了 P1b,
P1a 漏了。
改动:
- 新增 classify_result():valid / invalid(命中斗鱼鉴权类说法)/ error(其余);
- error 时**不覆盖该行原来的 ck_check_status**,只更新 ck_check_result(带
verdict 字段)与 ck_checked_at,并计入本轮 skipped;
- 一轮 error 占比 > 30% 且条数 >= 20 时自动把作业 enabled 置 false,message 与
detail.paused 写明原因,避免继续污染;
- 真实死号占比高**不触发**暂停 —— 首轮 100% invalid 是预期情况(选行「从没检测过
的优先」,积压的是两个月前批量导入、attempt_status 为空、从未登录的陈旧账号,
生产实测 200 条错误信息一致为斗鱼侧「用户未登录」)。
新增 6 条测试:分类正确性、error 保留原结论、异常不再标失效、大面积失败自动暂停、
真实死号不暂停。全量 271 条通过。
|
2026-10-02 20:35:30 +08:00 |
|
yml2213
|
65a4590291
|
refactor(time): 时间列统一走 UTCDateTime,并把 MySQL 会话时区对齐成 UTC
问题不是「UTC 还是本地时间」,而是这套口径有两个半吊子的地方:
1. 库里存 naive UTC、读出来也是裸时间,于是每一处比较/输出都得自己补时区。
项目里因此散了三份 _as_utc 和一堆 replace(tzinfo=UTC),P1a 排下一轮时间
时还炸过一次 TypeError: can't compare offset-naive and offset-aware。
2. MySQL 会话时区跟随系统 +08:00,而库里存的是 UTC —— SQL 里的 NOW()/
CURDATE() 比库里的时间快 8 小时,查询会静默返回空(P1a 排查时就遇到过,
看着像「没有数据」)。
改动:
- 新增 database.UTCDateTime:写时 aware→转 UTC 去 tzinfo、naive 视为 UTC;
读时一律补 UTC 时区。底层 DDL 仍是 DATETIME,**不需要迁移**。models.py 的
28 个时间列全部改用它,模型上的时间字段从此不再是裸值;
- docker-compose 给 mysql 加 --default-time-zone=+00:00,让 SQL 时间函数与存储
口径一致。安全性已核实:全库 0 个 TIMESTAMP 列、0 个 CURRENT_TIMESTAMP
默认值,改这里不会改变任何已有数据的语义;
- 新增 tests/test_utc_datetime.py:读出必须 aware、能直接和 datetime.now(UTC)
比较、带 +08:00 的写入要落成 UTC、naive 写入视为 UTC,并有一条元测试扫描
Base.metadata,防止以后新增时间列忘了用 UTCDateTime。
保留既有的 _as_utc 补丁(对 aware 值是幂等的,属防御性代码);新代码不再需要。
「存 UTC、算 UTC、显示本地」三条线至此各自明确:存储与比较统一 UTC,日志按
容器 TZ 显示本地时间,前端 formatTime 负责转本地。
|
2026-10-02 20:27:07 +08:00 |
|
yml2213
|
3d5d0f551f
|
fix(automation): 去掉 MySQL 不认的 NULLS FIRST,排序改用可移植写法
生产 MySQL 上手动跑第一轮就报 1064:
You have an error in your SQL syntax ... near 'NULLS FIRST, login_tasks.id ASC'
NULLS FIRST 是 PostgreSQL/SQLite 语法,MySQL 不支持。本地测试全绿是因为跑在
SQLite 上(它认识这个语法),属于方言差异漏网 —— 生产是 MySQL、测试是 SQLite,
行为测试覆盖不到这类问题。
改成 `ck_checked_at IS NULL DESC, ck_checked_at ASC, id ASC`:三个方言下语义
一致(没检测过的优先)且都是合法 SQL。顺带把选行查询抽成 build_select_query,
便于按方言编译做回归。
新增回归测试:用 MySQL 方言 compile() 选行 SQL,断言不含 NULLS FIRST/LAST,
且「没检测过优先」用可移植写法表达。
规划附录 C.2 记下这条:写 SQL 前先确认方言;P0 连的是 order_site 的 PostgreSQL,
项目里已经出现 MySQL / SQLite / PG 三套方言。
|
2026-10-02 20:14:49 +08:00 |
|
yml2213
|
7aaaeebe2b
|
fix(automation): 修正调度口径——作业每 5 分钟跑一轮,interval_seconds 只是单行重检间隔
P1a 把两个「间隔」混成了一个:next_run_at 用的是 job.interval_seconds,于是
作业 6 小时才跑一轮、每轮 200 条 = 800 条/天,全库 12,881 条要 16 天才能过
一遍 —— 等于没巡检,与规划里「账号 6 小时内被查一次」的目标差了两个数量级。
按规划原意修正:
- TICK_SECONDS 60 → 300:作业每个 tick(5 分钟)跑一轮;
- next_run_at 改为 finished + TICK_SECONDS,不再用 interval_seconds;
- interval_seconds 只作为「同一行多久重新检测」的选行 cutoff(选行逻辑本来就
是这么用的,无需改);
- 容量口径随之更新:5 分钟一轮 × 200 条 = 40 条/分钟 ≥ 需要的 36 条/分钟,
冷启动约 5.4 小时覆盖全库,稳态每轮一百多条;
- 前端标签由「巡检周期(小时)」改为「单账号重检间隔(小时)」,说明文案写清
「每 5 分钟跑一轮」,避免运维误以为是作业周期。
同步更新规划文档 §7.2/§7.3(含两个间隔不能混的说明)与附录 C 的三段上线
步骤(立即跑一次 → 每轮 50 观察 → 每轮 200 启用)。
|
2026-10-02 19:54:31 +08:00 |
|
yml2213
|
f745a61df1
|
feat(automation): CK 自动巡检(P1a),只检测不改 CK
后台原本靠人工逐批点「CK 检测」发现失效账号,1.2 万个账号根本盯不过来。
P1a 把「哪些账号失效了」自动化:自动挑久未检测的账号、调现成检测接口、
把结果写回 ck_check_*。**本作业不替换任何 CK**,重登仍由人工点,符合规划里
「先做只读/只提示,确认无误再做自动动作」的渐进上线原则。
实现:
- 迁移 20261002_0037:automation_jobs / automation_runs 两张表,
login_tasks 加 relogin_attempts / relogin_next_at / relogin_last_error
(为 P1b 备好),accounts 加 auto_managed(特殊账号不参与自动化);
- services/automation/scheduler.py:进程内调度线程,60s tick,状态全部落库
(重启不丢调度进度、不重复跑轮);AUTOMATION_ENABLED 默认关闭,作业开关
也默认关闭;ensure_jobs 只补缺失行、不覆盖运维改过的配置;
作业异常只记 failed,不拖垮调度线程;单容器 --workers 1,无需分布式锁;
- services/automation/jobs/ck_health.py:选行口径与人工检测一致
(cookie_holding_filter:持有 CK 且无在途尝试),叠加久未检测、
auto_managed、batch_size,按 ck_checked_at 升序(最久没查的优先);
只写 ck_check_status / ck_check_result / ck_checked_at;
- routers/automation.py:GET /jobs、PATCH /jobs/{key}、POST /jobs/{key}/run、
GET /runs;新增权限点 automation:view(运营可看)与 automation:manage
(仅超管),改配置与手动触发都写审计;
- 顺带补 POST /api/login/batch 的审计(此前批次是谁发起、多少账号无据可查);
- 前端 /automation 页:作业卡片(开关/周期/单轮条数/并发)、运行历史、
「立即跑一次」;总开关未打开、调度线程未运行时给明确提示。
验证:
- 22 条新测试覆盖调度器行为(只跑到点的、异常不抛出、下轮时间、配置不被重置)、
选行条件(在途尝试/auto_managed/间隔/batch_size)、接口与权限,其中一条
专门断言巡检后 cookie/status/message/attempt_status 一字未动;
- 全量 257 条通过;前端 tsc 与构建通过;
- 端到端用 3 个真实账号跑真实斗鱼接口:巡检结果与直接调 check_douyu_cookie
逐条一致(3/3 valid),CK 与尝试状态全程未变。
顺带修掉一处会炸生产的坑:DB 时间列读出来是 naive UTC,直接与
datetime.now(UTC) 比较会 TypeError,现统一走 _as_utc() 补时区。
|
2026-10-02 19:47:41 +08:00 |
|
yml2213
|
99db772ddd
|
feat(douyu): 精英宝典支持查询开通状态,开通前先校验且不再误判到账
线上两个问题:工作台看不到账号有没有开通精英宝典;点开通时二维码会「闪一下
就变小」——大图弹窗 2~4 秒后自动关闭,只剩列表里 56px 的小二维码。
根因:
- getUserInfo 的 manualType/expireTime 才是开通状态的权威口径,但只有兑换
流程用过一次,没有任务类型对外暴露;前端只看积分列,而「开通后积分花完」
和「从未开通」都是 0 分,区分不了(实测 13456 manualType=1/score=0);
- 开通前不查状态,且到账判定写成「积分 >= 300」:账上本来就有 680 分的账号
在出码后第一轮轮询就被判成功,前端按 paymentArrived 自动关掉了弹窗。
改动:
- 新增任务类型 query_elite_status:查 manualType/manualScore/expireTime 并
落库到 accounts.elite_opened / elite_expire_time(迁移 20261001_0036),
精英工作台加查询按钮与「宝典状态」列(已开通+到期 / 未开通);
- create_elite_qr 开通前先查状态:已开通直接判成功、不再生成支付码(方案 A),
既消除二维码闪现,也避免给已开通账号开出真实支付单;
- 到账判定改为「积分比开通前增长」,基线用与轮询同源的 credit/balance 取,
取不到基线才退回旧口径;
- 支付弹窗不再自动关闭:到账/失败/停止都在弹窗里给结论 + 手动关闭;列表小
二维码在任务进终态后隐藏。
新增 9 条测试覆盖上述行为,回退 runner 时其中 8 条失败。
|
2026-10-01 19:08:25 +08:00 |
|
yml2213
|
4d87cdc16d
|
fix(douyu): 取邮箱验证码取错邮件,导致登录永远报「邮箱验证码错误」
线上现象:同一个邮箱每次登录都取到同一个旧验证码(UID=1、几小时前那封),
提交必然失败;整体重试 20 次又把斗鱼的发信配额打爆。
两个根因:
1. Roundcube 返回的邮件列表本来就是 UID 降序(最新在前),代码又 reversed()
了一次,于是从收件箱最旧的一封开始读;
2. _parse_rc_date 用 UTC 作为基准,而 Roundcube 显示的是邮箱本地时间,旧邮件
被凭空加了 8 小时,看起来比发送时间还新,时间过滤形同虚设。
改动:
- 发信前用 latest_douyu_uid() 记录收件箱最新斗鱼邮件 UID,之后只接受 UID
更大的邮件,精确锁定「本次发送触发的那封」,不再依赖列表顺序和日期解析;
- 明确按 UID 降序读取,去掉多余的 reversed();
- 日期解析改为本地时区 aware datetime,时间兜底过滤才真正生效;
- 斗鱼返回「邮箱验证码发送次数已达上限」时抛 EmailQuotaError,直接终止批次
不再重试,避免继续烧配额。
线上实测(忧伤的心750 / aakpfc@bdhg.xyz):修复前每次读 UID=1 的旧码
942715;修复后基线 UID=20、按发送时间与快照过滤均正确跳过旧邮件,正文读取
取到最新一封。
|
2026-10-01 18:42:56 +08:00 |
|
yml2213
|
6a25097412
|
fix(douyu): 替换 CK 是最后一步,只有登录成功才写回记录
上一版把可见性改成「记录里还有 CK」,账号不会再消失,但根因还在:批次启动
时就把复用的成功记录改成 pending(旧 CK 仍在),停止或失败后没人恢复状态,
记录一直显示成一次没完成的登录。
按「替换 CK 是最后一步」把两者拆开:
- login_tasks 新增 attempt_status / attempt_message / attempt_batch_id /
attempt_at,批次只写 attempt_*,status/cookie/message 只在登录成功时更新;
- _begin_attempt 只登记尝试,_mark_attempt_failed 只记录失败(已有 CK 的记录
原样不动),_write_login_success 是唯一替换旧 CK 的入口;
- 停止批次、代理不可用、登录异常、进程重启清理全部改为收敛 attempt_*,
因此停止一个批次不可能再让账号失去 CK;
- 复用的记录改用「持有 CK 的记录」,不再创建第二条记录,失败记录在无 CK 时
才复用;
- 登录任务列表/统计按 attempt_* 展示「这次登录怎么样了」,批次筛选同时匹配
attempt_batch_id;CK 操作页的重登状态也从 attempt_* 映射;
- 迁移 20261001_0035 归一存量数据:持有 CK 的记录 status 统一为 success、
历史状态搬进 attempt_*,无 CK 且卡在 pending/running 的收敛为 failed。
新增测试:批次失败/停止不碰旧 CK、成功后替换 CK、列表展示尝试状态、
迁移存量数据归一。
|
2026-10-01 18:29:49 +08:00 |
|
yml2213
|
64c399617a
|
fix(douyu): 账号只要还持有 CK 就不再从工作台消失
线上事故:分配给客服的账号(如「远行者103」)在斗鱼工作台与 CK 列表里
查不到,只有账号管理里还能搜到。原因是可见性判定写成了
LoginTask.status == "success",而按设计保留旧 CK 的三种状态都不再是
success:
- 普通登录批次启动时会把复用的成功记录置为 pending/running(旧 CK 保留),
批次被停止或失败后一直停在 pending,账号永久消失;
- CK 重登失败置为 relogin_failed(旧 CK 保留),账号从工作台消失;
- 普通登录失败置为 failed(复用记录的旧 CK 未清空),同样消失。
线上现状:12545 个账号持有 CK,但只有 11703 个能出现在工作台,842 个
(644 重登失败 + 176 排队中 + …)对客服和管理员都不可见。
改动:
- douyu_service 新增 cookie_holding_filter()/latest_cookie_login_task(),
以「记录里还留着 Cookie」作为唯一判据,并抽出 LOGIN_IN_FLIGHT_STATUSES
与 cookie_operable_filter() 供检测/重登入口复用;
- 斗鱼工作台账号列表、任务账号校验、账号管理 has_cookie 筛选、分配校验与
概览、CK 管理/操作列表、首页 CK 统计统一改用该判据;
- 工作台取 CK 从 latest_success_login_task 换成 latest_cookie_login_task,
保证重登失败/排队中的账号仍能被任务正常执行;
- 新增 cleanup_orphan_login_tasks():进程重启后把遗留的 pending/running
收敛为 failed 并保留旧 CK,避免页面永久显示排队中。
新增回归测试覆盖上述状态下的可见性、可执行性与启动清理。
|
2026-10-01 18:18:02 +08:00 |
|
 yml2213andCursor
|
4806d4bbf1
|
feat(douyu): 精英宝典导入支持按多行账户名筛选
对齐 Cookie 自定义 CK 的粘贴导入方式,按账户名精确匹配并保持粘贴顺序。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-09-29 15:02:53 +08:00 |
|
yml2213
|
1ac6a13a2c
|
fix(audit): 修复审计日志时区差并支持供应商单号搜索与展示
- 解决审计日志 8 小时时区差:后端输出带时区 UTC ISO 字符串,前端 formatTime 增加 UTC 自动解析换算
- 审计日志支持单号检索:list_audit_logs 关联 DouyuTask 匹配供应商单号、外部单号、UID、昵称等
- 列表摘要与详情抽屉优化:摘要直观展示供应商单号与外部单号,抽屉增加专用供应商订单列表并支持一键复制
- 增加测试用例覆盖时间格式与单号反向检索
|
2026-09-12 14:52:26 +08:00 |
|
yml2213
|
4518b726ac
|
feat(huya): 浏览器兑换三目标直达并收窄扩展注入范围
- 操作列改为「直播间 / 精英宝典 / 电竞宝典」三个直达按钮,点哪个就按哪个目标写入登录态并打开,去掉弹窗内选择
- 新增 services/huya_exchange_targets.py 统一三个目标地址,接口支持可选 body {"target": "..."}(不传=精英宝典)
- 扩展内容脚本从 <all_urls> 收窄到后台站点白名单,service worker 校验 sender.tab.url,拒绝其它来源的注入
- 注入改为 Cookie 写完后回执(ok/written/failed/error),前端按回执提示成功或失败,不再静默
- 扩展图标兜底改用 world:'MAIN' 读取;一个 Cookie 都没写成功时不打开目标页
- 兑换材料签发写审计 huya:exchange:kit(含账号与目标)
- 控制台脚本增加 huya.com 域校验与 Secure,与扩展路径保持一致
- 修复兑换记录轮询的跨账号串扰与卸载后 setState;兑换请求加 epoch 防止过期结果覆盖弹窗
- 新增 tests/test_huya_browser_exchange.py(13 项)并同步 docs/HUYA_BROWSER_EXCHANGE.md
|
2026-09-11 10:31:46 +08:00 |
|
 yml2213andCursor
|
e0810a9c0b
|
style: 按 ruff 格式化登录队列代码并跳过已删除文件的推送检查
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-09-10 11:32:29 +08:00 |
|
 yml2213andCursor
|
e81119117f
|
feat(huya): 多选登录改单线程队列并拆分路由与工作台
默认同时只登一个号,失败两次跳下一个,号间留间隔,结束后可一键重试失败账号。
顺带拆分虎牙路由与斗鱼工作台页面,并补齐 raw_cookie 重建入口。
Co-authored-by: Cursor <cursoragent@cursor.com>
|
2026-09-10 11:31:50 +08:00 |
|
yml2213
|
cbc7f7c9c5
|
fix(huya): 优化账号密码导入交互并将导入类型严格限制为四段格式
- 交互优化:将账号标签选择器移至弹窗顶部,避免下拉列表向下展开时遮挡底部的'确定'/'导入'按钮
- 格式限制:严格限制仅允许'账号----密码----手机号----接码链接'四段格式导入
- 前后端校验:前端逐行校验格式并提示具体错误行号,后端限制 require_four_segments=True 兜底
|
2026-09-06 14:00:24 +08:00 |
|
yml2213
|
d3005478a9
|
feat(huya): 支持四段式账号导入接码及旋转/文本点选多级验证码闭环过验
- 账号导入:支持'账号----密码----手机号----接码链接'四段式解析与持久化存储
- 旋转验证码 (rotate_auth / xz):逆向分析官方协议,基于圆周边界采样互相关算法秒级计算旋转还原角度
- 文本点选验证码 (dx_auth):内置成语与古诗名句语料,支持题干菜名提取与古诗/成语挖空正则求解及小图动态合成
- 短信二次验证 (sms_auth2):结合 sms_url 自动轮询接码链接并 Hex 编码提交官方过验
- 前端交互:增加接码标签、在线查询短信验证码、一键自动短信登录与测试接码链接功能
- 回归测试:新增旋转验证、短信接码流与文本点选测试用例(173 passed)
|
2026-09-06 13:56:44 +08:00 |
|
yml2213
|
4f9a6864eb
|
优化验证码展示
|
2026-09-06 13:02:37 +08:00 |
|
yml2213
|
8309072120
|
统一推送前Python代码格式
|
2026-09-05 19:25:46 +08:00 |
|
yml2213
|
178eba1eea
|
浏览器兑换独立成页面并按斗鱼模式优化导入
新增 /huya/browser-exchange 页面(精英宝典下方),支持导入账号与
执行兑换,客服仅见已分配账号;账号管理页移除该功能。导入弹窗对齐
斗鱼操作台:服务端分页筛选、可搜索标签、无 CK 不展示、导入本页/
一键导入全部/导入选中;新增 /accounts/ids 接口与 workbench
browser_exchange scope。
|
2026-09-05 18:30:29 +08:00 |
|
yml2213
|
95ad900ef0
|
统一推送前Python代码格式
|
2026-09-02 18:11:41 +08:00 |
|
yml2213
|
aaaa568916
|
修正活动WSS会话guid一致性
|
2026-09-02 18:07:31 +08:00 |
|
yml2213
|
92ba6cbc62
|
闭合QIMEI h38兼容键
|
2026-09-02 17:51:12 +08:00 |
|
yml2213
|
1f3773de28
|
修正QIMEI UUID42随机段生成
|
2026-09-02 17:15:06 +08:00 |
|
yml2213
|
17ee943753
|
复刻QIMEI UUID42并默认使用无头浏览器
|
2026-09-02 16:59:46 +08:00 |
|
yml2213
|
c62c025ced
|
整理虎牙文档并接入设备画像指纹
|
2026-09-02 13:42:32 +08:00 |
|
yml2213
|
61eb434138
|
双份cookie存储:raw_cookie 保存App原始凭据,与网页运行ck分离
网页运行ck(cookie列)含本地随机生成的网页设备字段,若被风控标记
无法还原纯净登录凭据;新增 raw_cookie 保存16字段App原始态,供
设备态重建/审计/复核登录有效性。
- HuyaAccount 加 raw_cookie 列(alembic 0034,MySQL TEXT nullable)
- HuyaLoginResult 加 raw_cookie 字段;App登录链补齐前快照原始凭据
- upsert_huya_cookie 支持双写;app-password-login 路由透传 raw_cookie
- 存量行 raw_cookie 为 NULL(老账号无快照),新登录自动填充
|
2026-09-01 23:15:20 +08:00 |
|
yml2213
|
9f3e3a74ce
|
修正活动WSS AUTH帧对齐9.1抓包字节
|
2026-09-01 20:25:31 +08:00 |
|
yml2213
|
727c32a5f5
|
接入匿名设备态协议补齐Cookie字段并放宽保存
|
2026-09-01 19:29:56 +08:00 |
|
yml2213
|
8447ca82ed
|
真实浏览器抓包与匿名设备态协议生成器
|
2026-09-01 19:17:36 +08:00 |
|
yml2213
|
48c37bb8d7
|
虎牙网页Cookie来源驱动合并与WSS传输门禁
|
2026-09-01 19:17:32 +08:00 |
|
yml2213
|
26514b332d
|
完成虎牙宝典WSS绑定与快照隔离重构
|
2026-09-01 12:40:22 +08:00 |
|
yml2213
|
eb065a7c77
|
接入虎牙精英宝典最新商城前置流程
|
2026-09-01 11:42:52 +08:00 |
|
yml2213
|
684e16a07a
|
重构虎牙精英宝典协议与支付状态链路
|
2026-09-01 11:31:15 +08:00 |
|
yml2213
|
955ba45488
|
虎牙精英宝典
|
2026-08-31 19:34:59 +08:00 |
|
yml2213
|
d391e2ce3e
|
移除二维码信封历史数据依赖
|
2026-08-31 17:43:55 +08:00 |
|
yml2213
|
05b1325a04
|
清理虎牙登录旧数据依赖并统一动态环境
|
2026-08-31 17:27:18 +08:00 |
|
yml2213
|
76b14b69b7
|
修复虎牙手机号登录并统一部署项目名
|
2026-08-31 16:11:08 +08:00 |
|
yml2213
|
09ab80e062
|
完成 Ruff 全量清理
|
2026-08-31 10:55:44 +08:00 |
|
yml2213
|
b58c6b4357
|
执行 Ruff 安全自动修复
|
2026-08-31 10:28:14 +08:00 |
|
yml2213
|
2a1d27f953
|
补充设备画像兜底说明
|
2026-08-30 23:05:20 +08:00 |
|
yml2213
|
f4ed518b50
|
统一虎牙 App 登录设备画像
|
2026-08-30 23:04:28 +08:00 |
|
yml2213
|
c891ac982e
|
type: 收敛测试 schemas 与协议层类型
|
2026-08-30 20:35:08 +08:00 |
|
yml2213
|
cbd314f4e5
|
type: 收窄测试与响应模型类型
|
2026-08-30 20:21:14 +08:00 |
|
yml2213
|
13b5aedd1d
|
test: 全面迁移 pytest 并加入格式门禁
|
2026-08-30 19:19:32 +08:00 |
|
yml2213
|
3ce1c7a51b
|
test: pytest 工程化落地 — 本地门禁、容器测试镜像、迁移链冒烟测试
- 门禁: 本地 pre-push 钩子(.git/hooks,推送前强制跑全量 pytest)
- Docker: 新增 test 镜像阶段(含 dev 依赖与 tests),compose 提供
--profile test run --rm test 入口;dev.sh 支持 ./dev.sh test
- 测试基建: 根目录 conftest.py 统一 DATABASE_URL/APP_ENCRYPTION_KEY,
移除 9 个测试文件内的重复 setdefault(含多余 import os)
- 迁移冒烟: tests/test_migrations.py 校验链线性、脚本可编译、空库整链
upgrade head 后与 Base.metadata 表/列/索引对齐
- 修复冒烟测试发现的漂移: YybRechargeTask.task_id 冗余 index=True
(唯一索引已覆盖,迁移链未建普通索引,模型与真实 schema 对齐)
- alembic.ini: path_separator=os 消除弃用告警;README 补测试章节
|
2026-08-30 18:54:00 +08:00 |
|
yml2213
|
3b3a4bebcb
|
feat(douyu): 代理写读分离 — 仅兑换/锁单/支付/开通/充值/送礼走代理
此前代理配置页开启后所有斗鱼任务(含查积分/刷列表等只读任务)统一走代理:
- API 模式每任务 fetch 新代理, 查询任务白白消耗代理额度
- 查询任务失败面被代理抖动放大, 但查询本不怕 IP 频控
新策略 (DOUYU_PROXY_TASK_TYPES 白名单):
- 写操作/消耗类: lock/pay/exchange_goods, exchange_esports/xpd_goods,
create_elite/esports/gold_qr, donate_* 走代理 (静态模式或 API 每任务新代理)
- 读操作类: query_*/refresh_*/get_*_bind_qr 等始终直连, 不消耗额度
- 判型用批次 task_type (同批次同类型, 与任务一致); 总开关仍为代理配置页
测试: 新增读任务直连/白名单覆盖断言, 三模式行为断言保留, 101 单测通过
|
2026-08-30 11:28:10 +08:00 |
|