# -*- coding: utf-8 -*-
"""找封面上传函数"""
import sys, socket, json, time
sys.stdout.reconfigure(encoding='utf-8')
HOST = "localhost"; PORT = 28800
PAGE_ID = "70039F329097C14448996F189E3A42A1"

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. 找 Cheetah/封面相关函数
r = cdp(s, """
(function() {
  // 找 window 上的上传相关函数
  var result = [];
  for (var k in window) {
    if (k.toLowerCase().indexOf('upload') > -1 ||
        k.toLowerCase().indexOf('cheetah') > -1 ||
        k.toLowerCase().indexOf('cover') > -1 ||
        k.toLowerCase().indexOf('image') > -1) {
      try {
        var v = window[k];
        if (typeof v === 'function') {
          result.push({name: k, fn: v.toString().substring(0, 60)});
        }
      } catch(e) {}
    }
  }
  return JSON.stringify(result.slice(0, 10));
})()
""")
print("[上传函数]", r[:400] if r else 'empty')

# 2. 找 React/Vue 根组件
r = cdp(s, """
(function() {
  // 找 React root
  var rootEl = document.getElementById('root') || document.getElementById('app');
  if (rootEl) {
    var keys = Object.keys(rootEl);
    return 'root keys:' + keys.join(',') + ' | _reactRootContainer:' + rootEl._reactRootContainer + ' | __reactFiber:' + Object.keys(rootEl).filter(function(k){return k.includes('react')||k.includes('Fiber')||k.includes('Props')}).join(',');
  }
  return 'no root';
})()
""")
print("[React root]", r[:200] if r else 'empty')

# 3. 找"选择封面"按钮的事件监听器
r = cdp(s, """
(function() {
  // 找封面相关的 DOM 元素和它们的 Cheetah 组件
  var all = document.querySelectorAll('*');
  var result = [];
  for (var el of all) {
    var t = (el.innerText || '').trim();
    if (t === '选择封面' || t.includes('选择封面')) {
      // 找父级
      var parent = el;
      for (var i = 0; i < 5; i++) {
        if (parent.parentElement) parent = parent.parentElement;
      }
      result.push({
        tag: el.tagName,
        text: t,
        parent_tag: parent.tagName,
        parent_class: (parent.className || '').substring(0, 50),
        has_onclick: typeof el.onclick === 'function' || el.getAttribute('onclick'),
        onclick: el.getAttribute('onclick'),
        data_hook: el.getAttribute('data-hook') || el.getAttribute('data-eid') || ''
      });
    }
  }
  return JSON.stringify(result);
})()
""")
print("[封面按钮]", r[:400] if r else 'empty')

# 4. 直接找 iframe 里的上传逻辑
r = cdp(s, """
(function() {
  // 找所有 iframe
  var iframes = document.querySelectorAll('iframe');
  var result = [];
  for (var i of iframes) {
    var src = i.src || '';
    var id = i.id || '';
    if (src.indexOf('upload') > -1 || src.indexOf('cover') > -1 || id.indexOf('upload') > -1) {
      result.push({id: id, src: src.substring(0, 60)});
    }
  }
  // 也检查 iframe 内联脚本
  var allIframes = document.querySelectorAll('iframe');
  for (var j = 0; j < allIframes.length; j++) {
    var iframe = allIframes[j];
    try {
      var d = iframe.contentDocument || iframe.contentWindow.document;
      var body = d.body;
      if (body) {
        result.push({index: j, body_content_preview: (body.innerHTML || '').substring(0, 100)});
      }
    } catch(e) {}
  }
  return JSON.stringify(result);
})()
""")
print("[iframe]", r[:500] if r else 'empty')

# 5. 找 __reactFiber 等内部属性
r = cdp(s, """
(function() {
  var all = document.querySelectorAll('*');
  var fibers = [];
  for (var el of all) {
    var keys = Object.keys(el);
    for (var k of keys) {
      if (k.indexOf('__reactFiber') > -1 || k.indexOf('$reactFiber') > -1) {
        fibers.push({tag: el.tagName, key: k, val: typeof el[k]});
      }
    }
  }
  return JSON.stringify(fibers.slice(0, 5));
})()
""")
print("[React Fiber]", r[:200] if r else 'empty')

s.close()
