-- ============================================================ -- BONZIWORLD <-> OPENCOMPUTERS BRIDGE (FIXED) -- ============================================================ local internet = require("internet") local serialization = require("serialization") local component = require("component") local computer = require("computer") print("========================================") print(" BonziWORLD OpenComputers Bridge") print("========================================") print("") if not component.isAvailable("internet") then print("[-] Internet card is missing or disabled.") return end io.write("Server URL: ") local serverUrl = io.read() io.write("Room ID: ") local roomInput = io.read() io.write("Bot Name: ") local botName = io.read() if not botName or botName == "" then botName = "OC_Bot" end serverUrl = serverUrl:gsub("^https?://", ""):gsub("/+$", "") local room = tonumber(roomInput) or roomInput local host = serverUrl local path = "/socket.io/?EIO=4&transport=websocket" local ws = nil local socketConnected = false local loggedIn = false local shuttingDown = false local messageQueue = {} local pingInterval = 25000 local pingTimeout = 20000 local APP_HEARTBEAT = 10 local SEND_DELAY = 0.20 local LOGIN_DELAY = 1.5 local reconnectDelay = 2 local lastPacketTime = 0 local function now() return math.floor(computer.uptime() * 1000) end local function socketEvent(eventName, data) return "42" .. serialization.serialize({ eventName, data }) end local function rawSend(packet) if not ws or not socketConnected then return false end local ok, err = pcall(function() -- Frame basic text payload for WebSocket transmission over TCP local length = #packet local frame = string.char(0x81) if length <= 125 then frame = frame .. string.char(length) elseif length <= 65535 then frame = frame .. string.char(126, math.floor(length / 256), length % 256) else return error("Payload too large") end ws:write(frame .. packet) end) if not ok then print("\n[-] WebSocket send failed:\n " .. tostring(err)) return false end return true end local function sendChat(message) if not message or message == "" then return false end return rawSend(socketEvent("talk", { text = message, say = message })) end local function sendApplicationHeartbeat() return rawSend(socketEvent("talk", { text = "", say = "" })) end local function sendLogin() print("[>] Login: " .. botName) print("[>] Room: " .. tostring(room)) return rawSend(socketEvent("login", { name = botName, room = room })) end local function processPacket(packet) if not packet then return end lastPacketTime = now() if packet:sub(1, 1) == "0" then local ok, data = pcall(serialization.unserialize, packet:sub(2)) if ok and type(data) == "table" then pingInterval = tonumber(data.pingInterval) or pingInterval pingTimeout = tonumber(data.pingTimeout) or pingTimeout end rawSend("40") return end if packet == "2" then rawSend("3") return end if packet == "3" then return end if packet:sub(1, 1) == "1" then socketConnected, loggedIn = false, false return end if packet == "40" then if not socketConnected then socketConnected = true print("[+] Socket.IO connected.") end return end if packet:sub(1, 2) == "42" then local ok, decoded = pcall(serialization.unserialize, packet:sub(3)) if ok and type(decoded) == "table" then local eventName, payload = decoded[1], decoded[2] if eventName == "talk" and type(payload) == "table" then local sender = payload.name or "User" local text = payload.text or payload.say or "" if text ~= "" and sender ~= botName then print("\n[" .. sender .. "]: " .. text) io.write("> ") end end end return end end local function closeSocket() socketConnected, loggedIn = false, false if ws then pcall(function() ws:close() end) end ws = nil end local function connect() print("\n----------------------------------------") print("[*] Connecting...\n[*] " .. serverUrl) print("----------------------------------------") -- Open raw TCP connection over port 443 (or standard HTTP/WS ports) local stream, err = internet.open(host, 443) if not stream then print("[-] TCP connection failed: " .. tostring(err)) return false end ws = stream -- Perform basic WebSocket HTTP upgrade handshake local wsKey = "dGhlIHNhbXBsZSBub25jZQ==" ws:write("GET " .. path .. " HTTP/1.1\r\n" .. "Host: " .. host .. "\r\n" .. "Upgrade: websocket\r\n" .. "Connection: Upgrade\r\n" .. "Sec-WebSocket-Key: " .. wsKey .. "\r\n" .. "Sec-WebSocket-Version: 13\r\n\r\n") socketConnected = true loggedIn = true print("[+] Connected to BonziWORLD successfully!") return true end print("[*] Starting bridge...") while not shuttingDown do if not ws or not socketConnected then if not connect() then os.sleep(reconnectDelay) reconnectDelay = math.min(reconnectDelay * 2, 30) end else os.sleep(0.1) end end