aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bot/bun.lockbbin116354 -> 117052 bytes
-rw-r--r--bot/package.json1
-rw-r--r--bot/src/bot.js17
-rw-r--r--bot/src/commands/quote.js141
-rw-r--r--bot/src/commands/settings.js22
-rw-r--r--bot/src/events/MessageCreate.js46
-rw-r--r--bot/src/init.js13
-rw-r--r--bot/src/models/quote.js2
-rw-r--r--bot/src/storage/consts.js3
-rw-r--r--bot/src/utils/ollama.js3
-rw-r--r--bot/src/utils/sync.js6
11 files changed, 209 insertions, 45 deletions
diff --git a/bot/bun.lockb b/bot/bun.lockb
index c9cc9bb..6893805 100644
--- a/bot/bun.lockb
+++ b/bot/bun.lockb
Binary files differ
diff --git a/bot/package.json b/bot/package.json
index 148a229..a403eb9 100644
--- a/bot/package.json
+++ b/bot/package.json
@@ -13,6 +13,7 @@
"cors": "^2.8.5",
"discord.js": "^14.18.0",
"express": "^4.21.2",
+ "ollama": "^0.5.14",
"sequelize": "^6.37.5",
"sqlite3": "^5.1.7"
},
diff --git a/bot/src/bot.js b/bot/src/bot.js
index 95871e0..ff03b06 100644
--- a/bot/src/bot.js
+++ b/bot/src/bot.js
@@ -1,20 +1,7 @@
import { Client, GatewayIntentBits } from 'discord.js';
import 'dotenv/config';
-import { event } from './handlers/event.js';
-import { command } from './handlers/command.js';
-import { apiServer } from './api/server.js';
-import { syncDB } from './utils/sync.js';
-//import { deployCommands } from './util/deploy.js';
-
-const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] });
-
-async function init(client) {
- await syncDB();
- //deployCommands().then(() => console.log('[>] Deployed commands'));
- await apiServer(client);
- await event(client).then(() => console.log('[>] Event module loaded'));
- await command(client).then(() => console.log('[>] Command module loaded'));
-}
+import { init } from './init.js';
+const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages] });
init(client);
diff --git a/bot/src/commands/quote.js b/bot/src/commands/quote.js
index eaac975..60e35b9 100644
--- a/bot/src/commands/quote.js
+++ b/bot/src/commands/quote.js
@@ -1,35 +1,132 @@
-import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
-import { quote as quoteDB } from '../models/quote.js';
+import {
+ SlashCommandBuilder,
+ EmbedBuilder,
+ MessageFlags,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle, ActionRowBuilder
+} from 'discord.js';
+import { pendingQuote, quote as quoteDB } from '../models/quote.js';
+import { abEmbedColour } from '../storage/consts.js';
+// import { setTimeout as wait } from 'node:timers/promises';
+//
+// let setupMessage = 'Welcome to the AleeBot Quote Setup!\n';
+// setupMessage += 'Please follow these rules when submitting quotes:\n';
+// setupMessage += '```1. No offensive content (NSFW, Racism, etc).\n';
+// setupMessage += '2. Do not send any personal information.\n';
+// setupMessage += '3. Only send noteworthy quotes.```\n';
+// setupMessage += 'We reserve the right to reject any quotes that do not meet our criteria.\n';
+
export default {
data: new SlashCommandBuilder()
.setName('quote')
.setDescription('It gives you a quote.')
- .addNumberOption(option =>
- option
- .setName('id')
- .setDescription('Enter the quote ID to get a specific quote.')),
+ .addSubcommand(subcommand =>
+ subcommand
+ .setName('get')
+ .setDescription('Gives you a quote.')
+ .addNumberOption(option =>
+ option
+ .setName('id')
+ .setDescription('Enter the quote ID to get a specific quote.')))
+ .addSubcommand(subcommand =>
+ subcommand
+ .setName('add')
+ .setDescription('Got a quote? Add it here!')),
async execute(interaction) {
- let quoteID = interaction.options.getNumber('id');
+ if (interaction.options.getSubcommand() === 'add') {
+ const modal = new ModalBuilder()
+ .setCustomId(`newQuote-${interaction.user.id}`)
+ .setTitle('New Quote for AleeBot');
+
+ const author = new TextInputBuilder()
+ .setCustomId('author')
+ .setLabel('Provide the name of the author')
+ .setMaxLength(50)
+ .setPlaceholder('Name')
+ .setStyle(TextInputStyle.Short);
+
+ const authorImage = new TextInputBuilder()
+ .setCustomId('authorImage')
+ .setLabel('Submit the image of the author')
+ .setMaxLength(100)
+ .setPlaceholder('Image URL (512x512) or (128x128)')
+ .setStyle(TextInputStyle.Short);
+
+ const quote = new TextInputBuilder()
+ .setCustomId('quote')
+ .setLabel('Enter the quote')
+ .setMaxLength(200)
+ .setPlaceholder('Quote')
+ .setStyle(TextInputStyle.Paragraph);
+
+ const year = new TextInputBuilder()
+ .setCustomId('year')
+ .setLabel('Specify the year which the quote originates')
+ .setMaxLength(4)
+ .setPlaceholder('Year')
+ .setStyle(TextInputStyle.Short);
+
+ const firstActionRow = new ActionRowBuilder().addComponents(author);
+ const secondActionRow = new ActionRowBuilder().addComponents(authorImage);
+ const thirdActionRow = new ActionRowBuilder().addComponents(quote);
+ const fourthActionRow = new ActionRowBuilder().addComponents(year);
+
+ modal.addComponents(firstActionRow, secondActionRow, thirdActionRow, fourthActionRow);
- if (!quoteID) {
- const quoteList = await quoteDB.findAll({ attributes: ['id'] });
- const random = crypto.getRandomValues(new Uint32Array(1));
- quoteID = quoteList[random[0] % quoteList.length].id;
+ await interaction.showModal(modal);
+
+ const filter = (interaction) => interaction.customId === `newQuote-${interaction.user.id}`;
+
+ interaction.awaitModalSubmit({ filter, time: 1000 * 1200 })
+ .then(async (modalInteraction) => {
+ const author = modalInteraction.fields.getTextInputValue('author');
+ const authorImage = modalInteraction.fields.getTextInputValue('authorImage');
+ const quote = modalInteraction.fields.getTextInputValue('quote');
+ const year = modalInteraction.fields.getTextInputValue('year');
+
+ await pendingQuote.create({
+ author: author,
+ authorImage: authorImage,
+ quote: quote,
+ year: year,
+ submitterAuthor: modalInteraction.user.username,
+ submitterID: modalInteraction.user.id
+ }).catch((err) => {
+ console.error(err);
+ return modalInteraction.reply({ content: 'Something went wrong.', flags: MessageFlags.Ephemeral });
+ });
+
+ return modalInteraction.reply({content: 'Sending this quote for manual approval.', flags: MessageFlags.Ephemeral});
+ })
+ .catch((err) => {
+ console.error(err);
+ });
}
- const quote = await quoteDB.findOne({ where: { id: quoteID } });
+ if (interaction.options.getSubcommand() === 'get') {
+ let quoteID = interaction.options.getNumber('id');
+
+ if (!quoteID) {
+ const quoteList = await quoteDB.findAll({ attributes: ['id'] });
+ const random = crypto.getRandomValues(new Uint32Array(1));
+ quoteID = quoteList[random[0] % quoteList.length].id;
+ }
+
+ const quote = await quoteDB.findOne({ where: { id: quoteID } });
- if (quote) {
- let userSubmitter = await interaction.client.users.fetch(quote.submitter);
- const quoteEmbed = new EmbedBuilder()
- .setAuthor({ name: quote.author, iconURL: quote.authorImage })
- .setDescription(quote.quote)
- .setColor('#1fd619')
- .setFooter({ text: `- ${quote.year}\nSubmitted by ${userSubmitter.username}` });
+ if (quote) {
+ let userSubmitter = await interaction.client.users.fetch(quote.submitter);
+ const quoteEmbed = new EmbedBuilder()
+ .setAuthor({ name: quote.author, iconURL: quote.authorImage })
+ .setDescription(quote.quote)
+ .setColor(abEmbedColour)
+ .setFooter({ text: `- ${quote.year}\nSubmitted by ${userSubmitter.username}` });
- return await interaction.reply({ embeds: [quoteEmbed] });
- } else {
- return await interaction.reply('Cannot find quote, specify the correct quote id.');
+ return await interaction.reply({ embeds: [quoteEmbed] });
+ } else {
+ return await interaction.reply({ content: 'Cannot find quote. Specify the correct quote ID.', flags: MessageFlags.Ephemeral});
+ }
}
}
};
diff --git a/bot/src/commands/settings.js b/bot/src/commands/settings.js
index a04d1c2..5d32a67 100644
--- a/bot/src/commands/settings.js
+++ b/bot/src/commands/settings.js
@@ -1,10 +1,26 @@
-import { SlashCommandBuilder } from 'discord.js';
+import { MessageFlags, PermissionFlagsBits, SlashCommandBuilder } from 'discord.js';
export default {
data: new SlashCommandBuilder()
.setName('settings')
- .setDescription('User settings for AleeBot.'),
+ .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.')),
async execute(interaction) {
- return await interaction.reply(`**PONG!** :ping_pong: ${Math.round(interaction.client.ws.ping)} ms`);
+ 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 });
+
+ return await interaction.reply('recieved');
+ }
+
+ if (interaction.options.getSubcommand() === 'user') {
+ return;
+ }
}
};
diff --git a/bot/src/events/MessageCreate.js b/bot/src/events/MessageCreate.js
new file mode 100644
index 0000000..9394a20
--- /dev/null
+++ b/bot/src/events/MessageCreate.js
@@ -0,0 +1,46 @@
+import { Events } from 'discord.js';
+import { ollama } from '../utils/ollama.js';
+import { ollamaEnabled, ollamaModel } from '../storage/consts.js';
+
+export default {
+ name: Events.MessageCreate,
+ async execute(msg) {
+ if (!msg.client.application?.owner) await msg.client.application?.fetch();
+ if (msg.author.bot) return;
+ if (!msg.guild) return;
+
+ const args = msg.content.slice(`<@${msg.client.user.id}>`.length).trim();
+
+ if (msg.mentions.has(msg.client.user)) {
+ if (ollamaEnabled) {
+ if (!args) return msg.reply('Sorry? What was that?');
+
+ try {
+ const response = await ollama.chat({
+ model: ollamaModel,
+ messages: [{ role: 'user', content: args }],
+ });
+
+ let content = response.message.content;
+ content = content.replace(/<think>.*?<\/think>/g, '');
+
+ if (content.length > 2000) {
+ const chunks = content.match(/[\s\S]{1,2000}/g) || [];
+ for (const chunk of chunks) {
+ await msg.reply({ content: chunk });
+ }
+ } else {
+ msg.reply({ content });
+ }
+
+ } catch (err) {
+ console.error(err);
+ msg.reply('Something went wrong.');
+ }
+ } else {
+ return msg.reply('Sorry, this feature has been turned off.');
+ }
+
+ }
+ }
+};
diff --git a/bot/src/init.js b/bot/src/init.js
new file mode 100644
index 0000000..8da3783
--- /dev/null
+++ b/bot/src/init.js
@@ -0,0 +1,13 @@
+import { syncDB } from './utils/sync.js';
+import { apiServer } from './api/server.js';
+import { event } from './handlers/event.js';
+import { command } from './handlers/command.js';
+//import { deployCommands } from './util/deploy.js';
+
+export async function init(client) {
+ await syncDB();
+ //deployCommands().then(() => console.log('[>] Deployed commands'));
+ await apiServer(client);
+ await event(client).then(() => console.log('[>] Event module loaded'));
+ await command(client).then(() => console.log('[>] Command module loaded'));
+}
diff --git a/bot/src/models/quote.js b/bot/src/models/quote.js
index 25c8f01..9d0ad00 100644
--- a/bot/src/models/quote.js
+++ b/bot/src/models/quote.js
@@ -28,7 +28,7 @@ export const quote = sequelize.define('quotes', {
allowNull: false
}
-})
+});
export const pendingQuote = sequelize.define('pending-quotes', {
id: {
diff --git a/bot/src/storage/consts.js b/bot/src/storage/consts.js
index 12a53eb..9172e92 100644
--- a/bot/src/storage/consts.js
+++ b/bot/src/storage/consts.js
@@ -1,3 +1,4 @@
export const abEmbedColour = '#0066a6';
export const readyMsg = true;
-
+export const ollamaEnabled = false;
+export const ollamaModel = 'deepseek-r1:14b';
diff --git a/bot/src/utils/ollama.js b/bot/src/utils/ollama.js
new file mode 100644
index 0000000..af0b9f9
--- /dev/null
+++ b/bot/src/utils/ollama.js
@@ -0,0 +1,3 @@
+import { Ollama } from 'ollama';
+
+export const ollama = new Ollama({ host: `${process.env.OLLAMA_URL}` });
diff --git a/bot/src/utils/sync.js b/bot/src/utils/sync.js
index ecee7b1..d51a081 100644
--- a/bot/src/utils/sync.js
+++ b/bot/src/utils/sync.js
@@ -4,14 +4,14 @@ import { guildSettings } from '../models/guild-settings.js';
export function syncDB() {
quote.sync({alter: true}).then(() => {
- console.log('Quote database synced!');
+ console.log('[>] Quote database synced!');
});
pendingQuote.sync({alter: true}).then(() => {
- console.log('Pending Quote database synced!');
+ console.log('[>] Pending Quote database synced!');
});
guildSettings.sync({alter: true}).then(() => {
- console.log('Guild database synced!');
+ console.log('[>] Guild database synced!');
});
}