#!/usr/bin/env python3
"""给 wechat4u 打补丁: 降低微信风控识别特征
1. request.js: UA → 最新 Chrome 126 Windows (每账号可不同)
2. request.js: connection close → keep-alive
3. global.js: DeviceID 持久化 (不再每次随机)
4. wechat.js: syncPolling 加 25±5s 间隔 (模拟真人)
"""
import subprocess, os, re, shutil, time

def run(cmd, timeout=30):
    r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
    return (r.stdout + r.stderr).strip()

TMP = "/tmp/wechat4u-patch"
os.makedirs(TMP, exist_ok=True)

# 1. 拷贝文件出容器
print("=== 1. 拷贝文件出容器 ===")
files = {
    "request.js": "/app/node_modules/wechat4u/lib/util/request.js",
    "wechat.js": "/app/node_modules/wechat4u/lib/wechat.js",
    "global.js": "/app/node_modules/wechat4u/lib/util/global.js",
}
for name, path in files.items():
    run(["docker", "cp", f"wxBotWebhook:{path}", f"{TMP}/{name}"])
    print(f"  {name}: {os.path.getsize(f'{TMP}/{name}')}b")

# 2. 打补丁
print("\n=== 2. 打补丁 ===")

# 2.1 request.js: UA + connection
p = f"{TMP}/request.js"
c = open(p, encoding='utf-8').read()
old_ua = "defaults.headers['user-agent'] = defaults.headers['user-agent'] || 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36';"
new_ua = "defaults.headers['user-agent'] = defaults.headers['user-agent'] || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36';"
if old_ua in c:
    c = c.replace(old_ua, new_ua)
    print("  ✅ UA → Chrome 126 Windows")
else:
    print("  ⚠️ UA 未匹配")

old_conn = "defaults.headers['connection'] = defaults.headers['connection'] || 'close';"
new_conn = "defaults.headers['connection'] = defaults.headers['connection'] || 'keep-alive';"
if old_conn in c:
    c = c.replace(old_conn, new_conn)
    print("  ✅ connection → keep-alive")
else:
    print("  ⚠️ connection 未匹配")

# 补全浏览器 headers (Accept, Accept-Language 等)
old_headers = "defaults.headers['connection'] = defaults.headers['connection'] || 'keep-alive';"
if "Accept-Language" not in c:
    # 在 connection 行后插入完整浏览器 headers
    insert = """defaults.headers['Accept'] = defaults.headers['Accept'] || 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
defaults.headers['Accept-Language'] = defaults.headers['Accept-Language'] || 'zh-CN,zh;q=0.9,en;q=0.8';
defaults.headers['Accept-Encoding'] = defaults.headers['Accept-Encoding'] || 'gzip, deflate, br';
defaults.headers['Upgrade-Insecure-Requests'] = defaults.headers['Upgrade-Insecure-Requests'] || '1';
defaults.headers['Sec-Fetch-Dest'] = defaults.headers['Sec-Fetch-Dest'] || 'document';
defaults.headers['Sec-Fetch-Mode'] = defaults.headers['Sec-Fetch-Mode'] || 'navigate';
defaults.headers['Sec-Fetch-Site'] = defaults.headers['Sec-Fetch-Site'] || 'none';
defaults.headers['Sec-Fetch-User'] = defaults.headers['Sec-Fetch-User'] || '?1';
"""
    c = c.replace(old_headers, old_headers + "\n" + insert)
    print("  ✅ 补全浏览器 headers")
open(p, 'w', encoding='utf-8').write(c)

# 2.2 global.js: DeviceID 持久化
p = f"{TMP}/global.js"
c = open(p, encoding='utf-8').read()
old_did = """function getDeviceID() {
  return 'e' + ('' + Math.random().toFixed(15)).substring(2, 17);
}"""
new_did = """var _persistDeviceID = '';
function getDeviceID() {
  if (!_persistDeviceID) {
    _persistDeviceID = 'e' + ('' + Math.random().toFixed(15)).substring(2, 17);
  }
  return _persistDeviceID;
}"""
if old_did in c:
    c = c.replace(old_did, new_did)
    print("  ✅ DeviceID 持久化 (同进程固定)")
else:
    print("  ⚠️ DeviceID 未匹配")
open(p, 'w', encoding='utf-8').write(c)

# 2.3 wechat.js: syncPolling 加 25±5s 间隔
p = f"{TMP}/wechat.js"
c = open(p, encoding='utf-8').read()
# 找到 .then 里的 _this3.syncPolling(id);  (立即递归)
old_sync = """      }).then(function () {
        _this3.lastSyncTime = Date.now();
        _this3.syncPolling(id);
      }).catch(function (err) {"""
new_sync = """      }).then(function () {
        _this3.lastSyncTime = Date.now();
        setTimeout(function () {
          _this3.syncPolling(id);
        }, 25000 + Math.floor(Math.random() * 5000));
      }).catch(function (err) {"""
if old_sync in c:
    c = c.replace(old_sync, new_sync)
    print("  ✅ syncPolling 间隔 25±5s")
else:
    print("  ⚠️ syncPolling 未匹配")
open(p, 'w', encoding='utf-8').write(c)

# 3. 语法检查 (node)
print("\n=== 3. 语法检查 ===")
for name in ["request.js", "global.js", "wechat.js"]:
    r = run(["docker", "exec", "wxBotWebhook", "node", "--check", f"/tmp/{name}"], timeout=15)
    # node --check 需要文件在容器内, 先拷贝验证
    run(["docker", "cp", f"{TMP}/{name}", f"wxBotWebhook:/tmp/{name}"])
    r = run(["docker", "exec", "wxBotWebhook", "node", "--check", f"/tmp/{name}"], timeout=15)
    print(f"  {name}: {'OK' if 'SyntaxError' not in r else r[:200]}")

print("\n=== 补丁完成, 等待确认后拷回 ===")
print("验证通过后: 拷回容器 + 重启 wxBotWebhook")
