Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Mauzy0x00 committed Mar 12, 2023
0 parents commit 08d1d28
Show file tree
Hide file tree
Showing 17 changed files with 1,777 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
52 changes: 52 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// This file contains rules for eslint in the coding environment

{
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 2021
},
"rules": {
"arrow-spacing": ["warn", { "before": true, "after": true }],
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
"comma-dangle": ["error", "always-multiline"],
"comma-spacing": "error",
"comma-style": "error",
"curly": ["error", "multi-line", "consistent"],
"dot-location": ["error", "property"],
"handle-callback-err": "off",
"indent": ["error", "tab"],
"keyword-spacing": "error",
"max-nested-callbacks": ["error", { "max": 4 }],
"max-statements-per-line": ["error", { "max": 2 }],
"no-console": "off",
"no-empty-function": "error",
"no-floating-decimal": "error",
"no-inline-comments": "error",
"no-lonely-if": "error",
"no-multi-spaces": "error",
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
"no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }],
"no-trailing-spaces": ["error"],
"no-var": "error",
"object-curly-spacing": ["error", "always"],
"prefer-const": "error",
"quotes": ["error", "single"],
"semi": ["error", "always"],
"space-before-blocks": "error",
"space-before-function-paren": ["error", {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}],
"space-in-parens": "error",
"space-infix-ops": "error",
"space-unary-ops": "error",
"spaced-comment": "error",
"yoda": "error"

}
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.env
config.json
13 changes: 13 additions & 0 deletions commands/avatar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('avatar')
.setDescription('Get the avatar URL of the selected user, or your own avatar.')
.addUserOption(option => option.setName('target').setDescription('The user\'s avatar to show')),
async execute(interaction) {
const user = interaction.options.getUser('target');
if (user) return interaction.reply(`${user.username}'s avatar: ${user.displayAvatarURL({ dynamic: true })}`);
return interaction.reply(`Your avatar: ${interaction.user.displayAvatarURL()}`);
},
};
11 changes: 11 additions & 0 deletions commands/hug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('hug')
.setDescription('Give someone a hug :)')
.addIntegerOption(option => option.setName('hugee').setDescription('Person to hug')),
async execute(interaction) {
// Your code goes here
},
};
12 changes: 12 additions & 0 deletions commands/kick.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('kick')
.setDescription('Select a member and kick them (but not really).')
.addUserOption(option => option.setName('target').setDescription('The member to kick')),
async execute(interaction) {
const member = interaction.options.getMember('target');
return interaction.reply({ content: `You wanted to kick: ${member.user.username}`, ephemeral: true });
},
};
13 changes: 13 additions & 0 deletions commands/options-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('options-info')
.setDescription('Information about the options provided.')
.addStringOption(option => option.setName('input').setDescription('The input to echo back')),
async execute(interaction) {
const value = interaction.options.getString('input');
if (value) return interaction.reply(`The options value is: \`${value}\``);
return interaction.reply('No option was provided!');
},
};
10 changes: 10 additions & 0 deletions commands/ping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('bing')
.setDescription('Replies with Bong!'),
async execute(interaction) {
await interaction.reply('Bong!');
},
};
21 changes: 21 additions & 0 deletions commands/prune.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('prune')
.setDescription('Prune up to 99 messages.')
.addIntegerOption(option => option.setName('amount').setDescription('Number of messages to prune')),
async execute(interaction) {
const amount = interaction.options.getInteger('amount');

if (amount < 1 || amount > 99) {
return interaction.reply({ content: 'You need to input a number between 1 and 99.', ephemeral: true });
}
await interaction.channel.bulkDelete(amount, true).catch(error => {
console.error(error);
interaction.reply({ content: 'There was an error trying to prune messages in this channel!', ephemeral: true });
});

return interaction.reply({ content: `Successfully pruned \`${amount}\` messages.`, ephemeral: true });
},
};
11 changes: 11 additions & 0 deletions commands/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('server')
.setDescription('Provides information about the server.'),
async execute(interaction) {
// interaction.guild is the object representing the Guild in which the command was run
await interaction.reply(`This server is ${interaction.guild.name} and has ${interaction.guild.memberCount} members.`);
},
};
12 changes: 12 additions & 0 deletions commands/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
data: new SlashCommandBuilder()
.setName('user')
.setDescription('Provides information about the user.'),
async execute(interaction) {
// interaction.user is the object representing the User who ran the command
// interaction.member is the GuildMember object, which represents the user in the specific guild
await interaction.reply(`This command was run by ${interaction.user.username}, who joined on ${interaction.member.joinedAt}.`);
},
};
35 changes: 35 additions & 0 deletions deploy-commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { REST, Routes } = require('discord.js');
const { clientId, token } = require('./config.json');
const fs = require('node:fs');

const commands = [];
// Grab all the command files from the commands directory you created earlier
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));

// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands.push(command.data.toJSON());
}

// Construct and prepare an instance of the REST module
const rest = new REST({ version: '10' }).setToken(token);

// and deploy your commands!
(async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`);

// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationCommands(clientId),
{ body: commands },
);

console.log(`Successfully reloaded ${data.length} application (/) commands.`);
}
catch (error) {
// And of course, make sure you catch and log any errors!
console.error(error);
}
})();
26 changes: 26 additions & 0 deletions events/interactionCreate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Every slash command is an interaction, so to respond to a command, you need to create a listener for the client#event:interactionCreate event that will execute code when your application receives an interaction.
// This snippet will create the listener
const { Events } = require('discord.js');

module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
// Not every interaction is a slash command. This if statement makes sure to only handle slash commands in this function
if (!interaction.isChatInputCommand()) return;

const command = interaction.client.commands.get(interaction.commandName);

if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}

try {
await command.execute(interaction);
}
catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
},
};
14 changes: 14 additions & 0 deletions events/ready.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { Events } = require('discord.js');

// When the client is ready, run this code (only once)
module.exports = {
// The name property states which event this file is for,
// and the once property holds a boolean value that specifies if the event should run only once.
name: Events.ClientReady,
once: true,
// The execute function holds your event logic, which will be called by the event
// handler whenever the event emits
execute(client) {
console.log(`Ready! Logged in as ${client.user.tag}`);
},
};
57 changes: 57 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Require the necessary discord.js classes

// fs is Node's native file system module. used to read the commands
// path is Node's native path utility module. path helps construct paths to access files and directories. Path auto detects the OS and uses appropriate joiners.
// Collection class extends JavaScript's native Map class and includes more extensive, useful functionality. Collection is used to store and efficiently retrieve commands for execution.
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');

// Create a new client instance
const client = new Client({ intents: [GatewayIntentBits.Guilds] });

// Commands Class
client.commands = new Collection();

// Construct a path to the commands directory
const commandsPath = path.join(__dirname, 'commands');

// Read the path directory and return an array of all the file names it contains
// Array.filter() removes any non-JavaScript files from the array
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('js'));

// Code to dynamically retrieve all of the event files in the events folder
// fs.readdirSync().filter() returns an array of all the file names in the given directory and filters for only .js files, i.e. ['ready.js', 'interactionCreate.js']
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));

for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
// The callback function passed takes argument(s) returned by its respective event, collects them in an args array using the ... rest parameter syntax, then calls event.execute() while passing in the args array using the ... spread syntax
// They are used here because different events in discord.js have different numbers of arguments. The rest parameter collects these variable number of arguments into a single array, and the spread syntax then takes these elements and passes them to the execute function.
// After this, listening for other events is as easy as creating a new file in the events folder. The event handler will automatically retrieve and register it whenever you restart your bot.
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
}
else {
client.on(event.name, (...args) => event.execute(...args));
}
}
// Now the correct files have been identified; Loop over the array and dynamically set each command into the client.commands Collection
// For each file being loaded, check that it has at least the data and execute properties. --this prevents errors resulting from loading empty, unfinished or otherwise incorrect command files
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ('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.`);
}
}

// Log in to Discord with your client's token
client.login(token);
Loading

0 comments on commit 08d1d28

Please sign in to comment.