import asyncio, sys
import websockets

ORIGIN = "https://computernewb.com"
UA = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120 Safari/537.36"

def guac_encode(*elems):
    return ",".join(f"{len(e)}.{e}" for e in elems) + ";"

def guac_decode(msg):
    # returns list of instructions, each a list of elements
    out = []
    i = 0
    while i < len(msg):
        inst = []
        while True:
            dot = msg.index(".", i)
            ln = int(msg[i:dot])
            start = dot + 1
            val = msg[start:start+ln]
            inst.append(val)
            i = start + ln
            sep = msg[i]
            i += 1
            if sep == ";":
                break
        out.append(inst)
    return out

async def main():
    node = sys.argv[1] if len(sys.argv) > 1 else "vm0b"
    uri = f"wss://computernewb.com/collab-vm/{node}"
    print("connecting", uri, file=sys.stderr)
    proxy = sys.argv[2] if len(sys.argv) > 2 else None
    kw = dict(
        subprotocols=["guacamole"],
        origin=ORIGIN,
        additional_headers={"User-Agent": UA},
        max_size=None,
        open_timeout=25,
    )
    if proxy:
        kw["proxy"] = proxy
        print("via proxy", proxy, file=sys.stderr)
    async with websockets.connect(uri, **kw) as ws:
        print("CONNECTED subprotocol=", ws.subprotocol, file=sys.stderr)
        await ws.send(guac_encode("list"))
        try:
            while True:
                msg = await asyncio.wait_for(ws.recv(), timeout=6)
                if isinstance(msg, bytes):
                    print("BINARY", len(msg), "bytes", file=sys.stderr); continue
                for inst in guac_decode(msg):
                    op = inst[0]
                    if op == "list":
                        # list,id,name,b64thumb,id,name,b64thumb...
                        print("== VM LIST ==")
                        rest = inst[1:]
                        for k in range(0, len(rest), 3):
                            vmid = rest[k]
                            name = rest[k+1] if k+1 < len(rest) else "?"
                            print(f"  {vmid!r:20} {name!r}")
                    elif op == "png":
                        print("png <framebuffer>")
                    else:
                        # truncate long elements
                        shown = [ (e[:40]+"..." if len(e)>40 else e) for e in inst ]
                        print("INST", shown)
        except asyncio.TimeoutError:
            print("(timeout, done)", file=sys.stderr)

asyncio.run(main())
