# -*- coding: utf-8 -*-
"""用键盘输入方式填标题"""
import sys, socket, json, time, urllib.request, base64, os, glob, random
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')
    else: hdr = bytes([0x81, 0xFF]) + n.to_bytes(8, 'big')
    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 click(sock, x, y):
    global _msg_id
    for t in ['mousePressed', 'mouseReleased']:
        _msg_id += 1
        send_frame(sock, json.dumps({'id': _msg_id, 'method': 'Input.dispatchMouseEvent', 'params': {'type': t, 'x': x, 'y': y, 'button': 'left', 'clickCount': 1}}))
        recv_frame(sock)
        time.sleep(0.05)

def key_type(sock, text):
    global _msg_id
    for ch in text:
        _msg_id += 1
        send_frame(sock, json.dumps({'id': _msg_id, 'method': 'Input.dispatchKeyEvent', 'params': {'type': 'keyDown', 'text': ch, 'key': ch}}))
        recv_frame(sock)
        _msg_id += 1
        send_frame(sock, json.dumps({'id': _msg_id, 'method': 'Input.dispatchKeyEvent', 'params': {'type': 'keyUp', 'text': ch, 'key': ch}}))
        recv_frame(sock)
        time.sleep(0.08)

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

# 找标题 div 的坐标
r = call(sock, """
(function(){
    var all = document.querySelectorAll('div[class*="placeholder"]');
    for(var div of all){
        var t = (div.innerText||'').trim();
        if(t.includes('请输入标题')){
            var rect = div.getBoundingClientRect();
            return JSON.stringify({placeholder: true, x: Math.round(rect.left + rect.width/2), y: Math.round(rect.top + rect.height/2), w: Math.round(rect.width), h: Math.round(rect.height), text: t});
        }
    }
    return '{"found":false}';
})()
""")
print("[标题探测]", r)
info = json.loads(r)

if info.get('placeholder'):
    x, y = info['x'], info['y']
    print("[点击] 点击标题区域 (%d, %d)..." % (x, y))
    click(sock, x, y)
    time.sleep(0.5)

    # 清空
    call(sock, "document.execCommand('selectAll');")
    time.sleep(0.2)
    call(sock, "document.execCommand('delete');")
    time.sleep(0.2)

    # 键盘输入
    title = '百家号自动填写测试标题'
    print("[输入] 开始键盘输入: %s" % title)
    key_type(sock, title)
    time.sleep(0.5)

    # 验证
    r = call(sock, """
(function(){
    var all = document.querySelectorAll('div[contenteditable="true"], p[contenteditable]');
    for(var el of all){
        if((el.innerText||'').trim().length > 5 && !(el.innerText||'').includes('请输入标题')){
            return 'TITLE_SET:' + el.tagName + ':' + (el.innerText||'').trim().substring(0,40);
        }
    }
    // 也检查标题输入框是否真的有文字
    var els = document.querySelectorAll('[class*="editor"]');
    for(var el of els){
        if((el.innerText||'').trim().length > 0 && (el.innerText||'').trim().length < 100){
            return 'EDITOR_HAS_TEXT:' + el.tagName + ':' + (el.innerText||'').trim().substring(0,40);
        }
    }
    return 'TITLE_NOT_SET';
})()
""")
    print("[验证]", r)
else:
    print("[ERROR] 未找到标题 placeholder")

sock.close()
