From 329d3a131de19237c9e3436dada56e386dd33bea Mon Sep 17 00:00:00 2001 From: ScriptSorcerer20 Date: Wed, 12 Mar 2025 19:35:49 +0100 Subject: [PATCH] startet currency system, think i added temporary ban and a give command --- README.md | 2 +- commands/db/balance.js | 0 commands/db/give.js | 37 ++++++++++++ commands/moderation/mute.js | 20 +++--- commands/moderation/temp_ban.js | 104 ++++++++++++++++++++++++++++++++ deploy-commands.js | 2 +- events/tempban.js | 44 ++++++++++++++ 7 files changed, 194 insertions(+), 15 deletions(-) create mode 100644 commands/db/balance.js create mode 100644 commands/db/give.js create mode 100644 events/tempban.js diff --git a/README.md b/README.md index c5c10a4..753474b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Im going to make a To-do List for the features i want to implement for my Bot. - [ ] Allow admins to assign/remove roles with commands. 3. **Moderation Tools** - - [ ] Add commands to mute, x kick, and ban users. + - [ ] Add commands to mute, x kick, and x temp_ban users. - [ ] Create an auto-moderation feature to delete spam or inappropriate content. - [ ] Implement a warning system with a strike counter. diff --git a/commands/db/balance.js b/commands/db/balance.js new file mode 100644 index 0000000..e69de29 diff --git a/commands/db/give.js b/commands/db/give.js new file mode 100644 index 0000000..4bc2441 --- /dev/null +++ b/commands/db/give.js @@ -0,0 +1,37 @@ +// exampleCommand.js +const { SlashCommandBuilder } = require('discord.js'); +const { connectToDatabase } = require('../../db.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('give') + .setDescription('give somebody coins') + .addIntegerOption(option => + option + .setName('amount') + .setDescription('amount of the coins') + .setRequired(true)) + .addUserOption(option => + option.setName('target') + .setDescription('The user to give coins to') + .setRequired(true)), + async execute(interaction) { + const dbClient = await connectToDatabase(); + const target = interaction.options.getUser('target'); + const amount = interaction.options.getInteger('amount'); + + // Choose a DB + Collection + const db = dbClient.db('discord'); + const collection = db.collection('currency'); + + let targetData = await collection.findOne({ userID: target.id }); + if (!targetData) { + await collection.insertOne({ userID: target.id, balance: 0 }); + } + + // Perform the transaction: subtract from sender and add to target. + await collection.updateOne({ userID: target.id }, { $inc: { balance: amount } }, { upsert: true }); + + return interaction.reply({ content: `You have given ${amount} coins to ${target.tag}.` }); + } +}; \ No newline at end of file diff --git a/commands/moderation/mute.js b/commands/moderation/mute.js index 5d4df3b..09d56a8 100644 --- a/commands/moderation/mute.js +++ b/commands/moderation/mute.js @@ -19,26 +19,20 @@ module.exports = { .setName('reason') .setDescription('The reason of the mute')), async execute(interaction) { - // Get the user and duration from the command options const target = interaction.options.getUser('target'); const duration = interaction.options.getInteger('duration'); + const reason = interaction.options.getString('reason'); // Convert duration to milliseconds const durationMs = duration * 60 * 1000; - try { - // Apply the timeout - await target.timeout(durationMs); + const guildmember = await interaction.guild.members.fetch(target.id); - await interaction.reply({ - content: `${target.tag} has been muted for ${duration} minutes.` - }); - } catch (error) { - console.error(error); - await interaction.reply({ - content: 'I was unable to mute the member.', - ephemeral: true, - }); + const muteRole = interaction.guild.roles.find(role => role.name === "mute"); + if (!muteRole) { + + } else { + await guildmember.roles.add(muteRole, reason); } }, }; \ No newline at end of file diff --git a/commands/moderation/temp_ban.js b/commands/moderation/temp_ban.js index e69de29..871e467 100644 --- a/commands/moderation/temp_ban.js +++ b/commands/moderation/temp_ban.js @@ -0,0 +1,104 @@ +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const { connectToDatabase } = require('../../db.js'); + +module.exports = { + mod: true, + data: new SlashCommandBuilder() + .setName("temp-ban") + .setDescription("Kick misbehaving people") + .addUserOption(option => + option + .setName('target') + .setDescription('The member to kick') + .setRequired(true)) + .addIntegerOption(option => + option + .setName('durationms') + .setDescription('Duration of the temporary ban (in milliseconds).') + .setRequired(true)) + .addStringOption(option => + option + .setName('reason') + .setDescription('Reason for the ban') + .setRequired(true)) + .addIntegerOption(option => + option + .setName('delete-messages') + .setDescription('Number of days to delete messages') + .setMinValue(0).setMaxValue(7)), + async execute(interaction) { + const user = interaction.options.getUser('target'); + const reason = interaction.options.getString('reason'); + const durationms = interaction.options.getInteger('durationms'); + const deleteMessages = interaction.options.getInteger('delete-messages'); + + // If you want to parse time like "1d", "10m", etc., use ms package: + let banUntil; + try { + banUntil = Date.now() + durationms; + } catch (e) { + // If parsing fails, handle error + return interaction.reply({ + content: 'Invalid duration format. Please use something like "10m" or "1d".', + ephemeral: true + }); + } + + + // A function to send ephemeral messages + async function sendEphemeral(message) { + const embed = new EmbedBuilder() + .setColor("Blurple") + .setDescription(message); + + return interaction.reply({ embeds: [embed], ephemeral: true }); + } + + // Check if user is already banned + const bans = await interaction.guild.bans.fetch(); + if (bans.has(user.id)) { + return sendEphemeral("That user is already banned"); + } + + // --------- STORE BAN DATA IN MONGODB --------- + try { + // 1. Get or create the MongoDB client + const dbClient = await connectToDatabase(); + + // 2. Access a DB and a collection + const db = dbClient.db("discord"); + const tempBanCollection = db.collection("tempban"); + + // 3. Insert the ban record + await tempBanCollection.insertOne({ + guildId: interaction.guild.id, + userId: user.id, + banTime: banUntil, + reason: reason, + }); + } catch (err) { + console.error(err); + return sendEphemeral("Could not insert ban record into DB."); + } + + // --------- BAN THE USER IN DISCORD --------- + let error = false; + try { + await interaction.guild.bans.create(user.id, { + reason: reason, + deleteMessageDays: deleteMessages, + }); + } catch (err) { + error = true; + console.error(err); + } + + if (error) { + return sendEphemeral("Something went wrong banning the user."); + } else { + return sendEphemeral( + `${user} has been banned for **${durationms}** for *${reason}*` + ); + } + }, +}; diff --git a/deploy-commands.js b/deploy-commands.js index ed61030..fd3b346 100644 --- a/deploy-commands.js +++ b/deploy-commands.js @@ -34,7 +34,7 @@ const rest = new REST().setToken(token); // The put method is used to fully refresh all commands in the guild with the current set const data = await rest.put( - Routes.applicationGuildCommands(clientId, guildId), + Routes.applicationCommands(clientId), { body: commands }, ); diff --git a/events/tempban.js b/events/tempban.js new file mode 100644 index 0000000..dd2e9ab --- /dev/null +++ b/events/tempban.js @@ -0,0 +1,44 @@ +const { Events } = require('discord.js'); +const { connectToDatabase } = require('../db.js'); + +module.exports = { + name: Events.ClientReady, + async execute(client) { + const dbClient = await connectToDatabase(); + const db = dbClient.db('discord'); + const tempBanCollection = db.collection('tempban'); + + // 2) Define a function to schedule unbans + async function scheduleUnban(banData) { + const delay = banData.banTime - Date.now(); + + if (delay <= 0) { + return; + } + setTimeout(async () => { + try { + const guild = await client.guilds.fetch(banData.guildId); + await guild.bans.remove(banData.userId); + + await tempBanCollection.deleteOne({ _id: banData._id }); + } catch (err) { + console.error('Error unbanning member:', err); + } + }, delay); + } + + try { + const allBans = await tempBanCollection.find({}).toArray(); + allBans.forEach(scheduleUnban); + + tempBanCollection.watch().on('change', (change) => { + if (change.operationType === 'insert') { + const newBan = change.fullDocument; + scheduleUnban(newBan); + } + }); + } catch (err) { + console.error('Error setting up unban system:', err); + } + }, +};