add loop, and add categories to all commands

This commit is contained in:
Ayden Jahola 2025-09-20 01:22:31 +01:00
parent da481c6f01
commit 896f85136c
65 changed files with 170 additions and 27 deletions

View file

@ -12,6 +12,8 @@ module.exports = {
.setDescription("Your message to the AI")
.setRequired(true)
),
category: "AI",
async execute(interaction) {
await interaction.deferReply(); // Defer initial response

View file

@ -8,6 +8,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("help")
.setDescription("Lists all available commands"),
category: "Core",
async execute(interaction, client) {
try {
@ -16,16 +17,19 @@ module.exports = {
);
const serverName = interaction.guild.name;
const generalCommands = [];
const modCommands = [];
// Categorize commands
// Group commands by category
const categories = {};
client.commands.forEach((command) => {
const category = command.category || "Uncategorized"; // Default to "Uncategorized"
if (!categories[category]) {
categories[category] = [];
}
const commandLine = `/${command.data.name} - ${command.data.description}`;
if (!command.isModOnly) {
generalCommands.push(commandLine);
} else if (isMod) {
modCommands.push(`${commandLine} (Mods only)`);
// Check if command is mod-only and user has permissions
if (!command.isModOnly || (command.isModOnly && isMod)) {
categories[category].push(commandLine);
}
});
@ -43,47 +47,37 @@ module.exports = {
// Function to split commands into fields under 1024 characters
const addCommandFields = (embed, commands, title) => {
if (commands.length === 0) return;
let commandChunk = "";
let chunkCount = 1;
commands.forEach((command) => {
// Check if adding this command will exceed the 1024 character limit
if ((commandChunk + command).length > 1024) {
// Add current chunk as a new field
if ((commandChunk + command + "\n").length > 1024) {
embed.addFields({
name: `${title} (Part ${chunkCount})`,
value: commandChunk,
});
commandChunk = ""; // Reset chunk for new field
commandChunk = "";
chunkCount += 1;
}
// Append command to the current chunk
commandChunk += command + "\n";
});
// Add any remaining commands in the last chunk
if (commandChunk) {
embed.addFields({
name: `${title} (Part ${chunkCount})`,
name: chunkCount > 1 ? `${title} (Part ${chunkCount})` : title,
value: commandChunk,
});
}
};
// Add general commands in fields
if (generalCommands.length > 0) {
addCommandFields(helpEmbed, generalCommands, "General Commands");
// Add commands for each category
for (const [categoryName, commands] of Object.entries(categories)) {
addCommandFields(helpEmbed, commands, `${categoryName} Commands`);
}
// Add mod-only commands in fields, if user is a mod
if (isMod && modCommands.length > 0) {
addCommandFields(helpEmbed, modCommands, "Mod-Only Commands");
}
// Send the single embed
await interaction.reply({
embeds: [helpEmbed],
});
await interaction.reply({ embeds: [helpEmbed] });
} catch (error) {
console.error("Error executing the help command:", error);
await interaction.reply({

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("invite")
.setDescription("Provides an invite link to add the bot to your server."),
category: "Core",
async execute(interaction, client) {
try {

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("ping")
.setDescription("Replies with Pong! and bot latency"),
category: "Core",
async execute(interaction, client) {
try {

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("uptime")
.setDescription("Shows how long the bot has been running"),
category: "Core",
async execute(interaction, client) {
try {

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("balance")
.setDescription("Check your balance."),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("daily")
.setDescription("Claim your daily reward and start a streak!"),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -6,6 +6,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("inventory")
.setDescription("View your inventory with item rarity"),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -12,6 +12,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("sell")
.setDescription("Sell an item from your inventory."),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -13,6 +13,7 @@ module.exports = {
.setDescription("The item you want to buy (use item name)")
.setRequired(false)
),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -31,6 +31,7 @@ module.exports = {
.setDescription("Amount of coins to trade")
.setRequired(false)
),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("work")
.setDescription("Work to earn coins and experience random events!"),
category: "Economy",
async execute(interaction) {
const { user, guild } = interaction;

View file

@ -60,6 +60,8 @@ module.exports = {
{ name: "Monthly", value: "monthly" }
)
),
category: "Events",
async execute(interaction) {
const name = interaction.options.getString("name");
const description = interaction.options.getString("description");

View file

@ -55,6 +55,7 @@ module.exports = {
{ name: "Monthly", value: "monthly" }
)
),
category: "Events",
async execute(interaction) {
const name = interaction.options.getString("name");

View file

@ -13,6 +13,7 @@ module.exports = {
.setDescription("Name of the event to join")
.setRequired(true)
),
category: "Events",
async execute(interaction) {
const eventName = interaction.options.getString("event_name");

View file

@ -12,6 +12,7 @@ module.exports = {
.setDescription("Name of the event to leave")
.setRequired(true)
),
category: "Events",
async execute(interaction) {
const eventName = interaction.options.getString("event_name");

View file

@ -6,6 +6,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("listevents")
.setDescription("List all upcoming events."),
category: "Events",
async execute(interaction) {
const { user } = interaction;

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("bored")
.setDescription("Get a random activity to do."),
category: "Fun",
async execute(interaction) {
try {

View file

@ -49,6 +49,7 @@ module.exports = {
)
.setRequired(false)
),
category: "Fun",
async execute(interaction) {
const category = interaction.options.getString("category");

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("randomfact")
.setDescription("Get a random fun fact"),
category: "Fun",
async execute(interaction) {
try {

View file

@ -11,6 +11,8 @@ module.exports = {
.setDescription("The text to uwufy")
.setRequired(true)
),
category: "Fun",
async execute(interaction) {
const inputText = interaction.options.getString("text");

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("coinflip")
.setDescription("Flip a coin!"),
category: "Games",
async execute(interaction) {
const result = Math.random() < 0.5 ? "Heads" : "Tails";

View file

@ -12,6 +12,7 @@ module.exports = {
.setMinValue(2)
.setMaxValue(100)
),
category: "Games",
async execute(interaction) {
const sides = interaction.options.getInteger("sides") || 6;

View file

@ -15,6 +15,7 @@ module.exports = {
{ name: "Scissors", value: "scissors" }
)
),
category: "Games",
async execute(interaction) {
const userChoice = interaction.options.getString("choice");

View file

@ -102,6 +102,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("scramble")
.setDescription("Play a word scramble game"),
category: "Games",
async execute(interaction) {
const userId = interaction.user.id;

View file

@ -13,6 +13,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("spyfall")
.setDescription("Start a game of Spyfall."),
category: "Games",
async execute(interaction) {
const guildId = interaction.guild.id;

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("stopspyfall")
.setDescription("Stop the current Spyfall game in this server."),
category: "Games",
async execute(interaction) {
try {

View file

@ -293,6 +293,7 @@ module.exports = {
}))
)
),
category: "Games",
async execute(interaction, client) {
const userId = interaction.user.id;

View file

@ -26,6 +26,8 @@ module.exports = {
.setDescription("Whether the response should be ephemeral")
.setRequired(false)
),
category: "General",
async execute(interaction) {
const word = interaction.options.getString("word").toLowerCase();
const isEphemeral = interaction.options.getBoolean("ephemeral") || false;

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("thisdayinhistory")
.setDescription("Shows historical events that happened on this day."),
category: "General",
async execute(interaction) {
try {

View file

@ -12,6 +12,8 @@ module.exports = {
.setDescription("The term to look up")
.setRequired(true)
),
category: "General",
async execute(interaction, client) {
const term = interaction.options.getString("term").toLowerCase();
const guild = interaction.guild;

View file

@ -83,6 +83,7 @@ module.exports = {
.setDescription("The word to find associations for")
.setRequired(true)
),
category: "General",
async execute(interaction) {
const word = interaction.options.getString("word");

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("botinfo")
.setDescription("Displays information about the bot"),
category: "Information",
async execute(interaction, client) {
try {

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("serverinfo")
.setDescription("Displays information about the server"),
category: "Information",
async execute(interaction) {
try {

View file

@ -12,6 +12,7 @@ module.exports = {
.setRequired(true)
),
isModOnly: true,
category: "Minecraft",
async execute(interaction) {
const username = interaction.options.getString("username");

View file

@ -9,6 +9,7 @@ module.exports = {
.setName("servers")
.setDescription("Displays a list of servers the bot is currently in"),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
try {

View file

@ -15,6 +15,7 @@ module.exports = {
)
.setRequired(true)
),
category: "Moderation",
async execute(interaction) {
const serverSettings = await ServerSettings.findOne({

View file

@ -19,6 +19,7 @@ module.exports = {
.setRequired(true)
),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
let replySent = false;

View file

@ -6,6 +6,7 @@ module.exports = {
.setName("clearleaderboard")
.setDescription("Clears all entries in the trivia leaderboard"),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
try {

View file

@ -22,6 +22,7 @@ module.exports = {
.setRequired(true)
),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
try {

View file

@ -27,6 +27,7 @@ module.exports = {
.setMaxValue(100)
),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
try {

View file

@ -11,6 +11,7 @@ module.exports = {
.setDescription("Displays the current server settings"),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
let replySent = false;

View file

@ -51,6 +51,7 @@ module.exports = {
)
.setRequired(false)
),
category: "Moderation",
async execute(interaction) {
// Check if the user has admin permissions

View file

@ -28,6 +28,7 @@ module.exports = {
.setRequired(true)
),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
let replySent = false;

View file

@ -15,6 +15,7 @@ module.exports = {
.setRequired(false)
),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
try {

View file

@ -22,6 +22,7 @@ module.exports = {
.setRequired(true)
),
isModOnly: true,
category: "Moderation",
async execute(interaction) {
try {

71
commands/music/loop.js Normal file
View file

@ -0,0 +1,71 @@
const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("loop")
.setDescription("Loop the current song or entire queue")
.addStringOption((option) =>
option
.setName("mode")
.setDescription("Loop mode")
.setRequired(true)
.addChoices(
{ name: "Track (Current Song)", value: "track" },
{ name: "Queue (All Songs)", value: "queue" },
{ name: "Off (Disable Loop)", value: "off" }
)
),
category: "Music",
async execute(interaction, client) {
await interaction.deferReply();
const queue = client.distube.getQueue(interaction.guildId);
const mode = interaction.options.getString("mode");
if (!queue || !queue.songs.length) {
return interaction.followUp("❌ There is no music playing!");
}
try {
let modeValue;
let modeText;
switch (mode) {
case "track":
modeValue = 1;
modeText = "🔂 Track Loop";
break;
case "queue":
modeValue = 2;
modeText = "🔁 Queue Loop";
break;
case "off":
modeValue = 0;
modeText = "▶️ Loop Disabled";
break;
default:
modeValue = 0;
modeText = "▶️ Loop Disabled";
}
await queue.setRepeatMode(modeValue);
const embed = new EmbedBuilder()
.setColor("#0099ff")
.setTitle("🔁 Loop Mode Updated")
.setDescription(
`**${modeText}**\n\nCurrent song: **${queue.songs[0].name}**`
)
.setFooter({ text: `Requested by ${interaction.user.tag}` })
.setTimestamp();
await interaction.followUp({ embeds: [embed] });
} catch (error) {
console.error("Error setting loop mode:", error);
await interaction.followUp(
"❌ Failed to set loop mode. Please try again."
);
}
},
};

View file

@ -13,6 +13,8 @@ module.exports = {
.setDescription("Song name to search lyrics for (optional)")
.setRequired(false)
),
category: "Music",
async execute(interaction, client) {
await interaction.deferReply();

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("nowplaying")
.setDescription("Shows information about the current song"),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("pause")
.setDescription("Pauses the current song"),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);

View file

@ -10,6 +10,8 @@ module.exports = {
.setDescription("Song name or URL")
.setRequired(true)
),
category: "Music",
async execute(interaction, client) {
await interaction.deferReply();
const query = interaction.options.getString("query");

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("queue")
.setDescription("Shows the current music queue."),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);
if (!queue || queue.songs.length === 0) {

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("resume")
.setDescription("Resumes the paused song"),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("shuffle")
.setDescription("Shuffles the current queue"),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("skip")
.setDescription("Skips the current song."),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);
if (!queue) return interaction.reply("❌ No songs in queue!");

View file

@ -4,6 +4,8 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("stop")
.setDescription("Stops the music and clears the queue."),
category: "Music",
async execute(interaction, client) {
const queue = client.distube.getQueue(interaction.guildId);
if (!queue) return interaction.reply("❌ No music is playing!");

View file

@ -12,6 +12,8 @@ module.exports = {
.setMinValue(1)
.setMaxValue(100)
),
category: "Music",
async execute(interaction, client) {
const volume = interaction.options.getInteger("level");
const queue = client.distube.getQueue(interaction.guildId);

View file

@ -11,6 +11,7 @@ module.exports = {
.setDescription("The Steam ID to fetch stats for.")
.setRequired(true)
),
category: "Stats",
async execute(interaction) {
const steamId = interaction.options.getString("steam_id");

View file

@ -13,6 +13,7 @@ module.exports = {
)
.setRequired(true)
),
category: "Stats",
async execute(interaction) {
const username = interaction.options.getString("username");

View file

@ -41,6 +41,8 @@ module.exports = {
.setDescription("Include roles stats?")
.setRequired(false)
),
category: "Stats",
async execute(interaction) {
// Immediately defer the reply
await interaction.deferReply();

View file

@ -5,6 +5,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("leaderboard")
.setDescription("Displays the trivia leaderboard"),
category: "Utils",
async execute(interaction, client) {
const guild = interaction.guild;

View file

@ -4,6 +4,7 @@ module.exports = {
data: new SlashCommandBuilder()
.setName("stats")
.setDescription("Displays server statistics."),
category: "Utils",
async execute(interaction) {
try {

View file

@ -12,6 +12,7 @@ module.exports = {
.setDescription("Your verification code")
.setRequired(true)
),
category: "Verification",
async execute(interaction, client) {
// Fetch server settings from the database

View file

@ -21,6 +21,7 @@ module.exports = {
.setDescription("Your DCU email address")
.setRequired(true)
),
category: "Verification",
async execute(interaction, client) {
// Fetch the server settings from the database using guild ID

View file

@ -46,7 +46,7 @@ client.distube
`✅ Added: **${song.name}** - \`${song.formattedDuration}\``
);
})
.on("error", (channel, error) => {
.on("error", (queue, error) => {
console.error("DisTube error:", error);
queue.textChannel.send("❌ An error occurred: " + error.message);
})