# -*- coding: utf-8 -*-
"""探索 WebUploader API 并上传封面图"""
import sys, socket, json, time, base64, os, glob
from base64 import b64encode
sys.stdout.reconfigure(encoding='utf-8')
HOST = "localhost"; PORT = 28800
PAGE_ID = "70039F329097C14448996F189E3A42A1"

IMG_LIST = glob.glob(r'D:\wxpic\*.jpg') + glob.glob(r'D:\wxpic\*.png')
IMG_PATH = max(IMG_LIST, key=os.path.getmtime) if IMG_LIST else None
with open(IMG_PATH, 'rb') as f:
    IMG_B64 = b64encode(f.read()).decode()
ext = os.path.splitext(IMG_PATH)[1].lower()
IMG_MIME = 'image/jpeg' if ext in ['.jpg','.jpeg'] else 'image/png'
print("[INFO] 图片:", IMG_PATH, "size:", len(IMG_B64))

def ws():
    import urllib.parse
    u = "ws://%s:%s/devtools/page/%s" % (HOST, PORT, PAGE_ID)
    p = urllib.parse.urlparse(u)
    s = socket.create_connection((p.hostname, p.port or 80), timeout=15)
    req = ("GET %s HTTP/1.1\r\nHost: %s:%s\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n" % (p.path, p.hostname, p.port))
    s.send(req.encode())
    resp = b''
    while b'\r\n\r\n' not in resp: resp += s.recv(4096)
    return s

def send(s, d):
    d = d.encode('utf-8'); n = len(d); m = b'\x01\x02\x03\x04'
    if n <= 125: h = bytes([0x81, n|0x80]) + m
    elif n <= 65535: h = bytes([0x81, 0xFE]) + n.to_bytes(2,'big') + m
    else: h = bytes([0x81, 0xFF]) + n.to_bytes(8,'big') + m
    s.send(h + bytes(d[i]^m[i%4] for i in range(n)))

def recv(s):
    def rx(n):
        b = b''
        while len(b) < n: b += s.recv(n-len(b))
        return b
    h = rx(2); n = h[1]&0x7f
    if n == 126: n = int.from_bytes(rx(2),'big')
    elif n == 127: n = int.from_bytes(rx(8),'big')
    return rx(n).decode('utf-8')

_mid = 0
def cdp(s, js, timeout=20):
    global _mid
    _mid += 1
    send(s, json.dumps({'id':_mid,'method':'Runtime.evaluate','params':{'expression':js,'returnByValue':True}}))
    s.settimeout(timeout)
    for _ in range(300):
        try:
            r = json.loads(recv(s))
            if r.get('id') == _mid:
                return r.get('result',{}).get('result',{}).get('value','')
        except: pass
    return ''

s = ws()
print("[OK] Connected\n")

# 1. 探索 WebUploader
r = cdp(s, """
(function() {
  var wu = window.WebUploader;
  if (!wu) return 'not found';
  var info = {
    version: wu.version,
    keys: Object.keys(wu).join(',')
  };
  // try createInstance
  try {
    info.createInstance = typeof wu.createInstance;
  } catch(e) { info.createInstance = 'err'; }
  try {
    info.Uploader = typeof wu.Uploader;
  } catch(e) { info.Uploader = 'err'; }
  return JSON.stringify(info);
})()
""")
print("[WebUploader]", r[:300] if r else 'empty')

# 2. 找 WebUploader 实例
r = cdp(s, """
(function() {
  var result = [];
  for (var k in window) {
    if (k.toLowerCase().indexOf('uploader') > -1 || k.indexOf('Uploader') > -1) {
      try {
        var v = window[k];
        if (v && typeof v === 'object') {
          var keys = Object.keys(v);
          result.push({name: k, keys: keys.join(','), type: typeof v});
        }
      } catch(e) {}
    }
  }
  return JSON.stringify(result);
})()
""")
print("[Uploader实例]", r[:400] if r else 'empty')

# 3. 找 $EDITORUI_V2 - 这是编辑器的 UI
r = cdp(s, """
(function() {
  var ed = window.$EDITORUI_V2;
  if (!ed) return 'not found';
  var keys = Object.keys(ed);
  return JSON.stringify({keys: keys.join(','), edui1: ed.edui1 ? 'yes' : 'no'});
})()
""")
print("[$EDITORUI_V2]", r[:200] if r else 'empty')

# 4. 找封面上传相关的 API
r = cdp(s, """
(function() {
  // 找 cheetah 相关的全局对象
  var result = [];
  for (var k in window) {
    if (k.indexOf('Cheetah') > -1 || k.indexOf('cheetah') > -1) {
      try {
        var v = window[k];
        result.push({name: k, type: typeof v, keys: typeof v === 'object' && v !== null ? Object.keys(v).slice(0,10).join(',') : ''});
      } catch(e) {}
    }
  }
  return JSON.stringify(result);
})()
""")
print("[Cheetah全局]", r[:400] if r else 'empty')

# 5. 找封面按钮的父级中所有实例
r = cdp(s, """
(function() {
  var all = document.querySelectorAll('*');
  var result = [];
  var foundKeys = new Set();
  for (var el of all) {
    var keys = Object.keys(el);
    for (var k of keys) {
      if ((k.indexOf('upload') > -1 || k.indexOf('Upload') > -1 || k.indexOf('cover') > -1) && !foundKeys.has(k)) {
        try {
          var v = el[k];
          if (v && typeof v === 'function') {
            foundKeys.add(k);
            result.push({key: k, tag: el.tagName, preview: v.toString().substring(0,60)});
          }
        } catch(e) {}
      }
    }
  }
  return JSON.stringify(result.slice(0,10));
})()
""")
print("[upload函数]", r[:500] if r else 'empty')

# 6. 找 Cheetah 组件实例
r = cdp(s, """
(function() {
  // 找所有带 data-cid(Cheetah instance ID) 的元素
  var all = document.querySelectorAll('[data-cid], [data-cheetah-cid], [data-id]');
  var result = [];
  for (var el of all) {
    var cid = el.getAttribute('data-cid') || el.getAttribute('data-cheetah-cid') || el.getAttribute('data-id');
    if (cid) {
      var keys = Object.keys(el).filter(function(k){return k.indexOf('$') === 0 || k.indexOf('_') === 0});
      result.push({tag: el.tagName, class: el.className.substring(0,30), cid: cid, instanceKeys: keys.join(',')});
    }
  }
  return JSON.stringify(result.slice(0,10));
})()
""")
print("[Cheetah cid]", r[:500] if r else 'empty')

s.close()
