# -*- coding: utf-8 -*-
"""用 CDP 键盘事件填标题"""
import sys, socket, json, time, urllib.request
sys.stdout.reconfigure(encoding='utf-8')

HOST = "localhost"
PORT = 28800
PAGE_ID = "0C993BDF32DDC631BFC69F41B0755EF3"

def ws_connect(page_id):
    import urllib.parse
    ws_url = "ws://%s:%s/devtools/page/%s" % (HOST, PORT, page_id)
    parsed = urllib.parse.urlparse(ws_url)
    sock = socket.create_connection((parsed.hostname, parsed.port or 80), timeout=15)
    key = 'dGhlIHNhbXBsZSBub25jZQ=='
    req = ("GET %s HTTP/1.1\r\nHost: %s:%s\r\n"
           "Upgrade: websocket\r\nConnection: Upgrade\r\n"
           "Sec-WebSocket-Key: %s\r\nSec-WebSocket-Version: 13\r\n\r\n"
           % (parsed.path, parsed.hostname, parsed.port, key))
    sock.send(req.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
    mid = _msg_id
    send_frame(sock, json.dumps({'id': mid, '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') == mid:
            res = obj.get('result', {}).get('result', {})
            return res.get('value', res.get('description', ''))

def dispatch_key(sock, key_type, key, text=''):
    global _msg_id
    params = {'type': key_type, 'key': key}
    if text: params['text'] = text
    _msg_id += 1
    send_frame(sock, json.dumps({'id': _msg_id, 'method': 'Input.dispatchKeyEvent', 'params': params}))
    recv_frame(sock)

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

# 先清空可能已有的内容
call(sock, "document.execCommand('selectAll');")
time.sleep(0.2)
dispatch_key(sock, 'keyDown', 'Delete')
time.sleep(0.1)

# 键盘输入标题
title = '百家号自动填写测试标题成功'
print("[输入] 开始输入: %s" % title)
for ch in title:
    dispatch_key(sock, 'keyDown', ch, ch)
    dispatch_key(sock, 'keyUp', ch)
    time.sleep(0.06)
time.sleep(0.5)

# 验证
r = call(sock, """
(function(){
    var all = document.querySelectorAll('div[contenteditable="true"]');
    for(var el of all){
        var t = (el.innerText||'').trim();
        if(t.length > 0 && t.length < 100 && !t.includes('请输入')){
            return 'FOUND:' + el.tagName + ':' + el.className.substring(0,30) + ':' + t.substring(0,40);
        }
    }
    return 'NOT_FOUND';
})()
""")
print("[验证]", r)

sock.close()
