package main import ( "log" "os" "os/signal" "time" "github.com/playwright-community/playwright-go" ) const ( roomURL = "https://app.kosmi.io/room/@hyperspaceout" ) func main() { log.Println("šŸ” Starting Kosmi WebSocket Monitor") log.Printf("šŸ“” Room URL: %s", roomURL) log.Println("This will capture ALL WebSocket traffic from the browser...") log.Println() // Set up interrupt handler interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) // Launch Playwright pw, err := playwright.Run() if err != nil { log.Fatalf("Failed to start Playwright: %v", err) } defer pw.Stop() // Launch browser browser, err := pw.Chromium.Launch(playwright.BrowserTypeLaunchOptions{ Headless: playwright.Bool(false), // Keep visible so we can see what's happening }) if err != nil { log.Fatalf("Failed to launch browser: %v", err) } defer browser.Close() // Create context context, err := browser.NewContext(playwright.BrowserNewContextOptions{ UserAgent: playwright.String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"), }) if err != nil { log.Fatalf("Failed to create context: %v", err) } // Create page page, err := context.NewPage() if err != nil { log.Fatalf("Failed to create page: %v", err) } // Inject WebSocket monitoring script BEFORE navigation log.Println("šŸ“ Injecting WebSocket monitoring script...") if err := page.AddInitScript(playwright.Script{ Content: playwright.String(` (function() { const OriginalWebSocket = window.WebSocket; let messageCount = 0; window.WebSocket = function(url, protocols) { console.log('šŸ”Œ [WS MONITOR] WebSocket created:', url, 'protocols:', protocols); const socket = new OriginalWebSocket(url, protocols); socket.addEventListener('open', (event) => { console.log('āœ… [WS MONITOR] WebSocket OPENED'); }); socket.addEventListener('close', (event) => { console.log('šŸ”“ [WS MONITOR] WebSocket CLOSED:', event.code, event.reason); }); socket.addEventListener('error', (event) => { console.error('āŒ [WS MONITOR] WebSocket ERROR:', event); }); // Intercept outgoing messages const originalSend = socket.send; socket.send = function(data) { messageCount++; console.log('šŸ“¤ [WS MONITOR] SEND #' + messageCount + ':', data); try { const parsed = JSON.parse(data); console.log(' Type:', parsed.type, 'ID:', parsed.id); if (parsed.payload) { console.log(' Payload:', JSON.stringify(parsed.payload, null, 2)); } } catch (e) { // Not JSON } return originalSend.call(this, data); }; // Intercept incoming messages socket.addEventListener('message', (event) => { messageCount++; console.log('šŸ“„ [WS MONITOR] RECEIVE #' + messageCount + ':', event.data); try { const parsed = JSON.parse(event.data); console.log(' Type:', parsed.type, 'ID:', parsed.id); if (parsed.payload) { console.log(' Payload:', JSON.stringify(parsed.payload, null, 2)); } } catch (e) { // Not JSON } }); return socket; }; // Preserve WebSocket properties window.WebSocket.prototype = OriginalWebSocket.prototype; window.WebSocket.CONNECTING = OriginalWebSocket.CONNECTING; window.WebSocket.OPEN = OriginalWebSocket.OPEN; window.WebSocket.CLOSING = OriginalWebSocket.CLOSING; window.WebSocket.CLOSED = OriginalWebSocket.CLOSED; })(); `), }); err != nil { log.Fatalf("Failed to inject script: %v", err) } // Listen to console messages page.On("console", func(msg playwright.ConsoleMessage) { text := msg.Text() msgType := msg.Type() // Format the output nicely prefix := "šŸ’¬" switch msgType { case "log": prefix = "šŸ“‹" case "error": prefix = "āŒ" case "warning": prefix = "āš ļø" case "info": prefix = "ā„¹ļø" } log.Printf("%s [BROWSER %s] %s", prefix, msgType, text) }) // Navigate to room log.Printf("🌐 Navigating to %s...", roomURL) if _, err := page.Goto(roomURL, playwright.PageGotoOptions{ WaitUntil: playwright.WaitUntilStateDomcontentloaded, }); err != nil { log.Fatalf("Failed to navigate: %v", err) } log.Println("āœ… Page loaded! Monitoring WebSocket traffic...") log.Println("Press Ctrl+C to stop monitoring") log.Println() // Wait for a bit to see initial traffic time.Sleep(5 * time.Second) // Try to send a test message log.Println("\nšŸ“ Attempting to send a test message via UI...") result, err := page.Evaluate(` (async function() { // Find the chat input const textareas = document.querySelectorAll('textarea'); for (let ta of textareas) { if (ta.offsetParent !== null) { ta.value = 'Test message from monitor script šŸ”'; ta.dispatchEvent(new Event('input', { bubbles: true })); ta.dispatchEvent(new Event('change', { bubbles: true })); ta.focus(); // Wait a bit await new Promise(resolve => setTimeout(resolve, 100)); // Try to find and click send button const buttons = document.querySelectorAll('button'); for (let btn of buttons) { if (btn.textContent.toLowerCase().includes('send') || btn.getAttribute('aria-label')?.toLowerCase().includes('send')) { btn.click(); return { success: true, method: 'button' }; } } // If no button, press Enter const enterEvent = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true, cancelable: true }); ta.dispatchEvent(enterEvent); return { success: true, method: 'enter' }; } } return { success: false, error: 'No input found' }; })(); `) if err != nil { log.Printf("āŒ Failed to send test message: %v", err) } else { resultMap := result.(map[string]interface{}) if success, ok := resultMap["success"].(bool); ok && success { method := resultMap["method"].(string) log.Printf("āœ… Test message sent via %s", method) log.Println("šŸ“Š Check the console output above to see the WebSocket traffic!") } else { log.Printf("āŒ Failed to send: %v", resultMap["error"]) } } // Keep monitoring log.Println("\nā³ Continuing to monitor... Press Ctrl+C to stop") // Wait for interrupt <-interrupt log.Println("\nšŸ‘‹ Stopping monitor...") }