64 lines
2.6 KiB
Python
64 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
PATCHER_PATH = Path(__file__).resolve().parents[1] / 'fixes' / 'patch_openclaw_weixin_bigint.py'
|
|
|
|
|
|
def load_patcher():
|
|
spec = importlib.util.spec_from_file_location('patch_openclaw_weixin_bigint', PATCHER_PATH)
|
|
assert spec is not None and spec.loader is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_api_patch_is_idempotent_and_scoped() -> None:
|
|
patcher = load_patcher()
|
|
ts = '\n'.join([
|
|
'import { fileURLToPath } from "node:url";',
|
|
'import { redactBody, redactUrl } from "../util/redact.js";',
|
|
'const resp: GetUpdatesResp = JSON.parse(rawText);',
|
|
])
|
|
js = '\n'.join([
|
|
'import { fileURLToPath } from "node:url";',
|
|
'import { redactBody, redactUrl } from "../util/redact.js";',
|
|
'const resp = JSON.parse(rawText);',
|
|
])
|
|
types = 'export interface WeixinMessage {\n message_id?: number;\n}\n'
|
|
|
|
ts_once = patcher.patch_api_ts(ts)
|
|
js_once = patcher.patch_api_js(js)
|
|
types_once = patcher.patch_types_ts(types)
|
|
|
|
assert patcher.patch_api_ts(ts_once) == ts_once
|
|
assert patcher.patch_api_js(js_once) == js_once
|
|
assert patcher.patch_types_ts(types_once) == types_once
|
|
assert 'parseWeixinGetUpdatesJson(rawText)' in ts_once
|
|
assert 'parseWeixinGetUpdatesJson(rawText)' in js_once
|
|
assert 'message_id?: string | number;' in types_once
|
|
|
|
|
|
def test_node_reviver_preserves_only_weixin_exact_ids() -> None:
|
|
script = '''
|
|
const ids = new Set(["message_id", "msg_id", "root_id", "parent_id", "server_msg_id", "new_msg_id"]);
|
|
const parsed = JSON.parse('{"ret":0,"seq":42,"msgs":[{"message_id":7482038281766381234,"create_time_ms":1783856936191,"item_list":[{"msg_id":"3123141975110186863"}]}]}', (key, value, context) => {
|
|
if (!ids.has(key) || value == null || typeof value === "string") return value;
|
|
if (typeof value !== "number" || !context?.source || !/^(?:0|[1-9]\\d*)$/.test(context.source)) throw new Error("unsafe id");
|
|
return context.source;
|
|
});
|
|
console.log(JSON.stringify({ messageId: parsed.msgs[0].message_id, msgId: parsed.msgs[0].item_list[0].msg_id, seqType: typeof parsed.seq, timestampType: typeof parsed.msgs[0].create_time_ms }));
|
|
'''
|
|
completed = subprocess.run(['node', '-e', script], check=True, capture_output=True, text=True)
|
|
result = json.loads(completed.stdout)
|
|
assert result == {
|
|
'messageId': '7482038281766381234',
|
|
'msgId': '3123141975110186863',
|
|
'seqType': 'number',
|
|
'timestampType': 'number',
|
|
}
|