# -*- coding: utf-8 -*-
"""
百家号 - 模拟用户输入标题
"""
import sys, socket, json, time, urllib.request, base64, os, glob, random
sys.stdout.reconfigure(encoding='utf-8')

HOST = 'localhost'
PORT = 9223

TITLE = '山东两所医学院更名对比'
PARAGRAPHS = [('normal', '测试正文内容。'), ('normal', '第二段测试。')]

IMAGE_PATH = None
print(f"[INFO] 图片: {IMAGE_PATH}")

def rand_sleep(s, t):
    time.sleep(random.uniform(s, t))

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

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

def recv_f(sock):
    def rx(n):
        b = b''
        while len(b) < n:
            b += sock.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 call(sock, expr, timeout=15):
    global mid
    mid += 1
    send_f(sock, json.dumps({'id': mid, 'method': 'Runtime.evaluate', 'params': {'expression': expr, 'returnByValue': True}}))
    sock.settimeout(timeout)
    while True:
        o = json.loads(recv_f(sock))
        if o.get('id') == mid:
            return o.get('result', {}).get('result', {}).get('value', '')

pages = json.loads(urllib.request.urlopen(f'http://{HOST}:{PORT}/json').read())
page_id = [p['id'] for p in pages if 'baijiahao.baidu.com' in p['url']][0]
sock = ws_connect(page_id)
print("[OK] CDP connected")

# ============================================
# 模拟用户点击标题框，然后输入
# ============================================
print("\n[Step 1] 点击标题框并模拟输入...")

r = call(sock, """
(function(){
    var inputBox = document.querySelector('.input-box');
    if(!inputBox) return 'no_input_box';
    
    // 获取 contenteditable
    var editable = inputBox.querySelector('[contenteditable]');
    if(!editable) {
        // 如果没有 contenteditable，整个 input-box 就是
        editable = inputBox;
    }
    
    // 1. 点击聚焦
    editable.focus();
    
    // 2. 选中所有内容
    var range = document.createRange();
    range.selectNodeContents(editable);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
    
    // 3. 模拟键盘删除
    document.execCommand('delete', false, null);
    
    return 'focused_and_selected';
})()
""")
print(f"  [focus] {r}")
rand_sleep(0.5, 1)

# 通过 dispatchEvent 模拟输入
r = call(sock, f"""
(function(){{
    var inputBox = document.querySelector('.input-box');
    var editable = inputBox ? (inputBox.querySelector('[contenteditable]') || inputBox) : null;
    
    if(!editable) return 'no_editable';
    
    // 逐字输入（模拟用户）
    var text = {json.dumps(TITLE)};
    
    // 清空
    editable.innerText = '';
    
    // 使用 setTimeout 逐字添加
    var i = 0;
    function typeNext() {{
        if(i < text.length) {{
            editable.innerText += text.charAt(i);
            editable.dispatchEvent(new Event('input', {{bubbles:true}}));
            i++;
            setTimeout(typeNext, 50);
        }}
    }}
    
    typeNext();
    
    return 'TYPING_STARTED:' + text.length + 'chars';
}})()
""")
print(f"  [typing] {r}")
rand_sleep(3, 4)

# 验证标题
r = call(sock, """
(function(){
    var inputBox = document.querySelector('.input-box');
    if(inputBox){
        return 'title=' + (inputBox.innerText||'').trim().substring(0,40);
    }
    return 'no_input_box';
})()
""")
print(f"  [verify_title] {r}")

sock.close()
print("\n[DONE]")