# -*- coding: utf-8 -*-
import sys, socket, json, base64, urllib.request, time
sys.stdout.reconfigure(encoding='utf-8', errors='replace')

HOST = 'localhost'
PORT = 9222
pages = json.loads(urllib.request.urlopen(f'http://{HOST}:{PORT}/json').read())
page = [p for p in pages if p.get('type') == 'page'][0]

import urllib.parse
parsed = urllib.parse.urlparse(page['webSocketDebuggerUrl'])
sock = socket.create_connection((parsed.hostname, parsed.port or 80), timeout=10)
key = 'dGhlIHNhbXBsZSBub25jZQ=='
hs = 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(hs.encode())
resp = b''
while b'\r\n\r\n' not in resp:
    resp += sock.recv(4096)

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')

_mid = 0
def cdp_call(sock, method, params=None):
    global _mid
    _mid += 1
    msg = {'id': _mid, 'method': method}
    if params:
        msg['params'] = params
    send_frame(sock, json.dumps(msg))
    sock.settimeout(15)
    while True:
        raw = recv_frame(sock)
        obj = json.loads(raw)
        if obj.get('id') == _mid:
            return obj.get('result', {})

result = cdp_call(sock, 'Runtime.evaluate', {'expression': 'document.querySelector("#title").value'})
print('TITLE:', result)

result = cdp_call(sock, 'Runtime.evaluate', {'expression': 'document.querySelector(".ProseMirror").innerText.substring(0,100)'})
print('CONTENT:', result)

sock.close()
