From b60e681998a456adecb93b5fe04b66ad4ac9abb6 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Fri, 21 Mar 2025 22:24:53 -0400 Subject: Minor code fixes; Ditching settings on Discord in favour of using an API --- bot/src/api/routes/settings.js | 62 +++++++++++++++++ bot/src/api/server.js | 2 + bot/src/commands/eval.js | 5 +- bot/src/commands/quote.js | 2 +- bot/src/commands/settings.js | 147 ++++------------------------------------ bot/src/commands/suggest.js | 2 +- bot/src/commands/timer.js | 4 +- bot/src/events/MessageCreate.js | 2 + bot/src/plugins/chatbot.js | 1 - 9 files changed, 86 insertions(+), 141 deletions(-) create mode 100644 bot/src/api/routes/settings.js (limited to 'bot/src') diff --git a/bot/src/api/routes/settings.js b/bot/src/api/routes/settings.js new file mode 100644 index 0000000..68d8745 --- /dev/null +++ b/bot/src/api/routes/settings.js @@ -0,0 +1,62 @@ +import { ChannelType } from 'discord.js'; +import { Router } from 'express'; +import { guildSettings } from '../../models/guild-settings.js'; + +export function settingsRouter(client) { + const router = Router(); + + router.get('/settings/guild', async (req, res) => { + try { + const { guildID } = req.body; + if (!guildID) return res.status(400).send('Guild ID not provided'); + const settings = await guildSettings.findOne({ where: { guildID: guildID } }); + res.json(settings); + } catch (e) { + console.error('Error fetching settings:', e); + res.status(500).send('Internal Server Error'); + } + }); + + router.get('/settings/guild/:id', async (req, res) => { + try { + const settings = await guildSettings.findOne({ where: { guildID: req.params.id } }); + + let channels = []; + + client.guilds.cache.get(settings.guildID).channels.cache + .filter((channel) => channel.type === ChannelType.GuildText) + .forEach((channel) => { + const channelInfo = { + name: channel.name, + id: channel.id, + category: channel.parent ? channel.parent.name : 'No Category' + }; + + channels.push(channelInfo); + }); + + res.json(channels); + } catch (e) { + console.error('Error fetching settings:', e); + res.status(500).send('Internal Server Error'); + } + }); + + router.post('/settings/guild', async (req, res) => { + try { + const { guildID, ...newSettings } = req.body; + const [updated] = await guildSettings.update(newSettings, { where: { guildID: guildID } }); + if (updated) { + const updatedSettings = await guildSettings.findOne({ where: { guildID: guildID } }); + res.json(updatedSettings); + } else { + res.status(404).send('Settings not found'); + } + } catch (e) { + console.error('Error updating settings:', e); + res.status(500).send('Internal Server Error'); + } + }); + + return router; +} diff --git a/bot/src/api/server.js b/bot/src/api/server.js index 0b0397e..74d8511 100644 --- a/bot/src/api/server.js +++ b/bot/src/api/server.js @@ -5,6 +5,7 @@ import 'dotenv/config'; import { readFileSync } from 'node:fs'; import { quoteRouter } from './routes/quotes.js'; +import { settingsRouter } from './routes/settings.js'; const app = express(); @@ -13,6 +14,7 @@ export const apiServer = (client) => { app.use(express.json()); app.use('/api', quoteRouter); + app.use('/api', settingsRouter(client)); app.get('/api/version', (req, res) => { const { version } = JSON.parse(readFileSync('./package.json', 'utf-8')); diff --git a/bot/src/commands/eval.js b/bot/src/commands/eval.js index 598c7fd..68f3003 100644 --- a/bot/src/commands/eval.js +++ b/bot/src/commands/eval.js @@ -1,14 +1,13 @@ -import { SlashCommandBuilder } from 'discord.js'; +import { MessageFlags, SlashCommandBuilder } from 'discord.js'; import { inspect } from 'util'; import { userWhitelist } from '../storage/consts.js'; - export default { data: new SlashCommandBuilder() .setName('eval') .setDescription('Evaluates code'), async execute(interaction) { - if (!userWhitelist.includes(interaction.user.id)) return await interaction.reply('Nope! You don\'t have permission to use this command.'); + if (!userWhitelist.includes(interaction.user.id)) return await interaction.reply({ content: 'Nope! You don\'t have permission to use this command.', flags: MessageFlags.Ephemeral }); await interaction.reply('You have entered evaluation mode. Enter the code for AleeBot to evaluate.\nType in `exit` to exit evaluation mode.'); let evaled; diff --git a/bot/src/commands/quote.js b/bot/src/commands/quote.js index 5e5ae5b..55b8cbc 100644 --- a/bot/src/commands/quote.js +++ b/bot/src/commands/quote.js @@ -97,7 +97,7 @@ export default { return modalInteraction.reply({ content: 'Something went wrong.', flags: MessageFlags.Ephemeral }); }); - return await modalInteraction.reply({content: 'Sending this quote for manual approval.', flags: MessageFlags.Ephemeral}); + return await modalInteraction.reply({ content: 'Sending this quote for manual approval.', flags: MessageFlags.Ephemeral }); }) .catch((err) => { console.error(err); diff --git a/bot/src/commands/settings.js b/bot/src/commands/settings.js index e5f4ee3..7d7494d 100644 --- a/bot/src/commands/settings.js +++ b/bot/src/commands/settings.js @@ -1,143 +1,24 @@ -import { - EmbedBuilder, - MessageFlags, - PermissionFlagsBits, - SlashCommandBuilder, - ButtonBuilder, - ButtonStyle, - ActionRowBuilder, - ComponentType, - ChannelType, - ChannelSelectMenuBuilder -} from 'discord.js'; +import {ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, SlashCommandBuilder} from 'discord.js'; import { abEmbedColour } from '../storage/consts.js'; -import { guildSettings } from '../models/guild-settings.js'; - export default { data: new SlashCommandBuilder() .setName('settings') - .setDescription('User settings for AleeBot.') - .addSubcommand(subcommand => - subcommand - .setName('guild') - .setDescription('Change settings for the guild.')), - // .addSubcommand(subcommand => - // subcommand - // .setName('user') - // .setDescription('Change settings for the user.')), + .setDescription('Settings for AleeBot.'), async execute(interaction) { - if (interaction.options.getSubcommand() === 'guild') { - if (!interaction.guild) return await interaction.reply({ content: 'This command can only be run in a guild.' }); - //if (!interaction.member.permissions.has(PermissionFlagsBits.ManageGuild)) return await interaction.reply({ content: 'You do not have the permission to manage this guild.', flags: MessageFlags.Ephemeral }); - - const guildSetting = await guildSettings.findOne({ where: { guildID: interaction.guild.id } }); - - if (!guildSetting) { - await guildSettings.create({ guildID: interaction.guild.id }); - } - - const logMenu = new ChannelSelectMenuBuilder() - .setCustomId('logMenu') - .setPlaceholder('Select a channel') - .setChannelTypes(ChannelType.GuildText); - - const logging = new ButtonBuilder() - .setCustomId('logging') - .setLabel('Logging') - .setStyle(ButtonStyle.Primary); - - const suggestions = new ButtonBuilder() - .setCustomId('suggestions') - .setLabel('Suggestions') - .setStyle(ButtonStyle.Primary); - - const qotdChannel = new ButtonBuilder() - .setCustomId('qotdChannel') - .setLabel('QOTD Channel') - .setStyle(ButtonStyle.Primary); - - const llmChatbot = new ButtonBuilder() - .setCustomId('llmChatbot') - .setLabel('LLM Chatbot') - .setStyle(ButtonStyle.Primary); - - const qotdToggle = new ButtonBuilder() - .setCustomId('qotdToggle') - .setLabel('QOTD Toggle') - .setStyle(ButtonStyle.Primary); - - const done = new ButtonBuilder() - .setCustomId('done') - .setLabel('Suggestions') - .setStyle(ButtonStyle.Success); - - const row = new ActionRowBuilder() - .addComponents(logging, suggestions, qotdChannel, llmChatbot, qotdToggle); - - const row2 = new ActionRowBuilder() - .addComponents(logMenu); - - const guildEmbed = new EmbedBuilder() - .setAuthor({ name: 'AleeBot Guild Settings', iconURL: interaction.client.user.avatarURL() }) - .setDescription('Select the options') - .addFields( - { name: 'Logging', value: guildSetting?.logChannelID ? `<#${guildSetting.logChannelID}>` : 'N/A', inline: true }, - { name: 'Suggestions', value: guildSetting?.suggestionsChannelID ? `<#${guildSetting.suggestionsChannelID}>` : 'N/A', inline: true }, - { name: 'QOTD Channel', value: guildSetting?.qotdChannelID ? `<#${guildSetting.qotdChannelID}>` : 'N/A', inline: true }, - { name: 'LLM Chatbot', value: guildSetting?.ollamaEnabled ? 'Enabled' : 'Disabled', inline: true }, - { name: 'Quote of the Day', value: guildSetting?.qotdToggle ? 'Enabled' : 'Disabled', inline: true } - ) - .setColor(abEmbedColour); - - const guildSetup = await interaction.reply({ embeds: [guildEmbed], components: [row] }); - - const filter = (i) => i.user.id === interaction.user.id; - - const guildCollector = guildSetup.createMessageComponentCollector({ - componentType: ComponentType.Button, - filter, - time: 1000 * 120 - }); - - guildCollector.on('collect', async (interaction) => { - if (interaction.customId === 'logging') { - await interaction.reply({ components: [row2] }); - - const logMenuInteraction = await interaction.channel.awaitMessageComponent({ - componentType: ComponentType.ChannelSelectMenu, - filter: (i) => i.user.id === interaction.user.id, - time: 1000 * 120 - }); - - if (logMenuInteraction.customId === 'logMenu') { - await logMenuInteraction.reply({ content: `Selected <#${logMenuInteraction.values}>` }); - await guildSettings.update({ logChannelID: logMenuInteraction.values[0] }, { where: { guildID: interaction.guild.id } }); - } - - const logSetting = await guildSettings.findOne({ where: { guildID: interaction.guild.id } }); - guildEmbed.spliceFields(0, 1, { name: 'Logging', value: logSetting?.logChannelID ? `<#${logSetting.logChannelID}>` : 'N/A', inline: true }); - await interaction.editReply({ embeds: [guildEmbed], components: [row] }); + const settingEmbed = new EmbedBuilder() + .setAuthor({ name: 'AleeBot Settings', iconURL: interaction.client.user.avatarURL() }) + .setDescription(`To configure AleeBot, visit ${process.env.SETTINGS_URL}`) + .setColor(abEmbedColour); - await interaction.deleteReply(); - } + let settingButtons = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('Configure') + .setURL(process.env.SETTINGS_URL) + ); - if (interaction.customId === 'suggestions') { - await interaction.reply({ content: 'Clicked on suggestions' }); - } - }); - } + return await interaction.reply({ embeds: [settingEmbed], components: [settingButtons] }); - // if (interaction.options.getSubcommand() === 'user') { - // const userEmbed = new EmbedBuilder() - // .setAuthor({ name: 'AleeBot User Settings', iconURL: interaction.client.user.avatarURL() }) - // .setDescription('Select the options') - // .addFields( - // { name: 'Language', value: 'logchannel', inline: true }, - // { name: 'Location', value: 'channel', inline: true } - // ) - // .setColor(abEmbedColour); - // - // return await interaction.reply({ embeds: [userEmbed] }); - // } } }; diff --git a/bot/src/commands/suggest.js b/bot/src/commands/suggest.js index b8fe68a..b8b164b 100644 --- a/bot/src/commands/suggest.js +++ b/bot/src/commands/suggest.js @@ -56,7 +56,7 @@ export default { .setFooter({ text: `Sending from ${modalInteraction.guild.name}`, iconURL: modalInteraction.guild.iconURL() }) ]}); - return await modalInteraction.reply({content: 'Your suggestion has been sent.', flags: MessageFlags.Ephemeral}); + return await modalInteraction.reply({ content: 'Your suggestion has been sent.', flags: MessageFlags.Ephemeral }); }) .catch((err) => { console.error(err); diff --git a/bot/src/commands/timer.js b/bot/src/commands/timer.js index 68a113c..c86fd20 100644 --- a/bot/src/commands/timer.js +++ b/bot/src/commands/timer.js @@ -1,4 +1,4 @@ -import { SlashCommandBuilder, time, TimestampStyles } from 'discord.js'; +import { MessageFlags, SlashCommandBuilder, time, TimestampStyles } from 'discord.js'; export default { data: new SlashCommandBuilder() @@ -27,7 +27,7 @@ export default { const hours = interaction.options.getInteger('hours') || 0; const message = interaction.options.getString('message'); const content = message ? `Reason: \`\`\`\n${message}\n\`\`\`` : ''; - if (!seconds && !minutes && !hours) return await interaction.reply({ content: 'Please provide a time to wait for.', ephemeral: true }); + if (!seconds && !minutes && !hours) return await interaction.reply({ content: 'Please provide a time to wait for.', flags: MessageFlags.Ephemeral }); timer = seconds + (minutes * 60) + (hours * 3600); diff --git a/bot/src/events/MessageCreate.js b/bot/src/events/MessageCreate.js index 06f0808..4895ab2 100644 --- a/bot/src/events/MessageCreate.js +++ b/bot/src/events/MessageCreate.js @@ -7,10 +7,12 @@ export default { if (!msg.client.application?.owner) await msg.client.application?.fetch(); if (msg.author.bot) return; if (!msg.guild) return; + if (msg.mentions.everyone) return; const args = msg.content.slice(`${msg.client.user}`.length).trim(); if (msg.mentions.has(msg.client.user)) { + if (!args) return; await ChatBot(msg, args); } } diff --git a/bot/src/plugins/chatbot.js b/bot/src/plugins/chatbot.js index 3da7421..17a26ee 100644 --- a/bot/src/plugins/chatbot.js +++ b/bot/src/plugins/chatbot.js @@ -8,7 +8,6 @@ export async function ChatBot(msg, args) { if (!guildSetting.ollamaEnabled) return; if (!ollamaGlobal) return msg.reply('Sorry, the LLM chatbot feature has been turned off.'); - if (!args) return msg.reply('Sorry? What was that?'); try { const loadingMessage = await msg.reply('Thinking...'); -- cgit v1.2.3