From 2925fb59dd883e50092ba869ff4db713b097cfdc Mon Sep 17 00:00:00 2001 From: DeSqBlocki Date: Fri, 2 Aug 2024 13:25:06 +0200 Subject: [PATCH] trying to handle music --- .gitignore | 3 +- VoiceStateUpdatesOld.js | 50 + buttons/_global/abort.js | 18 + buttons/honor/honor_menu_dishonor.js | 42 + buttons/honor/honor_menu_history.js | 36 + buttons/honor/honor_menu_honor.js | 43 + buttons/honor/honor_multi_confirm.js | 66 + buttons/honor/honors_leaderboard_left.js | 33 + buttons/honor/honors_leaderboard_right.js | 31 + buttons/honor/honors_leaderboard_self.js | 41 + buttons/nuts/nuts_give_confirm.js | 46 + buttons/nuts/nuts_give_fake.js | 42 + buttons/nuts/nuts_leaderboard_left.js | 33 + buttons/nuts/nuts_leaderboard_right.js | 31 + buttons/nuts/nuts_leaderboard_self.js | 41 + buttons/test/test_button_1.js | 9 + commands/honors/honors.js | 272 ++++ commands/music/music.js | 165 ++ commands/nuts/nuts.js | 345 ++++ commands/quotes/quotes.js | 135 ++ commands/test/ping.js | 11 + events/ClientReady.js | 17 + events/InteractionCreate.js | 58 + events/MessageCreate.js | 24 + events/VoiceStateUpdates.js | 50 + handlers/buttons.js | 20 + handlers/commands.js | 42 + handlers/events.js | 18 + handlers/legacyCommands.js | 29 + handlers/selectMenus.js | 20 + index.js | 40 + legacyCommands/nuts/nutsCheck.js | 54 + legacyCommands/nuts/nutsCooldown.js | 31 + legacyCommands/nuts/nutsGet.js | 47 + legacyCommands/nuts/nutsGive.js | 78 + legacyCommands/nuts/nutsLeaderboard.js | 47 + legacyCommands/nuts/nutsStats.js | 58 + legacyCommands/test/interactive.js | 16 + legacyCommands/test/ping.js | 8 + package-lock.json | 1475 ++++++++++++++++++ package.json | 34 + selectMenus/honors/honor_menu_mentionable.js | 50 + 42 files changed, 3708 insertions(+), 1 deletion(-) create mode 100644 VoiceStateUpdatesOld.js create mode 100644 buttons/_global/abort.js create mode 100644 buttons/honor/honor_menu_dishonor.js create mode 100644 buttons/honor/honor_menu_history.js create mode 100644 buttons/honor/honor_menu_honor.js create mode 100644 buttons/honor/honor_multi_confirm.js create mode 100644 buttons/honor/honors_leaderboard_left.js create mode 100644 buttons/honor/honors_leaderboard_right.js create mode 100644 buttons/honor/honors_leaderboard_self.js create mode 100644 buttons/nuts/nuts_give_confirm.js create mode 100644 buttons/nuts/nuts_give_fake.js create mode 100644 buttons/nuts/nuts_leaderboard_left.js create mode 100644 buttons/nuts/nuts_leaderboard_right.js create mode 100644 buttons/nuts/nuts_leaderboard_self.js create mode 100644 buttons/test/test_button_1.js create mode 100644 commands/honors/honors.js create mode 100644 commands/music/music.js create mode 100644 commands/nuts/nuts.js create mode 100644 commands/quotes/quotes.js create mode 100644 commands/test/ping.js create mode 100644 events/ClientReady.js create mode 100644 events/InteractionCreate.js create mode 100644 events/MessageCreate.js create mode 100644 events/VoiceStateUpdates.js create mode 100644 handlers/buttons.js create mode 100644 handlers/commands.js create mode 100644 handlers/events.js create mode 100644 handlers/legacyCommands.js create mode 100644 handlers/selectMenus.js create mode 100644 legacyCommands/nuts/nutsCheck.js create mode 100644 legacyCommands/nuts/nutsCooldown.js create mode 100644 legacyCommands/nuts/nutsGet.js create mode 100644 legacyCommands/nuts/nutsGive.js create mode 100644 legacyCommands/nuts/nutsLeaderboard.js create mode 100644 legacyCommands/nuts/nutsStats.js create mode 100644 legacyCommands/test/interactive.js create mode 100644 legacyCommands/test/ping.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 selectMenus/honors/honor_menu_mentionable.js diff --git a/.gitignore b/.gitignore index 2eea525..a4908c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.env \ No newline at end of file +.env +node_modules diff --git a/VoiceStateUpdatesOld.js b/VoiceStateUpdatesOld.js new file mode 100644 index 0000000..862a129 --- /dev/null +++ b/VoiceStateUpdatesOld.js @@ -0,0 +1,50 @@ +const { Events, ActivityType } = require('discord.js') +require('dotenv').config() +const { client } = require('./index') +const { RepeatMode } = require('distube') +const delay = ms => new Promise(res => setTimeout(res, ms)); +var usersInTartaros = new Set() +var joined = false +const playlist = `https://www.youtube.com/playlist?list=PLjSh2s1ASTgsSdjCgFbpo18RAYF_dHf46` + +module.exports = { + name: Events.VoiceStateUpdate, + once: false, + async execute(oldUser, newUser) { + const guild = client.guilds.cache.get(newUser.guild.id) + const tartarosChannel = await guild.channels.fetch(process.env.D_TartarosID) + + if (newUser.channelId === tartarosChannel.id && oldUser.channelId != newUser.channelId) { + if (newUser.id === '1152718975529140265') { + console.log('Bot joined Tartaros!') + await newUser.setMute(false) + //await newUser.setSuppress(false) + console.log(newUser) + } + + usersInTartaros.add(newUser.id) + console.log(`${usersInTartaros.size} User(s) in Tartaros`) + + if (!joined) { + joined = true; + await client.distube.voices.join(tartarosChannel) + //console.log(await guild.members.me.edit({ mute: false})) + + await delay(3000) + //await tartarosChannel.guild.members.me.edit({ mute: false }) + + // await client.distube.play(playlist) + // const queue = interaction.client.distube.getQueue(interaction.guild) + // await queue.setRepeatMode('Queue') + // await queue.setVolume(40) + console.log('Unmuted') + } + } + + if (oldUser.channelID === tartarosChannel.id && oldUser.channelID != newUser.channelID) { + usersInTartaros.delete(oldUser.id) + //await client.distube.voices.leave(tartarosChannel) + joined = false + } + } +} \ No newline at end of file diff --git a/buttons/_global/abort.js b/buttons/_global/abort.js new file mode 100644 index 0000000..daacfd4 --- /dev/null +++ b/buttons/_global/abort.js @@ -0,0 +1,18 @@ +const { EmbedBuilder } = require("discord.js") +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } + +module.exports = { + name: 'abort', + description: 'abort it', + async execute(interaction) { + const embed = new EmbedBuilder() + .setTitle('Aborted') + .setDescription('Schließe Menü. . .') + + await interaction.update({ + embeds: [embed], + components: [] + }) + await delay(2000).then(interaction.deleteReply()) + } +} \ No newline at end of file diff --git a/buttons/honor/honor_menu_dishonor.js b/buttons/honor/honor_menu_dishonor.js new file mode 100644 index 0000000..c499851 --- /dev/null +++ b/buttons/honor/honor_menu_dishonor.js @@ -0,0 +1,42 @@ +const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'honor_menu_dishonor', + description: 'honor menu dishonor button', + async execute(interaction) { + let description = interaction.message.embeds[0].data.description + const target = await interaction.guild.members.fetch(description.split(' ')[0].slice(2, -1)) + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + const reason = `[-] Quick Menu Dishonor` + const theirHonorLevel = await honorsColl.findOne({ userID: target.id }) + + const embed = new EmbedBuilder() + .setTitle('- Honor Menu WIP -') + .setDescription(`Willst du wirklich <@${target.id}> einen **Dishonor** geben?\r\n[Grund: ${reason}]`) + .addFields({ + name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**-1**)` + }) + .setThumbnail(target.displayAvatarURL()) + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('✔') + .setCustomId('honor_multi_confirm') + .setStyle(ButtonStyle.Success) + ) + .addComponents( + new ButtonBuilder() + .setLabel('✖') + .setCustomId('abort') + .setStyle(ButtonStyle.Danger) + ) + await interaction.reply({ + embeds: [embed], + components: [row], + ephemeral: true + }) + } +} \ No newline at end of file diff --git a/buttons/honor/honor_menu_history.js b/buttons/honor/honor_menu_history.js new file mode 100644 index 0000000..45cfbba --- /dev/null +++ b/buttons/honor/honor_menu_history.js @@ -0,0 +1,36 @@ +const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'honor_menu_history', + description: 'show selected user honor history', + async execute(interaction) { + let description = interaction.message.embeds[0].data.description + const target = await interaction.guild.members.fetch(description.split(' ')[0].slice(2, -1)) + const db = mClient.db(process.env.M_DB) + const reasonsColl = db.collection('honor-reasons') + const history = await reasonsColl.findOne({ userID: target.user.id }) + + const embed = new EmbedBuilder() + .setTitle('- Honor History -') + .setDescription(`${target} - ${target.user.globalName ?? target.user.username}`) + .setThumbnail(target.displayAvatarURL()) + .setFooter({text: 'Um zurückzukehren, wähle einen Nutzer!'}) + if(history){ + let temp = '' + history.reasons.forEach(reason => { + temp += reason + '\r\n' + }) + embed.setDescription(temp) + } + const select = await interaction.message.components[0] + const row = await interaction.message.components[1] + + await interaction.reply({ + embeds: [embed], + components: [select, row], + ephemeral: true + }) + } +} \ No newline at end of file diff --git a/buttons/honor/honor_menu_honor.js b/buttons/honor/honor_menu_honor.js new file mode 100644 index 0000000..5252636 --- /dev/null +++ b/buttons/honor/honor_menu_honor.js @@ -0,0 +1,43 @@ +const { EmbedBuilder, ButtonBuilder, ActionRowBuilder, ButtonStyle } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'honor_menu_honor', + description: 'honor menu honor button', + async execute(interaction) { + let description = interaction.message.embeds[0].data.description + const target = await interaction.guild.members.fetch(description.split(' ')[0].slice(2, -1)) + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + const reason = `[+] Quick Menu Honor` + const theirHonorLevel = await honorsColl.findOne({ userID: target.id }) + + const embed = new EmbedBuilder() + .setTitle('- Honor Up! -') + .setDescription(`Willst du wirklich <@${target.id}> einen **Honor** geben?\r\n[Grund: ${reason}]`) + .addFields({ + name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**+1**)` + }) + .setThumbnail(target.displayAvatarURL()) + //.setFooter('Honor Level updaten sich nicht automatisch!') + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('✔') + .setCustomId('honor_multi_confirm') + .setStyle(ButtonStyle.Success) + ) + .addComponents( + new ButtonBuilder() + .setLabel('✖') + .setCustomId('abort') + .setStyle(ButtonStyle.Danger) + ) + await interaction.reply({ + embeds: [embed], + components: [row], + ephemeral: true + }) + } +} \ No newline at end of file diff --git a/buttons/honor/honor_multi_confirm.js b/buttons/honor/honor_multi_confirm.js new file mode 100644 index 0000000..820786d --- /dev/null +++ b/buttons/honor/honor_multi_confirm.js @@ -0,0 +1,66 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'honor_multi_confirm', + description: 'confirm it', + async execute(interaction) { + let temp = await interaction.message.embeds[0].description.split(' ') + var honor + if (temp[5].slice(2, -2) == 'Honor') { + honor = 1 + } else { + honor = -1 + } + const target = await interaction.message.guild.members.fetch(temp[3].slice(2, -1)) + temp = interaction.message.embeds[0].description.split('\r\n') + const reason = `${temp[1].slice(7, -1)}` + + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + const reasonsColl = db.collection('honor-reasons') + const theirHonorLevel = await honorsColl.findOne({ userID: target.id }) + + await honorsColl.findOneAndUpdate({ userID: target.id }, { $inc: { honors: honor } }, { upsert: true }) + await reasonsColl.findOneAndUpdate({ userID: target.id }, { $push: { reasons: reason } }, { upsert: true }) + + var description + var newTitle + var newDescription + var newThumbnail + + if (honor == 1) { + description = `Willst du wirklich <@${target.id}> einen Honor geben?\r\n[Grund: ${reason}]` + newTitle = 'Honor Up!' + newDescription = `<@${target.id}> erhält einen Honor!\r\n[Grund: ${reason}]` + newThumbnail = "https://cdn.discordapp.com/emojis/748176295535443968.webp" + } else { + description = `Willst du wirklich <@${target.id}> einen Dishonor geben?\r\n[Grund: ${reason}]` + newTitle = 'Honor Down!' + newDescription = `<@${target.id}> erhält einen Dishonor!\r\n[Grund: ${reason}]` + newThumbnail = "https://cdn.discordapp.com/emojis/748176295132790786.webp" + } + + + const embed = new EmbedBuilder() + .setTitle('- Honor Menu -') + .setDescription(description) + .addFields({ + name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} ${honor == 1 ? '(**+1**)' : '(**-1**)'}` + }) + .setThumbnail(target.displayAvatarURL()) + await interaction.update({ + embeds: [embed] + }) + + const newEmbed = new EmbedBuilder() + .setTitle(newTitle) + .setDescription(newDescription) + .setThumbnail(newThumbnail) + await interaction.followUp({ + embeds: [newEmbed], + components: [], + }) + } +} \ No newline at end of file diff --git a/buttons/honor/honors_leaderboard_left.js b/buttons/honor/honors_leaderboard_left.js new file mode 100644 index 0000000..a6c0d89 --- /dev/null +++ b/buttons/honor/honors_leaderboard_left.js @@ -0,0 +1,33 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'honors_leaderboard_left', + description: 'navigate a page up', + async execute(interaction) { + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + const min = 0 + let skip = interaction.message.embeds[0].data.description.split('.') + skip = Number(skip[0]) - 6 + skip = skip - ( skip % 5) + if ( skip < 4){ + skip = 0 + } + const honorsData = await honorsColl.find().sort({ honors: -1 }).skip(skip).limit(5).toArray() + let fields + honorsData.forEach((data) => { + skip++ + fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.honors} Honors\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Honors Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.update({ + embeds: [embed], + components: [interaction.message.components[0]] + }) + } +} \ No newline at end of file diff --git a/buttons/honor/honors_leaderboard_right.js b/buttons/honor/honors_leaderboard_right.js new file mode 100644 index 0000000..94679db --- /dev/null +++ b/buttons/honor/honors_leaderboard_right.js @@ -0,0 +1,31 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() +module.exports = { + name: 'honors_leaderboard_right', + description: 'navigate a page down', + async execute(interaction) { + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + const max = await honorsColl.countDocuments() + let skip = interaction.message.embeds[0].data.description.split('.') + skip = Number(skip[0]) +4 + if (skip >= (max - (max % 5))) { + skip = max - (max % 5) + } + const honorsData = await honorsColl.find().sort({ honors: -1 }).skip(skip).limit(5).toArray() + let fields + honorsData.forEach((data) => { + skip++ + fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.honors} Honors\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Honors Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.update({ + embeds: [embed], + components: [interaction.message.components[0]] + }) + } +} \ No newline at end of file diff --git a/buttons/honor/honors_leaderboard_self.js b/buttons/honor/honors_leaderboard_self.js new file mode 100644 index 0000000..b60c33d --- /dev/null +++ b/buttons/honor/honors_leaderboard_self.js @@ -0,0 +1,41 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() +module.exports = { + name: 'honors_leaderboard_self', + description: 'navigate to your own placement', + async execute(interaction) { + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + + const self = await honorsColl.find({ userID: interaction.user.id }).toArray() + const all = await honorsColl.find().sort({ honors: -1 }).toArray() + + function findIndex(){ + let index = 0 + for (let i = 0; i < all.length; i++) { + index++ + if (all[i].honors === self[0].honors) { + return index + } + } + } + let selfIndex = findIndex() + let skip = selfIndex - ( selfIndex % 5) + + const honorsData = await honorsColl.find().sort({ honors: -1 }).skip(skip).limit(5).toArray() + let fields + honorsData.forEach((data) => { + skip++ + fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.honors} Honors\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Honors Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.update({ + embeds: [embed], + components: [interaction.message.components[0]] + }) + } +} \ No newline at end of file diff --git a/buttons/nuts/nuts_give_confirm.js b/buttons/nuts/nuts_give_confirm.js new file mode 100644 index 0000000..800995f --- /dev/null +++ b/buttons/nuts/nuts_give_confirm.js @@ -0,0 +1,46 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'nuts_give_confirm', + description: 'confirm it', + async execute(interaction) { + const from = interaction.user + let temp = await interaction.message.embeds[0].description.split(' ') + const amount = Number(temp[3].split('**')[1]) + const to = await interaction.message.guild.members.fetch(temp[6].slice(2,-1)) + + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + await nutsColl.findOneAndUpdate({ userID: from.id }, { $inc: { nuts: -amount } }, { upsert: true }) + await nutsColl.findOneAndUpdate({ userID: to.id }, { $inc: { nuts: +amount } }, { upsert: true }) + + const yourBalance = await nutsColl.findOne({ userID: from.id }) + const theirBalance = await nutsColl.findOne({ userID: to.id }) + const embed = new EmbedBuilder() + .setTitle('Gib Nuss!') + .setDescription(`Willst du wirklich **${amount}** Nüsse an <@${to.id}> senden?`) + .addFields( + { name: `Your Current Balance`, value: `${yourBalance.nuts} (**-${amount}**)`, inline: true }, + { name: `Your New Balance`, value: `${yourBalance.nuts - amount}`, inline: true }, + { name: '\u200B', value: '\u200B' }, + { name: `Their Current Balance`, value: `${theirBalance.nuts} (**+${amount}**)`, inline: true }, + { name: `Their New Balance`, value: `${theirBalance.nuts + amount}`, inline: true } + ) + .setThumbnail(to.displayAvatarURL()) + await interaction.update({ + embeds: [ embed ] + }) + + const newEmbed = new EmbedBuilder() + .setTitle('Gib Nuss!') + .setDescription(`Du hast **${amount}** Nuts an <@${to.id}> gesendet!`) + .setFooter({ text: 'Um den gleichen Wert zu senden, klick einfach nochmal auf ✔' }) + .setThumbnail(to.user.displayAvatarURL()) + await interaction.followUp({ + embeds: [ newEmbed ], + components: [], + }) + } +} \ No newline at end of file diff --git a/buttons/nuts/nuts_give_fake.js b/buttons/nuts/nuts_give_fake.js new file mode 100644 index 0000000..57ac848 --- /dev/null +++ b/buttons/nuts/nuts_give_fake.js @@ -0,0 +1,42 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +module.exports = { + name: 'nuts_give_fake', + description: 'fake it', + async execute(interaction) { + const from = interaction.user + let temp = await interaction.message.embeds[0].description.split(' ') + const amount = Number(temp[3].split('**')[1]) + const to = await interaction.message.guild.members.fetch(temp[6].slice(2,-1)) + + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + + const yourBalance = await nutsColl.findOne({ userID: from.id }) + const theirBalance = await nutsColl.findOne({ userID: to.id }) + + const embed = new EmbedBuilder() + .setTitle('Gib Nuss!') + .setDescription(`Willst du wirklich **${amount}** Nüsse an <@${to.id}> senden?`) + .addFields( + { name: `Your Current Balance`, value: `${yourBalance.nuts} (**-${amount}**)`, inline: true }, + { name: `Your New Balance`, value: `${yourBalance.nuts - amount}`, inline: true }, + { name: '\u200B', value: '\u200B' }, + { name: `Their Current Balance`, value: `${theirBalance.nuts} (**+${amount}**)`, inline: true }, + { name: `Their New Balance`, value: `${theirBalance.nuts + amount}`, inline: true } + ) + .setThumbnail(to.displayAvatarURL()) + await interaction.update({ + embeds: [ embed ] + }) + + const newEmbed = new EmbedBuilder() + .setTitle('Du Fieser Gauner!') + .setDescription(`Yee Haw! Was tust du hier?!`) + .setThumbnail(interaction.client.user.displayAvatarURL()) + await interaction.followUp({ + embeds: [ newEmbed ], + components: [], + }) + } +} \ No newline at end of file diff --git a/buttons/nuts/nuts_leaderboard_left.js b/buttons/nuts/nuts_leaderboard_left.js new file mode 100644 index 0000000..4c08bc3 --- /dev/null +++ b/buttons/nuts/nuts_leaderboard_left.js @@ -0,0 +1,33 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'nuts_leaderboard_left', + description: 'navigate a page up', + async execute(interaction) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const min = 0 + let skip = interaction.message.embeds[0].data.description.split('.') + skip = Number(skip[0]) - 6 + skip = skip - ( skip % 5) + if ( skip < 4){ + skip = 0 + } + const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray() + let fields + nutsData.forEach((data) => { + skip++ + fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.nuts} Nuts\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Nuts Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.update({ + embeds: [embed], + components: [interaction.message.components[0]] + }) + } +} \ No newline at end of file diff --git a/buttons/nuts/nuts_leaderboard_right.js b/buttons/nuts/nuts_leaderboard_right.js new file mode 100644 index 0000000..77eb2ff --- /dev/null +++ b/buttons/nuts/nuts_leaderboard_right.js @@ -0,0 +1,31 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() +module.exports = { + name: 'nuts_leaderboard_right', + description: 'navigate a page down', + async execute(interaction) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const max = await nutsColl.countDocuments({ nuts: { $gt: 0 } }) + let skip = interaction.message.embeds[0].data.description.split('.') + skip = Number(skip[0]) +4 + if (skip >= (max - (max % 5))) { + skip = max - (max % 5) + } + const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray() + let fields + nutsData.forEach((data) => { + skip++ + fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.nuts} Nuts\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Nuts Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.update({ + embeds: [embed], + components: [interaction.message.components[0]] + }) + } +} \ No newline at end of file diff --git a/buttons/nuts/nuts_leaderboard_self.js b/buttons/nuts/nuts_leaderboard_self.js new file mode 100644 index 0000000..e1960dc --- /dev/null +++ b/buttons/nuts/nuts_leaderboard_self.js @@ -0,0 +1,41 @@ +const { EmbedBuilder } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() +module.exports = { + name: 'nuts_leaderboard_self', + description: 'navigate to your own placement', + async execute(interaction) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + + const self = await nutsColl.find({ userID: interaction.user.id }).toArray() + const all = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).toArray() + + function findIndex(){ + let index = 0 + for (let i = 0; i < all.length; i++) { + index++ + if (all[i].nuts === self[0].nuts) { + return index + } + } + } + let selfIndex = findIndex() + let skip = selfIndex - ( selfIndex % 5) + + const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray() + let fields + nutsData.forEach((data) => { + skip++ + fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.nuts} Nuts\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Nuts Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.update({ + embeds: [embed], + components: [interaction.message.components[0]] + }) + } +} \ No newline at end of file diff --git a/buttons/test/test_button_1.js b/buttons/test/test_button_1.js new file mode 100644 index 0000000..0e81975 --- /dev/null +++ b/buttons/test/test_button_1.js @@ -0,0 +1,9 @@ +module.exports = { + name: 'test_button_1', + description: 'a test button', + execute(interaction){ + interaction.reply({ + content: 'Success' + }) + } +} \ No newline at end of file diff --git a/commands/honors/honors.js b/commands/honors/honors.js new file mode 100644 index 0000000..2dc6e37 --- /dev/null +++ b/commands/honors/honors.js @@ -0,0 +1,272 @@ +const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, UserSelectMenuBuilder } = require('discord.js') +const { mClient } = require('../..') +require('dotenv').config() +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } + +async function honorHoner(interaction) { + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + + const target = await interaction.options.getUser('target') + const reason = `[+] ${await interaction.options.getString('reason') ?? 'No reason provided'}` + + const theirHonorLevel = await honorsColl.findOne({ userID: target.id }) + + const embed = new EmbedBuilder() + .setTitle('- Honor Up! -') + .setDescription(`Willst du wirklich <@${target.id}> einen **Honor** geben?\r\n[Grund: ${reason}]`) + .addFields({ + name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**+1**)` + }) + .setThumbnail(target.displayAvatarURL()) + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('✔') + .setCustomId('honor_multi_confirm') + .setStyle(ButtonStyle.Success) + ) + .addComponents( + new ButtonBuilder() + .setLabel('✖') + .setCustomId('abort') + .setStyle(ButtonStyle.Danger) + ) + await interaction.reply({ + embeds: [embed], + components: [row], + ephemeral: true + }) +} +async function honerDishonor(interaction) { + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + + const target = await interaction.options.getUser('target') + const reason = `[-] ${await interaction.options.getString('reason') ?? 'No reason provided'}` + const theirHonorLevel = await honorsColl.findOne({ userID: target.id }) + + const embed = new EmbedBuilder() + .setTitle('- Honor Down! -') + .setDescription(`Willst du wirklich <@${target.id}> einen **Dishonor** geben?\r\n[Grund: ${reason}]`) + .addFields({ + name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**-1**)` + }) + .setThumbnail(target.displayAvatarURL()) + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('✔') + .setCustomId('honor_multi_confirm') + .setStyle(ButtonStyle.Success) + ) + .addComponents( + new ButtonBuilder() + .setLabel('✖') + .setCustomId('abort') + .setStyle(ButtonStyle.Danger) + ) + await interaction.reply({ + embeds: [embed], + components: [row], + ephemeral: true + }) +} +async function honorLeaderboard(interaction) { + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('◄') + .setStyle(ButtonStyle.Primary) + .setCustomId('honors_leaderboard_left') + ) + .addComponents( + new ButtonBuilder() + .setLabel('🧑') + .setStyle(ButtonStyle.Primary) + .setCustomId('honors_leaderboard_self') + ) + .addComponents( + new ButtonBuilder() + .setLabel('►') + .setStyle(ButtonStyle.Primary) + .setCustomId('honors_leaderboard_right') + ) + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + let skip = 0 + const honorsData = await honorsColl.find({}).sort({ honors: -1 }).skip(skip).limit(5).toArray() + let fields + let placements = skip + 1 + honorsData.forEach((data) => { + fields = (fields ? fields : '') + (`${placements}. <@${data.userID}> : ${data.honors} Honors\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('- Honors Leaderboard -') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.editReply({ + embeds: [embed], + components: [row] + }) +} +async function honorHistory(interaction) { + var target = interaction.options.getUser('target') + if (!target) { target = interaction.user } + const db = mClient.db(process.env.M_DB) + const reasonsColl = db.collection('honor-reasons') + var history = await reasonsColl.findOne({ userID: target.id }) + + const embed = new EmbedBuilder() + .setTitle('- Honor History -') + .setThumbnail(target.displayAvatarURL()) + + if (history) { + let temp = '' + history.reasons.forEach(reason => { + temp += reason + '\r\n' + }) + embed.setDescription(temp) + } + await interaction.editReply({ embeds: [embed] }) +} +async function honorCheck(interaction) { + var target = interaction.options.getUser('target') + if (!target) { target = interaction.user } + const db = mClient.db(process.env.M_DB) + const honorsColl = db.collection('honors') + var honors = await honorsColl.findOne({ userID: target.id }) + honors = honors?.honors ?? 0 + + if (!honors) { + content = 'Choose a goddamn side!' + } else { + if (honors === -20) { + content = 'They are is at max Dishonor Level! <:lowhonor:748176295132790786> <:lowhonor:748176295132790786> <:lowhonor:748176295132790786>\n```' + `You don't get to live a bad life and have good things happen to you. - Arthur M.` + '```' + } else if (honors === 20) { + content = 'They are at max Honor Level! <:highhonor:748176295535443968> <:highhonor:748176295535443968> <:highhonor:748176295535443968>' + } else if (honors > 0) { + content = 'real good, boah, REAL GOOD! <:highhonor:748176295535443968>' + } else if (honors < 0) { + content = 'What happened to Loyalty?! <:lowhonor:748176295132790786>' + } + } + const embed = new EmbedBuilder() + .setTitle('- Honor Check -') + .setDescription(`${target} has an Honor Level of **${honors}**!`) + .setThumbnail(target.displayAvatarURL()) + .addFields({ name: '\u200B', value: `*${content}*` }) + + await interaction.editReply({ + embeds: [embed] + }) +} +async function honorMenu(interaction) { + const embed = new EmbedBuilder() + .setTitle('- Honor Menu WIP! -') + .setDescription('- Choose someone from the Select Menu below\r\n- Choose Honor Dishonor, or History\r\n- Confirm your Selection') + .setThumbnail(interaction.guild.iconURL()) + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('Honor') + .setEmoji(`<:honorhigh:748176295535443968>`) + .setCustomId('honor_menu_honor') + .setStyle(ButtonStyle.Primary) + ) + .addComponents( + new ButtonBuilder() + .setLabel('Dishonor') + .setEmoji(`<:honorlow:748176295132790786>`) + .setCustomId('honor_menu_dishonor') + .setStyle(ButtonStyle.Primary) + ) + .addComponents( + new ButtonBuilder() + .setLabel('History') + .setEmoji('📜') + .setCustomId('honor_menu_history') + .setStyle(ButtonStyle.Secondary) + ) + const select = new ActionRowBuilder() + .addComponents( + new UserSelectMenuBuilder() + .setCustomId('honor_menu_mentionable') + .setPlaceholder('Select a User') + + ) + + await interaction.reply({ + embeds: [embed], + components: [select, row], + ephemeral: true + }) +} +module.exports = { + data: new SlashCommandBuilder() + .setName('honors') + .setDescription('rund um den honor') + .addSubcommand(s => + s + .setName('honor') + .setDescription('honor someone') + .addUserOption(o => o.setName('target').setDescription('wer wird gehonored?').setRequired(true)) + .addStringOption(o => o.setName('reason').setDescription('reason?')) + ) + .addSubcommand(s => + s + .setName('dishonor') + .setDescription('dishonor someone') + .addUserOption(o => o.setName('target').setDescription('wer wird gehonored?').setRequired(true)) + .addStringOption(o => o.setName('reason').setDescription('reason?')) + ) + .addSubcommand(s => + s + .setName('check') + .setDescription("check someone's honor level") + .addUserOption(o => o.setName('target').setDescription('wer wird gehonored?')) + ) + .addSubcommand(s => + s + .setName('history') + .setDescription("check someone's honor history") + .addUserOption(o => o.setName('target').setDescription('von wem?')) + ) + .addSubcommand(s => + s + .setName('leaderboard') + .setDescription("check who's got the most honor") + ) + .addSubcommand(s => + s + .setName('menu') + .setDescription('WIP universal honor menu')) + , + async execute(interaction) { + switch (interaction.options._subcommand) { + case 'honor': + honorHoner(interaction) + break; + case 'dishonor': + honerDishonor(interaction) + break; + case 'leaderboard': + await interaction.deferReply() + honorLeaderboard(interaction) + break; + case 'history': + await interaction.deferReply() + honorHistory(interaction) + break; + case 'check': + await interaction.deferReply() + honorCheck(interaction) + break; + case 'menu': + honorMenu(interaction) + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/commands/music/music.js b/commands/music/music.js new file mode 100644 index 0000000..1632aa3 --- /dev/null +++ b/commands/music/music.js @@ -0,0 +1,165 @@ +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const { configDotenv } = require("dotenv"); +configDotenv + +async function musicJoin(interaction) { + const voiceChannel = await interaction.guild.channels.fetch(process.env.D_RealTartarosID) + await interaction.client.distube.voices.join(voiceChannel) + await voiceChannel.guild.members.me.edit({ mute: false }) + await interaction.reply({ + content: `Joined ${voiceChannel}`, + ephemeral: true + }) +} +async function musicLeave(interaction) { + const voiceChannel = await interaction.guild.channels.fetch(process.env.D_RealTartarosID) + await interaction.client.distube.voices.leave(voiceChannel) + await interaction.reply({ + content: `Left ${voiceChannel}`, + ephemeral: true + }) +} +async function musicPlay(interaction) { + const url = await interaction.options.getString('url') + const regex = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/gm + const voiceChannel = await interaction.member.voice.channel + + if (!url.match(regex)) { + return await interaction.editReply({ + content: `Invalid URL`, + ephemeral: true + }) + } + await interaction.client.distube.play(voiceChannel, url) + const queue = interaction.client.distube.getQueue(interaction.guild) + const { name, thumbnail } = queue.songs[0] + const embed = new EmbedBuilder() + .setThumbnail(thumbnail) + .setTitle(`Added ${name} to Queue`) + .setURL(url) + await interaction.editReply({ + embeds: [embed] + }) +} +async function musicVolume(interaction) { + const queue = interaction.client.distube.getQueue(interaction.guild) + if (!queue) { + return await interaction.reply({ + content: `There is nothing in the queue right now!`, + ephemeral: true + }) + } + const volume = await interaction.options.getNumber('volume') + queue.setVolume(volume) + await interaction.reply({ + content: `Set Volume to ${volume}%`, + ephemeral: true + }) +} +async function musicQueue(interaction) { + const queue = interaction.client.distube.getQueue(interaction.guild) + if (!queue) { + return await interaction.reply({ + content: `There is nothing in the queue right now!`, + ephemeral: true + }) + } + const songs = queue.songs.map((song, i) => `${i === 0 ? 'Playing:' : `${i}.`} ${song.name} - \`${song.formattedDuration}\``) + .join('\n') + + const embed = new EmbedBuilder() + .setTitle(`Server Queue`) + .setDescription(songs.toString()) + await interaction.reply({ + embeds: [ embed ] + }) +} +async function musicSkip(interaction) { + const queue = interaction.client.distube.getQueue(interaction.guild) + if (!queue) { + return await interaction.reply({ + content: `There is nothing in the queue right now!`, + ephemeral: true + }) + } + try { + const song = await queue.skip() + await interaction.reply({ + content: `Skipped! Now playing:\n${song.name}` + }) + } catch (e) { + await interaction.reply({ + content: e + }) + } +} +module.exports = { + data: new SlashCommandBuilder() + .setName('music') + .setDescription('handles all music related commands') + .addSubcommand(s => + s + .setName('play') + .setDescription('plays music') + .addStringOption(o => o.setName('url').setDescription('youtube url').setRequired(true)) + ).addSubcommand(s => + s + .setName('join') + .setDescription('join default music channel') + ).addSubcommand(s => + s + .setName('leave') + .setDescription('leave default music channel') + ).addSubcommand(s => + s + .setName('volume') + .setDescription('adjust music volume (default: 50%)') + .addNumberOption(o => o.setName('volume').setDescription('choose volume').addChoices( + { name: '100%', value: 100 }, + { name: '90%', value: 90 }, + { name: '80%', value: 80 }, + { name: '70%', value: 70 }, + { name: '60%', value: 60 }, + { name: '50%', value: 50 }, + { name: '40%', value: 40 }, + { name: '30%', value: 30 }, + { name: '20%', value: 20 }, + { name: '10%', value: 10 }, + { name: '0%', value: 0 }, + ).setRequired(true)) + ).addSubcommand(s => + s + .setName('queue') + .setDescription('show current queue') + ).addSubcommand(s => + s + .setName('skip') + .setDescription('skip current song') + ), + async execute(interaction) { + const subcommand = await interaction.options._subcommand + switch (subcommand) { + case 'play': + interaction.deferReply() + musicPlay(interaction) + break; + case 'join': + musicJoin(interaction) + break; + case 'leave': + musicLeave(interaction) + break; + case 'volume': + musicVolume(interaction) + break; + case 'queue': + musicQueue(interaction) + break; + case 'skip': + musicSkip(interaction) + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/commands/nuts/nuts.js b/commands/nuts/nuts.js new file mode 100644 index 0000000..17bd342 --- /dev/null +++ b/commands/nuts/nuts.js @@ -0,0 +1,345 @@ +const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') +const { mClient } = require('../..') +require('dotenv').config() +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } +async function nutsGive(interaction) { + async function tradeWindow(buttonID1, buttonID2) { + const embed = new EmbedBuilder() + .setTitle('Gib Nuss!') + .setDescription(`Willst du wirklich **${amount}** Nüsse an <@${to.id}> senden?`) + .addFields( + { name: `Your Current Balance`, value: `${yourBalance.nuts} (**-${amount}**)`, inline: true }, + { name: `Your New Balance`, value: `${yourBalance.nuts - amount}`, inline: true }, + { name: '\u200B', value: '\u200B' }, + { name: `Their Current Balance`, value: `${theirBalance.nuts} (**+${amount}**)`, inline: true }, + { name: `Their New Balance`, value: `${theirBalance.nuts + amount}`, inline: true } + ) + .setThumbnail(to.displayAvatarURL()) + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('✔') + .setCustomId(buttonID1) + .setStyle(ButtonStyle.Success) + ) + .addComponents( + new ButtonBuilder() + .setLabel('✖') + .setCustomId(buttonID2) + .setStyle(ButtonStyle.Danger) + ) + await interaction.reply({ + embeds: [embed], + components: [row], + ephemeral: true + }) + } + const from = interaction.user + const to = await interaction.options.getUser('target') + var amount = await interaction.options.getNumber('amount') + + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const yourBalance = await nutsColl.findOne({ userID: from.id }) + const theirBalance = await nutsColl.findOne({ userID: to.id }) + if (amount <= 0) { + amount = yourBalance.nuts + return tradeWindow('nuts_give_fake', 'abort') + } + if (yourBalance.nuts < amount) { + return await interaction.reply({ + content: 'Du kannst nicht mehr geben als du hast!', + ephemeral: true + }) + } + return tradeWindow('nuts_give_confirm', 'abort') +} +async function nutsCheck(interaction) { + let target = interaction.options.getUser('target') + let addressing + if (!target) { + target = interaction.user + addressing = `Du hast` + } + + if (!target.globalName) { + addressing = `${target.username} hat` + } else { + addressing = `${target.globalName} hat` + } + + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const nutsData = await nutsColl.findOne({ userID: target.id }) + + let content + if (!nutsData) { + content = `${addressing} noch keine Nüsse gesammelt :(` + } else { + content = `${addressing} bereits **${nutsData.nuts}** Nüsse gesammelt!` + } + + let title = 'Zähle Nüsse' + const embed = new EmbedBuilder() + for (let i = 0; i < 4; i++) { + embed.setTitle(title) + await interaction.editReply({ + embeds: [embed] + }) + title = title + ' .' + await delay(500); + } + embed + .setTitle(content) + .setThumbnail('https://cdn-icons-png.flaticon.com/512/628/628206.png') + + await interaction.editReply({ + embeds: [embed] + }) +} +async function nutsLeaderboard(interaction) { + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('◄') + .setStyle(ButtonStyle.Primary) + .setCustomId('nuts_leaderboard_left') + ) + .addComponents( + new ButtonBuilder() + .setLabel('🧑') + .setStyle(ButtonStyle.Primary) + .setCustomId('nuts_leaderboard_self') + ) + .addComponents( + new ButtonBuilder() + .setLabel('►') + .setStyle(ButtonStyle.Primary) + .setCustomId('nuts_leaderboard_right') + ) + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + let skip = 0 + const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray() + let fields + let placements = skip + 1 + nutsData.forEach((data) => { + fields = (fields ? fields : '') + (`${placements}. <@${data.userID}> : ${data.nuts} Nuts\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Nuts Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await interaction.editReply({ + embeds: [embed], + components: [row] + }) +} +async function nutsStats(interaction) { + const db = mClient.db(process.env.M_DB) + const nStatsColl = db.collection('nut-stats') + const stats = await nStatsColl.find({}).sort({ amount: 1 }).toArray() + let nutMin = { + count: 0, + amount: 0 + } + let nutMax = { + count: 0, + amount: 0 + } + let totalNuts = 0 + let totalCount = 0 + stats.forEach(stat => { + totalCount += stat.count + totalNuts += (stat.count * stat.amount) + if (nutMin.count > stat.count) { nutMin = stat } + if (nutMax.count < stat.count) { nutMax = stat } + }) + let nutAvg = totalNuts / totalCount + const embed = new EmbedBuilder() + .setTitle("Nut Statistic") + .setDescription( + `Total Nut Actions: **${totalCount}**\r\n + Total Nuts nutted: **${totalNuts}**\r\n + Nut Average: **${nutAvg.toFixed(3)}**\r\n + Best Nut: **${nutMax.amount}**\r\n + Worst Nut: **${nutMin.amount}**` + ) + .addFields( + { name: '[0]', value: `x${stats[0].count}`, inline: true }, + { name: '[1]', value: `x${stats[1].count}`, inline: true }, + { name: '[2]', value: `x${stats[2].count}`, inline: true }, + { name: '[3]', value: `x${stats[3].count}`, inline: true }, + { name: '[4]', value: `x${stats[4].count}`, inline: true }, + { name: '[5]', value: `x${stats[5].count}`, inline: true }, + { name: '[6]', value: `x${stats[6].count}`, inline: true }, + { name: '[7]', value: `x${stats[7].count}`, inline: true }, + { name: '[8]', value: `x${stats[8].count}`, inline: true }, + { name: '[9]', value: `x${stats[9].count}`, inline: true } + ) + .setColor(0x51267) + .setTimestamp() + .setThumbnail(interaction.guild.iconURL()) + await interaction.editReply({ + embeds: [embed] + }) +} +async function nutsCooldown(interaction) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('cooldown') + const cooldown = await nutsColl.findOne({ userID: interaction.user.id }) + + let content = `Du kannst wieder nussen! :)` + let thumbnail = 'https://cdn-icons-png.flaticon.com/512/7451/7451659.png' + let title = 'Go Nuts!' + if (cooldown) { + content = ` kannst du wieder nussen! ;)` + thumbnail = 'https://cdn.discordapp.com/attachments/1152723542836772914/1152987472788193361/No-nuts-PhotoRoom.png-PhotoRoom.png' + title = 'To Nut or Not to Nut...' + } + + const embed = new EmbedBuilder() + .setThumbnail(thumbnail) + .setTitle(title) + .setDescription(content) + + await interaction.editReply({ + embeds: [embed] + }) +} +async function nutsNut(interaction) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const cdColl = db.collection('cooldown') + + const cdData = await cdColl.findOne({ userID: interaction.user.id }) + + let content + const images = { + "high": "https://as2.ftcdn.net/v2/jpg/02/24/65/39/1000_F_224653943_r3xltiwJsK6am0mGZE5DTWk1yocUwHLd.jpg", + "normal": 'https://c8.alamy.com/comp/PPPBXK/surprised-pecan-nuts-pile-on-plate-cartoon-PPPBXK.jpg', + "low": 'https://as2.ftcdn.net/v2/jpg/02/24/65/37/1000_F_224653769_ceJk0tq9UT1hSu5FIVUi7BeaN4ucSZGv.jpg', + "none": 'https://cdn4.vectorstock.com/i/1000x1000/87/08/afraid-pecan-nuts-pile-on-plate-cartoon-vector-22028708.jpg', + "onCD": 'https://cdn.discordapp.com/attachments/1152723542836772914/1152987472788193361/No-nuts-PhotoRoom.png-PhotoRoom.png' + } + let image + if (!cdData || cdData.cooldown < (Date.now() / 1000)) { + let cd = Math.floor((Date.now() + 3600000) / 1000) + await cdColl.findOneAndUpdate({ + userID: interaction.user.id + }, { + $set: { cooldown: cd } + }, { + upsert: true + }) + + const amount = Math.floor(Math.random() * 10) + + await nutsColl.findOneAndUpdate({ + userID: interaction.user.id + }, { + $inc: { nuts: amount } + }, { + upsert: true + }) + + if (amount) { + content = `Du hast **${amount}** Nüsse bekommen!` + if (amount > 8) { + image = images["high"] + } else if (amount > 4) { + image = images["normal"] + } else { + image = images["low"] + } + } else { + content = `Du hast leider keine Nüsse bekommen :(` + image = images["none"] + } + } else { + content = `Du kannst erst wieder nussen :(` + image = images["onCD"] + } + + const embed = new EmbedBuilder() + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152991361113538621/png-transparent-subscription-box-label-bag-mysterious-miscellaneous-purple-blue-thumbnail-PhotoRoom.png-PhotoRoom.png') + + await interaction.editReply({ + embeds: [embed] + }) + await delay(1000) + embed.setThumbnail('https://i.pinimg.com/originals/9d/58/37/9d5837c6f0cb8b18be6ddd1e2742472a.gif') + await interaction.editReply({ + embeds: [embed] + }) + + await delay(1000) + embed.setDescription(content) + embed.setThumbnail(image) + await interaction.editReply({ + embeds: [embed] + }) + + +} +module.exports = { + data: new SlashCommandBuilder() + .setName('nuts') + .setDescription('rund um die nuss') + .addSubcommand(s => + s + .setName('give') + .setDescription('gib nuss!!') + .addUserOption(o => o.setName('target').setDescription('wer bekommt da nuts?').setRequired(true)) + .addNumberOption(o => o.setName('amount').setDescription('wie viele?').setRequired(true))) + .addSubcommand(s => + s + .setName('check') + .setDescription('check out deez nuts') + .addUserOption(o => o.setName('target').setDescription('check out those nuts!'))) + .addSubcommand(s => + s + .setName('leaderboard') + .setDescription('wer hat die dicksten Nüsse?')) + .addSubcommand(s => + s + .setName('stats') + .setDescription('wie viele Nüsse wurden genusst, Genosse?')) + .addSubcommand(s => + s + .setName('cooldown') + .setDescription('wie lange bis ich nussen kann?')) + .addSubcommand(s => + s + .setName('nut') + .setDescription('willst du nuss?')), + async execute(interaction) { + switch (interaction.options._subcommand) { + case 'give': + nutsGive(interaction) + break; + case 'check': + await interaction.deferReply() + nutsCheck(interaction) + break; + case 'leaderboard': + await interaction.deferReply() + nutsLeaderboard(interaction) + break; + case 'stats': + await interaction.deferReply() + nutsStats(interaction) + break; + case 'cooldown': + await interaction.deferReply() + nutsCooldown(interaction) + break; + case 'nut': + await interaction.deferReply() + nutsNut(interaction) + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/commands/quotes/quotes.js b/commands/quotes/quotes.js new file mode 100644 index 0000000..709ca21 --- /dev/null +++ b/commands/quotes/quotes.js @@ -0,0 +1,135 @@ +/* +Add +Delete +Random +Random By Person +Direct Search by ID + +Random By Year? +List? +Counter (Leaderboard?) +*/ +const { SlashCommandBuilder, EmbedBuilder } = require('discord.js') +const { mClient } = require('../..') +require('dotenv').config() + +async function quotesAdd(interaction) { + const messageLink = await interaction.options.getString('link') + let temp = messageLink.split('/') + let messageID = temp[temp.length - 1] + let channelID = temp[temp.length - 2] + let guildID = temp[temp.length - 3] + + const guild = await interaction.client.guilds.fetch(guildID) + const channel = await guild.channels.fetch(channelID) + const message = await channel.messages.fetch(messageID) + + var msgData = { + content: message.content, + author: await message.author, + reference: await message.reference, + embed: await message.embeds ? 'embed' : null + } // debug + if (msgData.reference) { + let refMessage = await channel.messages.fetch(msgData.reference.messageId) + var refData = { + content: refMessage.content, + author: await refMessage.author, + embed: await refMessage.embeds ? 'embed' : null + } + } + + const db = mClient.db(process.env.M_DB) + const quotesColl = db.collection('quotes') + const found = await quotesColl.findOne({ messageID: messageID }) + if (found) { return await interaction.reply({ content: 'Quote Already in Database', ephemeral: true }) } + await quotesColl.findOneAndUpdate({ messageID: messageID }, { + $set: { + messageID: messageID, + channelID: channelID, + guildID: guildID + } + }, { upsert: true }) + + var description = '' + if (refData) { + description += `> ${refData.author}` + if (refData.embed) { + description += '*an embed / a command* ' + } + description += `\r\n↳` + } + description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}` + let timestamp = new Date(message.createdTimestamp) + let footer = timestamp.toDateString().toString() + + const embed = new EmbedBuilder() + .setThumbnail(msgData.author.displayAvatarURL()) + .setURL(messageLink) + .setTitle(`Quote #${messageID} Added!`) + .setDescription(description) + .setFooter({ text: footer}) + await interaction.reply({ embeds: [embed] }) +} +async function quotesRemove(interaction) { + +} +async function quotesSearch(interaction) { + +} +async function quotesRandom(interaction) { + +} +async function quotesLeaderboard(interaction) { + +} +module.exports = { + data: new SlashCommandBuilder() + .setName('quotes') + .setDescription('quoten pfoten') + .addSubcommand(s => + s + .setName('add') + .setDescription('add a new quote') + .addStringOption(o => o.setName('link').setDescription('insert message link').setRequired(true))) + .addSubcommand(s => + s + .setName('remove') + .setDescription('remove a quote') + .addStringOption(o => o.setName('id').setDescription('insert message ID').setRequired(true))) + .addSubcommand(s => + s + .setName('search') + .setDescription('search by ID') + .addStringOption(o => o.setName('id').setDescription('insert message ID').setRequired(true))) + .addSubcommand(s => + s + .setName('random') + .setDescription('get a random quote') + .addUserOption(o => o.setName('target').setDescription('by user'))) + .addSubcommand(s => + s + .setName('leaderboard') + .setDescription('see the most used quotes')), + async execute(interaction) { + switch (interaction.options._subcommand) { + case 'add': + quotesAdd(interaction) + break; + case 'remove': + quotesRemove(interaction) + break; + case 'search': + quotesSearch(interaction) + break; + case 'random': + quotesRandom(interaction) + break; + case 'leaderboard': + quotesLeaderboard(interaction) + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/commands/test/ping.js b/commands/test/ping.js new file mode 100644 index 0000000..cd2dde7 --- /dev/null +++ b/commands/test/ping.js @@ -0,0 +1,11 @@ +const { SlashCommandBuilder } = require('discord.js') +module.exports = { + data: new SlashCommandBuilder() + .setName('ping') + .setDescription('returns pong'), + async execute(interaction) { + await interaction.deferReply() + await interaction.editReply('pong!') + await interaction.followUp('another pong!') + } +} \ No newline at end of file diff --git a/events/ClientReady.js b/events/ClientReady.js new file mode 100644 index 0000000..5f08030 --- /dev/null +++ b/events/ClientReady.js @@ -0,0 +1,17 @@ +const { Events, ActivityType } = require('discord.js') + +module.exports = { + name: Events.ClientReady, + once: true, + async execute(client) { + console.log(`Ready! Logged in as ${client.user.tag}`) + client.user.setPresence({ + activities: [{ + name: 'Red Dead Depression', + type: ActivityType.Streaming, + url: 'https://twitch.tv/desq_blocki' + }], + status: 'online' + }) + } +} diff --git a/events/InteractionCreate.js b/events/InteractionCreate.js new file mode 100644 index 0000000..3dc8e34 --- /dev/null +++ b/events/InteractionCreate.js @@ -0,0 +1,58 @@ +const { Events } = require('discord.js') + +module.exports = { + name: Events.InteractionCreate, + once: false, + async execute(interaction) { + if (interaction.isChatInputCommand()) { commandHandler(interaction) }; + if (interaction.isButton()) { buttonHandler(interaction) } + if (interaction.isMentionableSelectMenu()) { selectMenuHandler(interaction)} + if (interaction.isUserSelectMenu()) { selectMenuHandler(interaction) } + } +} +async function commandHandler(interaction) { + 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); + 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 }); + } + } +} +async function buttonHandler(interaction) { + const button = interaction.client.buttons.get(interaction.customId) + if (!button) { return console.error(`No button registered matching ${interaction.customId}.`) } + try { + await button.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 }); + } + } +} +async function selectMenuHandler(interaction) { + const selectMenu = interaction.client.selectMenus.get(interaction.customId) + if (!selectMenu) { return console.error(`No Select Menu registered matching ${interaction.customId}.`) } + try { + await selectMenu.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 }); + } + } +} \ No newline at end of file diff --git a/events/MessageCreate.js b/events/MessageCreate.js new file mode 100644 index 0000000..4e38e1c --- /dev/null +++ b/events/MessageCreate.js @@ -0,0 +1,24 @@ +const { Events } = require('discord.js') +require('dotenv').config() +const { client } = require('../index') +const prefix = process.env.D_Prefix + +module.exports = { + name: Events.MessageCreate, + once: false, + async execute(message) { + if (!message.content.startsWith(prefix) || message.author.bot) return; + + const args = message.content.slice(prefix.length).trim().split(/ +/); + const cmd = args.shift().toLowerCase(); + let command = client.legacyCommands.get(cmd) + if(!command) command = client.legacyCommands.get(client.aliases.get(cmd)) + if(!command) return + try { + client.legacyCommands.get(command.name).execute(message, args) + } catch (error) { + console.error(error) + } + + } +} \ No newline at end of file diff --git a/events/VoiceStateUpdates.js b/events/VoiceStateUpdates.js new file mode 100644 index 0000000..960f7c6 --- /dev/null +++ b/events/VoiceStateUpdates.js @@ -0,0 +1,50 @@ +const { Events, ClientVoiceManager } = require("discord.js"); +const { getVoiceConnection } = require('@discordjs/voice') +require('dotenv').config() +const { client } = require('../index') +const users_in_afk = new Set(); +const delay = ms => new Promise(res => setTimeout(res, ms)); +var connected = false; +const playlist = `https://www.youtube.com/playlist?list=PLjSh2s1ASTgsSdjCgFbpo18RAYF_dHf46` + +module.exports = { + name: Events.VoiceStateUpdate, + once: false, + async execute(oldState, newState) { + const guild = client.guilds.cache.get(process.env.D_GuildID) + const afk_channel = await guild.channels.fetch(guild.afkChannelId) + const real_afk_channel = await guild.channels.fetch(process.env.D_RealTartarosID) + const user = await guild.members.fetch(newState.id) + + if(user.id === process.env.D_ID) return; + + // if someone enters the official AFK channel, move them to one where we can play music + if (newState.channelId === afk_channel.id) { + await delay(1000) + + await user.voice.setChannel(real_afk_channel) + users_in_afk.add(newState.id) + console.log(`${users_in_afk.size} User(s) in Channel`) + + if (!connected) { + connected = true; + await client.distube.voices.join(real_afk_channel) + await client.distube.play(real_afk_channel, "https://www.youtube.com/watch?v=dQw4w9WgXcQ") + const queue = client.distube.getQueue(guild) + await queue.setRepeatMode('Queue') + await queue.setVolume(40) + } + } + + // if someone leaves the real AFK channel, remove them from cache but wait for rejoiners, then leave if none are here + if (oldState.channelId === real_afk_channel.id && oldState.channelId != newState.channelId) { + users_in_afk.delete(oldState.id) + } + + if (users_in_afk.size === 0) { + //leave if empty + await client.distube.voices.leave(real_afk_channel) + connected = false; + } + } +} \ No newline at end of file diff --git a/handlers/buttons.js b/handlers/buttons.js new file mode 100644 index 0000000..6748d39 --- /dev/null +++ b/handlers/buttons.js @@ -0,0 +1,20 @@ +const fs = require('node:fs') +const path = require('node:path') +module.exports = (client) => { + const buttonsFoldersPath = path.join(__dirname, '../buttons'); + const buttonsFolders = fs.readdirSync(buttonsFoldersPath); + let buttonCount = 0 + for (const folder of buttonsFolders) { + const buttonsPath = path.join(buttonsFoldersPath, folder); + const buttonsFiles = fs.readdirSync(buttonsPath).filter(file => file.endsWith('.js')); + for (const file of buttonsFiles) { + buttonCount++ + const filePath = path.join(buttonsPath, file); + const button = require(filePath); + if ('execute' in button) { + client.buttons.set(button.name, button); + } + } + } + console.log(`[${buttonCount}] Button(s) initialized`) +} diff --git a/handlers/commands.js b/handlers/commands.js new file mode 100644 index 0000000..7495ba7 --- /dev/null +++ b/handlers/commands.js @@ -0,0 +1,42 @@ +// ich hab das einfach _commands genannt, damit es beim Startup als erstes initialisiert wird. +const { REST, Routes } = require('discord.js') +const fs = require('node:fs') +const path = require('node:path') + +module.exports = (client) => { + let commands = [] // only used for REST API + const foldersPath = path.join(__dirname, '../commands'); + const commandFolders = fs.readdirSync(foldersPath); + for (const folder of commandFolders) { + // Grab all the command files from the commands directory you created earlier + const commandsPath = path.join(foldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment + for (const file of commandFiles) { + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('data' in command && 'execute' in command) { + commands.push(command.data.toJSON()); + client.commands.set(command.data.name, command); + } else { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); + } + } + } + const rest = new REST().setToken(process.env.D_Token); + (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.applicationGuildCommands(process.env.D_ID, process.env.D_GuildID), + { 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); + } + })(); +} diff --git a/handlers/events.js b/handlers/events.js new file mode 100644 index 0000000..eda2825 --- /dev/null +++ b/handlers/events.js @@ -0,0 +1,18 @@ +const fs = require('node:fs') +const path = require('node:path') +module.exports = (client) => { + 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) + if (event.once) { + client.once(event.name, (...args) => event.execute(...args)) + // added client to commomerate global usage + } else { + client.on(event.name, (...args) => event.execute(...args)) + // added client to commomerate global usage + } + } +} \ No newline at end of file diff --git a/handlers/legacyCommands.js b/handlers/legacyCommands.js new file mode 100644 index 0000000..78575fb --- /dev/null +++ b/handlers/legacyCommands.js @@ -0,0 +1,29 @@ +const fs = require('node:fs') +const path = require('node:path') +module.exports = (client) => { + const legacyFoldersPath = path.join(__dirname, '../legacyCommands'); + const legacyCommandFolders = fs.readdirSync(legacyFoldersPath); + let legacyCount = 0 + let aliasCount = 0 + for (const folder of legacyCommandFolders) { + const commandsPath = path.join(legacyFoldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + for (const file of commandFiles) { + legacyCount++ + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('execute' in command) { + client.legacyCommands.set(command.name, command); + } + if (command.aliases && Array.isArray(command.aliases)) { + command.aliases.forEach(alias => { + aliasCount++ + client.aliases.set(alias, command.name) + }) + } + } + } + console.log(`[${aliasCount}] Aliase(s) initialized`) + console.log(`[${legacyCount}] Legacy Command(s) initialized`) + +} diff --git a/handlers/selectMenus.js b/handlers/selectMenus.js new file mode 100644 index 0000000..73066e9 --- /dev/null +++ b/handlers/selectMenus.js @@ -0,0 +1,20 @@ +const fs = require('node:fs') +const path = require('node:path') +module.exports = (client) => { + const selectMenusFoldersPath = path.join(__dirname, '../selectMenus'); + const selectMenusFolders = fs.readdirSync(selectMenusFoldersPath); + let selectMenuCount = 0 + for (const folder of selectMenusFolders) { + const Path = path.join(selectMenusFoldersPath, folder); + const Files = fs.readdirSync(Path).filter(file => file.endsWith('.js')); + for (const file of Files) { + selectMenuCount++ + const filePath = path.join(Path, file); + const button = require(filePath); + if ('execute' in button) { + client.selectMenus.set(button.name, button); + } + } + } + console.log(`[${selectMenuCount}] Select Menu(s) initialized`) +} diff --git a/index.js b/index.js index e69de29..7a14d1a 100644 --- a/index.js +++ b/index.js @@ -0,0 +1,40 @@ +const { Client, GatewayIntentBits, Collection, Partials } = require('discord.js') +const { MongoClient } = require('mongodb') +const { DisTube } = require('distube'); +const { YtDlpPlugin } = require('@distube/yt-dlp') +require('dotenv').config() +const mClient = new MongoClient(process.env.M_URI) +exports.mClient = mClient; +const fs = require('node:fs') + +const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.GuildPresences, + GatewayIntentBits.GuildMessageReactions, + GatewayIntentBits.GuildVoiceStates, + GatewayIntentBits.DirectMessages, + GatewayIntentBits.MessageContent + ], + partials: [Partials.Channel, Partials.Message, Partials.User, Partials.GuildMember, Partials.Reaction] +}); +exports.client = client + +client.commands = new Collection() // slash commands collection +client.legacyCommands = new Collection() // legacy commands collection +client.aliases = new Collection() // list of command aliases +client.buttons = new Collection() // list of buttons +client.selectMenus = new Collection() // list of selectMenus + +const distube = new DisTube(client, { + plugins: [new YtDlpPlugin({ update: true })], + }); + +client.distube = distube + +fs.readdirSync('./handlers').forEach((handler) => { + require(`./handlers/${handler}`)(client) + }); + +client.login(process.env.D_Token) \ No newline at end of file diff --git a/legacyCommands/nuts/nutsCheck.js b/legacyCommands/nuts/nutsCheck.js new file mode 100644 index 0000000..580dd6a --- /dev/null +++ b/legacyCommands/nuts/nutsCheck.js @@ -0,0 +1,54 @@ +const { EmbedBuilder } = require('discord.js') +const { mClient } = require('../../index') +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } +require('dotenv').config() +module.exports = { + name: 'checknuts', + description: 'get nuts', + aliases: ['chn'], + async execute(message, args) { + var target = message.author + var addressing = `Du hast` + if (args[0]) { + if (!args[0].startsWith('<@' || !args[0].endsWith('>'))) { return message.reply('Invalid User Specification') } + try { + target = await message.guild.members.fetch(args[0].slice(2, -1)) + } catch (error) { + return message.reply({ + content: `User: ${args[0]} nicht gefunden!` + }).then(async (msg) => { + await delay(4000) + message.delete() + msg.delete() + }) + } + + if (target.user.id !== message.author.id) { + if (!target.user.globalName) { + addressing = `${target.user.username} hat` + } else { + addressing = `${target.user.globalName} hat` + } + } + } + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + var nutsData = await nutsColl.findOne({ userID: target.id }) + + let content + if (!nutsData) { + content = `${addressing} noch keine Nüsse gesammelt :(` + } else { + content = `${addressing} bereits **${nutsData.nuts}** Nüsse gesammelt!` + } + + const embed = new EmbedBuilder() + .setTitle('Checknuts!') + .setThumbnail(target.displayAvatarURL()) + .setDescription(content) + + return message.reply({ + embeds: [embed] + }) + } +} \ No newline at end of file diff --git a/legacyCommands/nuts/nutsCooldown.js b/legacyCommands/nuts/nutsCooldown.js new file mode 100644 index 0000000..7cec55d --- /dev/null +++ b/legacyCommands/nuts/nutsCooldown.js @@ -0,0 +1,31 @@ +const { EmbedBuilder } = require('discord.js') +const { mClient } = require('../../index') +require('dotenv').config() +module.exports = { + name: 'nutsCooldown', + description: 'shows nut cooldown', + aliases: ['ncd'], + async execute(message, args) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('cooldown') + const cooldown = await nutsColl.findOne({ userID: message.author.id }) + + let content = `Du kannst wieder nussen! :)` + let thumbnail = 'https://cdn-icons-png.flaticon.com/512/7451/7451659.png' + let title = 'Go Nuts!' + if (cooldown) { + content = ` kannst du wieder nussen! ;)` + thumbnail = 'https://cdn.discordapp.com/attachments/1152723542836772914/1152987472788193361/No-nuts-PhotoRoom.png-PhotoRoom.png' + title = 'To Nut or Not to Nut...' + } + + const embed = new EmbedBuilder() + .setThumbnail(thumbnail) + .setTitle(title) + .setDescription(content) + + await message.reply({ + embeds: [embed] + }) + } +} \ No newline at end of file diff --git a/legacyCommands/nuts/nutsGet.js b/legacyCommands/nuts/nutsGet.js new file mode 100644 index 0000000..b0cf1b3 --- /dev/null +++ b/legacyCommands/nuts/nutsGet.js @@ -0,0 +1,47 @@ +const { mClient } = require('../../index') +require('dotenv').config() +module.exports = { + name: 'nuts', + description: 'get nuts', + aliases: ['n', 'nget', 'nutsget'], + async execute(message, args) { + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const cdColl = db.collection('cooldown') + + const cdData = await cdColl.findOne({ userID: message.author.id }) + + if (!cdData || cdData.cooldown < Date.now() / 1000) { + let cd = Math.floor((Date.now() + 3600000) / 1000) + await cdColl.findOneAndUpdate({ + userID: message.author.id + }, { + $set: { cooldown: cd } + }, { + upsert: true + }) + + const amount = Math.floor(Math.random() * 10) + + await nutsColl.findOneAndUpdate({ + userID: message.author.id + }, { + $inc: { nuts: amount } + }, { + upsert: true + }) + + let content = `Du hast ${amount} Nüsse bekommen! :chestnut:` + if (!amount) { + content = `Du hast leider keine Nüsse bekommen :(` + } + return await message.reply({ + content: content + }) + } else { + return await message.reply({ + content: `Du kannst erst wieder nussen :(`, + }) + } + }, +}; \ No newline at end of file diff --git a/legacyCommands/nuts/nutsGive.js b/legacyCommands/nuts/nutsGive.js new file mode 100644 index 0000000..e6189a9 --- /dev/null +++ b/legacyCommands/nuts/nutsGive.js @@ -0,0 +1,78 @@ +const { EmbedBuilder } = require('discord.js') +const { mClient } = require('../../index') +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } +require('dotenv').config() +module.exports = { + name: 'givenuts', + description: 'give nuts', + aliases: ['gn'], + async execute(message, args) { + const from = message.author + if (args[0] == `<@${message.author.id}>` || !args[0]) { + return message.reply({ + content: "Du musst einen anderen User erwähnen" + }).then(async (msg) => { + await delay(4000) + message.delete() + msg.delete() + }) + } + if (!args[0].startsWith('<@' || !args[0].endsWith('>'))) { return message.reply('Invalid User Specification') } + try { + target = await message.guild.members.fetch(args[0].slice(2, -1)) + } catch (error) { + return message.reply({ + content: `User: ${args[0]} nicht gefunden!` + }).then(async (msg) => { + await delay(4000) + message.delete() + msg.delete() + }) + } + const to = target + + try { + var amount = Number(args[1]) + } catch (error) { + console.log(error) + return message.reply({ + content: 'Du musst eine Menge angeben!' + }).then(async (msg) => { + await delay(4000) + message.delete() + msg.delete() + }) + } + if (!amount) { + return message.reply({content : 'Danke für nichts, du Hu-'}) + } + + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + const yourBalance = await nutsColl.findOne({ userID: from.id }) + if (amount <= 0) { + return await message.reply({ + content: `Hier wird nicht geklaut >:(\r\nDas gibt **${yourBalance.nuts}** Abzug!` + }) + } + if (yourBalance.nuts < amount) { + return await message.reply({ + content: 'Du kannst nicht mehr geben als du hast!', + ephemeral: true + }) + } + var content = `Du sendest **${amount}** Nüsse an <@${target.id}>` + + if (amount == 1) { + content = `Du sendest **eine** Nuss an <@${target.id}>` + } + await nutsColl.findOneAndUpdate({ userID: from.id }, { $inc: { nuts: -amount } }, { upsert: true }) + await nutsColl.findOneAndUpdate({ userID: to.id }, { $inc: { nuts: +amount } }, { upsert: true }) + + const embed = new EmbedBuilder() + .setTitle('Gib Nuss!') + .setDescription(content) + .setThumbnail(target.displayAvatarURL()) + return message.reply({ embeds: [embed] }) + } +} \ No newline at end of file diff --git a/legacyCommands/nuts/nutsLeaderboard.js b/legacyCommands/nuts/nutsLeaderboard.js new file mode 100644 index 0000000..dca79fb --- /dev/null +++ b/legacyCommands/nuts/nutsLeaderboard.js @@ -0,0 +1,47 @@ +const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') +const { mClient } = require('../../index') +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } +require('dotenv').config() +module.exports = { + name: 'nutsleaderboard', + description: 'show nuts leaderboard', + aliases: ['nl', 'tn', 'topnuts'], + async execute(message, args) { + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('◄') + .setStyle(ButtonStyle.Primary) + .setCustomId('nuts_leaderboard_left') + ) + .addComponents( + new ButtonBuilder() + .setLabel('🧑') + .setStyle(ButtonStyle.Primary) + .setCustomId('nuts_leaderboard_self') + ) + .addComponents( + new ButtonBuilder() + .setLabel('►') + .setStyle(ButtonStyle.Primary) + .setCustomId('nuts_leaderboard_right') + ) + const db = mClient.db(process.env.M_DB) + const nutsColl = db.collection('nuts') + let skip = 0 + const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray() + let fields + let placements = skip + 1 + nutsData.forEach((data) => { + fields = (fields ? fields : '') + (`${placements}. <@${data.userID}> : ${data.nuts} Nuts\r\n`) + }) + const embed = new EmbedBuilder() + .setTitle('Nuts Leaderboard') + .setThumbnail('https://cdn.discordapp.com/attachments/1152723542836772914/1152940755539722240/pngwing.com.png') + .setDescription(fields.toString()); + await message.reply({ + embeds: [embed], + components: [row] + }) + } +} diff --git a/legacyCommands/nuts/nutsStats.js b/legacyCommands/nuts/nutsStats.js new file mode 100644 index 0000000..5c67912 --- /dev/null +++ b/legacyCommands/nuts/nutsStats.js @@ -0,0 +1,58 @@ +const { EmbedBuilder } = require('discord.js') +const { mClient } = require('../../index') +function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } +require('dotenv').config() +module.exports = { + name: 'nutsstats', + description: 'shows nuts statistic', + aliases: ['nstat', 'ns'], + async execute(message, args) { + const db = mClient.db(process.env.M_DB) + const nStatsColl = db.collection('nut-stats') + const stats = await nStatsColl.find({}).sort({ amount: 1 }).toArray() + let nutMin = { + count: 0, + amount: 0 + } + let nutMax = { + count: 0, + amount: 0 + } + let totalNuts = 0 + let totalCount = 0 + stats.forEach(stat => { + totalCount += stat.count + totalNuts += (stat.count * stat.amount) + if (nutMin.count > stat.count) { nutMin = stat } + if (nutMax.count < stat.count) { nutMax = stat } + }) + let nutAvg = totalNuts / totalCount + const embed = new EmbedBuilder() + .setTitle("Nut Statistic") + .setDescription( + `Total Nut Actions: **${totalCount}**\r\n + Total Nuts nutted: **${totalNuts}**\r\n + Nut Average: **${nutAvg.toFixed(3)}**\r\n + Best Nut: **${nutMax.amount}**\r\n + Worst Nut: **${nutMin.amount}**` + ) + .addFields( + { name: '[0]', value: `x${stats[0].count}`, inline: true }, + { name: '[1]', value: `x${stats[1].count}`, inline: true }, + { name: '[2]', value: `x${stats[2].count}`, inline: true }, + { name: '[3]', value: `x${stats[3].count}`, inline: true }, + { name: '[4]', value: `x${stats[4].count}`, inline: true }, + { name: '[5]', value: `x${stats[5].count}`, inline: true }, + { name: '[6]', value: `x${stats[6].count}`, inline: true }, + { name: '[7]', value: `x${stats[7].count}`, inline: true }, + { name: '[8]', value: `x${stats[8].count}`, inline: true }, + { name: '[9]', value: `x${stats[9].count}`, inline: true } + ) + .setColor(0x51267) + .setTimestamp() + .setThumbnail(message.guild.iconURL()) + await message.reply({ + embeds: [embed] + }) + } +} \ No newline at end of file diff --git a/legacyCommands/test/interactive.js b/legacyCommands/test/interactive.js new file mode 100644 index 0000000..fc3d3e4 --- /dev/null +++ b/legacyCommands/test/interactive.js @@ -0,0 +1,16 @@ +const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') +module.exports = { + name: 'interactive', + description: 'testing interactive buttons', + async execute(message, args) { + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setLabel('Test') + .setStyle(ButtonStyle.Primary) + .setCustomId('test_button_1') + ) + + await message.reply({ content: 'Here is an interactive button:', components: [row] }); + } +} \ No newline at end of file diff --git a/legacyCommands/test/ping.js b/legacyCommands/test/ping.js new file mode 100644 index 0000000..d416c96 --- /dev/null +++ b/legacyCommands/test/ping.js @@ -0,0 +1,8 @@ +module.exports = { + name: 'ping', + description: 'returns pong!', + aliases: [''], + async execute(message, args) { + message.reply('pong!') + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..65e4e13 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1475 @@ +{ + "name": "arthonor-3", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "arthonor-3", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@discordjs/voice": "^0.17.0", + "@distube/yt-dlp": "^2.0.1", + "discord.js": "^14.15.3", + "distube": "^5.0.2", + "dotenv": "^16.4.5", + "mongodb": "^6.8.0", + "node-pre-gyp": "^0.17.0", + "nodemon": "^3.1.4", + "rebuild": "^0.1.2", + "sodium-native": "^4.1.1" + } + }, + "node_modules/@discordjs/builders": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.2.tgz", + "integrity": "sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==", + "dependencies": { + "@discordjs/formatters": "^0.4.0", + "@discordjs/util": "^1.1.0", + "@sapphire/shapeshift": "^3.9.7", + "discord-api-types": "0.37.83", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/collection": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", + "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", + "engines": { + "node": ">=16.11.0" + } + }, + "node_modules/@discordjs/formatters": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz", + "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==", + "dependencies": { + "discord-api-types": "0.37.83" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/rest": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz", + "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==", + "dependencies": { + "@discordjs/collection": "^2.1.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@sapphire/snowflake": "^3.5.3", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "magic-bytes.js": "^1.10.0", + "tslib": "^2.6.2", + "undici": "6.13.0" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/rest/node_modules/undici": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", + "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==", + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@discordjs/util": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz", + "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==", + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/voice": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.17.0.tgz", + "integrity": "sha512-hArn9FF5ZYi1IkxdJEVnJi+OxlwLV0NJYWpKXsmNOojtGtAZHxmsELA+MZlu2KW1F/K1/nt7lFOfcMXNYweq9w==", + "dependencies": { + "@types/ws": "^8.5.10", + "discord-api-types": "0.37.83", + "prism-media": "^1.3.5", + "tslib": "^2.6.2", + "ws": "^8.16.0" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/ws": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz", + "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==", + "dependencies": { + "@discordjs/collection": "^2.1.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@types/ws": "^8.5.10", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "tslib": "^2.6.2", + "ws": "^8.16.0" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/ws/node_modules/@discordjs/collection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", + "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@distube/yt-dlp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@distube/yt-dlp/-/yt-dlp-2.0.1.tgz", + "integrity": "sha512-9c16lRU6jbyal38UUr5E36+2lp36s0DaJySOtFjuAPgaJkp2xvKvyd+s4rFZSqVQGJO5GOhBiH+HD115SKfKAw==", + "hasInstallScript": true, + "dependencies": { + "dargs": "^7.0.0", + "undici": "^6.18.2" + }, + "funding": { + "url": "https://github.com/skick1234/DisTube?sponsor" + }, + "peerDependencies": { + "distube": "5" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz", + "integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@sapphire/async-queue": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.3.tgz", + "integrity": "sha512-x7zadcfJGxFka1Q3f8gCts1F0xMwCKbZweM85xECGI0hBTeIZJGGCrHgLggihBoprlQ/hBmDR5LKfIPqnmHM3w==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@sapphire/shapeshift": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz", + "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v16" + } + }, + "node_modules/@sapphire/snowflake": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", + "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@types/node": { + "version": "22.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.3.tgz", + "integrity": "sha512-/e0NZtK2gs6Vk2DoyrXSZZ4AlamqTkx0CcKx1Aq8/P4ITlRgU9OtVf5fl+LXkWWJce1M89pkSlH6lJJEnK7bQA==", + "dependencies": { + "undici-types": "~6.11.1" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vladfrangu/async_event_emitter": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.5.tgz", + "integrity": "sha512-J7T3gUr3Wz0l7Ni1f9upgBZ7+J22/Q1B7dl0X6fG+fTsD+H+31DIosMHj4Um1dWQwqbcQ3oQf+YS2foYkDc9cQ==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bson": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/discord-api-types": { + "version": "0.37.83", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", + "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" + }, + "node_modules/discord.js": { + "version": "14.15.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.3.tgz", + "integrity": "sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==", + "dependencies": { + "@discordjs/builders": "^1.8.2", + "@discordjs/collection": "1.5.3", + "@discordjs/formatters": "^0.4.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@discordjs/ws": "^1.1.1", + "@sapphire/snowflake": "3.5.3", + "discord-api-types": "0.37.83", + "fast-deep-equal": "3.1.3", + "lodash.snakecase": "4.1.1", + "tslib": "2.6.2", + "undici": "6.13.0" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/discord.js/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/discord.js/node_modules/undici": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", + "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==", + "engines": { + "node": ">=18.0" + } + }, + "node_modules/distube": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/distube/-/distube-5.0.2.tgz", + "integrity": "sha512-VR+js/RS+sbxQIGaewh1jZtQDeSE1x05V6CFDb7/KATXSln+nUemIh/RTqKPuPeFJhcPcYGdZWPvEliDU/RS/g==", + "dependencies": { + "tiny-typed-emitter": "^2.1.0", + "undici": "^6.18.2" + }, + "engines": { + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/skick1234/DisTube?sponsor" + }, + "peerDependencies": { + "@discordjs/voice": "*", + "discord.js": "14" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, + "node_modules/magic-bytes.js": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", + "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mongodb": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", + "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-pre-gyp": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.17.0.tgz", + "integrity": "sha512-abzZt1hmOjkZez29ppg+5gGqdPLUuJeAEwVPtHYEJgx0qzttCbcKFpxrCQn2HYbwCv2c+7JwH4BgEzFkUGpn4A==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "dependencies": { + "detect-libc": "^1.0.3", + "mkdirp": "^0.5.5", + "needle": "^2.5.2", + "nopt": "^4.0.3", + "npm-packlist": "^1.4.8", + "npmlog": "^4.1.2", + "rc": "^1.2.8", + "rimraf": "^2.7.1", + "semver": "^5.7.1", + "tar": "^4.4.13" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/nodemon": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prism-media": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.5.tgz", + "integrity": "sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==", + "peerDependencies": { + "@discordjs/opus": ">=0.8.0 <1.0.0", + "ffmpeg-static": "^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.8" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + } + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rebuild": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rebuild/-/rebuild-0.1.2.tgz", + "integrity": "sha512-EtDZ5IapND57htCrOOcfH7MzXCQKivzSZUIZIuc8H0xDHfmi9HDBZIyjT7Neh5GcUoxQ6hfsXluC+UrYLgGbZg==", + "dependencies": { + "optimist": "0.3.x" + }, + "bin": { + "rebuild": "cli.js" + }, + "engines": { + "node": ">=0.8.8" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sodium-native": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.1.1.tgz", + "integrity": "sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.8.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/tar/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/ts-mixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/undici": { + "version": "6.19.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.5.tgz", + "integrity": "sha512-LryC15SWzqQsREHIOUybavaIHF5IoL0dJ9aWWxL/PgT1KfqAW5225FZpDUFlt9xiDMS2/S7DOKhFWA7RLksWdg==", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", + "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1804a71 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "arthonor-3", + "version": "1.0.0", + "description": "discord companion", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/DeSqBlocki/Arthonor-3.git" + }, + "keywords": [ + "discord" + ], + "author": "DeSqBlocki", + "license": "ISC", + "bugs": { + "url": "https://github.com/DeSqBlocki/Arthonor-3/issues" + }, + "homepage": "https://github.com/DeSqBlocki/Arthonor-3#readme", + "dependencies": { + "@discordjs/voice": "^0.17.0", + "@distube/yt-dlp": "^2.0.1", + "discord.js": "^14.15.3", + "distube": "^5.0.2", + "dotenv": "^16.4.5", + "mongodb": "^6.8.0", + "node-pre-gyp": "^0.17.0", + "nodemon": "^3.1.4", + "rebuild": "^0.1.2", + "sodium-native": "^4.1.1" + } +} diff --git a/selectMenus/honors/honor_menu_mentionable.js b/selectMenus/honors/honor_menu_mentionable.js new file mode 100644 index 0000000..49b5a3e --- /dev/null +++ b/selectMenus/honors/honor_menu_mentionable.js @@ -0,0 +1,50 @@ +const { EmbedBuilder, ActionRowBuilder, MentionableSelectMenuBuilder, UserSelectMenuBuilder, PermissionFlagsBits } = require("discord.js") +const { mClient } = require("../..") +require('dotenv').config() + +module.exports = { + name: 'honor_menu_mentionable', + description: 'handles honor menu mentionables', + async execute(interaction) { + const embedData = await interaction.message.embeds[0].data + const embed = new EmbedBuilder() + if (!interaction.members) { + embed.setTitle(embedData.title) + .setThumbnail(embedData.thumbnail.url) + .setDescription(embedData.description); + } else { + var target = await interaction.guild.members.fetch(interaction.members.keys().next().value) + var db = mClient.db(process.env.M_DB) + var honorsColl = db.collection('honors') + var theirHonorLevel = await honorsColl.findOne({ userID: target.id }) + + const member = interaction.message.guild.members.cache.get(target.user.id) + const memberRoles = member.roles.cache + .filter((roles) => roles.id !== interaction.message.guild.id) + .map((role) => role.toString()) + // var userHas = member.permissions.toArray() // Scratched Idea for Menu + + const description = String(`${target} - ${target.user.globalName ?? target.user.username} - ${target.user.id}\r\n\r\n${memberRoles}`).replaceAll(',', ' ') + embed.setTitle(`- User Stats -`) + .setDescription(description) + .addFields({ + name: 'Current Honor Level:', value: `${theirHonorLevel?.honors ?? 0}`, inline: true + }) + .setFooter({text: 'Honor Level updaten sich nicht automatisch!'}) + } + const select = new ActionRowBuilder() + .addComponents( + new UserSelectMenuBuilder() + .setCustomId('honor_menu_mentionable') + .setPlaceholder('Select a User') + ) + + + + const row = interaction.message.components[1] + await interaction.update({ + embeds: [embed], + components: [select, row] + }) + } +} \ No newline at end of file