const { Client, GatewayIntentBits, EmbedBuilder } = require('discord.js'); const axios = require('axios'); const he = require('he'); const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const { userResetMessages } = require('./assets/messages.js'); const cheerio = require('cheerio'); require('dotenv').config(); const channelIDs = process.env.CHANNEL_IDS.split(','); const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent] }); const MAX_CONTENT_LENGTH = process.env.MAX_CONTENT_LENGTH || 8000; client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); }); client.on('messageCreate', async message => { if (message.guildId == "1192181551526584380") return if (message.content.includes("[LOG]")) return console.log(`Received message: ${message.content}, from ${message.author.tag}, in channel: ${message.channel.name}`); console.log(message.guildId) // Function to send a random message from any array async function sendRand(array) { const arrayChoice = array[Math.floor(Math.random() * array.length)]; console.log(`Sending random response: ${arrayChoice}`); await message.channel.send(arrayChoice); // give a notification of reset using a human-like response. } if (message.author.bot) return; // Only respond in the specified channels if (!channelIDs.includes(message.channel.id)) { console.log(`Ignoring message from channel: ${message.channel.id}, not in the specified channels.`); return; } const content = message.content.trim(); let additionalContent = ''; if (content === '!r' || content === '!reset') { console.log("Reset command received."); await resetConversation(message); // Handle conversation reset return await sendRand(userResetMessages); } if (content === '!restartCore') { console.log("Restart core command received."); // Handle core restart return await restartCore(message); } console.log(`Handling user message: ${content}`); await handleUserMessage(message, content, additionalContent); }); async function handleUserMessage(message, content, additionalContent) { const encodedMessage = he.encode(content + additionalContent); console.log(`Encoded message: ${encodedMessage}`); const typingInterval = setInterval(() => { message.channel.sendTyping(); }, 9000); message.channel.sendTyping(); // Initial typing indicator try { console.log(`Sending message to API at: http://${process.env.ROOT_IP}:${process.env.ROOT_PORT}/api/v1/chat`); const response = await axios.post(`http://${process.env.ROOT_IP}:${process.env.ROOT_PORT}/api/v1/chat`, { message: encodedMessage, max_tokens: Number(process.env.MAX_TOKENS), repeat_penalty: Number(process.env.REPEAT_PENALTY) }, { headers: { 'Content-Type': 'application/json', 'x-forwarded-for-id': message.author.id, 'x-forwarded-for-name': message.author.username, 'x-forwarded-for-guild': message.guild.name } }); console.log("API response received:", response.data); // If response.data is a string (no 'content' property), use it directly const responseText = typeof response.data === 'string' ? response.data : response.data.content; if (!responseText) { console.error("No content found in API response."); return message.channel.send("Oops, something went wrong. No response content."); } clearInterval(typingInterval); // Stop typing indicator await sendLongMessage(message, responseText); } catch (error) { console.error("Error during API call:", error.message); clearInterval(typingInterval); // Stop typing indicator if (error.response && error.response.status === 429) { console.log("API rate limited, trying to send DM."); try { await message.author.send('I am currently busy. Please try again later.'); } catch (dmError) { console.error('Failed to send DM:', dmError); message.reply('I am currently busy. Please try again later.'); } } else { message.reply('Error: ' + error.message); } } } async function resetConversation(message) { try { console.log("Resetting conversation..."); const response = await axios.post( `${process.env.API_PATH}/reset-conversation`, {}, { headers: { 'Content-Type': 'application/json', 'x-forwarded-for-id': message.author.id, 'x-forwarded-for-name': message.author.username, 'x-forwarded-for-guild': message.guild.name } } ); console.log(`Reset conversation status: ${response.status}`); } catch (error) { console.error("Error during reset conversation:", error); } } async function restartCore(message) { try { console.log("Restarting core..."); const response = await axios.post(`${process.env.API_PATH}/restart-core`); console.log(`Core restart status: ${response.status}`); } catch (error) { console.error("Error during core restart:", error); } } async function sendLongMessage(message, responseText) { console.log(`Preparing to send response. Length: ${responseText ? responseText.length : 'undefined'}`); const limit = 8096; if (!responseText) { console.error("Response text is undefined or null."); return message.channel.send("Oops, I didn't get any response. Please try again."); } if (responseText.length > limit) { console.log("Response too long, splitting into chunks..."); const lines = responseText.split('\n'); const chunks = []; let currentChunk = ''; for (const line of lines) { if (currentChunk.length + line.length > limit) { chunks.push(currentChunk); currentChunk = ''; } currentChunk += line + '\n'; } if (currentChunk.trim() !== '') { chunks.push(currentChunk.trim()); } if (chunks.length >= 80) return await message.channel.send("Response chunks too large. Try again"); for (let i = 0; i < chunks.length; i++) { const chunk = chunks[i]; const embed = new EmbedBuilder() .setDescription(chunk) // Wraps the chunk in a code block .setColor("#3498DB") .setTimestamp(); console.log(`Sending chunk ${i + 1}/${chunks.length}`); setTimeout(() => { message.channel.send({ embeds: [embed] }); }, i * (process.env.OVERFLOW_DELAY || 3) * 1000); } } else { console.log("Response fits within limit, sending single message."); const embed = new EmbedBuilder() .setDescription(responseText) // Wraps the response in a code block .setColor("#3498DB") .setTimestamp(); message.channel.send({ embeds: [embed] }); } } client.login(process.env.THE_TOKEN);