From 5693cdffe68aa40ea2d08a10400beaa831ae335c Mon Sep 17 00:00:00 2001 From: BusyBee3333 Date: Sat, 3 Jan 2026 09:10:20 -0500 Subject: [PATCH] Create bot.js --- bot.js | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 bot.js diff --git a/bot.js b/bot.js new file mode 100644 index 0000000..ce0c64f --- /dev/null +++ b/bot.js @@ -0,0 +1,230 @@ +const http = require('http'); +const https = require('https'); +const querystring = require('querystring'); + +// Configuration +const GATHER_SPACE_ID = 'dashore-enterprises-db198865-9dd4-4406-8d0c-0bb71896f09e'; +const GATHER_API_KEY = 'gtr_L8dR5b9x8im9itQGYTc194Lia9KSTwTSCHAhN84av1s'; +const CLAUDE_API_KEY = process.env.CLAUDE_API_KEY || 'your-anthropic-key-here'; +const BOT_USER_ID = 'claude-bot-agent'; // This will be the bot's user ID +const BOT_NAME = 'Claude Agent'; + +// Store bot position and state +let botState = { + position: { x: 10, y: 10 }, // Starting position in the space + isActive: true, + lastActivity: Date.now() +}; + +// Function to call Claude API for AI responses +async function askClaude(question) { + return new Promise((resolve, reject) => { + const data = JSON.stringify({ + model: 'claude-3-5-sonnet-20241022', + max_tokens: 300, + messages: [ + { + role: 'user', + content: question + } + ] + }); + + const options = { + hostname: 'api.anthropic.com', + port: 443, + path: '/v1/messages', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': CLAUDE_API_KEY, + 'anthropic-version': '2023-06-01' + } + }; + + const req = https.request(options, (res) => { + let body = ''; + res.on('data', chunk => body += chunk); + res.on('end', () => { + try { + const parsed = JSON.parse(body); + if (parsed.content && parsed.content[0]) { + resolve(parsed.content[0].text); + } else { + reject(new Error('Invalid response from Claude API')); + } + } catch (e) { + reject(e); + } + }); + }); + + req.on('error', reject); + req.write(data); + req.end(); + }); +} + +// Function to send message to chat in Gather +async function sendMessage(text) { + return new Promise((resolve, reject) => { + const data = JSON.stringify({ + message: text, + userId: BOT_USER_ID + }); + + const options = { + hostname: 'gather.town', + port: 443, + path: `/api/v1/spaces/${GATHER_SPACE_ID}/chat`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${GATHER_API_KEY}` + } + }; + + const req = https.request(options, (res) => { + let body = ''; + res.on('data', chunk => body += chunk); + res.on('end', () => { + try { + const parsed = JSON.parse(body); + resolve(parsed); + } catch (e) { + reject(e); + } + }); + }); + + req.on('error', reject); + req.write(data); + req.end(); + }); +} + +// Function to move bot to a location +async function moveBotTo(x, y) { + botState.position = { x, y }; + return new Promise((resolve, reject) => { + const data = JSON.stringify({ + x: x, + y: y, + userId: BOT_USER_ID + }); + + const options = { + hostname: 'gather.town', + port: 443, + path: `/api/v1/spaces/${GATHER_SPACE_ID}/users/${BOT_USER_ID}/position`, + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${GATHER_API_KEY}` + } + }; + + const req = https.request(options, (res) => { + let body = ''; + res.on('data', chunk => body += chunk); + res.on('end', () => { + try { + const parsed = JSON.parse(body); + resolve(parsed); + } catch (e) { + reject(e); + } + }); + }); + + req.on('error', reject); + req.write(data); + req.end(); + }); +} + +// Listen for chat messages +async function listenForMessages() { + // This would use Gather's webhook system in a real implementation + // For now, we'll use polling to check for new messages + + const checkMessages = async () => { + try { + // Simulated message polling - in production use webhooks + console.log('Bot is listening for messages...'); + + // Keep the bot active + botState.lastActivity = Date.now(); + } catch (err) { + console.error('Error listening for messages:', err); + } + + setTimeout(checkMessages, 5000); + }; + + checkMessages(); +} + +// Process incoming command +async function processCommand(command) { + console.log(`Processing command: ${command}`); + + let response; + + if (command.toLowerCase().includes('@claude')) { + // Extract the actual question + const question = command.replace(/@claude\s*/i, '').trim(); + + if (question) { + try { + console.log(`Asking Claude: ${question}`); + response = await askClaude(question); + await sendMessage(`Claude: ${response}`); + } catch (err) { + console.error('Error calling Claude:', err); + await sendMessage(`Sorry, I encountered an error: ${err.message}`); + } + } + } else if (command.toLowerCase() === 'come here') { + await moveBotTo(15, 15); + await sendMessage('I moved to a new location!'); + } else if (command.toLowerCase() === 'hello') { + await sendMessage(`Hello! I'm ${BOT_NAME}, your AI assistant. Ask me anything by typing @claude followed by your question.`); + } +} + +// Initialize the bot +async function initializeBot() { + console.log(`\nšŸ¤– Starting ${BOT_NAME}...`); + console.log(`Space ID: ${GATHER_SPACE_ID}`); + console.log(`Initial Position: (${botState.position.x}, ${botState.position.y})`); + + // Move bot to starting position + try { + await moveBotTo(botState.position.x, botState.position.y); + console.log('āœ… Bot positioned successfully'); + } catch (err) { + console.error('āŒ Error positioning bot:', err); + } + + // Start listening for messages + await listenForMessages(); + + console.log('āœ… Bot initialized and listening for commands'); + console.log('Commands:'); + console.log(' - @claude [question] - Ask Claude anything'); + console.log(' - come here - Move bot to your location'); + console.log(' - hello - Say hello to the bot'); +} + +// Handle graceful shutdown +process.on('SIGINT', () => { + console.log('\nšŸ‘‹ Shutting down bot...'); + process.exit(0); +}); + +// Start the bot +initializeBot().catch(err => { + console.error('Fatal error:', err); + process.exit(1); +});