This commit is contained in:
eric
2026-03-31 13:05:02 -05:00
parent c3a61831ca
commit 65b58d613c

View File

@@ -75,9 +75,15 @@ def aes_decrypt_base64(cipher_b64: str, encoding_aes_key: str) -> str:
cipher = AES.new(aes_key, AES.MODE_CBC, iv) cipher = AES.new(aes_key, AES.MODE_CBC, iv)
decrypted = pkcs5_unpadding(cipher.decrypt(cipher_bytes)) decrypted = pkcs5_unpadding(cipher.decrypt(cipher_bytes))
try: try:
if len(decrypted) < 20:
raise ValueError("payload too short")
content = decrypted[16:] content = decrypted[16:]
msg_len = struct.unpack("!I", content[:4])[0] msg_len = struct.unpack("!I", content[:4])[0]
msg = content[4 : 4 + msg_len] msg_start = 4
msg_end = msg_start + msg_len
if msg_end > len(content):
raise ValueError("msg length out of range")
msg = content[msg_start:msg_end]
text = msg.decode("utf-8") text = msg.decode("utf-8")
if text: if text:
return text return text
@@ -434,8 +440,8 @@ async def _handle_wechat_request(request: Request, app_id: Optional[str], backgr
response_app_id = str(data.get("ChannelId", "") or data.get("appid", "")).strip() or APP_ID response_app_id = str(data.get("ChannelId", "") or data.get("appid", "")).strip() or APP_ID
else: else:
resp_plain = json.dumps({"answer_type": "text", "text_info": {"short_answer": answer_text}}, ensure_ascii=False) resp_plain = json.dumps({"answer_type": "text", "text_info": {"short_answer": answer_text}}, ensure_ascii=False)
# thirdapi 场景也要携带 app_id 参与加密,否则平台可能判定回包无效 # 与原始 chatbot 服务保持一致:thirdapiURL 带 app_id)回包使用纯 AES不拼 app_id
response_app_id = (app_id or APP_ID).strip() if isinstance(app_id, str) else APP_ID response_app_id = None if app_id else APP_ID
return aes_encrypt_base64(resp_plain, ENCODING_AES_KEY, response_app_id) return aes_encrypt_base64(resp_plain, ENCODING_AES_KEY, response_app_id)
@@ -555,6 +561,11 @@ def chatbot_private_message_page():
<section class="card"> <section class="card">
<h2>Chatbot 私信调试台</h2> <h2>Chatbot 私信调试台</h2>
<div id="status">准备就绪</div> <div id="status">准备就绪</div>
<label>默认配置</label>
<select id="preset" style="width:100%;border-radius:8px;border:1px solid #475569;background:#0b1220;color:#e2e8f0;padding:10px;box-sizing:border-box;">
<option value="eric">Eric在旅行</option>
<option value="xidu">异度世界</option>
</select>
<label>authtoken</label> <label>authtoken</label>
<textarea id="authtoken" placeholder="粘贴抓包 authtoken"></textarea> <textarea id="authtoken" placeholder="粘贴抓包 authtoken"></textarea>
<label>wxbot_bid</label> <label>wxbot_bid</label>
@@ -588,6 +599,16 @@ def chatbot_private_message_page():
<script> <script>
const $ = (id) => document.getElementById(id); const $ = (id) => document.getElementById(id);
const presets = {
eric: {
authtoken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyaWQiOjE5MzE1MjcsIm9wZW5pZCI6Im85VS04NW1DSXZ0eDZ0a0pteTQyMkkzcUNHVWciLCJzaWduZXRpbWUiOjE3NzQ5MzM0NDQ4MTgsImlhdCI6MTc3NDkzMzQ0NCwiZXhwIjoxNzc3NTI1NDQ0fQ.iC9vdjBqa2LGlqA6F-Dg4GcfDyv3Rp8JwpBaO3j_eE4",
wxbot_bid: "75021053883a9090c67d5becde7f4b0a",
},
xidu: {
authtoken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyaWQiOjE5MzE1MjcsIm9wZW5pZCI6Im85VS04NW1DSXZ0eDZ0a0pteTQyMkkzcUNHVWciLCJzaWduZXRpbWUiOjE3NzQ5MzM0NDQ4MTgsImlhdCI6MTc3NDkzMzQ0NCwiZXhwIjoxNzc3NTI1NDQ0fQ.iC9vdjBqa2LGlqA6F-Dg4GcfDyv3Rp8JwpBaO3j_eE4",
wxbot_bid: "4888c6ab5cb70dcc3adea1e2d2ff0201",
}
};
function setStatus(s){ $("status").textContent = s; } function setStatus(s){ $("status").textContent = s; }
function renderJson(v){ $("out").textContent = JSON.stringify(v, null, 2); } function renderJson(v){ $("out").textContent = JSON.stringify(v, null, 2); }
function renderUsers(users){ function renderUsers(users){
@@ -604,6 +625,13 @@ def chatbot_private_message_page():
}).join(""); }).join("");
} }
function applyPreset(key){
const p = presets[key];
if(!p) return;
$("authtoken").value = p.authtoken;
$("wxbot_bid").value = p.wxbot_bid;
}
async function queryPm(){ async function queryPm(){
try{ try{
setStatus("查询中..."); setStatus("查询中...");
@@ -645,6 +673,9 @@ def chatbot_private_message_page():
renderJson({ error: String(e) }); renderJson({ error: String(e) });
} }
} }
$("preset").addEventListener("change", (e) => applyPreset(e.target.value));
applyPreset("eric");
</script> </script>
</body> </body>
</html> </html>