fix(gpc): consume local helper OTP by selected record
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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',
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user