| | |
| | const DubAPI = require('./index.js'); |
| | const AIHandler = require('./ai-handler.js'); |
| | const MemoryHandler = require('./memory-handler.js'); |
| |
|
| | console.log('Starting DubAPI example...'); |
| |
|
| | |
| | const username = 'kuber'; |
| | const password = 'cookTV12'; |
| |
|
| | |
| | const roomName = 'nononono'; |
| |
|
| | |
| | const config = { |
| | commandPrefix: '!', |
| | autoReconnect: true, |
| | reconnectInterval: 15000, |
| | greetUsers: true, |
| | autoUpvote: true, |
| | botName: 'Kuber', |
| | respondToMentions: true, |
| | useAI: true, |
| | geminiAPIKey: 'AIzaSyAQAw_EZv1kX_l24ViMGnPYGC3ExbIZFCU' |
| | }; |
| |
|
| | console.log('Attempting to create DubAPI instance with username:', username); |
| | console.log('Connecting to room:', roomName); |
| |
|
| | |
| | let memoryHandler = new MemoryHandler({ |
| | maxMessagesPerUser: 50, |
| | maxMemoryAge: 30 * 60 * 1000 |
| | }); |
| |
|
| | |
| | let aiHandler = null; |
| | if (config.useAI && config.geminiAPIKey) { |
| | aiHandler = new AIHandler(config.geminiAPIKey, memoryHandler); |
| | console.log('AI handler initialized with Gemini API and conversation memory'); |
| | } |
| |
|
| | new DubAPI({username: username, password: password}, function(err, bot) { |
| | if (err) return console.error('Error connecting:', err); |
| |
|
| | console.log('Running DubAPI v' + bot.version); |
| |
|
| | |
| | |
| | |
| | function formatTime(seconds) { |
| | const mins = Math.floor(seconds / 60); |
| | const secs = Math.floor(seconds % 60); |
| | return `${mins}:${secs < 10 ? '0' + secs : secs}`; |
| | } |
| | |
| | |
| | function isStaff(user) { |
| | return user && bot.isStaff(user); |
| | } |
| | |
| | |
| | |
| | |
| | function handleCommand(data) { |
| | |
| | if (!data.message.startsWith(config.commandPrefix)) return; |
| | |
| | |
| | const args = data.message.slice(config.commandPrefix.length).trim().split(/\s+/); |
| | const command = args.shift().toLowerCase(); |
| | |
| | |
| | const user = bot.getUser(data.user.id); |
| | |
| | switch (command) { |
| | case 'ping': |
| | bot.sendChat('Pong! 🏓'); |
| | break; |
| | |
| | case 'memory': |
| | if (memoryHandler) { |
| | const stats = memoryHandler.getStats(); |
| | const now = Date.now(); |
| | const oldestTime = stats.oldestMessage ? new Date(stats.oldestMessage).toISOString().substring(11, 19) : 'none'; |
| | |
| | bot.sendChat(`Memory stats: ${stats.userCount} users, ${stats.totalMessages} messages, oldest from ${oldestTime}`); |
| | |
| | if (args[0] === 'clear' && isStaff(user)) { |
| | |
| | memoryHandler.memories.clear(); |
| | bot.sendChat('Memory cleared by ' + user.username); |
| | } |
| | } else { |
| | bot.sendChat('Memory system is not active.'); |
| | } |
| | break; |
| | |
| | case 'info': |
| | const currentMedia = bot.getMedia(); |
| | if (currentMedia) { |
| | bot.sendChat(`Current track: ${currentMedia.name} by ${currentMedia.artist || 'Unknown'}`); |
| | } else { |
| | bot.sendChat('No track is currently playing.'); |
| | } |
| | break; |
| | |
| | case 'time': |
| | const remaining = bot.getTimeRemaining(); |
| | const elapsed = bot.getTimeElapsed(); |
| | if (remaining >= 0) { |
| | bot.sendChat(`Time remaining: ${formatTime(remaining)} | Elapsed: ${formatTime(elapsed)}`); |
| | } else { |
| | bot.sendChat('No track is currently playing.'); |
| | } |
| | break; |
| | |
| | case 'skip': |
| | if (isStaff(user) && bot.hasPermission(user, 'skip')) { |
| | bot.moderateSkip(function(err) { |
| | if (err) return console.error('Error skipping track:', err); |
| | bot.sendChat('Track skipped by ' + user.username); |
| | }); |
| | } else { |
| | bot.sendChat('You need to be staff with skip permission to use this command.'); |
| | } |
| | break; |
| | |
| | case 'users': |
| | const users = bot.getUsers(); |
| | bot.sendChat(`There are ${users.length} users in the room.`); |
| | break; |
| | |
| | case 'staff': |
| | const staff = bot.getStaff(); |
| | bot.sendChat(`There are ${staff.length} staff members in the room.`); |
| | break; |
| | |
| | case 'help': |
| | bot.sendChat('Available commands: !ping, !info, !time, !users, !staff, !help'); |
| | break; |
| | |
| | default: |
| | |
| | break; |
| | } |
| | } |
| |
|
| | |
| | |
| | function connect() { |
| | console.log('Attempting to connect to room:', roomName); |
| | bot.connect(roomName); |
| | } |
| |
|
| | |
| | |
| | bot.on('connected', function(name) { |
| | console.log('Connected to ' + name); |
| | console.log('Bot is ready to respond to commands. Use ' + config.commandPrefix + 'help for available commands'); |
| | }); |
| |
|
| | bot.on('disconnected', function(name) { |
| | console.log('Disconnected from ' + name); |
| | |
| | if (config.autoReconnect) { |
| | console.log(`Attempting to reconnect in ${config.reconnectInterval / 1000} seconds...`); |
| | setTimeout(connect, config.reconnectInterval); |
| | } |
| | }); |
| |
|
| | bot.on('error', function(err) { |
| | console.error('Error:', err); |
| | }); |
| |
|
| | |
| | bot.on(bot.events.chatMessage, function(data) { |
| | console.log(data.user.username + ': ' + data.message); |
| | |
| | |
| | if (data.user.username !== config.botName && memoryHandler) { |
| | memoryHandler.addMessage(data.user.username, data.message, false); |
| | } |
| | |
| | |
| | handleCommand(data); |
| | |
| | |
| | if (config.respondToMentions && data.user.username !== config.botName) { |
| | |
| | const message = data.message; |
| | const lowerMessage = message.toLowerCase(); |
| | const botName = config.botName.toLowerCase(); |
| | |
| | |
| | const isMentioned = |
| | lowerMessage.includes('@' + botName) || |
| | lowerMessage.startsWith(botName) || |
| | lowerMessage.includes(' ' + botName + ' ') || |
| | lowerMessage.endsWith(' ' + botName); |
| | |
| | console.log('Checking for mentions in message:', message, 'Mentioned:', isMentioned); |
| | |
| | |
| | if (isMentioned) { |
| | console.log(`Bot was mentioned by ${data.user.username}`); |
| | |
| | |
| | let userMessage = data.message; |
| | const botNamePattern = new RegExp(`@?${config.botName}`, 'gi'); |
| | userMessage = userMessage.replace(botNamePattern, '').trim(); |
| | |
| | |
| | if (userMessage.toLowerCase().includes('what') && |
| | (userMessage.toLowerCase().includes('song') || |
| | userMessage.toLowerCase().includes('track') || |
| | userMessage.toLowerCase().includes('playing'))) { |
| | |
| | |
| | const currentMedia = bot.getMedia(); |
| | if (currentMedia) { |
| | const response = `@${data.user.username}, we're listening to ${currentMedia.name} by ${currentMedia.artist || 'Unknown'}.`; |
| | return bot.sendChat(response); |
| | } |
| | } |
| | |
| | if (userMessage.toLowerCase() === 'help' || userMessage.toLowerCase() === '?') { |
| | const response = `@${data.user.username}, try using ${config.commandPrefix}help to see my commands.`; |
| | return bot.sendChat(response); |
| | } |
| | |
| | |
| | if (config.useAI && aiHandler) { |
| | |
| | bot.sendChat(`/me 생각중...`); |
| | |
| | |
| | console.log(`Sending to AI: ${userMessage} (from: ${data.user.username})`); |
| | aiHandler.getAIResponse(userMessage, data.user.username) |
| | .then(aiResponse => { |
| | |
| | |
| | |
| | console.log(`===== FULL AI RESPONSE (${aiResponse.length} chars) ====`); |
| | console.log(aiResponse); |
| | console.log(`===== END OF FULL AI RESPONSE ====`); |
| | |
| | |
| | const maxLength = 250; |
| | const chunks = []; |
| | |
| | |
| | let firstChunk = `@${data.user.username}, `; |
| | |
| | |
| | |
| | |
| | |
| | let remaining = aiResponse; |
| | let isFirst = true; |
| | |
| | while (remaining.length > 0) { |
| | |
| | const limit = isFirst ? (maxLength - firstChunk.length) : maxLength; |
| | let splitAt = Math.min(remaining.length, limit); |
| | |
| | |
| | if (remaining.length > limit) { |
| | |
| | const lastSpace = remaining.substring(0, limit).lastIndexOf(' '); |
| | if (lastSpace > limit / 2) { |
| | splitAt = lastSpace + 1; |
| | } |
| | } |
| | |
| | |
| | const part = remaining.substring(0, splitAt).trim(); |
| | |
| | |
| | if (part.length > 0) { |
| | chunks.push(isFirst ? (firstChunk + part) : part); |
| | } |
| | |
| | |
| | remaining = remaining.substring(splitAt).trim(); |
| | isFirst = false; |
| | } |
| | |
| | |
| | console.log(`Sending response in ${chunks.length} chunks`); |
| | let sentCount = 0; |
| | |
| | function sendNextChunk() { |
| | if (sentCount < chunks.length) { |
| | const chunk = chunks[sentCount]; |
| | console.log(`Sending chunk ${sentCount + 1}/${chunks.length}: ${chunk.length} chars`); |
| | bot.sendChat(chunk); |
| | sentCount++; |
| | |
| | if (sentCount < chunks.length) { |
| | |
| | setTimeout(sendNextChunk, 800); |
| | } else { |
| | |
| | if (memoryHandler) { |
| | memoryHandler.addMessage(data.user.username, aiResponse, true); |
| | } |
| | console.log('All chunks sent successfully'); |
| | } |
| | } |
| | } |
| | |
| | |
| | sendNextChunk(); |
| | }) |
| | .catch(err => { |
| | console.error('AI Response Error:', err); |
| | bot.sendChat(`@${data.user.username}, sorry, my AI brain is having trouble right now. Try again later?`); |
| | }); |
| | } else { |
| | |
| | const responses = [ |
| | `Yes, @${data.user.username}? How can I help you?`, |
| | `I'm here, @${data.user.username}! Need something?`, |
| | `Hey @${data.user.username}, what's up?`, |
| | `@${data.user.username}, at your service! Try ${config.commandPrefix}help for commands.` |
| | ]; |
| | const response = responses[Math.floor(Math.random() * responses.length)]; |
| | |
| | |
| | setTimeout(() => { |
| | bot.sendChat(response); |
| | }, 1000 + Math.random() * 1000); |
| | } |
| | } |
| | } |
| | }); |
| |
|
| | |
| | bot.on(bot.events.userJoin, function(data) { |
| | console.log(`${data.user.username} joined the room`); |
| | |
| | |
| | if (config.greetUsers) { |
| | bot.sendChat(`Welcome to the room, @${data.user.username}!`); |
| | } |
| | }); |
| |
|
| | |
| | bot.on(bot.events.userLeave, function(data) { |
| | console.log(`${data.user.username} left the room`); |
| | }); |
| |
|
| | |
| | bot.on(bot.events.roomPlaylistUpdate, function(data) { |
| | if (!data.media) return; |
| | |
| | console.log(`Now playing: ${data.media.name} by ${data.media.artist || 'Unknown'}`); |
| | |
| | |
| | if (config.autoUpvote) { |
| | setTimeout(() => { |
| | bot.updub(function(err) { |
| | if (err) console.error('Error upvoting:', err); |
| | else console.log('Auto-upvoted current song'); |
| | }); |
| | }, 5000); |
| | } |
| | }); |
| |
|
| | |
| | connect(); |
| | }); |
| |
|