rayai/bot/discord-bot.js

168 lines
5.2 KiB
JavaScript

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 => {
// Function to send a random message from any array
async function sendRand(array) {
const arrayChoice = array[Math.floor(Math.random() * array.length)];
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)) {
return;
}
const content = message.content.trim();
let additionalContent = '';
if (content === '!r' || content === '!reset') {
await resetConversation(message)
// Handle conversation reset
return await sendRand(userResetMessages)
}
if (content === '!restartCore') {
// Handle core restart
return await restartCore(message);
}
await handleUserMessage(message, content, additionalContent);
});
async function handleUserMessage(message, content, additionalContent) {
const encodedMessage = he.encode(content + additionalContent);
// Start typing indicator
const typingInterval = setInterval(() => {
message.channel.sendTyping();
}, 9000);
message.channel.sendTyping(); // Initial typing indicator
try {
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
}
});
clearInterval(typingInterval); // Stop typing indicator
const data = response.data;
await sendLongMessage(message, data.content);
} catch (error) {
clearInterval(typingInterval); // Stop typing indicator
if (error.response && error.response.status === 429) {
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 {
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(response.status)
} catch (error) {
console.log(error)
}
}
async function restartCore(message) {
try {
const response = await axios.post(`${process.env.API_PATH}/restart-core`);
} catch (error) {
console.log(error)
}
}
async function sendLongMessage(message, responseText) {
const limit = 8096;
if (responseText.length > limit) {
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();
setTimeout(() => {
message.channel.send({
embeds: [embed]
});
}, i * (process.env.OVERFLOW_DELAY || 3) * 1000);
}
} else {
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);