let ws; function connectWebSocket() { console.log("Attempting to connect to Twitch chat with websocket..."); ws = new WebSocket('wss://irc-ws.chat.twitch.tv:443'); ws.onopen = () => { console.log('Connected to Twitch chat'); const oauthToken = import.meta.env.VITE_TWITCH_BOT_OAUTH_TOKEN; const username = import.meta.env.VITE_TWITCH_BOT_USERNAME; const channel = import.meta.env.VITE_TWITCH_CHANNEL; console.log('OAuth Token:', oauthToken ? 'Loaded' : 'Missing'); console.log('Username:', username ? username : 'Missing'); console.log('Channel:', channel ? channel : 'Missing'); if (!oauthToken || !username || !channel) { console.error('Missing required environment variables'); return; } ws.send(`PASS ${oauthToken}`); ws.send(`NICK ${username}`); ws.send(`JOIN #${channel}`); }; ws.onmessage = (event) => { console.log('Received:', event.data); const parsedMessage = parseTwitchMessage(event.data); console.log('Parsed Message:', parsedMessage); if (parsedMessage.command === '376') { console.log('End of MOTD received. Ready to process messages.'); return; } if (parsedMessage && parsedMessage.command === 'JOIN') { console.log(`Joined channel: ${parsedMessage.params[0]}`); } if (parsedMessage && parsedMessage.command === 'PRIVMSG') { const chatMessage = parsedMessage.params.slice(1).join(' ').trim(); const username = parsedMessage.prefix.split('!')[0]; console.log('Chat Message:', chatMessage); console.log('Username:', username); // Update the regular expression to handle color names with hyphens const commandPattern = /^(?:!place|!p|!paint)\s+([A-P])\s*(\d{1,2})\s+([\w-]+)$/i; const commandMatch = chatMessage.match(commandPattern); console.log('Command Match:', commandMatch); if (commandMatch) { const [, x, y, color] = commandMatch; console.log(`Parsed Command: !place ${x}${y} ${color}`); sendPlaceCommand(chatMessage, username, x, y, color); } else { console.log('No matching command found in the message.'); } } else { console.log('Message is not a PRIVMSG.'); } }; ws.onerror = (error) => { console.error('WebSocket Error:', error); }; ws.onclose = () => { console.log('WebSocket connection closed'); console.log('WebSocket attempting to reconnect'); setTimeout(connectWebSocket, 5000); // Reconnect after 5 seconds }; } function parseTwitchMessage(message) { console.log('Raw Message:', message); const prefixEnd = message.indexOf(' '); const prefix = message.substring(1, prefixEnd); const commandEnd = message.indexOf(' ', prefixEnd + 1); const command = message.substring(prefixEnd + 1, commandEnd); const params = message.substring(commandEnd + 1).split(' :'); const tagsStart = message.indexOf('@'); const tags = {}; if (tagsStart !== -1) { const tagsEnd = message.indexOf(' ', tagsStart + 1); const tagsRaw = message.substring(tagsStart + 1, tagsEnd); tagsRaw.split(';').forEach(tag => { const [key, value] = tag.split('='); tags[key] = value; }); } console.log('Parsed Tags:', tags); console.log('Parsed Command:', command); console.log('Parsed Params:', params); return { prefix, command, params, tags }; } function sendPlaceCommand(chatMessage, username, x, y, color) { console.log(`Sending command to server: !place ${x}${y} ${color}`); fetch('/twitch/parse', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ message: chatMessage, username: username, game_session_id: 1 }) // Adjust game_session_id as needed }) .then(response => response.json()) .then(data => { console.log('Server Response:', data); if (data && data.command.command === 'place') { console.log('Parsed Place Command from server:', data); colorCell(`${data.command.x}${data.command.y}`, data.color.hex_value); } else { console.error('Invalid command in server response.'); } }) .catch(error => { console.error('Parsing Error:', error); }); } // Connect to the WebSocket when the script loads connectWebSocket();