From 98a6b7092d4d8157097046a4c90915d30f5fbf42 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Thu, 7 May 2026 13:15:01 +0800 Subject: [PATCH] fix(gpc): consume local helper OTP by selected record --- scripts/gpc_sms_helper_macos.py | 45 ++++++++++++++++---- tests/gpc-sms-helper-script.test.js | 64 +++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/scripts/gpc_sms_helper_macos.py b/scripts/gpc_sms_helper_macos.py index a4d4a36..7300bf4 100644 --- a/scripts/gpc_sms_helper_macos.py +++ b/scripts/gpc_sms_helper_macos.py @@ -267,24 +267,51 @@ def consume_otp_record(phone: str = "", record: Optional[dict] = None) -> None: consumed_message_id = str((record or {}).get("message_id") or "").strip() consumed_rowid = int((record or {}).get("rowid") or 0) - def should_keep(item: object) -> bool: + def is_consumed_record(item: object) -> bool: if not isinstance(item, dict): return False - if wanted: - return not record_matches_phone(item, wanted) - if consumed_message_id: - return str(item.get("message_id") or "").strip() != consumed_message_id - if consumed_rowid: - return int(item.get("rowid") or 0) != consumed_rowid + if consumed_message_id and str(item.get("message_id") or "").strip() == consumed_message_id: + return True + if consumed_rowid and int(item.get("rowid") or 0) == consumed_rowid: + return True return False + def is_same_record(left: object, right: object) -> bool: + if not isinstance(left, dict) or not isinstance(right, dict): + return False + left_message_id = str(left.get("message_id") or "").strip() + right_message_id = str(right.get("message_id") or "").strip() + if left_message_id and right_message_id and left_message_id == right_message_id: + return True + left_rowid = int(left.get("rowid") or 0) + right_rowid = int(right.get("rowid") or 0) + if left_rowid > 0 and right_rowid > 0 and left_rowid == right_rowid: + return True + return left == right + with STATE_LOCK: records = STATE.get("otps") if not isinstance(records, list): records = [] - STATE["otps"] = [item for item in records if should_keep(item)] + + if consumed_message_id or consumed_rowid: + next_records = [item for item in records if isinstance(item, dict) and not is_consumed_record(item)] + elif wanted: + removed_once = False + next_records = [] + for item in records: + if not isinstance(item, dict): + continue + if not removed_once and record_matches_phone(item, wanted): + removed_once = True + continue + next_records.append(item) + else: + next_records = [] + + STATE["otps"] = next_records last_otp = STATE.get("last_otp") - if isinstance(last_otp, dict) and not should_keep(last_otp): + if isinstance(last_otp, dict) and not any(is_same_record(last_otp, item) for item in STATE["otps"]): STATE["last_otp"] = STATE["otps"][0] if STATE["otps"] else None diff --git a/tests/gpc-sms-helper-script.test.js b/tests/gpc-sms-helper-script.test.js index 2b62bc7..f3ebb59 100644 --- a/tests/gpc-sms-helper-script.test.js +++ b/tests/gpc-sms-helper-script.test.js @@ -135,3 +135,67 @@ print(json.dumps(payload)) global_after: '222222', }); }); + +test('GPC SMS helper consume keeps newer same-phone OTP when consuming an older record', () => { + const code = ` +import importlib.util +import json + +script_path = ${JSON.stringify(scriptPath)} +spec = importlib.util.spec_from_file_location("gpc_sms_helper_macos", script_path) +module = importlib.util.module_from_spec(spec) +spec.loader.exec_module(module) + +record_old = { + "otp": "111111", + "code": "111111", + "message_id": "old", + "rowid": 1, + "phone_e164": "+8613800138000", + "account_phone": "+8613800138000", + "received_at": "2026-05-05T00:00:00+00:00", +} +record_new = { + "otp": "222222", + "code": "222222", + "message_id": "new", + "rowid": 2, + "phone_e164": "+8613800138000", + "account_phone": "+8613800138000", + "received_at": "2026-05-05T00:00:10+00:00", +} +record_other = { + "otp": "333333", + "code": "333333", + "message_id": "other", + "rowid": 3, + "phone_e164": "+8618984829950", + "account_phone": "+8618984829950", + "received_at": "2026-05-05T00:00:20+00:00", +} +module.STATE.update({"last_otp": record_new, "otps": [record_new, record_old, record_other]}) +module.consume_otp_record(phone="+8613800138000", record=record_old) +state_after = module.get_state() +payload = { + "same_phone_after": module.select_otp_record(state_after, phone="+8613800138000")["otp"], + "other_phone_after": module.select_otp_record(state_after, phone="+8618984829950")["otp"], + "records_after": [item["message_id"] for item in state_after.get("otps", [])], + "global_after": module.select_otp_record(state_after)["otp"], +} +print(json.dumps(payload)) +`; + const run = runPython(['-c', code], { + timeout: 3000, + env: { GPC_SMS_HELPER_ALLOW_NON_MAC: '1' }, + }); + if (!run) { + return; + } + assert.equal(run.status, 0, run.stderr); + assert.deepEqual(JSON.parse(run.stdout.trim()), { + same_phone_after: '222222', + other_phone_after: '333333', + records_after: ['new', 'other'], + global_after: '222222', + }); +});