diff options
| author | Andrew Lee <andrew@alee14.me> | 2025-03-02 16:24:26 -0500 |
|---|---|---|
| committer | Andrew Lee <andrew@alee14.me> | 2025-03-02 16:24:26 -0500 |
| commit | 1c253d25cb1d35aa987d76e07806999c562712d6 (patch) | |
| tree | 02655b6a3bed5b3604b56deb4c2af199f2609a64 /bot | |
| parent | f98f7e6a34f02e8d6ea6673fbe68ab6db28a2e89 (diff) | |
| download | AleeBot-1c253d25cb1d35aa987d76e07806999c562712d6.tar.gz AleeBot-1c253d25cb1d35aa987d76e07806999c562712d6.tar.bz2 AleeBot-1c253d25cb1d35aa987d76e07806999c562712d6.zip | |
Bringing more features from 2.x; ESLint; API
Diffstat (limited to 'bot')
| -rw-r--r-- | bot/api/server.js | 75 | ||||
| -rw-r--r-- | bot/bun.lockb | bin | 42007 -> 69331 bytes | |||
| -rw-r--r-- | bot/deploy-command.js | 2 | ||||
| -rw-r--r-- | bot/eslint.config.js | 26 | ||||
| -rw-r--r-- | bot/package.json | 5 | ||||
| -rw-r--r-- | bot/src/bot.js | 14 | ||||
| -rw-r--r-- | bot/src/commands/about.js | 14 | ||||
| -rw-r--r-- | bot/src/commands/ask.js | 33 | ||||
| -rw-r--r-- | bot/src/commands/avatar.js | 22 | ||||
| -rw-r--r-- | bot/src/commands/info.js | 21 | ||||
| -rw-r--r-- | bot/src/commands/ping.js | 1 | ||||
| -rw-r--r-- | bot/src/commands/uptime.js | 25 | ||||
| -rw-r--r-- | bot/src/events/ClientReady.js | 6 | ||||
| -rw-r--r-- | bot/src/events/GuildCreate.js | 20 | ||||
| -rw-r--r-- | bot/src/events/GuildDelete.js | 19 | ||||
| -rw-r--r-- | bot/src/events/InteractionCreate.js | 6 | ||||
| -rw-r--r-- | bot/src/handler/commands.js | 20 | ||||
| -rw-r--r-- | bot/src/handlers/command.js | 22 | ||||
| -rw-r--r-- | bot/src/handlers/event.js (renamed from bot/src/handler/event.js) | 10 | ||||
| -rw-r--r-- | bot/src/storage/activities.js | 4 |
20 files changed, 291 insertions, 54 deletions
diff --git a/bot/api/server.js b/bot/api/server.js new file mode 100644 index 0000000..ac4f8ca --- /dev/null +++ b/bot/api/server.js @@ -0,0 +1,75 @@ +import express from 'express'; +import cors from 'cors'; + +import 'dotenv/config'; +import { readFileSync } from 'node:fs'; + +const app = express(); + +export const apiServer = (client) => { + app.use(cors()); // Allow cross-origin requests + app.use(express.json()); + + app.get('/api/version', (req, res) => { + const { version } = JSON.parse(readFileSync('./package.json', 'utf-8')); + res.json({ + version: version + }); + + }); + + app.get('/api/uptime', (req, res) => { + res.json({ + uptime: client.uptime + }); + }); + + app.get('/api/servers', (req, res) => { + const guildsInfo = []; + + if (client.guilds.cache.size === 0) { + res.json({ + message: 'No servers found' + }); + } else { + client.guilds.cache.forEach((guild) => { + const guildInfo = { + name: guild.name, + members: guild.memberCount, + id: guild.id + }; + guildsInfo.push(guildInfo); + }); + } + + res.json(guildsInfo); + + }); + + app.post('/api/leave', (req, res) => { + const { id } = req.body; + let guild = client.guilds.cache.get(id); + + try { + guild.leave().then(guild => { + res.json({ + guild: guild.name, + left: true + }); + }); + + } catch (error) { + console.error('Error leaving server:', error); + res.status(500).res.json({ + guild: guild.name, + left: false + }); + } + }); + + // Start the server + app.listen(process.env.port, () => { + console.log(`[i] Starting API at http://localhost:${process.env.port}`); + }); +}; + diff --git a/bot/bun.lockb b/bot/bun.lockb Binary files differindex c0c384f..27f2b53 100644 --- a/bot/bun.lockb +++ b/bot/bun.lockb diff --git a/bot/deploy-command.js b/bot/deploy-command.js index aed5890..8aa3b68 100644 --- a/bot/deploy-command.js +++ b/bot/deploy-command.js @@ -1,6 +1,6 @@ import fs from 'node:fs'; import { REST, Routes } from 'discord.js'; -import 'dotenv/config' +import 'dotenv/config'; const commands = []; const commandFiles = fs.readdirSync('./src/commands').filter(file => file.endsWith('.js')); diff --git a/bot/eslint.config.js b/bot/eslint.config.js index e67ce26..6f258fe 100644 --- a/bot/eslint.config.js +++ b/bot/eslint.config.js @@ -1,15 +1,27 @@ -import globals from "globals"; -import pluginJs from "@eslint/js"; +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import stylisticJs from '@stylistic/eslint-plugin-js'; /** @type {import('eslint').Linter.Config[]} */ export default [ { - languageOptions: { - ecmaVersion: "latest", - sourceType: "module", - globals: globals.node - } + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: globals.node + }, + + plugins: { + '@stylistic/js': stylisticJs + }, + + rules: { + '@stylistic/js/quotes': ['error', 'single'], + '@stylistic/js/semi-style': ['error', 'last'], + '@stylistic/js/semi': ['error', 'always'], + '@stylistic/js/indent': ['error', 4] + } }, pluginJs.configs.recommended, ]; diff --git a/bot/package.json b/bot/package.json index c09e16b..a343f58 100644 --- a/bot/package.json +++ b/bot/package.json @@ -10,10 +10,13 @@ "lint": "eslint ." }, "dependencies": { - "discord.js": "^14.18.0" + "cors": "^2.8.5", + "discord.js": "^14.18.0", + "express": "^4.21.2" }, "devDependencies": { "@eslint/js": "^9.21.0", + "@stylistic/eslint-plugin-js": "^4.1.0", "dotenv": "^16.4.7", "eslint": "^9.21.0", "globals": "^16.0.0" diff --git a/bot/src/bot.js b/bot/src/bot.js index af2aec2..07b13a8 100644 --- a/bot/src/bot.js +++ b/bot/src/bot.js @@ -1,12 +1,14 @@ -import { Client, GatewayIntentBits } from 'discord.js' -import 'dotenv/config' -import { event } from './handler/event.js' -import { commands } from "./handler/commands.js"; +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'; const client = new Client({ intents: [GatewayIntentBits.Guilds] }); -commands(client); -event(client); +command(client).then(() => console.log('[i] Command module loaded')); +event(client).then(() => console.log('[i] Event module loaded')); +apiServer(client); if (process.argv.indexOf('--beta') === -1) { client.login(process.env.abtoken).catch(function() { diff --git a/bot/src/commands/about.js b/bot/src/commands/about.js index 9983857..c75391a 100644 --- a/bot/src/commands/about.js +++ b/bot/src/commands/about.js @@ -5,21 +5,21 @@ import { SlashCommandBuilder, ButtonStyle } from 'discord.js'; -import { readFileSync } from "node:fs"; +import { readFileSync } from 'node:fs'; const { version } = JSON.parse(readFileSync('./package.json', 'utf-8')); export default { data: new SlashCommandBuilder() .setName('about') - .setDescription('Information about this bot'), + .setDescription('Information about this bot.'), async execute(interaction) { const aboutEmbed = new EmbedBuilder() .setAuthor({ name: `AleeBot ${version}`, iconURL: interaction.client.user.avatarURL() }) .addFields( { name: 'About AleeBot', value: 'AleeBot is an all-in-one bot that\'s made from the Discord.JS API!' }, - { name: 'License', value: 'GNU General Public License v3.0' } - //{ name: 'Contributors', value: '' } + { 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' }) .setColor('#1fd619'); @@ -29,17 +29,17 @@ export default { new ButtonBuilder() .setStyle(ButtonStyle.Link) .setLabel('Source Code') - .setURL('https://github.com/alee14-projects/AleeBot'), + .setURL('https://github.com/Alee14/AleeBot'), new ButtonBuilder() .setStyle(ButtonStyle.Link) .setLabel('Invite AleeBot') - .setURL('https://discord.com/oauth2/authorize?client_id=282547024547545109&permissions=68185158&scope=bot'), + .setURL('https://discord.com/oauth2/authorize?client_id=282547024547545109'), new ButtonBuilder() .setStyle(ButtonStyle.Link) .setLabel('Join Andrew Lee Projects') .setURL('https://discord.gg/EFhRDqG') ); - return await interaction.reply({embeds: [aboutEmbed], components: [Buttons]}); + return await interaction.reply({ embeds: [aboutEmbed], components: [Buttons] }); } }; diff --git a/bot/src/commands/ask.js b/bot/src/commands/ask.js new file mode 100644 index 0000000..fec0846 --- /dev/null +++ b/bot/src/commands/ask.js @@ -0,0 +1,33 @@ +import { SlashCommandBuilder } from 'discord.js'; + +export default { + data: new SlashCommandBuilder() + .setName('ask') + .setDescription('Ask AleeBot a question.') + .addStringOption(option => + option + .setName('question') + .setDescription('The question you will be asking AleeBot.') + .setRequired(true)), + async execute(interaction) { + const question = interaction.options.getString('question'); + + const answers = [ + 'Yes.', + 'Nope. Just kidding :P', + 'Definitely!', + 'No.', + 'Yep. Just kidding :P', + 'I doubt it.', + 'Maybe?', + 'Perhaps...', + 'I don\'t know?', + 'Can you ask me later? My CPU is overloading.', + 'Hmm let me think :thinking:', + ]; + + return await interaction.reply( + `<@${interaction.user.id}> asked:\n**${question}**\nMy answer:\n**${answers[Math.floor(Math.random() * answers.length)]}**` + ); + } +}; diff --git a/bot/src/commands/avatar.js b/bot/src/commands/avatar.js new file mode 100644 index 0000000..2c3cdeb --- /dev/null +++ b/bot/src/commands/avatar.js @@ -0,0 +1,22 @@ +import { SlashCommandBuilder } from 'discord.js'; + +export default { + data: new SlashCommandBuilder() + .setName('avatar') + .setDescription('Gives the profile picture of the user.') + .addUserOption(option => + option + .setName('username') + .setDescription('The user to get the avatar of.') + .setRequired(false)), + + async execute(interaction) { + const username = interaction.options.getUser('username'); + + if(!username) { + await interaction.reply(interaction.user.avatarURL({ dynamic: true, format: 'png', size: 1024 })); + } else { + await interaction.reply(username.avatarURL({ dynamic: true, format: 'png', size: 1024 })); + } + } +}; diff --git a/bot/src/commands/info.js b/bot/src/commands/info.js new file mode 100644 index 0000000..e9de440 --- /dev/null +++ b/bot/src/commands/info.js @@ -0,0 +1,21 @@ +import { SlashCommandBuilder, EmbedBuilder, version } from 'discord.js'; +import { hostname, platform, release } from 'os'; + +export default { + data: new SlashCommandBuilder() + .setName('info') + .setDescription('Shows information about the host.'), + async execute(interaction) { + const embed = new EmbedBuilder() + .setTitle('Information on AleeBot\'s Host') + .addFields( + { name: 'OS Hostname: ', value: hostname(), inline: true }, + { name: 'NodeJS Version: ', value: process.versions.node, inline: true }, + { name: 'Discord.JS Version: ', value: version, inline: true }, + { name: 'OS Platform: ', value: platform(), inline: true }, + { name: 'OS Version: ', value: release(), inline: true } + ) + .setColor('#1fd619'); + return await interaction.reply({ embeds: [embed] }); + } +}; diff --git a/bot/src/commands/ping.js b/bot/src/commands/ping.js index 996c705..1bb4ccb 100644 --- a/bot/src/commands/ping.js +++ b/bot/src/commands/ping.js @@ -1,4 +1,5 @@ import { SlashCommandBuilder } from 'discord.js'; + export default { data: new SlashCommandBuilder() .setName('ping') diff --git a/bot/src/commands/uptime.js b/bot/src/commands/uptime.js new file mode 100644 index 0000000..f24adad --- /dev/null +++ b/bot/src/commands/uptime.js @@ -0,0 +1,25 @@ +import { SlashCommandBuilder } from 'discord.js'; + +export default { + data: new SlashCommandBuilder() + .setName('uptime') + .setDescription('Shows how long the bot is up for.'), + async execute(interaction) { + let uptime = parseInt(interaction.client.uptime); + uptime = Math.floor(uptime / 1000); + let uptimeMinutes = Math.floor(uptime / 60); + const minutes = uptime % 60; + let hours = 0; + let days = 0; + while (uptimeMinutes >= 60) { + hours++; + uptimeMinutes = uptimeMinutes - 60; + } + while (hours >= 24) { + days++; + hours = hours - 24; + } + const uptimeSeconds = minutes % 60; + return await interaction.reply(`:clock3: AleeBot has been up for ${days} days, ${hours} hours, ${uptimeMinutes} minutes, and ${uptimeSeconds} seconds.`); + } +}; diff --git a/bot/src/events/ClientReady.js b/bot/src/events/ClientReady.js index 06b5cce..c3c6055 100644 --- a/bot/src/events/ClientReady.js +++ b/bot/src/events/ClientReady.js @@ -1,4 +1,4 @@ -import { Events } from "discord.js"; +import { Events } from 'discord.js'; import { readFileSync } from 'node:fs'; import { activities as activity } from '../storage/activities.js'; @@ -28,9 +28,9 @@ export default { botActivity(client); setInterval(function() { - botActivity(); + botActivity(client); }, 200000); } -} +}; diff --git a/bot/src/events/GuildCreate.js b/bot/src/events/GuildCreate.js new file mode 100644 index 0000000..f31be46 --- /dev/null +++ b/bot/src/events/GuildCreate.js @@ -0,0 +1,20 @@ +import { Events } from 'discord.js'; + +export default { + name: Events.GuildCreate, + async execute(guild) { + console.log(`[i] New guild joined: ${guild.name} (${guild.id}). This guild has ${guild.memberCount} members!`); + // const logEmbed = new Discord.MessageEmbed() + // .setAuthor('AleeBot', client.user.avatarURL()) + // .setDescription('I got added to a server!') + // .addField('Server Name:', `${guild.name}`, true) + // .addField('Server ID:', `${guild.id}`, true) + // .addField('Members', `${guild.memberCount}`, true) + // .setColor('#5cd65c') + // .setFooter(`We now run on ${client.guilds.cache.size} guilds.`); + // + // let statusChannel = client.channels.cache.get(statusChannelID); + // if (!statusChannel) return; + // statusChannel.send({ embeds: [logEmbed]}); + } +}; diff --git a/bot/src/events/GuildDelete.js b/bot/src/events/GuildDelete.js new file mode 100644 index 0000000..a684632 --- /dev/null +++ b/bot/src/events/GuildDelete.js @@ -0,0 +1,19 @@ +import { Events } from 'discord.js'; + +export default { + name: Events.GuildDelete, + async execute(guild) { + console.log(`[i] I have been removed from: ${guild.name} (${guild.id})`); + // const logEmbed = new Discord.MessageEmbed() + // .setAuthor('AleeBot', client.user.avatarURL()) + // .setDescription('I got removed from a server...') + // .addField('Server Name:', `${guild.name}`, true) + // .addField('Server ID:', `${guild.id}`, true) + // .setColor('#ff021b') + // .setFooter(`We now run on ${client.guilds.cache.size} guilds.`); + // + // let statusChannel = client.channels.cache.get(statusChannelID); + // if (!statusChannel) return; + // statusChannel.send({ embeds: [logEmbed]}); + } +}; diff --git a/bot/src/events/InteractionCreate.js b/bot/src/events/InteractionCreate.js index b1e7593..4e39241 100644 --- a/bot/src/events/InteractionCreate.js +++ b/bot/src/events/InteractionCreate.js @@ -1,4 +1,4 @@ -import { Events, MessageFlags } from "discord.js"; +import { Events, MessageFlags } from 'discord.js'; export default { name: Events.InteractionCreate, @@ -13,7 +13,7 @@ export default { await command.execute(interaction, client); } catch (e) { console.error(e); - await interaction.reply({ content: 'Something went wrong.', flags: MessageFlags.Ephemeral }); + await interaction.reply({ content: `Something went wrong. Send the following error message to Alee:\n\`\`\`${e}\`\`\``, flags: MessageFlags.Ephemeral }); } } -} +}; diff --git a/bot/src/handler/commands.js b/bot/src/handler/commands.js deleted file mode 100644 index d4b7bdc..0000000 --- a/bot/src/handler/commands.js +++ /dev/null @@ -1,20 +0,0 @@ -import { Collection } from 'discord.js' -import { readdirSync } from 'node:fs'; -import path from "node:path"; -import { fileURLToPath } from "url"; -import { dirname } from "path"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const commandPath = path.join(__dirname, '../commands'); - -export async function commands(client) { - client.commands = new Collection(); - const commandFiles = readdirSync(commandPath).filter(file => file.endsWith('.js')); - - for (const file of commandFiles) { - const { default: command } = await import(`../commands/${file}`); - client.commands.set(command.data.name, command); - } -} diff --git a/bot/src/handlers/command.js b/bot/src/handlers/command.js new file mode 100644 index 0000000..0da2fab --- /dev/null +++ b/bot/src/handlers/command.js @@ -0,0 +1,22 @@ +import { Collection } from 'discord.js'; +import { readdirSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const commandPath = path.join(__dirname, '../commands'); +const commandFiles = readdirSync(commandPath).filter(file => file.endsWith('.js')); + +export async function command(client) { + client.commands = new Collection(); + console.log(`[i] Loading ${commandFiles.length} commands into memory...`); + + for (const file of commandFiles) { + const { default: command } = await import(`../commands/${file}`); + console.log(`[i] Loading command: ${command.data.name}`); + client.commands.set(command.data.name, command); + } +} diff --git a/bot/src/handler/event.js b/bot/src/handlers/event.js index 0783741..b15cbf2 100644 --- a/bot/src/handler/event.js +++ b/bot/src/handlers/event.js @@ -1,7 +1,7 @@ -import { fileURLToPath } from "url"; -import { dirname } from "path"; -import path from "node:path"; -import fs from "node:fs"; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; +import path from 'node:path'; +import fs from 'node:fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -10,9 +10,11 @@ const eventsPath = path.join(__dirname, '../events'); const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js')); export async function event(client) { + console.log(`[i] Loading ${eventFiles.length} events into memory...`); for (const file of eventFiles) { const filePath = path.join(eventsPath, file); const event = (await import(filePath)).default; + console.log(`[i] Loading event: ${event.name}`); if (event.once) { client.once(event.name, (...args) => event.execute(...args)); } else { diff --git a/bot/src/storage/activities.js b/bot/src/storage/activities.js index f4bd4ff..4702594 100644 --- a/bot/src/storage/activities.js +++ b/bot/src/storage/activities.js @@ -1,5 +1,5 @@ -import { version as discordVersion } from "discord.js"; -import { readFileSync } from "node:fs"; +import { version as discordVersion } from 'discord.js'; +import { readFileSync } from 'node:fs'; const { version: abVersion } = JSON.parse(readFileSync('./package.json', 'utf-8')); |
