From 55e2299efac4c079437eaa51f7ccaa2c0de4ee77 Mon Sep 17 00:00:00 2001 From: zhuhjay Date: Sat, 7 Nov 2026 19:45:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(cmcc):=20=E7=AD=BE=E5=88=B0=E5=A4=A9?= =?UTF-8?q?=E6=95=B0=E5=A5=96=E5=8A=B1=E9=A2=86=E5=8F=96=20+=20=E6=9C=88?= =?UTF-8?q?=E7=AD=BE=E8=BD=AC=E7=9B=98=E6=8E=A5=E5=85=A5=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=20%=20=E6=A0=BC=E5=BC=8F=E5=8C=96=E7=82=B8=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - claim_day_prizes: mark31/taskAwardChance 查可领 → 逐个 taskAward/ 领取 (11-05 真机「1签2GB」同款接口;服务端发了才领,无奖静默) - month_lottery: 月签大转盘 /month/getMonthPrize(无池 data=null 静默跳过) - 单号流程扩展:签到 → 天数奖励 → 转盘,汇总进通知文案 - 修 3 处 % 格式化注入炸点(服务端文本含 % 时 TypeError, 真机日志 19:44 '天数奖励领取异常' 实证)改 .format --- cmcc/scrip_cmcc_mark.py | 99 +++++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 18 deletions(-) diff --git a/cmcc/scrip_cmcc_mark.py b/cmcc/scrip_cmcc_mark.py index 54b3a92..0795224 100644 --- a/cmcc/scrip_cmcc_mark.py +++ b/cmcc/scrip_cmcc_mark.py @@ -182,7 +182,7 @@ def send_notify(title, content): j = r.json() if "json" in r.headers.get("content-type", "") else {} ok = j.get("code") == 200 sent = sent or ok - log("[通知] pushplus code=%s %s" % (j.get("code"), "成功" if ok else (j.get("msg") or ""))) + log("[通知] pushplus code={} {}".format(j.get("code"), "成功" if ok else (j.get("msg") or ""))) except Exception as e: log("[通知] pushplus 异常 %r" % e) if not hook and not token: @@ -434,6 +434,46 @@ class Mark: def mark(self): return self.post("/mark31/domark", {"date": today_str()}) + # ---------------- 签到奖励领取 + 月签转盘(2026-11-07 端点表全量逆向) ---------------- + + def claim_day_prizes(self): + """领取「签到天数奖励」:mark31 的累计签到奖励(2/3/5/7/10/14/21/30天档)。 + 协议:GET taskAwardChance 查可领的 prizeId 列表 → 逐个 POST /mark31/taskAward/。 + (11-05 实测 21:29 真机领过「1签2GB」就是这个接口。)""" + out = [] + r = self.post("/mark31/taskAwardChance", {}) + if r.get("_token_invalid") or r.get("code") != "SUCCESS": + return out + for item in (r.get("data") or []): + pid = item.get("prizeId") or item.get("id") + name = item.get("prizeName") or item.get("name") or ("prize {}".format(pid)) + if not pid: + continue + time.sleep(THROTTLE) + rr = self.post("/mark31/taskAward/%s" % pid, {}) + ok = rr.get("code") == "SUCCESS" + out.append((name, ok, rr.get("msg") or "")) + log(" [奖] {} → {}".format(name, "✅领取" if ok else (rr.get("msg") or rr.get("code")))) + return out + + def month_lottery(self): + """「连续月签大转盘」:POST /month/getMonthPrize {channel,phone,prov,month}。 + 无池/无机会时服务端返回 SUCCESS+空 data(实测 monthInfo data=null)——不报错,静默跳过。""" + res = {"config": None, "draw": None} + r = self.post("/month/monthInfo", {}) + if r.get("_token_invalid") or not r.get("data"): + return res # 无转盘池(本月未开放) + res["config"] = r.get("data") + # 抽奖参数从 whoami 的数据拿不到 phone/prov(服务端掩码),从 monthInfo 里带啥用啥 + d = r["data"] or {} + payload = {k: d.get(k) for k in ("channel", "phone", "prov", "month") if d.get(k)} + if not payload.get("month"): + payload["month"] = today_str()[:6] + time.sleep(THROTTLE) + rr = self.post("/month/getMonthPrize", payload) + res["draw"] = rr + return res + # ---------------------------------------------------------------- 单号流程 @@ -471,25 +511,48 @@ def run_one_account(name, payload, stats): acct["detail"] = "markstatus 时 token 已失效" return 3, acct log("[%s] 今日已签=%s 累计=%s天" % (name, st["signed"], st["days"])) - if st["signed"]: - acct["ok"] = True - acct["detail"] = "今日已签到,幂等跳过(累计 %s 天)" % st["days"] - return 0, acct - mk = m.mark() - if mk.get("_token_invalid"): - acct["detail"] = "domark 时 token 失效" - return 3, acct - log("[%s] 签到 code=%s status=%s msg=%s" % (name, mk.get("code"), mk.get("status"), mk.get("msg"))) + extras = [] + if not st["signed"]: + mk = m.mark() + if mk.get("_token_invalid"): + acct["detail"] = "domark 时 token 失效" + return 3, acct + log("[{}] 签到 code={} status={} msg={}".format(name, mk.get("code"), mk.get("status"), mk.get("msg"))) + st2 = m.state() + if not (st2 and st2["signed"]): + acct["detail"] = "复核未通过:%s/%s" % (mk.get("code"), mk.get("status")) + return 1, acct + extras.append("签到✅ %s→%s天" % (st["days"], st2["days"])) + days_now = st2["days"] + else: + extras.append("已签(%s天)" % st["days"]) + days_now = st["days"] - st2 = m.state() - if st2 and st2["signed"]: - acct["ok"] = True - acct["detail"] = "签到成功:累计 %s→%s 天(%s/%s)" % ( - st["days"], st2["days"], mk.get("code"), mk.get("status")) - return 0, acct - acct["detail"] = "复核未通过:%s/%s" % (mk.get("code"), mk.get("status")) - return 1, acct + # 签到天数奖励(累计档位奖:7天10元话费这类,服务端发了才能领) + try: + prizes = m.claim_day_prizes() + for pname, ok, msg in prizes: + extras.append("奖[%s]%s" % (pname, "✅" if ok else "×")) + except Exception as e: + log("[%s] 天数奖励领取异常 %r" % (name, e)) + + # 月签转盘(有池才抽,无池静默) + try: + lot = m.month_lottery() + if lot.get("draw"): + dr = lot["draw"] + prize = ((dr.get("data") or {}).get("prize") if isinstance(dr.get("data"), dict) else None) + if dr.get("code") == "SUCCESS": + extras.append("转盘✅%s" % ((prize or {}).get("name", "中奖") if prize else "已抽")) + else: + extras.append("转盘×%s" % (dr.get("msg") or "")) + except Exception as e: + log("[%s] 月签转盘异常 %r" % (name, e)) + + acct["ok"] = True + acct["detail"] = " ".join(extras) + "|累计 %s 天" % days_now + return 0, acct # ---------------------------------------------------------------- 主流程