aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bot/eslint.config.js3
-rw-r--r--bot/package.json1
-rw-r--r--bot/src/bot.js6
-rw-r--r--bot/src/commands/about.js2
-rw-r--r--bot/src/commands/quote.js2
-rw-r--r--bot/src/commands/rm.js2
-rw-r--r--bot/src/commands/settings.js79
-rw-r--r--bot/src/commands/suggest.js2
-rw-r--r--bot/src/events/ClientReady.js3
-rw-r--r--bot/src/events/GuildBanAdd.js13
-rw-r--r--bot/src/events/GuildCreate.js3
-rw-r--r--bot/src/events/GuildDelete.js16
-rw-r--r--bot/src/events/GuildMemberRemove.js2
-rw-r--r--bot/src/events/InteractionCreate.js10
-rw-r--r--bot/src/events/MessageCreate.js10
-rw-r--r--bot/src/events/MessageUpdate.js18
-rw-r--r--bot/src/models/guild-settings.js28
-rw-r--r--bot/src/storage/consts.js2
18 files changed, 146 insertions, 56 deletions
diff --git a/bot/eslint.config.js b/bot/eslint.config.js
index 6f258fe..e9901f8 100644
--- a/bot/eslint.config.js
+++ b/bot/eslint.config.js
@@ -20,7 +20,8 @@ export default [
'@stylistic/js/quotes': ['error', 'single'],
'@stylistic/js/semi-style': ['error', 'last'],
'@stylistic/js/semi': ['error', 'always'],
- '@stylistic/js/indent': ['error', 4]
+ '@stylistic/js/indent': ['error', 4],
+ 'require-await': 'error'
}
},
pluginJs.configs.recommended,
diff --git a/bot/package.json b/bot/package.json
index 75534b4..72568aa 100644
--- a/bot/package.json
+++ b/bot/package.json
@@ -8,6 +8,7 @@
"scripts": {
"start": "node src/bot.js",
"dev": "nodemon src/bot.js",
+ "deploy": "node deploy-command.js",
"lint": "eslint ."
},
"dependencies": {
diff --git a/bot/src/bot.js b/bot/src/bot.js
index ff03b06..3236817 100644
--- a/bot/src/bot.js
+++ b/bot/src/bot.js
@@ -1,11 +1,13 @@
import { Client, GatewayIntentBits } from 'discord.js';
import 'dotenv/config';
import { init } from './init.js';
-const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages] });
+const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildBans ] });
init(client);
-client.login(process.env.token).catch(function() {
+client.login(process.env.token).then(() => {
+ console.log('[>] Successfully authenticated.');
+}).catch(() => {
console.log('[X] Login failed. The token that you have put in is invalid.');
process.exit(1);
});
diff --git a/bot/src/commands/about.js b/bot/src/commands/about.js
index 8d3efab..311200e 100644
--- a/bot/src/commands/about.js
+++ b/bot/src/commands/about.js
@@ -23,7 +23,7 @@ export default {
{ name: 'License', value: 'GNU General Public License v3.0' },
{ name: 'Contributors', value: '- <@297201585090723841> (Uptime command from 2.x)' }
)
- .setFooter({ text: '© Copyright 2017-2025 Andrew Lee Projects' })
+ .setFooter({ text: '© Copyright 2017-2025 Andrew Lee & contributors' })
.setColor(abEmbedColour);
let Buttons = new ActionRowBuilder()
diff --git a/bot/src/commands/quote.js b/bot/src/commands/quote.js
index 60e35b9..3ae1de3 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 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/rm.js b/bot/src/commands/rm.js
index 7a1351c..9edfdc4 100644
--- a/bot/src/commands/rm.js
+++ b/bot/src/commands/rm.js
@@ -12,7 +12,7 @@ export default {
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
async execute(interaction) {
const amount = interaction.options.getNumber('amount');
- if (amount > 100) return interaction.reply({ content: 'Put a number less than 100.', flags: MessageFlags.Ephemeral });
+ if (amount > 100) return await interaction.reply({ content: 'Put a number less than 100.', flags: MessageFlags.Ephemeral });
return await interaction.channel.bulkDelete(amount)
.then( (messages) => interaction.reply(`Deleted ${messages.size} messages.`));
diff --git a/bot/src/commands/settings.js b/bot/src/commands/settings.js
index 00f7caf..5fdf0cd 100644
--- a/bot/src/commands/settings.js
+++ b/bot/src/commands/settings.js
@@ -1,5 +1,17 @@
-import { EmbedBuilder, MessageFlags, PermissionFlagsBits, SlashCommandBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder, ComponentType } from 'discord.js';
+import {
+ EmbedBuilder,
+ MessageFlags,
+ PermissionFlagsBits,
+ SlashCommandBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ActionRowBuilder,
+ ComponentType,
+ ChannelType,
+ ChannelSelectMenuBuilder
+} from 'discord.js';
import { abEmbedColour } from '../storage/consts.js';
+import { guildSettings } from '../models/guild-settings.js';
export default {
data: new SlashCommandBuilder()
@@ -17,6 +29,17 @@ export default {
if (interaction.options.getSubcommand() === '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')
@@ -27,18 +50,41 @@ export default {
.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);
+ .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: 'logchannel', inline: true },
- { name: 'Suggestions', value: 'channel', inline: true },
- { name: 'LLM Chatbot', value: 'Enabled', inline: true },
- { name: 'Quote of the Day', value: 'logchannel', inline: true },
- { name: 'QOTD Channel', value: 'logchannel', inline: true }
+ { 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);
@@ -54,7 +100,24 @@ export default {
guildCollector.on('collect', async (interaction) => {
if (interaction.customId === 'logging') {
- await interaction.reply({ content: 'Clicked on 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] });
+ await interaction.deleteReply();
}
if (interaction.customId === 'suggestions') {
diff --git a/bot/src/commands/suggest.js b/bot/src/commands/suggest.js
index 8f75915..e4bed85 100644
--- a/bot/src/commands/suggest.js
+++ b/bot/src/commands/suggest.js
@@ -55,7 +55,7 @@ export default {
.setFooter({ text: `Sending from ${modalInteraction.guild.name}`, iconURL: modalInteraction.guild.iconURL() })
]});
- return 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/events/ClientReady.js b/bot/src/events/ClientReady.js
index af03e25..ec22ba6 100644
--- a/bot/src/events/ClientReady.js
+++ b/bot/src/events/ClientReady.js
@@ -28,7 +28,7 @@ export default {
console.log(`[i] Bot ID: ${client.user.id}`);
console.log(`[i] Running version ${abVersion} | Serving in ${client.guilds.cache.size} guilds`);
- botActivity(client);
+ await botActivity(client);
if (readyMsg) {
const readyEmbed = new EmbedBuilder()
@@ -41,7 +41,6 @@ export default {
)
.setColor(abEmbedColour);
-
let statusChannel = client.channels.cache.get(process.env.statusChannelID);
if (!statusChannel) return console.error('The status channel does not exist! Skipping.');
await statusChannel.send({ embeds: [readyEmbed]});
diff --git a/bot/src/events/GuildBanAdd.js b/bot/src/events/GuildBanAdd.js
index 1e52040..e68701d 100644
--- a/bot/src/events/GuildBanAdd.js
+++ b/bot/src/events/GuildBanAdd.js
@@ -1,9 +1,17 @@
-import { EmbedBuilder, Events } from 'discord.js';
+import { EmbedBuilder, Events, AuditLogEvent } from 'discord.js';
import { guildSettings } from '../models/guild-settings.js';
export default {
name: Events.GuildBanAdd,
async execute(guild, user) {
+
+ const banLog = await guild.fetchAuditLogs({
+ type: AuditLogEvent.MemberBanAdd,
+ limit: 1,
+ });
+
+ const banEntry = banLog.entries.first();
+
const guildSetting = await guildSettings.findOne({ where: { guildID: guild.id } });
if (!guildSetting || !guildSetting.logChannelID) return;
@@ -12,7 +20,8 @@ export default {
.setDescription(`This user got banned from ${guild.name}`)
.addFields(
{ name: 'User:', value: `${user.tag}` },
- { name: 'User ID:', value: `${user.id}`}
+ { name: 'User ID:', value: `${user.id}`},
+ { name: 'Reason:', value: `${banEntry.reason || 'No reason provided'}` }
)
.setColor('#ff021b')
.setTimestamp();
diff --git a/bot/src/events/GuildCreate.js b/bot/src/events/GuildCreate.js
index 7bcd0d1..4d73f08 100644
--- a/bot/src/events/GuildCreate.js
+++ b/bot/src/events/GuildCreate.js
@@ -1,5 +1,6 @@
import { EmbedBuilder, Events } from 'discord.js';
import { abEmbedColour } from '../storage/consts.js';
+import { guildSettings } from '../models/guild-settings.js';
export default {
name: Events.GuildCreate,
@@ -16,6 +17,8 @@ export default {
.setColor(abEmbedColour)
.setFooter({ text: `We now run on ${guild.client.guilds.cache.size} guilds.` });
+ await guildSettings.create({ guildID: guild.id });
+
let statusChannel = guild.client.channels.cache.get(process.env.statusChannelID);
if (!statusChannel) return;
await statusChannel.send({ embeds: [logEmbed]});
diff --git a/bot/src/events/GuildDelete.js b/bot/src/events/GuildDelete.js
index 2dcba22..5ca1cbe 100644
--- a/bot/src/events/GuildDelete.js
+++ b/bot/src/events/GuildDelete.js
@@ -6,16 +6,6 @@ export default {
name: Events.GuildDelete,
async execute(guild) {
console.log(`[i] I have been removed from: ${guild.name} (${guild.id})`);
-
- try {
- const guildSetting = await guildSettings.findOne({ where: { guildID: guild.id } });
- if (guildSetting) {
- await guildSettings.destroy({ where: { guildID: guild.id } });
- }
- } catch (error) {
- console.error(`Failed to remove guild settings for ${guild.id}:`, error);
- }
-
const logEmbed = new EmbedBuilder()
.setAuthor({ name: 'AleeBot', iconURL: guild.client.user.avatarURL() })
.setDescription('I got removed from a server...')
@@ -26,6 +16,12 @@ export default {
.setColor(abEmbedColour)
.setFooter({ text: `We now run on ${guild.client.guilds.cache.size} guilds.` });
+ const guildSetting = await guildSettings.findOne({ where: { guildID: guild.id } });
+
+ if (guildSetting) {
+ await guildSettings.destroy({ where: { guildID: guild.id } });
+ }
+
let statusChannel = guild.client.channels.cache.get(process.env.statusChannelID);
if (!statusChannel) return;
await statusChannel.send({ embeds: [logEmbed]});
diff --git a/bot/src/events/GuildMemberRemove.js b/bot/src/events/GuildMemberRemove.js
index 9bf5e9d..aa109b1 100644
--- a/bot/src/events/GuildMemberRemove.js
+++ b/bot/src/events/GuildMemberRemove.js
@@ -9,7 +9,7 @@ export default {
const logEmbed = new EmbedBuilder()
.setAuthor({ name: 'AleeBot Logging', iconURL: member.client.user.avatarURL() })
- .setDescription('A user has joined this server!')
+ .setDescription('A user has left this server!')
.addFields(
{ name: 'Username: ', value: `${member.user.tag}`, inline: true },
{ name: 'User ID: ', value: `${member.id}`, inline: true },
diff --git a/bot/src/events/InteractionCreate.js b/bot/src/events/InteractionCreate.js
index eadef09..8f1e998 100644
--- a/bot/src/events/InteractionCreate.js
+++ b/bot/src/events/InteractionCreate.js
@@ -1,5 +1,9 @@
import { Events, MessageFlags } from 'discord.js';
+function error(e) {
+ return `Something went wrong. [Submit an issue at the AleeBot repository.](<https://github.com/Alee14/AleeBot/issues>)\nMessage:\n\`\`\`${e.stack}\`\`\``;
+}
+
export default {
name: Events.InteractionCreate,
async execute(interaction) {
@@ -12,11 +16,11 @@ export default {
try {
await command.execute(interaction);
} catch (e) {
- console.log(e);
+ console.error(e);
if (interaction.replied || interaction.deferred) {
- await interaction.followUp({ content: `Something went wrong. The following error message:\n\`\`\`${e}\`\`\``, flags: MessageFlags.Ephemeral });
+ await interaction.followUp({ content: error(e), flags: MessageFlags.Ephemeral });
} else {
- await interaction.reply({ content: `Something went wrong. The following error message:\n\`\`\`${e}\`\`\``, flags: MessageFlags.Ephemeral });
+ await interaction.reply({ content: error(e), flags: MessageFlags.Ephemeral });
}
}
}
diff --git a/bot/src/events/MessageCreate.js b/bot/src/events/MessageCreate.js
index 90b517d..e7af3a8 100644
--- a/bot/src/events/MessageCreate.js
+++ b/bot/src/events/MessageCreate.js
@@ -1,6 +1,7 @@
import { Events } from 'discord.js';
import { ollama } from '../utils/ollama.js';
-import { ollamaEnabled, ollamaModel } from '../storage/consts.js';
+import { ollamaGlobal, ollamaModel } from '../storage/consts.js';
+import { guildSettings } from '../models/guild-settings.js';
export default {
name: Events.MessageCreate,
@@ -9,10 +10,13 @@ export default {
if (msg.author.bot) return;
if (!msg.guild) return;
+ const guildSetting = await guildSettings.findOne({ where: { guildID: msg.guild.id } });
+
const args = msg.content.slice(`<@${msg.client.user.id}>`.length).trim();
if (msg.mentions.has(msg.client.user)) {
- if (!ollamaEnabled) return msg.reply('Sorry, this feature has been turned off.');
+ if (!guildSetting.ollamaEnabled) return;
+ if (!ollamaGlobal) return msg.reply('Sorry, this feature has been turned off.');
if (!args) return msg.reply('Sorry? What was that?');
try {
@@ -35,7 +39,7 @@ export default {
} catch (err) {
console.error(err);
- await msg.reply('Something went wrong.');
+ await msg.reply(`Something went wrong. [Submit an issue at the AleeBot repository.](<https://github.com/Alee14/AleeBot/issues>)\nMessage:\n\`\`\`${err.stack}\`\`\``);
}
}
}
diff --git a/bot/src/events/MessageUpdate.js b/bot/src/events/MessageUpdate.js
index 26f6ab3..118f51d 100644
--- a/bot/src/events/MessageUpdate.js
+++ b/bot/src/events/MessageUpdate.js
@@ -3,23 +3,23 @@ import { guildSettings } from '../models/guild-settings.js';
export default {
name: Events.MessageUpdate,
- async execute(oldmsg, newmsg) {
- const guildSetting = await guildSettings.findOne({ where: { guildID: oldmsg.guild.id } });
- if (!oldmsg.guild || !guildSetting || !guildSetting.logChannelID) return;
- if (oldmsg.content === newmsg.content) return;
+ async execute(msg, newmsg) {
+ const guildSetting = await guildSettings.findOne({ where: { guildID: msg.guild.id } });
+ if (!msg.guild || !guildSetting || !guildSetting.logChannelID) return;
+ if (msg.content === newmsg.content) return;
const logEmbed = new EmbedBuilder()
- .setAuthor({ name: 'AleeBot Logging', iconURL: oldmsg.client.user.avatarURL() })
- .setDescription(`A message from ${oldmsg.author.username} was edited in <#${oldmsg.channel.id}>`)
+ .setAuthor({ name: 'AleeBot Logging', iconURL: msg.client.user.avatarURL() })
+ .setDescription(`A message from ${msg.author.username} was edited in <#${msg.channel.id}>`)
.addFields(
- { name: 'Before: ', value: `\`\`\`${oldmsg.content}\`\`\`` },
+ { name: 'Before: ', value: `\`\`\`${msg.content}\`\`\`` },
{ name: 'After: ', value: `\`\`\`${newmsg.content}\`\`\`` }
)
.setColor('#ffff1a')
.setTimestamp()
- .setFooter(`Author ID: ${oldmsg.author.id}`);
+ .setFooter(`Author ID: ${msg.author.id}`);
- let editMessage = oldmsg.client.channels.cache.get(guildSetting.logChannelID);
+ let editMessage = msg.client.channels.cache.get(guildSetting.logChannelID);
if (!editMessage) return;
await editMessage.send({ embeds: [logEmbed]});
diff --git a/bot/src/models/guild-settings.js b/bot/src/models/guild-settings.js
index 81cfbc2..bb4d30b 100644
--- a/bot/src/models/guild-settings.js
+++ b/bot/src/models/guild-settings.js
@@ -1,4 +1,4 @@
-import { INTEGER, STRING } from 'sequelize';
+import { INTEGER, STRING, BOOLEAN } from 'sequelize';
import { sequelize } from '../utils/sequelize.js';
export const guildSettings = sequelize.define('guild-settings', {
@@ -14,14 +14,22 @@ export const guildSettings = sequelize.define('guild-settings', {
logChannelID: {
type: STRING,
allowNull: true
- }
- // qotdChannelID: {
- // type: Sequelize.STRING,
- // allowNull: true
- // },
- // qotdToggle: {
- // type: Sequelize.BOOLEAN,
- // allowNull: true
- // }
+ },
+ suggestionsChannelID: {
+ type: STRING,
+ allowNull: true
+ },
+ qotdChannelID: {
+ type: STRING,
+ allowNull: true
+ },
+ qotdToggle: {
+ type: BOOLEAN,
+ allowNull: true
+ },
+ ollamaEnabled: {
+ type: BOOLEAN,
+ allowNull: true
+ },
});
diff --git a/bot/src/storage/consts.js b/bot/src/storage/consts.js
index 905ef79..0787528 100644
--- a/bot/src/storage/consts.js
+++ b/bot/src/storage/consts.js
@@ -1,5 +1,5 @@
export const abEmbedColour = '#0066a6';
export const readyMsg = false;
-export const ollamaEnabled = false;
+export const ollamaGlobal = false;
export const ollamaModel = 'deepseek-r1:14b';
export const featureSuggestChannel = '427495678390960148';