Skip to content

Instantly share code, notes, and snippets.

@simonw
Created January 6, 2025 18:04
Show Gist options
  • Save simonw/9c4525e0364d60c1a8a7bd663ff0df35 to your computer and use it in GitHub Desktop.
Save simonw/9c4525e0364d60c1a8a7bd663ff0df35 to your computer and use it in GitHub Desktop.

Bluesky WebSocket Feed Monitor with Custom JSON Sending

human (Jan 5, 2025, 11:32 AM)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bluesky WebSocket Feed Monitor</title>
    <style>
        body {
            font-family: system-ui, -apple-system, sans-serif;
            max-width: 800px;
            margin: 20px auto;
            padding: 0 20px;
        }
        #output {
            width: 100%;
            height: 400px;
            margin-top: 20px;
            padding: 10px;
            font-family: monospace;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .controls {
            margin: 20px 0;
        }
        button {
            padding: 8px 16px;
            margin-right: 10px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>Bluesky WebSocket Feed Monitor</h1>
    <div class="controls">
        <button id="connect">Connect</button>
        <button id="disconnect">Disconnect</button>
        <button id="clear">Clear Log</button>
    </div>
    <textarea id="output" readonly></textarea>

    <script>
        let ws = null;
        const output = document.getElementById('output');
        
        function log(message) {
            const timestamp = new Date().toISOString();
            output.value += `[${timestamp}] ${message}\n`;
            output.scrollTop = output.scrollHeight;
        }

        function connect() {
            if (ws) {
                log('Already connected!');
                return;
            }

            try {
                ws = new WebSocket('wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.feed.post');
                
                ws.onopen = () => {
                    log('Connected to Bluesky WebSocket');
                };

                ws.onmessage = (event) => {
                    try {
                        const data = JSON.parse(event.data);
                        log(`Received: ${JSON.stringify(data, null, 2)}`);
                    } catch (e) {
                        log(`Raw message: ${event.data}`);
                    }
                };

                ws.onerror = (error) => {
                    log(`WebSocket Error: ${error.message}`);
                };

                ws.onclose = () => {
                    log('Disconnected from Bluesky WebSocket');
                    ws = null;
                };

            } catch (error) {
                log(`Connection Error: ${error.message}`);
                ws = null;
            }
        }

        function disconnect() {
            if (ws) {
                ws.close();
                ws = null;
                log('Disconnected by user');
            } else {
                log('Not connected');
            }
        }

        // Event Listeners
        document.getElementById('connect').addEventListener('click', connect);
        document.getElementById('disconnect').addEventListener('click', disconnect);
        document.getElementById('clear').addEventListener('click', () => {
            output.value = '';
        });
    </script>
</body>
</html>

Add a feature where I can paste JSON into a textarea and then send that back over the websocket

assistant (Jan 5, 2025, 11:32 AM)

I'll help you add a feature to send custom JSON over the WebSocket connection. I'll add a new textarea for input and a "Send" button, along with the necessary JavaScript code to handle sending the message.

create Bluesky WebSocket Feed Monitor with Message Sending

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bluesky WebSocket Feed Monitor</title>
    <style>
        body {
            font-family: system-ui, -apple-system, sans-serif;
            max-width: 800px;
            margin: 20px auto;
            padding: 0 20px;
        }
        .textarea-container {
            margin: 20px 0;
        }
        textarea {
            width: 100%;
            height: 200px;
            margin-top: 10px;
            padding: 10px;
            font-family: monospace;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        #output {
            height: 400px;
        }
        .controls {
            margin: 20px 0;
        }
        button {
            padding: 8px 16px;
            margin-right: 10px;
            cursor: pointer;
        }
        .error {
            color: red;
            margin-top: 5px;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <h1>Bluesky WebSocket Feed Monitor</h1>
    <div class="controls">
        <button id="connect">Connect</button>
        <button id="disconnect">Disconnect</button>
        <button id="clear">Clear Log</button>
    </div>
    
    <div class="textarea-container">
        <h3>Send Message</h3>
        <textarea id="input" placeholder="Paste your JSON message here..."></textarea>
        <div id="jsonError" class="error"></div>
        <button id="send">Send Message</button>
    </div>

    <div class="textarea-container">
        <h3>Log Output</h3>
        <textarea id="output" readonly></textarea>
    </div>

    <script>
        let ws = null;
        const output = document.getElementById('output');
        const input = document.getElementById('input');
        const jsonError = document.getElementById('jsonError');
        
        function log(message) {
            const timestamp = new Date().toISOString();
            output.value += `[${timestamp}] ${message}\n`;
            output.scrollTop = output.scrollHeight;
        }

        function connect() {
            if (ws) {
                log('Already connected!');
                return;
            }

            try {
                ws = new WebSocket('wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.feed.post');
                
                ws.onopen = () => {
                    log('Connected to Bluesky WebSocket');
                };

                ws.onmessage = (event) => {
                    try {
                        const data = JSON.parse(event.data);
                        log(`Received: ${JSON.stringify(data, null, 2)}`);
                    } catch (e) {
                        log(`Raw message: ${event.data}`);
                    }
                };

                ws.onerror = (error) => {
                    log(`WebSocket Error: ${error.message}`);
                };

                ws.onclose = () => {
                    log('Disconnected from Bluesky WebSocket');
                    ws = null;
                };

            } catch (error) {
                log(`Connection Error: ${error.message}`);
                ws = null;
            }
        }

        function disconnect() {
            if (ws) {
                ws.close();
                ws = null;
                log('Disconnected by user');
            } else {
                log('Not connected');
            }
        }

        function sendMessage() {
            if (!ws) {
                log('Not connected to WebSocket');
                return;
            }

            const message = input.value.trim();
            if (!message) {
                jsonError.textContent = 'Please enter a message';
                return;
            }

            try {
                // Validate JSON
                const jsonMessage = JSON.parse(message);
                
                // Send the message
                ws.send(JSON.stringify(jsonMessage));
                log(`Sent: ${message}`);
                jsonError.textContent = '';
            } catch (error) {
                jsonError.textContent = 'Invalid JSON format';
                log(`Failed to send message: Invalid JSON format`);
            }
        }

        // Event Listeners
        document.getElementById('connect').addEventListener('click', connect);
        document.getElementById('disconnect').addEventListener('click', disconnect);
        document.getElementById('clear').addEventListener('click', () => {
            output.value = '';
        });
        document.getElementById('send').addEventListener('click', sendMessage);

        // Add keyboard shortcut (Ctrl/Cmd + Enter) to send message
        input.addEventListener('keydown', (e) => {
            if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
                sendMessage();
            }
        });
    </script>
</body>
</html>

I've added the following new features to the WebSocket monitor:

  1. A new textarea for entering JSON messages to send
  2. A "Send Message" button
  3. JSON validation before sending
  4. Error handling and display
  5. A keyboard shortcut (Ctrl/Cmd + Enter) to send messages
  6. Improved styling and layout

The new features include:

  • JSON validation before sending to ensure valid format
  • Error messages displayed below the input textarea
  • Automatic logging of sent messages
  • Visual feedback for connection status and errors
  • Responsive layout with consistent styling

To use the new sending feature:

  1. Connect to the WebSocket first using the "Connect" button
  2. Paste your JSON into the new textarea
  3. Click "Send Message" or use Ctrl/Cmd + Enter to send
  4. The message will be validated and sent if it's valid JSON
  5. Both sent and received messages will appear in the log output

Let me know if you'd like any adjustments to the new features or styling!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment