feat(mmp): 领取进度/过期状态,并展示红包与领取人ID
状态优先显示已全部领取或已领取N/M,未领完才附加已过期;列表与最高最低补全 activityId、receiverId。
This commit is contained in:
@@ -19,8 +19,8 @@ PACKETS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "mmp_pac
|
||||
HOOK_STATUS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "mmp_hook_status.json")
|
||||
|
||||
# 与 xposed-module / App MmpModuleInfo 同步
|
||||
EXPECTED_MODULE_CODE = 3
|
||||
EXPECTED_MODULE_NAME = "1.2.0"
|
||||
EXPECTED_MODULE_CODE = 5
|
||||
EXPECTED_MODULE_NAME = "1.2.2"
|
||||
|
||||
_messages = deque(maxlen=MAX_MESSAGES)
|
||||
_mmp_messages = deque(maxlen=MAX_MESSAGES)
|
||||
@@ -629,6 +629,9 @@ def _normalize_synced_packet(raw):
|
||||
elif sum_claimed:
|
||||
total = "{0:.2f}".format(sum_claimed)
|
||||
issued = raw.get("issuedAt") or raw.get("issued") or ""
|
||||
expires = raw.get("expiresAt") or raw.get("expire") or raw.get("expireTime") or ""
|
||||
status = raw.get("status") or raw.get("activityStatus") or ""
|
||||
finished = bool(raw.get("finished")) or _is_terminal_status(status) or _is_expire_passed(expires)
|
||||
return {
|
||||
"packetId": pid,
|
||||
"title": raw.get("title") or "TNG 红包",
|
||||
@@ -637,11 +640,15 @@ def _normalize_synced_packet(raw):
|
||||
"total": total,
|
||||
"via": raw.get("via") or "phone-sync",
|
||||
"issuedAt": issued,
|
||||
"expiresAt": expires,
|
||||
"status": status,
|
||||
"updatedAt": raw.get("updatedAt") or "",
|
||||
"fetchedAt": raw.get("updatedAt") or raw.get("fetchedAt") or _now_iso(),
|
||||
"latestAt": issued or raw.get("updatedAt") or "",
|
||||
"finished": bool(raw.get("finished")),
|
||||
"finished": finished,
|
||||
"snapshots": int(raw.get("snapshots") or 1),
|
||||
"claimedCount": int(raw.get("claimedCount") or 0),
|
||||
"totalCount": int(raw.get("totalCount") or 0),
|
||||
"leaderboard": norm_board,
|
||||
"claimantCount": len(norm_board) if norm_board else int(raw.get("claimantCount") or 0),
|
||||
"sumClaimed": sum_claimed,
|
||||
@@ -741,7 +748,8 @@ def _mmp_packets():
|
||||
key = str(packet_id)
|
||||
issued = meta.get("issued") or ""
|
||||
finished = str(meta.get("done") or "").lower() in ("1", "true") \
|
||||
or str(meta.get("status") or "").upper() in ("FINISHED", "COMPLETE", "COMPLETED", "EXPIRED")
|
||||
or _is_terminal_status(meta.get("status") or "") \
|
||||
or _is_expire_passed(meta.get("expire") or meta.get("expireTime") or "")
|
||||
item = {
|
||||
"packetId": key,
|
||||
"title": msg.get("title") or "TNG 红包",
|
||||
@@ -750,12 +758,15 @@ def _mmp_packets():
|
||||
"total": meta.get("total") or "",
|
||||
"via": meta.get("via") or "",
|
||||
"issuedAt": issued,
|
||||
"expiresAt": meta.get("expire") or meta.get("expireTime") or "",
|
||||
"status": meta.get("status") or "",
|
||||
"fetchedAt": msg.get("receivedAt") or "",
|
||||
"latestAt": issued or (msg.get("receivedAt") or ""),
|
||||
"finished": finished,
|
||||
"snapshots": 1,
|
||||
"claims": claims,
|
||||
}
|
||||
_apply_counts_from_meta(item, meta)
|
||||
existing = packets.get(key)
|
||||
def _score(it):
|
||||
return (
|
||||
@@ -801,6 +812,10 @@ def _mmp_packets():
|
||||
p["bestAmount"] = (best or {}).get("amountText") or ""
|
||||
p["worstNick"] = (worst or {}).get("nickname") or ""
|
||||
p["worstAmount"] = (worst or {}).get("amountText") or ""
|
||||
if not p.get("claimedCount"):
|
||||
p["claimedCount"] = len(ranked)
|
||||
if p.get("totalCount") and int(p.get("claimedCount") or 0) >= int(p.get("totalCount") or 0):
|
||||
p["finished"] = True
|
||||
del p["claims"]
|
||||
result.append(p)
|
||||
# 合并手机全量同步落盘数据(电脑重启后仍可看)
|
||||
@@ -821,6 +836,9 @@ def _mmp_packets():
|
||||
merged["latestAt"] = merged["issuedAt"]
|
||||
by_id[key] = merged
|
||||
result = list(by_id.values())
|
||||
for p in result:
|
||||
_refresh_packet_closed(p)
|
||||
p["statusLabel"] = _packet_status_label(p)
|
||||
result.sort(key=lambda x: _mmp_time_sort_key(x.get("issuedAt") or x.get("latestAt") or ""), reverse=True)
|
||||
return result
|
||||
|
||||
@@ -834,6 +852,100 @@ def _mmp_time_sort_key(text):
|
||||
return s
|
||||
|
||||
|
||||
def _parse_mmp_time_ms(text):
|
||||
s = (text or "").strip()
|
||||
if not s:
|
||||
return 0
|
||||
m = re.match(r"^(\d{2})/(\d{2})/(\d{4})(?:\s+(\d{2}):(\d{2})(?::(\d{2}))?)?", s)
|
||||
if m:
|
||||
try:
|
||||
dt = datetime(
|
||||
int(m.group(3)), int(m.group(2)), int(m.group(1)),
|
||||
int(m.group(4) or 23), int(m.group(5) or 59), int(m.group(6) or 59))
|
||||
return int(dt.timestamp() * 1000)
|
||||
except ValueError:
|
||||
return 0
|
||||
m = re.match(r"^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?", s)
|
||||
if m:
|
||||
try:
|
||||
dt = datetime(
|
||||
int(m.group(1)), int(m.group(2)), int(m.group(3)),
|
||||
int(m.group(4) or 0), int(m.group(5) or 0), int(m.group(6) or 0))
|
||||
return int(dt.timestamp() * 1000)
|
||||
except ValueError:
|
||||
return 0
|
||||
if re.match(r"^\d{13}$", s):
|
||||
return int(s)
|
||||
if re.match(r"^\d{10}$", s):
|
||||
return int(s) * 1000
|
||||
return 0
|
||||
|
||||
|
||||
def _is_terminal_status(status):
|
||||
s = (status or "").upper()
|
||||
if not s:
|
||||
return False
|
||||
return any(k in s for k in (
|
||||
"FINISH", "COMPLETE", "EXPIRE", "ENDED", "CLOSED", "CANCEL", "DONE"))
|
||||
|
||||
|
||||
def _is_expire_passed(expire_text):
|
||||
ms = _parse_mmp_time_ms(expire_text)
|
||||
return ms > 0 and int(time.time() * 1000) >= ms
|
||||
|
||||
|
||||
def _refresh_packet_closed(p):
|
||||
if not isinstance(p, dict):
|
||||
return p
|
||||
if p.get("finished"):
|
||||
return p
|
||||
if _is_terminal_status(p.get("status") or "") or _is_expire_passed(
|
||||
p.get("expiresAt") or p.get("expire") or ""):
|
||||
p["finished"] = True
|
||||
return p
|
||||
|
||||
|
||||
def _packet_status_label(p):
|
||||
_refresh_packet_closed(p)
|
||||
claimed = int(p.get("claimedCount") or 0)
|
||||
total = int(p.get("totalCount") or 0)
|
||||
board_n = len(p.get("leaderboard") or []) if isinstance(p.get("leaderboard"), list) else 0
|
||||
claimed = max(claimed, board_n, int(p.get("claimantCount") or 0))
|
||||
fully = total > 0 and claimed >= total
|
||||
if fully:
|
||||
progress = "已全部领取"
|
||||
elif total > 0:
|
||||
progress = "已领取 {0}/{1} 人".format(claimed, total)
|
||||
elif claimed > 0:
|
||||
progress = "已领取 {0} 人".format(claimed)
|
||||
else:
|
||||
progress = "未领取" if p.get("finished") else "领取中"
|
||||
expired = _is_expire_passed(p.get("expiresAt") or "") or any(
|
||||
k in (p.get("status") or "").upper() for k in ("EXPIRE", "ENDED", "CLOSED", "CANCEL"))
|
||||
if expired and not fully:
|
||||
return progress + " · 已过期"
|
||||
return progress
|
||||
|
||||
|
||||
def _apply_counts_from_meta(item, meta):
|
||||
counts = (meta.get("counts") or "").strip()
|
||||
if counts and "/" in counts:
|
||||
left, right = counts.split("/", 1)
|
||||
try:
|
||||
item["claimedCount"] = int(left.strip() or 0)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
item["totalCount"] = int(right.strip() or 0)
|
||||
except ValueError:
|
||||
pass
|
||||
board = item.get("claims") or item.get("leaderboard") or []
|
||||
if not item.get("claimedCount") and isinstance(board, list):
|
||||
item["claimedCount"] = len(board)
|
||||
if item.get("totalCount") and item.get("claimedCount", 0) >= item["totalCount"]:
|
||||
item["finished"] = True
|
||||
|
||||
|
||||
def _mmp_html_page(filename="mmp_page.html"):
|
||||
page = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename)
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user