Created
September 9, 2025 12:36
-
-
Save tjdevries/b8e241eb2645c9089feeae08b0a77d90 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { chromium } from 'playwright'; | |
| const struArgs = process.argv.slice(2) | |
| const browser = await chromium.launch({ | |
| headless: false, | |
| args: struArgs, | |
| }); // Set headless: true for background execution | |
| const context = await browser.newContext({ | |
| viewport: null // This removes viewport restrictions, making it use full browser window | |
| }); | |
| const page = await context.newPage(); | |
| // Navigate to the Strudel REPL page | |
| await page.goto('https://strudel.cc/'); | |
| // Wait for the editor to be visible | |
| await page.waitForSelector('.cm-content'); | |
| // Locate the CodeMirror contenteditable div | |
| const editor = page.locator('.cm-content'); | |
| const connections: any[] = []; | |
| const extraLines: string[] = []; | |
| const queue: string[] = [] | |
| let running = false | |
| async function flush() { | |
| if (queue.length == 0 || running) { | |
| return | |
| } | |
| running = true | |
| const next = queue.shift()! | |
| await editor.click(); | |
| // Select all text | |
| await page.keyboard.down('Control'); | |
| await page.keyboard.press('A'); | |
| await page.keyboard.up('Control'); | |
| // Delete all text | |
| await page.keyboard.press('Backspace'); | |
| await editor.fill(next); | |
| // Optionally, click the "update" button to apply changes | |
| const updateButton = page.locator('button[title="update"]'); | |
| await updateButton.click(); | |
| running = false | |
| flush() | |
| } | |
| Bun.serve({ | |
| port: 3000, | |
| async fetch(req, server) { | |
| const url = new URL(req.url); | |
| if (url.pathname === "/twitch") { | |
| console.log("got twitch request", "extraLines", extraLines.length) | |
| if (req.method === "POST") { | |
| const lines = await req.json() | |
| extraLines.push(...lines) | |
| return new Response("Ok", { status: 200 }); | |
| } else { | |
| const lines = JSON.stringify(extraLines) | |
| extraLines.length = 0 | |
| return new Response(lines, { status: 200 }); | |
| } | |
| } | |
| if (url.pathname === "/update" && req.method === "POST") { | |
| queue.push(await req.text()) | |
| flush() | |
| return new Response("Updated", { status: 200 }); | |
| } | |
| if (url.pathname === "/ws" && server.upgrade(req)) { | |
| return; | |
| } | |
| return new Response("Not found", { status: 404 }); | |
| }, | |
| websocket: { | |
| open(ws) { connections.push(ws); }, | |
| message(_ws, _message) {}, | |
| close(ws) { | |
| const index = connections.indexOf(ws); | |
| if (index !== -1) { | |
| connections.splice(index, 1); | |
| } | |
| }, | |
| }, | |
| }); | |
| console.log("Server running at http://localhost:3000"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment