# -*- coding: utf-8 -*-
"""诊断百家号标题元素"""
import sys, socket, json, time, urllib.request, base64, os
sys.stdout.reconfigure(encoding='utf-8')

HOST = "localhost"
PORT = 28800

def ws_connect(page_id):
    import urllib.parse
    ws_url = f"ws://{HOST}:{PORT}/devtools/page/{page_id}"
    parsed = urllib.parse.urlparse(ws_url)
    sock = socket.create_connection((parsed.hostname, parsed.port or 80), timeout=15)
    key = 'dGhlIHNhbXBsZSBub25jZQ=='
    handshake = f'GET {parsed.path} HTTP/1.1\r\nHost: {parsed.hostname}:{parsed.port}\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: {key}\r\nSec-WebSocket-Version: 13\r\n\r\n'
    sock.send(handshake.encode())
    resp = b''
    while b'\r\n\r\n' not in resp:
        resp += sock.recv(4096)
    return sock

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

def recv_frame(sock):
    def rx(n):
        buf = b''
        while len(buf) < n:
            buf += sock.recv(n - len(buf))
        return buf
    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')

_msg_id = 0
def call(sock, expr, timeout=15):
    global _msg_id
    _msg_id += 1
    send_frame(sock, json.dumps({'id': _msg_id, 'method': 'Runtime.evaluate', 'params': {'expression': expr, 'returnByValue': True}}))
    sock.settimeout(timeout)
    while True:
        raw = recv_frame(sock)
        obj = json.loads(raw)
        if obj.get('id') == _msg_id:
            res = obj.get('result', {}).get('result', {})
            return res.get('value', res.get('description', ''))

PAGE_ID = "0C993BDF32DDC631BFC69F41B0755EF3"
sock = ws_connect(PAGE_ID)
print("[OK] Connected")

# 详细探测标题区域 DOM
r = call(sock, """
(function(){
    // 找包含"请输入标题"的父容器
    var all = document.querySelectorAll('*');
    var results = [];
    for(var el of all){
        var t = (el.innerText || '').trim();
        if(t === '请输入标题（2 - 64字）'){
            results.push('FOUND placeholder: ' + el.tagName + 
                ' class=' + (el.className||'').substring(0,40) +
                ' contenteditable=' + el.getAttribute('contenteditable') +
                ' childCount=' + el.children.length +
                ' childTags=' + Array.from(el.children).map(c=>c.tagName).join(',') +
                ' innerHTML=' + el.innerHTML.substring(0,100));
            // 也看看兄弟元素
            var parent = el.parentElement;
            if(parent) results.push('parent: ' + parent.tagName + ' class=' + (parent.className||'').substring(0,40));
            var grand = parent ? parent.parentElement : null;
            if(grand) results.push('grand: ' + grand.tagName + ' class=' + (grand.className||'').substring(0,40));
        }
    }
    // 找所有 p 标签
    var ps = document.querySelectorAll('p');
    for(var p of ps){
        var t = (p.innerText||'').trim();
        if(t.includes('请输入标题') || (t === '' && p.children.length === 0)){
            results.push('p: class=' + (p.className||'').substring(0,40) + 
                ' contenteditable=' + p.getAttribute('contenteditable') +
                ' childCount=' + p.children.length +
                ' html=' + p.innerHTML.substring(0,80));
        }
    }
    return results.join(' | ');
})()
""")
print("[DOM 探测]", r)

# 测试：找段落 + 赋值
r = call(sock, """
(function(){
    // 找所有 contenteditable p
    var all = document.querySelectorAll('[contenteditable]');
    var found = [];
    for(var el of all){
        found.push(el.tagName + '[' + (el.className||'').substring(0,30) + '] ce=' + el.getAttribute('contenteditable') + ' text=' + (el.innerText||'').substring(0,20));
    }
    return found.join(' || ');
})()
""")
print("[contenteditable 元素]", r)

sock.close()
