Skip to content

Commit 2af4b8e

Browse files
committed
Initial commit: Advanced Discord.js v14 Bot Template
0 parents  commit 2af4b8e

26 files changed

Lines changed: 839 additions & 0 deletions

.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Discord Bot Configuration
2+
# Get your token and client ID from: https://discord.com/developers/applications
3+
DISCORD_TOKEN=your_bot_token_here
4+
CLIENT_ID=your_client_id_here
5+
6+
# Optional: Guild ID for instant command deployment to a specific server.
7+
# If left empty, commands will be deployed globally (can take up to an hour to update).
8+
GUILD_ID=your_guild_id_here
9+
10+
# MongoDB Connection String (Optional)
11+
# Example: mongodb+srv://user:pass@cluster.mongodb.net/database
12+
# If left empty, database features will be disabled.
13+
MONGODB_URI=your_mongodb_uri_here

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Dependencies
2+
node_modules/
3+
package-lock.json
4+
5+
# Environment Variables
6+
.env
7+
8+
# Logs
9+
Logs/
10+
*.log
11+
12+
# System Files
13+
.DS_Store
14+
Thumbs.db

Commands/Fun/8ball.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const { SlashCommandBuilder } = require('discord.js');
2+
const Embeds = require('../../Utils/Embeds');
3+
4+
module.exports = {
5+
cooldown: 3,
6+
data: new SlashCommandBuilder()
7+
.setName('8ball')
8+
.setDescription('Ask the magic 8-ball a question.')
9+
.addStringOption(option =>
10+
option.setName('question')
11+
.setDescription('The question you want to ask')
12+
.setRequired(true)),
13+
async execute(interaction) {
14+
const responses = [
15+
'It is certain.',
16+
'It is decidedly so.',
17+
'Without a doubt.',
18+
'Yes – definitely.',
19+
'You may rely on it.',
20+
'As I see it, yes.',
21+
'Most likely.',
22+
'Outlook good.',
23+
'Yes.',
24+
'Signs point to yes.',
25+
'Reply hazy, try again.',
26+
'Ask again later.',
27+
'Better not tell you now.',
28+
'Cannot predict now.',
29+
'Concentrate and ask again.',
30+
"Don't count on it.",
31+
'My reply is no.',
32+
'My sources say no.',
33+
'Outlook not so good.',
34+
'Very doubtful.'
35+
];
36+
37+
const question = interaction.options.getString('question');
38+
const answer = responses[Math.floor(Math.random() * responses.length)];
39+
40+
await interaction.reply({
41+
embeds: [Embeds.info(`**Question:** ${question}\n**Answer:** ${answer}`, '🔮 Magic 8-Ball')]
42+
});
43+
},
44+
};

Commands/Fun/joke.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const { SlashCommandBuilder } = require('discord.js');
2+
const axios = require('axios');
3+
const Embeds = require('../../Utils/Embeds');
4+
const logger = require('../../Utils/Logger');
5+
6+
module.exports = {
7+
cooldown: 5,
8+
data: new SlashCommandBuilder()
9+
.setName('joke')
10+
.setDescription('Tells a random joke.'),
11+
async execute(interaction) {
12+
try {
13+
const response = await axios.get('https://official-joke-api.appspot.com/random_joke');
14+
const { setup, punchline } = response.data;
15+
16+
await interaction.reply({
17+
embeds: [Embeds.info(`${setup}\n\n*${punchline}*`, '😂 Random Joke')]
18+
});
19+
} catch (error) {
20+
logger.error('Error fetching joke:', error);
21+
await interaction.reply({ embeds: [Embeds.error('Failed to fetch a joke. Please try again later.')], ephemeral: true });
22+
}
23+
},
24+
};

Commands/Moderation/ban.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js');
2+
const Embeds = require('../../Utils/Embeds');
3+
4+
module.exports = {
5+
userPermissions: [PermissionFlagsBits.BanMembers],
6+
data: new SlashCommandBuilder()
7+
.setName('ban')
8+
.setDescription('Bans a member from the server.')
9+
.addUserOption(option =>
10+
option.setName('target')
11+
.setDescription('The member to ban')
12+
.setRequired(true))
13+
.addStringOption(option =>
14+
option.setName('reason')
15+
.setDescription('The reason for banning')),
16+
async execute(interaction) {
17+
const target = interaction.options.getMember('target');
18+
const reason = interaction.options.getString('reason') ?? 'No reason provided';
19+
20+
if (!target) {
21+
return interaction.reply({ embeds: [Embeds.error('Could not find that member.')], ephemeral: true });
22+
}
23+
24+
if (!target.bannable) {
25+
return interaction.reply({ embeds: [Embeds.error('I cannot ban this member. They might have a higher role than me.')], ephemeral: true });
26+
}
27+
28+
await target.ban({ reason });
29+
await interaction.reply({ embeds: [Embeds.success(`Successfully banned **${target.user.tag}** for: ${reason}`)] });
30+
},
31+
};

Commands/Moderation/kick.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js');
2+
const Embeds = require('../../Utils/Embeds');
3+
4+
module.exports = {
5+
userPermissions: [PermissionFlagsBits.KickMembers],
6+
data: new SlashCommandBuilder()
7+
.setName('kick')
8+
.setDescription('Kicks a member from the server.')
9+
.addUserOption(option =>
10+
option.setName('target')
11+
.setDescription('The member to kick')
12+
.setRequired(true))
13+
.addStringOption(option =>
14+
option.setName('reason')
15+
.setDescription('The reason for kicking')),
16+
async execute(interaction) {
17+
const target = interaction.options.getMember('target');
18+
const reason = interaction.options.getString('reason') ?? 'No reason provided';
19+
20+
if (!target) {
21+
return interaction.reply({ embeds: [Embeds.error('Could not find that member.')], ephemeral: true });
22+
}
23+
24+
if (!target.kickable) {
25+
return interaction.reply({ embeds: [Embeds.error('I cannot kick this member. They might have a higher role than me.')], ephemeral: true });
26+
}
27+
28+
await target.kick(reason);
29+
await interaction.reply({ embeds: [Embeds.success(`Successfully kicked **${target.user.tag}** for: ${reason}`)] });
30+
},
31+
};

Commands/Moderation/purge.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const { SlashCommandBuilder, PermissionFlagsBits } = require('discord.js');
2+
const Embeds = require('../../Utils/Embeds');
3+
4+
module.exports = {
5+
userPermissions: [PermissionFlagsBits.ManageMessages],
6+
data: new SlashCommandBuilder()
7+
.setName('purge')
8+
.setDescription('Deletes a specified amount of messages.')
9+
.addIntegerOption(option =>
10+
option.setName('amount')
11+
.setDescription('Amount of messages to delete (1-100)')
12+
.setMinValue(1)
13+
.setMaxValue(100)
14+
.setRequired(true)),
15+
async execute(interaction) {
16+
const amount = interaction.options.getInteger('amount');
17+
18+
await interaction.channel.bulkDelete(amount, true).then(messages => {
19+
interaction.reply({
20+
embeds: [Embeds.success(`Successfully deleted \`${messages.size}\` messages.`)],
21+
ephemeral: true
22+
});
23+
}).catch(err => {
24+
interaction.reply({
25+
embeds: [Embeds.error('There was an error trying to purge messages in this channel!')],
26+
ephemeral: true
27+
});
28+
});
29+
},
30+
};

Commands/Utility/help.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
2+
3+
module.exports = {
4+
cooldown: 10,
5+
data: new SlashCommandBuilder()
6+
.setName('help')
7+
.setDescription('List all available commands.'),
8+
async execute(interaction, client) {
9+
const embed = new EmbedBuilder()
10+
.setTitle('📚 Bot Commands')
11+
.setDescription('Here is a list of all available slash commands:')
12+
.setColor('#3498DB')
13+
.setTimestamp();
14+
15+
client.commands.forEach(command => {
16+
const name = command.data.name;
17+
const description = command.data.description;
18+
embed.addFields({ name: `/${name}`, value: description, inline: true });
19+
});
20+
21+
await interaction.reply({ embeds: [embed] });
22+
},
23+
};

Commands/Utility/ping.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const { SlashCommandBuilder } = require('discord.js');
2+
const Embeds = require('../../Utils/Embeds');
3+
4+
module.exports = {
5+
cooldown: 5,
6+
data: new SlashCommandBuilder()
7+
.setName('ping')
8+
.setDescription('Replies with Pong and latency!'),
9+
async execute(interaction, client) {
10+
const sent = await interaction.reply({ content: 'Pinging...', fetchReply: true });
11+
const latency = sent.createdTimestamp - interaction.createdTimestamp;
12+
const apiLatency = Math.round(client.ws.ping);
13+
14+
await interaction.editReply({
15+
content: null,
16+
embeds: [Embeds.success(`🏓 Pong!\n\n**Latency:** \`${latency}ms\`\n**API Latency:** \`${apiLatency}ms\``)]
17+
});
18+
},
19+
};

Commands/Utility/search.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const { SlashCommandBuilder } = require('discord.js');
2+
3+
module.exports = {
4+
cooldown: 5,
5+
data: new SlashCommandBuilder()
6+
.setName('search')
7+
.setDescription('Example command with autocomplete.')
8+
.addStringOption(option =>
9+
option.setName('query')
10+
.setDescription('The item to search for')
11+
.setAutocomplete(true)
12+
.setRequired(true)),
13+
async autocomplete(interaction) {
14+
const focusedValue = interaction.options.getFocused();
15+
const choices = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape'];
16+
const filtered = choices.filter(choice => choice.toLowerCase().startsWith(focusedValue.toLowerCase()));
17+
18+
await interaction.respond(
19+
filtered.map(choice => ({ name: choice, value: choice })),
20+
);
21+
},
22+
async execute(interaction) {
23+
const query = interaction.options.getString('query');
24+
await interaction.reply(`You searched for: **${query}**`);
25+
},
26+
};

0 commit comments

Comments
 (0)