From cdb82b771ebd5a2800b7dd9a1adade508027e67c Mon Sep 17 00:00:00 2001 From: Ahmad <103906421+ahmadk953@users.noreply.github.com> Date: Sun, 3 Mar 2024 17:43:26 -0500 Subject: [PATCH] General Updates --- .eslintrc.json | 1 + .vscode/launch.json | 47 ++++++++-------- .vscode/tasks.json | 26 ++++----- source/commands/ping.ts | 10 ++-- source/commands/rules.ts | 34 +++++++++--- source/commands/server.ts | 22 ++++---- source/commands/user.ts | 36 +++++++----- source/config.example.json | 8 +-- source/discord-bot.ts | 103 +++++++++++++++++++---------------- source/util/deployCommand.ts | 3 - 10 files changed, 161 insertions(+), 129 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 8966089..ef0225f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,6 +5,7 @@ "es6": true }, "parserOptions": { + "sourceType": "module", "ecmaVersion": 2021 }, "rules": { diff --git a/.vscode/launch.json b/.vscode/launch.json index 0ba7509..64de8d6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,27 +1,26 @@ { - "version": "0.1.0", - "configurations": [ - { - "name": "Build and Run", - "type": "node", - "request": "launch", - "program": "${workspaceFolder}/target/_.cjs", - "preLaunchTask": "build", - "skipFiles": ["/**"], - "outFiles": ["${workspaceFolder}/target/**/*.cjs"] + "version": "0.1.0", + "configurations": [ + { + "name": "Build and Run", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/target/_.cjs", + "preLaunchTask": "build", + "skipFiles": ["/**"], + "outFiles": ["${workspaceFolder}/target/**/*.cjs"] + } + ], + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "node", + "args": ["${workspaceFolder}/build/compile.js"], + "group": { + "kind": "build", + "isDefault": true } - ], - "tasks": [ - { - "label": "build", - "type": "shell", - "command": "node", - "args": ["${workspaceFolder}/build/compile.js"], - "group": { - "kind": "build", - "isDefault": true - } - } - ] + } + ] } - \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d81aad7..a03a72f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,14 +1,14 @@ { - "tasks": [ - { - "label": "build", - "type": "shell", - "command": "node", - "args": ["${workspaceFolder}/build/compile.js"], - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} \ No newline at end of file + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "node", + "args": ["${workspaceFolder}/build/compile.js"], + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/source/commands/ping.ts b/source/commands/ping.ts index eba6243..20dd2f3 100644 --- a/source/commands/ping.ts +++ b/source/commands/ping.ts @@ -1,4 +1,4 @@ -import { SlashCommandBuilder, CommandInteraction } from 'discord.js'; +import { SlashCommandBuilder, CommandInteraction } from "discord.js"; interface Command { data: Omit; @@ -7,11 +7,11 @@ interface Command { const command: Command = { data: new SlashCommandBuilder() - .setName('ping') - .setDescription('Replies with Pong!'), + .setName("ping") + .setDescription("Check the latency of the bot"), execute: async (interaction) => { - await interaction.reply(`Pong!`); + await interaction.reply(`Pong! Latency: ${Date.now() - interaction.createdTimestamp}ms`); }, }; -export default command; \ No newline at end of file +export default command; diff --git a/source/commands/rules.ts b/source/commands/rules.ts index 1623b2c..439b994 100644 --- a/source/commands/rules.ts +++ b/source/commands/rules.ts @@ -2,6 +2,7 @@ import { SlashCommandBuilder, CommandInteraction, EmbedBuilder, + CommandInteractionOptionResolver , } from "discord.js"; interface Command { @@ -12,19 +13,34 @@ interface Command { const rulesEmbed = new EmbedBuilder() .setColor(0x0099ff) .setTitle("Server Rules") - .setAuthor({ name: "Poixixel", iconURL: "https://cdn.discordapp.com/avatars/1052017329376071781/922947c726d7866d313744186c42ef49.webp" }) - .setDescription("These are the rules for the server. Please read and follow them carefully.") + .setAuthor({ + name: "Poixixel", + iconURL: + "https://cdn.discordapp.com/avatars/1052017329376071781/922947c726d7866d313744186c42ef49.webp", + }) + .setDescription( + "These are the rules for the server. Please read and follow them carefully." + ) .addFields( - { name: "Rule #1: Be respectful", value: "This means no mean, rude, or harassing comments. Treat others the way you want to be treated." }, - { name: '\u200B', value: '\u200B' }, - { name: "Rule #2: No inappropriate language", value: "All profanity language is prohibited in this server. Any derogatory language towards any user is prohibited. Swearing is not permitted in any channels." }, - { name: '\u200B', value: '\u200B' } - //TODO Add all the rest of Poixpixel's rules here + { + name: "Rule #1: Be respectful", + value: + "This means no mean, rude, or harassing comments. Treat others the way you want to be treated.", + }, + { name: "\u200B", value: "\u200B" }, + { + name: "Rule #2: No inappropriate language", + value: + "All profanity language is prohibited in this server. Any derogatory language towards any user is prohibited. Swearing is not permitted in any channels.", + }, + { name: "\u200B", value: "\u200B" } + //TODO Add all the rest of Poixpixel's rules here ) .setTimestamp() .setFooter({ text: "Sent by the Poixpixel Bot", - iconURL: "https://cdn.discordapp.com/avatars/1052017329376071781/922947c726d7866d313744186c42ef49.webp", + iconURL: + "https://cdn.discordapp.com/avatars/1052017329376071781/922947c726d7866d313744186c42ef49.webp", }); const command: Command = { @@ -34,7 +50,7 @@ const command: Command = { execute: async (interaction) => { const channel = interaction.channel; channel?.send({ embeds: [rulesEmbed] }); - await interaction.reply(`Here are the server rules:`); + await interaction.reply({ content: 'The Rules Were Sent in the Current Channel', ephemeral: true }); }, }; diff --git a/source/commands/server.ts b/source/commands/server.ts index ce02b79..5fb2317 100644 --- a/source/commands/server.ts +++ b/source/commands/server.ts @@ -1,17 +1,19 @@ -import { SlashCommandBuilder, CommandInteraction } from 'discord.js'; +import { SlashCommandBuilder, CommandInteraction } from "discord.js"; interface Command { - data: Omit; - execute: (interaction: CommandInteraction) => Promise; + data: Omit; + execute: (interaction: CommandInteraction) => Promise; } const command: Command = { - data: new SlashCommandBuilder() - .setName('server') - .setDescription('Provides information about the server.'), - execute: async (interaction) => { - await interaction.reply(`This server is ${interaction?.guild?.name} and has ${interaction?.guild?.memberCount} members.`); - }, + data: new SlashCommandBuilder() + .setName("server") + .setDescription("Provides information about the server."), + execute: async (interaction) => { + await interaction.reply( + `The server name is ${interaction?.guild?.name} and it has ${interaction?.guild?.memberCount} members.` + ); + }, }; -export default command; \ No newline at end of file +export default command; diff --git a/source/commands/user.ts b/source/commands/user.ts index e354aa2..0a2965e 100644 --- a/source/commands/user.ts +++ b/source/commands/user.ts @@ -1,21 +1,29 @@ -import { SlashCommandBuilder, CommandInteraction, GuildMember } from 'discord.js'; +import { + SlashCommandBuilder, + CommandInteraction, + GuildMember, +} from "discord.js"; interface Command { - data: Omit; - execute: (interaction: CommandInteraction) => Promise; + data: Omit; + execute: (interaction: CommandInteraction) => Promise; } const command: Command = { - data: new SlashCommandBuilder() - .setName('user') - .setDescription('Provides information about the user.'), - execute: async (interaction) => { - if (interaction.member instanceof GuildMember) { - await interaction.reply(`This command was run by ${interaction.user.username}, who joined on ${interaction.member.joinedAt}.`); - } else { - await interaction.reply(`This command was run by ${interaction.user.username}.`); - } - }, + data: new SlashCommandBuilder() + .setName("user") + .setDescription("Provides information about the user."), + execute: async (interaction) => { + if (interaction.member instanceof GuildMember) { + await interaction.reply( + `This command was run by ${interaction.user.username}, who joined this server on ${interaction.member.joinedAt}.` + ); + } else { + await interaction.reply( + `This command was run by ${interaction.user.username}.` + ); + } + }, }; -export default command; \ No newline at end of file +export default command; diff --git a/source/config.example.json b/source/config.example.json index a3d2f0e..6ef0daf 100644 --- a/source/config.example.json +++ b/source/config.example.json @@ -1,5 +1,5 @@ { - "token": "DISCORD_BOT_API_KEY", - "clientId": "DISCORD_BOT_ID", - "guildId": "DISCORD_SERVER_ID" -} \ No newline at end of file + "token": "DISCORD_BOT_API_KEY", + "clientId": "DISCORD_BOT_ID", + "guildId": "DISCORD_SERVER_ID" +} diff --git a/source/discord-bot.ts b/source/discord-bot.ts index 8eeb68b..7a33b13 100644 --- a/source/discord-bot.ts +++ b/source/discord-bot.ts @@ -1,70 +1,79 @@ -// Require the necessary discord.js classes -import fs from'node:fs'; -import path from 'node:path'; -import { Client, Collection, Events, GatewayIntentBits } from'discord.js'; -import config from './config.json' assert { type: 'json' }; -import { deployCommands } from './util/deployCommand.js'; +import fs from "node:fs"; +import path from "node:path"; +import { Client, Collection, Events, GatewayIntentBits } from "discord.js"; +import config from "./config.json" assert { type: "json" }; +import { deployCommands } from "./util/deployCommand.js"; const { token } = config; -// Create a new client instance const client: any = new Client({ intents: [GatewayIntentBits.Guilds] }); client.commands = new Collection(); try { - const __dirname = path.resolve(); - - const commandsPath = path.join(__dirname, '/target/commands/'); - const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); - - for (const file of commandFiles) { - const filePath = path.join('file://', commandsPath, file); - const commandModule = await import(filePath); - const command = commandModule.default; - - if (command instanceof Object && 'data' in command && 'execute' in command) { - client.commands.set(command.data.name, command); - } else { - console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); - } - } + const __dirname = path.resolve(); + + const commandsPath = path.join(__dirname, "/target/commands/"); + const commandFiles = fs + .readdirSync(commandsPath) + .filter((file) => file.endsWith(".js")); + + for (const file of commandFiles) { + const filePath = path.join("file://", commandsPath, file); + const commandModule = await import(filePath); + const command = commandModule.default; + + if ( + command instanceof Object && + "data" in command && + "execute" in command + ) { + client.commands.set(command.data.name, command); + } else { + console.log( + `[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.` + ); + } + } } catch (error: any) { - console.log(`Error while getting commands up: ${error}`) + console.log(`Error while getting commands up: ${error}`); } try { - await deployCommands(); + await deployCommands(); } catch (error: any) { - console.log(`Error while registering commands: ${error}`) + console.log(`Error while registering commands: ${error}`); } -// When the client is ready, run this code (only once) -// We use 'c' for the event parameter to keep it separate from the already defined 'client' client.once(Events.ClientReady, (c: any) => { - console.log(`Ready! Logged in as ${c.user.tag}`); + console.log(`Ready! Logged in as ${c.user.tag}`); }); client.on(Events.InteractionCreate, async (interaction: any) => { - if (!interaction.isChatInputCommand()) return; + if (!interaction.isChatInputCommand()) return; - const command = interaction.client.commands.get(interaction.commandName); + const command = interaction.client.commands.get(interaction.commandName); - if (!command) { - console.error(`No command matching ${interaction.commandName} was found.`); - return; - } + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } - try { - await command.execute(interaction); - } catch (error) { - console.error(error); - if (interaction.replied || interaction.deferred) { - await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }); - } else { - await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); - } - } + try { + await command.execute(interaction); + } catch (error) { + console.error(error); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ + content: "There was an error while executing this command!", + ephemeral: true, + }); + } else { + await interaction.reply({ + content: "There was an error while executing this command!", + ephemeral: true, + }); + } + } }); -// Log in to Discord with your client's token -client.login(token); \ No newline at end of file +client.login(token); diff --git a/source/util/deployCommand.ts b/source/util/deployCommand.ts index 47b725e..a32a5b8 100644 --- a/source/util/deployCommand.ts +++ b/source/util/deployCommand.ts @@ -15,7 +15,6 @@ export const deployCommands = async () => { try { console.log(`Started refreshing ${commandFiles.length} application (/) commands.`); - // Prepare the commands array const commands = commandFiles.map(async (file) => { const filePath = path.join('file://', commandsPath, file); const commandModule = await import(filePath); @@ -29,10 +28,8 @@ export const deployCommands = async () => { } }); - // Filter out any null values from the commands array const validCommands = await Promise.all(commands.filter(command => command !== null)); - // Use the provided way of registering commands const data: any = await rest.put( Routes.applicationGuildCommands(clientId, guildId), { body: validCommands },