From 41ad8a65749f5d1fe279d3aab44374d003fc9911 Mon Sep 17 00:00:00 2001 From: Tejas Lamba Date: Wed, 28 Jun 2023 12:35:01 +0530 Subject: [PATCH] Add message option and improve handler --- botconfig/components.js | 34 + botconfig/permissions.js | 43 + commands/Info/ping.js | 130 ++ events/guild/interactionCreate.js | 243 ++- events/guild/messageCreate.js | 663 +++++++- .../Info/ping.js => exampleCommand.js | 96 +- handlers/functions.js | 1485 ++++++++++++++--- handlers/messageCommands.js | 30 + handlers/slashCommands.js | 562 +++++-- slashCommands/Info/botinfo.js | 303 ---- slashCommands/Info/commandcount.js | 47 - slashCommands/Info/help.js | 112 -- slashCommands/Info/invite.js | 47 - slashCommands/Info/source.js | 47 - slashCommands/Info/support.js | 43 - slashCommands/Info/uptime.js | 50 - 16 files changed, 2777 insertions(+), 1158 deletions(-) create mode 100644 botconfig/components.js create mode 100644 botconfig/permissions.js create mode 100644 commands/Info/ping.js rename slashCommands/Info/ping.js => exampleCommand.js (50%) create mode 100644 handlers/messageCommands.js delete mode 100644 slashCommands/Info/botinfo.js delete mode 100644 slashCommands/Info/commandcount.js delete mode 100644 slashCommands/Info/help.js delete mode 100644 slashCommands/Info/invite.js delete mode 100644 slashCommands/Info/source.js delete mode 100644 slashCommands/Info/support.js delete mode 100644 slashCommands/Info/uptime.js diff --git a/botconfig/components.js b/botconfig/components.js new file mode 100644 index 0000000..9052378 --- /dev/null +++ b/botconfig/components.js @@ -0,0 +1,34 @@ +const { ButtonBuilder, ButtonStyle, EmbedBuilder, ActionRowBuilder } = require("discord.js"); +const allEmojis = require("./emojis.js"); +module.exports = { + yes: new ButtonBuilder() + .setStyle(ButtonStyle.Success) + .setLabel("Yes") + .setCustomId("yes") + .setEmoji(allEmojis.nova_yes), + no: new ButtonBuilder() + .setStyle(ButtonStyle.Danger) + .setLabel("No") + .setCustomId("no") + .setEmoji(allEmojis.nova_no), + cancel: new ButtonBuilder() + .setStyle(ButtonStyle.Secondary) + .setLabel("Cancel") + .setCustomId("cancel") + .setEmoji(allEmojis.nova_no), + /** + * + * @param {String} url | The URL to redirect to + * @param {String} label | The label of the button, defaults to "Click Here" + * @param {Snowflake} emoji | The emoji to use, defaults to the link emoji + * @returns {Discord.ButtonBuilder} | The button + */ + link: function (url, label = "Click Here", emoji = allEmojis.nova_link) { + return new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel(label) + .setURL(url) + .setEmoji(emoji); + } + +}; \ No newline at end of file diff --git a/botconfig/permissions.js b/botconfig/permissions.js new file mode 100644 index 0000000..e850fb5 --- /dev/null +++ b/botconfig/permissions.js @@ -0,0 +1,43 @@ +module.exports = { + AddReactions: "Add Reactions", + Administrator: "Administrator", + AttachFiles: "Attach files", + BanMembers: "Ban members", + ChangeNickname: "Change nickname", + Connect: "Connect", + CreateInstantInvite: "Create instant invite", + CreatePrivateThreads: "Create private threads", + CreatePublicThreads: "Create public threads", + DeafenMembers: "Deafen members", + EmbedLinks: "Embed links", + KickMembers: "Kick members", + ManageChannels: "Manage channels", + ManageEmojisAndStickers: "Manage emojis and stickers", + ManageEvents: "Manage Events", + ManageGuild: "Manage server", + ManageMessages: "Manage messages", + ManageNicknames: "Manage nicknames", + ManageRoles: "Manage roles", + ManageThreads: "Manage Threads", + ManageWebhooks: "Manage webhooks", + MentionEveryone: "Mention everyone", + ModerateMembers: "Moderate Members", + MoveMembers: "Move members", + MuteMembers: "Mute members", + PrioritySpeaker: "Priority speaker", + ReadMessageHistory: "Read message history", + RequestToSpeak: "Request to Speak", + SendMessages: "Send messages", + SendMessagesInThreads: "Send Messages In Threads", + SendTTSMessages: "Send TTS messages", + Speak: "Speak", + Stream: "Video", + UseApplicationCommands: "Use Application Commands", + UseEmbeddedActivities: "Use Embedded Activities", + UseExternalEmojis: "Use External Emojis", + UseExternalStickers: "Use External Stickers", + UseVAD: "Use voice activity", + ViewAuditLog: "View audit log", + ViewChannel: "View channel", + ViewGuildInsights: "View server insights", + }; \ No newline at end of file diff --git a/commands/Info/ping.js b/commands/Info/ping.js new file mode 100644 index 0000000..2f9b13f --- /dev/null +++ b/commands/Info/ping.js @@ -0,0 +1,130 @@ +const { EmbedBuilder, PermissionFlagsBits } = require("discord.js"); +const config = require("../../botconfig/config.js"); + +const settings = require("../../botconfig/settings.js"); +const mongoose = require("mongoose"); +module.exports = { + name: "ping", //the command name for the Slash Command + slashName: "ping", //the command name for the Slash Command + category: "Info", + description: "Gives you information on how fast the Bot is", //the command description for Slash Command Overview + cooldown: 1, + memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] + botpermissions: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.EmbedLinks], + requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] + alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] + options: [ + //OPTIONAL OPTIONS, make the array empty / dont add this option if you don't need options! + //INFORMATIONS! You can add Options, but mind that the NAME MUST BE LOWERCASED! AND NO SPACES!!!, for the CHOCIES you need to add a array of arrays; [ ["",""] , ["",""] ] + //{"Integer": { name: "ping_amount", description: "How many times do you want to ping?", required: true }}, //to use in the code: interacton.getInteger("ping_amount") + //{"String": { name: "ping_amount", description: "How many times do you want to ping?", required: true }}, //to use in the code: interacton.getString("ping_amount") + //{"User": { name: "ping_a_user", description: "To Ping a user lol", required: false }}, //to use in the code: interacton.getUser("ping_a_user") + //{"Channel": { name: "what_channel", description: "To Ping a Channel lol", required: false }}, //to use in the code: interacton.getChannel("what_channel") + //{"Role": { name: "what_role", description: "To Ping a Role lol", required: false }}, //to use in the code: interacton.getRole("what_role") + //{"IntChoices": { name: "what_ping", description: "What Ping do you want to get?", required: true, choices: [["Bot", 1], ["Discord Api", 2]] }, //here the second array input MUST BE A NUMBER // TO USE IN THE CODE: interacton.getInteger("what_ping") + //here the second array input MUST BE A STRING // TO USE IN THE CODE: interacton.getString("what_ping") + ], + usage: "ping", + slashRun: async (client, interaction) => { + try { + //things u can directly access in an interaction! + const { + member, + channelId, + guildId, + applicationId, + commandName, + deferred, + replied, + ephemeral, + options, + id, + createdTimestamp, + } = interaction; + const { guild } = member; + await interaction.deferReply({ ephemeral: false }).catch((e) => {console.log(e)}); + const ping = Math.floor(createdTimestamp - interaction.createdTimestamp); + const result = await mongoose.connection.db.admin().ping(); + const mongooseSeconds = (result.ok % 60000) / 1000; + var pingSeconds = (ping % 60000) / 1000; + var apiSeconds = (client.ws.ping % 60000) / 1000; + interaction.editReply({ + embeds: [ + new EmbedBuilder() + .setTitle(`🏓 Pong!`) + .setColor(client.embed.color) + .addFields({ + name: `📡 Websocket Latency`, + value: `>>> \`\`\`yml + ${ping}ms (${pingSeconds}s)\`\`\``, + inline: true, + }, + { + name: `🛰 API Latency`, + value: `>>> \`\`\`yml + ${client.ws.ping}ms (${apiSeconds}s)\`\`\``, + inline: true, + }, + { + name: `📂 Database Latency`, + value: `>>> \`\`\`yml + ${result.ok}ms (${mongooseSeconds}s)\`\`\``, + inline: false, + }) + + ] + }); + + } catch (e) { + console.log(e); + } + }, + messageRun: async ( + client, + message, + args, + plusArgs, + cmdUser, + text, + prefix + ) => { + const msg = await message.reply({ + embeds: [ + new EmbedBuilder() + .setDescription(`Calculating ping...`) + .setColor(client.embed.color), + ], + }); + const ping = Math.floor(msg.createdTimestamp - message.createdTimestamp); + const result = await mongoose.connection.db.admin().ping(); + const mongooseSeconds = (result.ok % 60000) / 1000; + var pingSeconds = (ping % 60000) / 1000; + var apiSeconds = (client.ws.ping % 60000) / 1000; + msg.edit({ + embeds: [ + new EmbedBuilder() + .setTitle(`🏓 Pong!`) + .setColor(client.embed.color) + .addFields({ + name: `📡 Websocket Latency`, + value: `>>> \`\`\`yml + ${ping}ms (${pingSeconds}s)\`\`\``, + inline: true, + }, + { + name: `🛰 API Latency`, + value: `>>> \`\`\`yml + ${client.ws.ping}ms (${apiSeconds}s)\`\`\``, + inline: true, + }, + { + name: `📂 Database Latency`, + value: `>>> \`\`\`yml + ${result.ok}ms (${mongooseSeconds}s)\`\`\``, + inline: false, + }) + + ] + }); + }, +}; diff --git a/events/guild/interactionCreate.js b/events/guild/interactionCreate.js index 7201781..50f175b 100644 --- a/events/guild/interactionCreate.js +++ b/events/guild/interactionCreate.js @@ -1,23 +1,32 @@ //Import Modules const config = require(`../../botconfig/config.js`); -const ee = require(`../../botconfig/embed.js`); + const settings = require(`../../botconfig/settings.js`); -const { - onCoolDown, - replacemsg -} = require("../../handlers/functions"); +const { onCoolDown, replacemsg } = require("../../handlers/functions"); const Discord = require("discord.js"); -let prefix = '/'; -module.exports = (client, interaction) => { - if (interaction.isAutocomplete()) { - //DO STUFF HERE - } - // do autocomplete handling +module.exports = async (client, interaction) => { + if (interaction.isAutocomplete()) { + //DO STUFF HERE + } + if (interaction.isContextMenuCommand()) { + //DO STUFF HERE + } + if (interaction.isButton()) { + //DO STUFF HERE + + } + const CategoryName = interaction.commandName; let command = false; try { - if (client.slashCommands.has(CategoryName + interaction.options.getSubcommand())) { - command = client.slashCommands.get(CategoryName + interaction.options.getSubcommand()); + if ( + client.slashCommands.has( + CategoryName + interaction.options.getSubcommand() + ) + ) { + command = client.slashCommands.get( + CategoryName + interaction.options.getSubcommand() + ); } } catch { if (client.slashCommands.has("normal" + CategoryName)) { @@ -25,68 +34,190 @@ module.exports = (client, interaction) => { } } if (command) { - + + //if cmd is restricted check if user is moderator or developer + if (String(command.restricted) === "true") { + return interaction + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ text: client.embed.footertext, iconURL: client.embed.footericon }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description.restricted, + { + command: command, + prefix: prefix, + res: interaction, + } + ) + ), + ], + }) + } + //check if command is disabled, also check if person is owner then let him pass + if (String(command.enabled) === "false") { + return interaction.reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ text: client.embed.footertext, iconURL: client.embed.footericon }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description.disabled, + { + command: command, + prefix: client.config.prefix, + res: interaction, + } + ) + ), + ], + }); + } + + if(command.specialFunction) { + Promise.resolve(command.specialFunction?.(client, interaction)) + } if (onCoolDown(interaction, command)) { return interaction.reply({ ephemeral: true, - embeds: [new Discord.EmbedBuilder() - .setColor(ee.wrongcolor) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setTitle(replacemsg(settings.messages.cooldown, { - prefix: prefix, - command: command, - timeLeft: onCoolDown(interaction, command) - })) - ] + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ text: client.embed.footertext, iconURL: client.embed.footericon }) + .setTitle( + replacemsg(settings.messages.cooldown, { + prefix: client.config.prefix, + command: command, + timeLeft: onCoolDown(interaction, command), + res: interaction, + }) + ), + ], }); } //if Command has specific permission return error - if (command.memberpermissions && command.memberpermissions.length > 0 && !interaction.member.permissions.has(command.memberpermissions)) { + if ( + command.memberpermissions && + command.memberpermissions.length > 0 && + !interaction.member.permissions.has(command.memberpermissions) + ) { + return interaction.reply({ + ephemeral: true, + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ text: client.embed.footertext, iconURL: client.embed.footericon }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .memberpermissions, + { + command: command, + prefix: client.config.prefix, + res: interaction, + } + ) + ), + ], + }); + } + //if bot has not enough permissions return error + if ( + command.botpermissions && + command.botpermissions.length > 0 && + (!interaction.guild.members.me.permissions.has(command.botpermissions) || + interaction.channel + .permissionsFor(interaction.guild.members.me) + .missing(command.botpermissions).length > 0) + ) { return interaction.reply({ ephemeral: true, - embeds: [new Discord.EmbedBuilder() - .setColor(ee.wrongcolor) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setTitle(replacemsg(settings.messages.notallowed_to_exec_cmd.title)) - .setDescription(replacemsg(settings.messages.notallowed_to_exec_cmd.description.memberpermissions, { + content: `${ + settings.messages.notallowed_to_exec_cmd.titlebotperms + }\n> ${replacemsg( + settings.messages.notallowed_to_exec_cmd.description.botpermissions, + { command: command, - prefix: prefix - })) - ] + prefix: prefix, + res: interaction, + } + )}`, }); } //if Command has specific needed roles return error - if (command.requiredroles && command.requiredroles.length > 0 && interaction.member.roles.cache.size > 0 && !interaction.member.roles.cache.some(r => command.requiredroles.includes(r.id))) { + if ( + command.requiredroles && + command.requiredroles.length > 0 && + interaction.member.roles.cache.size > 0 && + !interaction.member.roles.cache.some((r) => + command.requiredroles.includes(r.id) + ) + ) { return interaction.reply({ ephemeral: true, - embeds: [new Discord.EmbedBuilder() - .setColor(ee.wrongcolor) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setTitle(replacemsg(settings.messages.notallowed_to_exec_cmd.title)) - .setDescription(replacemsg(settings.messages.notallowed_to_exec_cmd.description.requiredroles, { - command: command, - prefix: prefix - })) - ] - }) + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ text: client.embed.footertext, iconURL: client.embed.footericon }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .requiredroles, + { + command: command, + prefix: client.config.prefix, + res: interaction, + } + ) + ), + ], + }); } //if Command has specific users return error - if (command.alloweduserids && command.alloweduserids.length > 0 && !command.alloweduserids.includes(interaction.member.id)) { + if ( + command.alloweduserids && + command.alloweduserids.length > 0 && + !command.alloweduserids.includes(interaction.member.id) + ) { return message.channel.send({ ephemeral: true, - embeds: [new Discord.EmbedBuilder() - .setColor(ee.wrongcolor) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setTitle(replacemsg(settings.messages.notallowed_to_exec_cmd.title)) - .setDescription(replacemsg(settings.messages.notallowed_to_exec_cmd.description.alloweduserids, { - command: command, - prefix: prefix - })) - ] + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ text: client.embed.footertext, iconURL: client.embed.footericon }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .alloweduserids, + { + command: command, + prefix: client.config.prefix, + res: interaction, + } + ) + ), + ], }); } //execute the Command - command.run(client, interaction) + command.slashRun(client, interaction); } -} - +}; diff --git a/events/guild/messageCreate.js b/events/guild/messageCreate.js index a0e1fd3..cae5140 100644 --- a/events/guild/messageCreate.js +++ b/events/guild/messageCreate.js @@ -1,22 +1,661 @@ const config = require(`../../botconfig/config.js`); -const ee = require(`../../botconfig/embed.js`); + const settings = require(`../../botconfig/settings.js`); -const { - onCoolDown, - replacemsg -} = require(`../../handlers/functions`); -const Discord = require(`discord.js`); +const { onCoolDown, replacemsg } = require(`../../handlers/functions`); +const Discord = require("discord.js"); +const { discordTimestamp } = require("visa2discord"); +const { createPaginationEmbed } = require("../../handlers/functions.js"); module.exports = async (client, message) => { - if (!message.guild || !message.channel || message.author.bot) return; - if (message.channel.partial) await message.channel.fetch(); - if (message.partial) await message.fetch(); - -} + try { + //if the message is not in a guild (aka in dms), return aka ignore the inputs + if ( + !message.guild || + message.guild.available === false || + !message.channel || + message.webhookId || + message.author.bot + ) + return; + //if the channel is on partial fetch it + if (message.channel?.partial) await message.channel.fetch().catch(() => {}); + if (message.member?.partial) await message.member.fetch().catch(() => {}); + + + // if the message author is a bot, return aka ignore the inputs + if (message.author.bot) return; + const prefix = config.prefix; + const prefixRegex = new RegExp( + `^(<@!?${client.user.id}>|${escapeRegex(prefix)})` + ); + if (!prefixRegex.test(message.content)) return; + const [, mPrefix] = message.content.match(prefixRegex); + const args = message.content + .slice(mPrefix.length) + .trim() + .split(/ +/) + .filter(Boolean); + const cmd = args.length > 0 ? args.shift().toLowerCase() : ""; + const cmdString = args.length > 0 ? cmd + " " + args[0].toLowerCase() : ""; + if (cmd.length == 0 || !cmd) { + if (mPrefix.includes(client.user.id)) { + message.reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.color) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle(`:thumbsup: **My Prefix here, is __\`${prefix}\`__**`), + ], + }); + } + return; + } + let command = + client.commands.get(cmdString) || + client.commands.get(client.aliases.get(cmdString)) || + client.commands.get(cmd) || + client.commands.get(client.aliases.get(cmd)); + if (command?.name.toLowerCase() === cmdString) args.shift(); + if (command) { + //if user data is not there then ask him to accept bot rules and add him in the database + //if cmd is restricted check if user is moderator or developer + if ( + String(command.restricted) === "true" ) { + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .restricted, + { + command: command, + prefix: prefix, + res: message, + } + ) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.notallowed_to_exec_cmd.memberpermissions); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + + //check if command is disabled, also check if person is owner then let him pass + if ( + String(command.enabled) === "false") { + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .disabled, + { + command: command, + prefix: prefix, + res: message, + } + ) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.notallowed_to_exec_cmd.memberpermissions); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + if (command.specialFunction) { + Promise.resolve( + command.specialFunction?.(client, message) + ); + } + if (onCoolDown(message, command)) { + return message.reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.cooldown, { + prefix: prefix, + command: command, + timeLeft: onCoolDown(message, command), + res: message, + }) + ), + ], + }); + } + try { + //if Command has specific permission return error + if ( + command.memberpermissions && + command.memberpermissions.length > 0 && + !message.member.permissions.has(command.memberpermissions) + ) { + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .memberpermissions, + { + command: command, + prefix: prefix, + res: message, + } + ) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.notallowed_to_exec_cmd.memberpermissions); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //if bot needs specific permissions return error + if ( + command.botpermissions && + command.botpermissions.length > 0 && + (!message.guild.members.me.permissions.has(command.botpermissions) || + message.channel + .permissionsFor(message.guild.members.me) + .missing(command.botpermissions).length > 0) + ) { + return message + .reply({ + content: `${ + settings.messages.notallowed_to_exec_cmd.titlebotperms + }\n> ${replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .botpermissions, + { + command: command, + prefix: prefix, + res: message, + } + )}`, + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.notallowed_to_exec_cmd.memberpermissions); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //if Command has specific needed roles return error + if ( + command.requiredroles && + command.requiredroles.length > 0 && + message.member.roles.cache.size > 0 && + !message.member.roles.cache.some((r) => + command.requiredroles.includes(r.id) + ) + ) { + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .requiredroles, + { + command: command, + prefix: prefix, + res: message, + } + ) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.notallowed_to_exec_cmd.requiredroles); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //if Command has specific users return error + if ( + command.alloweduserids && + command.alloweduserids.length > 0 && + !command.alloweduserids.includes(message.author.id) + ) { + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.notallowed_to_exec_cmd.title) + ) + .setDescription( + replacemsg( + settings.messages.notallowed_to_exec_cmd.description + .alloweduserids, + { + command: command, + prefix: prefix, + res: message, + } + ) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.notallowed_to_exec_cmd.alloweduserids); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //if command has minimum args, and user dont entered enough, return error + if ( + command.minargs && + command.minargs > 0 && + args.length < command.minargs + ) { + const embed = new Discord.EmbedBuilder() + .setColor(client.embed.color) + .setTitle(`Detailed Information about: \`${command.name}\``); + + if (command.aliases && command.aliases.length > 0) + embed.addFields({ + name: "**Aliases**", + value: command.aliases.map((alias) => `\`${alias}\``).join(", "), + }); + + embed.addFields({ + name: "**Cooldown**", + value: command.cooldown + ? `\`${command.cooldown} Seconds\`` + : `\`${settings.default_cooldown_in_sec} Second\``, + }); + + if (command.usage) + embed.addFields({ + name: "**Usage**", + value: `\`${prefix}${command.usage}\``, + }); + + embed.setDescription(`${Discord.codeBlock( + "diff", + `- [] = optional argument +- <> = required argument +- Do NOT type these when using commands!` + )} + > ${command.description}`); + return message + .reply({ + embeds: [embed], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.minargs); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //if command has maximum args, and user enters too many, return error + if ( + command.maxargs && + command.maxargs > 0 && + args.length > command.maxargs + ) { + const embed = new Discord.EmbedBuilder() + .setColor(client.embed.color) + .setTitle(`Detailed Information about: \`${command.name}\``); + + if (command.aliases && command.aliases.length > 0) + embed.addFields({ + name: "**Aliases**", + value: command.aliases.map((alias) => `\`${alias}\``).join(", "), + }); + + embed.addFields({ + name: "**Cooldown**", + value: command.cooldown + ? `\`${command.cooldown} Seconds\`` + : `\`${settings.default_cooldown_in_sec} Second\``, + }); + + if (command.usage) + embed.addFields({ + name: "**Usage**", + value: `\`${prefix}${command.usage}\``, + }); + + embed.setDescription(`${Discord.codeBlock( + "diff", + `- [] = optional argument +- <> = required argument +- Do NOT type these when using commands!` + )} + > ${command.description}`); + return message + .reply({ + embeds: [embed], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.maxargs); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + + //if command has minimum args (splitted with "++"), and user dont entered enough, return error + if ( + command.minplusargs && + command.minplusargs > 0 && + args.join(" ").split("++").filter(Boolean).length < + command.minplusargs + ) { + const embed = new Discord.EmbedBuilder() + .setColor(client.embed.color) + .setTitle(`Detailed Information about: \`${command.name}\``); + + if (command.aliases && command.aliases.length > 0) + embed.addFields({ + name: "**Aliases**", + value: command.aliases.map((alias) => `\`${alias}\``).join(", "), + }); + + embed.addFields({ + name: "**Cooldown**", + value: command.cooldown + ? `\`${command.cooldown} Seconds\`` + : `\`${settings.default_cooldown_in_sec} Second\``, + }); + + if (command.usage) + embed.addFields({ + name: "**Usage**", + value: `\`${prefix}${command.usage}\``, + }); + + embed.setDescription(`${Discord.codeBlock( + "diff", + `- [] = optional argument +- <> = required argument +- Do NOT type these when using commands!` + )} + > ${command.description}`); + return message + .reply({ + embeds: [embed], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.minplusargs); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //if command has maximum args (splitted with "++"), and user enters too many, return error + if ( + command.maxplusargs && + command.maxplusargs > 0 && + args.join(" ").split("++").filter(Boolean).length > + command.maxplusargs + ) { + const embed = new Discord.EmbedBuilder() + .setColor(client.embed.color) + .setTitle(`Detailed Information about: \`${command.name}\``); + + if (command.aliases && command.aliases.length > 0) + embed.addFields({ + name: "**Aliases**", + value: command.aliases.map((alias) => `\`${alias}\``).join(", "), + }); + + embed.addFields({ + name: "**Cooldown**", + value: command.cooldown + ? `\`${command.cooldown} Seconds\`` + : `\`${settings.default_cooldown_in_sec} Second\``, + }); + + if (command.usage) + embed.addFields({ + name: "**Usage**", + value: `\`${prefix}${command.usage}\``, + }); + + embed.setDescription(`${Discord.codeBlock( + "diff", + `- [] = optional argument +- <> = required argument +- Do NOT type these when using commands!` + )} + > ${command.description}`); + return message + .reply({ + embeds: [embed], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, settings.timeout.maxplusargs); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + //run the command with the parameters: client, message, args, Cmduser, text, prefix, + command.messageRun( + client, + message, + args, + args.join(" ").split("++").filter(Boolean), + message.member, + args.join(" "), + prefix + ); + } catch (error) { + if (settings.somethingwentwrong_cmd) { + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.somethingwentwrong_cmd.title, { + prefix: prefix, + command: command, + res: message, + }) + ) + .setDescription( + replacemsg( + settings.messages.somethingwentwrong_cmd.description, + { + error: error, + prefix: prefix, + command: command, + res: message, + } + ) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch((e) => { + console.log(String(e).grey); + }); + }, 4000); + }) + .catch((e) => { + console.log(String(e).grey); + }); + } + } + } //if the command is not found send an info msg + else { + if ( + client.commands.filter((cmdss) => cmdss.name.startsWith(cmd)).size > 1 + ) { + const cmdList = client.commands + .filter((cmdss) => cmdss.name.startsWith(cmd)) + .map((cmdss) => { + return `\`${cmdss.name}\` \n ${cmdss.description}`; + }); + await createPaginationEmbed(`\`${cmd}\``, cmdList, message); + return; + } + return message + .reply({ + embeds: [ + new Discord.EmbedBuilder() + .setColor(client.embed.wrongcolor) + .setFooter({ + text: client.embed.footertext, + iconURL: client.embed.footericon, + }) + .setTitle( + replacemsg(settings.messages.unknown_cmd, { + prefix: prefix, + }) + ), + ], + }) + .then((msg) => { + setTimeout(() => { + msg.delete().catch(() => { + }); + }, 4000); + }) + .catch(() => { + }); + } + } catch (e) { + console.log(e); + } +}; function escapeRegex(str) { try { return str.replace(/[.*+?^${}()|[\]\\]/g, `\\$&`); } catch { - return str + return str; + } +} + +function formatRelativeTime(timestamp) { + const currentTime = new Date().getTime(); + const timeDifference = currentTime - timestamp; + + // Convert time difference to seconds + const seconds = Math.floor(timeDifference / 1000); + + if (seconds < 60) { + return seconds + " seconds"; + } else if (seconds < 3600) { + const minutes = Math.floor(seconds / 60); + return minutes + " minutes"; + } else if (seconds < 86400) { + const hours = Math.floor(seconds / 3600); + return hours + " hours"; + } else { + const days = Math.floor(seconds / 86400); + return days + " days"; } } diff --git a/slashCommands/Info/ping.js b/exampleCommand.js similarity index 50% rename from slashCommands/Info/ping.js rename to exampleCommand.js index d5cf10d..1fe3515 100644 --- a/slashCommands/Info/ping.js +++ b/exampleCommand.js @@ -1,17 +1,24 @@ const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -const ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); + EmbedBuilder, + ActionRowBuilder, + ButtonStyle, + ButtonBuilder, + PermissionFlagsBits + } = require("discord.js"); module.exports = { name: "ping", //the command name for the Slash Command - category: "Info", + slashName: "ping", //the command name for the Slash Command + category: "Info", + enabled: true, + aliases: [], //the command aliases [OPTIONAL] description: "Gives you information on how fast the Bot is", //the command description for Slash Command Overview cooldown: 1, - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] + restricted: false, //if the command is restricted [OPTIONAL] - [OPTIONAL = Permissions] + memberpermissions: [PermissionFlagsBits.SendMessages], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] + botpermissions: [PermissionFlagsBits.SendMessages, PermissionFlagsBits.EmbedLinks], //Permission needed by the Bot to execute this Command [OPTIONAL] requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] + specialFunction: (client, res) => {}, //Special function to do something after the Command got triggered [OPTIONAL] options: [ //OPTIONAL OPTIONS, make the array empty / dont add this option if you don't need options! //INFORMATIONS! You can add Options, but mind that the NAME MUST BE LOWERCASED! AND NO SPACES!!!, for the CHOCIES you need to add a array of arrays; [ ["",""] , ["",""] ] //{"Integer": { name: "ping_amount", description: "How many times do you want to ping?", required: true }}, //to use in the code: interacton.getInteger("ping_amount") @@ -20,19 +27,26 @@ module.exports = { //{"Channel": { name: "what_channel", description: "To Ping a Channel lol", required: false }}, //to use in the code: interacton.getChannel("what_channel") //{"Role": { name: "what_role", description: "To Ping a Role lol", required: false }}, //to use in the code: interacton.getRole("what_role") //{"IntChoices": { name: "what_ping", description: "What Ping do you want to get?", required: true, choices: [["Bot", 1], ["Discord Api", 2]] }, //here the second array input MUST BE A NUMBER // TO USE IN THE CODE: interacton.getInteger("what_ping") - { - "StringChoices": { - name: "what_ping", - description: "What Ping do you want to get?", - required: false, - choices: [ - ["Bot", "botping"], - ["Discord Api", "api"] - ] - } - }, //here the second array input MUST BE A STRING // TO USE IN THE CODE: interacton.getString("what_ping") + // { + // "StringChoices": { + // name: "what_ping", + // description: "What Ping do you want to get?", + // required: false, + // choices: [ + // ["Bot", "botping"], + // ["Discord Api", "api"] + // ] + // } + // }, //here the second array input MUST BE A STRING // TO USE IN THE CODE: interacton.getString("what_ping") ], - run: async (client, interaction) => { + usage: "", //the Command usage [OPTIONAL] + minargs: 0, // minimum args for the message, 0 == none [OPTIONAL] + maxargs: 0, // maximum args for the message, 0 == none [OPTIONAL] + minplusargs: 0, // minimum args for the message, splitted with "++" , 0 == none [OPTIONAL] + maxplusargs: 0, // maximum args for the message, splitted with "++" , 0 == none [OPTIONAL] + argsmissing_message: "", //Message if the user has not enough args / not enough plus args, which will be sent, leave emtpy / dont add, if you wanna use command.usage or the default message! [OPTIONAL] + argstoomany_message: "", //Message if the user has too many / not enough args / too many plus args, which will be sent, leave emtpy / dont add, if you wanna use command.usage or the default message! [OPTIONAL] + slashRun: async (client, interaction) => { try { //things u can directly access in an interaction! const { @@ -52,46 +66,20 @@ module.exports = { guild } = member; //let IntOption = options.getInteger("OPTIONNAME"); //same as in IntChoices - const StringOption = options.getString("what_ping"); //same as in StringChoices + //const StringOption = options.getString("what_ping"); //same as in StringChoices //let UserOption = options.getUser("OPTIONNAME"); //let ChannelOption = options.getChannel("OPTIONNAME"); //let RoleOption = options.getRole("OPTIONNAME"); - if (StringOption) { - if (StringOption == "botping") { - await interaction.reply({ - ephemeral: true, - content: `${client.allEmojis.loading} Getting the Bot Ping...`, - ephemeral: true - }); - interaction.editReply({ - ephemeral: true, - content: `${client.allEmojis.ping} Bot Ping: \`${Math.floor((Date.now() - createdTimestamp) - 2 * Math.floor(client.ws.ping))} ms\``, - ephemeral: true - }) - } - //Other Option is API so we are alright - else { - interaction.reply({ - ephemeral: true, - content: `${client.allEmojis.ping} Api Ping: \`${Math.floor(client.ws.ping)} ms\``, - ephemeral: true - }) - } - } else { - await interaction.reply({ - ephemeral: true, - content: `${client.allEmojis.loading} Getting the Bot Ping...`, - ephemeral: true - }); - interaction.editReply({ - ephemeral: true, - content: `${client.allEmojis.ping} Bot Ping: \`${Math.floor((Date.now() - createdTimestamp) - 2 * Math.floor(client.ws.ping))} ms\`\n\n${client.allEmojis.ping} Api Ping: \`${Math.floor(client.ws.ping)} ms\``, - ephemeral: true - }) - } } catch (e) { console.log(String(e.stack).bgRed) } - } + }, + messageRun: async (client, message, args, plusArgs, cmdUser, text, prefix) => { + try { + + } catch (e) { + console.log(String(e.stack).bgRed) + } + } } diff --git a/handlers/functions.js b/handlers/functions.js index 08210b2..55c9feb 100644 --- a/handlers/functions.js +++ b/handlers/functions.js @@ -1,11 +1,12 @@ -const { - EmbedBuilder, - Collection -} = require("discord.js"); -const Discord = require("discord.js") +const { EmbedBuilder, Collection, PermissionFlagsBits, PermissionsBitField, formatEmoji, userMention } = require("discord.js"); +const Discord = require("discord.js"); const config = require("../botconfig/config.js"); +const permissions = require("../botconfig/permissions.js"); const ee = require("../botconfig/embed.js"); const settings = require("../botconfig/settings.js"); +const sourcebin = require("sourcebin_js"); +const allEmojis = require("../botconfig/emojis.js"); + //EXPORT ALL FUNCTIONS module.exports.nFormatter = nFormatter; module.exports.shuffle = shuffle; @@ -25,20 +26,31 @@ module.exports.GetRole = GetRole; module.exports.GetGlobalUser = GetGlobalUser; module.exports.parseMilliseconds = parseMilliseconds; module.exports.onCoolDown = onCoolDown; - +module.exports.GetGlobalUser = GetGlobalUser; module.exports.formatDate = formatDate; - -module.exports.replacemsg = replacedefaultmessages +module.exports.generateCaptcha = generateCaptcha; +module.exports.create_transcript_buffer = create_transcript_buffer; +module.exports.replacemsg = replacedefaultmessages; +module.exports.createPaginationEmbed = createPaginationEmbed; +module.exports.createEmbed = createEmbed; +module.exports.smartSlice = smartSlice; +module.exports.postToBin = postToBin; +module.exports.containsLink = containsLink; +module.exports.containsDiscordInvite = containsDiscordInvite; +module.exports.parsePermissions = parsePermissions; +module.exports.gReRoll = gReRoll; +module.exports.generateGiveawayEmbed = generateGiveawayEmbed; +module.exports.disableButtons = disableButtons /** - * + * * @param {*} text The Text that should be replaced, usually from /botconfig/settings.json - * @param {*} options Those Options are what are needed for the replaceMent! Valid ones are: { + * @param {*} options Those Options are what are needed for the replaceMent! Valid ones are: { * timeLeft: "", - * commandmemberpermissions: { memberpermissions: [] }, - * commandalloweduserids: { alloweduserids: [] }, - * commandrequiredroles: { requiredroles: [] }, - * commandname: { name: "" }, - * commandaliases: { aliases: [] }, + * commandmemberpermissions: { memberpermissions: [] }, + * commandalloweduserids: { alloweduserids: [] }, + * commandrequiredroles: { requiredroles: [] }, + * commandname: { name: "" }, + * commandaliases: { aliases: [] }, * prefix: "", * errormessage: { message: "" } * errorstack: { stack: STACK } @@ -47,47 +59,130 @@ module.exports.replacemsg = replacedefaultmessages * @returns STRING */ function replacedefaultmessages(text, o = {}) { - if (!text || text == undefined || text == null) throw "No Text for the replacedefault message added as First Parameter"; - const options = Object(o) - if (!options || options == undefined || options == null) return String(text) + if (!text || text == undefined || text == null) + throw "No Text for the replacedefault message added as First Parameter"; + const options = Object(o); + if (!options || options == undefined || options == null) return String(text); return String(text) - .replace(/%{timeleft}%/gi, options && options.timeLeft ? options.timeLeft.toFixed(1) : "%{timeleft}%") - .replace(/%{commandname}%/gi, options && options.command && options.command.name ? options.command.name : "%{commandname}%") - .replace(/%{commandaliases}%/gi, options && options.command && options.command.aliases ? options.command.aliases.map(v => `\`${v}\``).join(",") : "%{commandaliases}%") - .replace(/%{prefix}%/gi, options && options.prefix ? options.prefix : "%{prefix}%") - .replace(/%{commandmemberpermissions}%/gi, options && options.command && options.command.memberpermissions ? options.command.memberpermissions.map(v => `\`${v}\``).join(",") : "%{commandmemberpermissions}%") - .replace(/%{commandalloweduserids}%/gi, options && options.command && options.command.alloweduserids ? options.command.alloweduserids.map(v => `<@${v}>`).join(",") : "%{commandalloweduserids}%") - .replace(/%{commandrequiredroles}%/gi, options && options.command && options.command.requiredroles ? options.command.requiredroles.map(v => `<@&${v}>`).join(",") : "%{commandrequiredroles}%") - .replace(/%{errormessage}%/gi, options && options.error && options.error.message ? options.error.message : options && options.error ? options.error : "%{errormessage}%") - .replace(/%{errorstack}%/gi, options && options.error && options.error.stack ? options.error.stack : options && options.error && options.error.message ? options.error.message : options && options.error ? options.error : "%{errorstack}%") - .replace(/%{error}%/gi, options && options.error ? options.error : "%{error}%") + .replace( + /%{timeleft}%/gi, + options && options.timeLeft ? options.timeLeft.toFixed(1) : "%{timeleft}%" + ) + .replace( + /%{commandname}%/gi, + options && options.command && options.command.name + ? options.command.name + : "%{commandname}%" + ) + .replace( + /%{commandaliases}%/gi, + options && options.command && options.command.aliases + ? options.command.aliases.map((v) => `\`${v}\``).join(",") + : "%{commandaliases}%" + ) + .replace( + /%{prefix}%/gi, + options && options.prefix ? options.prefix : "%{prefix}%" + ) + .replace( + /%{commandmemberpermissions}%/gi, + options && options.command && options.command.memberpermissions + ? parsePermissions(removeDuplicatesPerms(new PermissionsBitField(options.command.memberpermissions).toArray(), options.res.member.permissions.toArray())) + : "%{commandmemberpermissions}%" + ) + .replace( + /%{commandbotpermissions}%/gi, + options && options.command && options.command.botpermissions + ? parsePermissions(removeDuplicatesPerms(new PermissionsBitField(options.command.botpermissions).toArray(), options.res.guild.members.me.permissions.toArray())) + : "%{commandbotpermissions}%" + ) + .replace( + /%{commandalloweduserids}%/gi, + options && options.command && options.command.alloweduserids + ? options.command.alloweduserids.map((v) => `<@${v}>`).join(",") + : "%{commandalloweduserids}%" + ) + .replace( + /%{commandrequiredroles}%/gi, + options && options.command && options.command.requiredroles + ? options.command.requiredroles.map((v) => `<@&${v}>`).join(",") + : "%{commandrequiredroles}%" + ) + .replace( + /%{errormessage}%/gi, + options && options.error && options.error.message + ? options.error.message + : options && options.error + ? options.error + : "%{errormessage}%" + ) + .replace( + /%{errorstack}%/gi, + options && options.error && options.error.stack + ? options.error.stack + : options && options.error && options.error.message + ? options.error.message + : options && options.error + ? options.error + : "%{errorstack}%" + ) + .replace( + /%{error}%/gi, + options && options.error ? options.error : "%{error}%" + ); } /** - * + * @param {Number} num Length of the captcha + * @returns STRING + * @description Makes a captcha + * @example generateCaptcha() // -> abcd12 + */ + +function generateCaptcha(length) { + let charset = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; + let retVal = ""; + + for (let i = 0; i < length; i++) { + retVal += charset.charAt(Math.floor(Math.random() * charset.length)); + } + + return retVal; +} + +/** + * * @param {*} message A DiscordMessage, with the client, information * @param {*} command The Command with the command.name * @returns BOOLEAN */ function onCoolDown(message, command) { - if (!message || !message.client) throw "No Message with a valid DiscordClient granted as First Parameter"; - if (!command || !command.name) throw "No Command with a valid Name granted as Second Parameter"; + if (!message || !message.client) + throw "No Message with a valid DiscordClient granted as First Parameter"; + if (!command || !command.name) + throw "No Command with a valid Name granted as Second Parameter"; + if (settings.ownerIDS.includes(message.author?.id || message.member?.id)) + return false; const client = message.client; - if (!client.cooldowns.has(command.name)) { //if its not in the cooldown, set it too there + if (!client.cooldowns.has(command.name)) { + //if its not in the cooldown, set it too there client.cooldowns.set(command.name, new Collection()); } const now = Date.now(); //get the current time const timestamps = client.cooldowns.get(command.name); //get the timestamp of the last used commands - const cooldownAmount = (command.cooldown || settings.default_cooldown_in_sec) * 1000; //get the cooldownamount of the command, if there is no cooldown there will be automatically 1 sec cooldown, so you cannot spam it^^ - if (timestamps.has(message.member.id)) { //if the user is on cooldown + const cooldownAmount = + (command.cooldown || settings.default_cooldown_in_sec) * 1000; //get the cooldownamount of the command, if there is no cooldown there will be automatically 1 sec cooldown, so you cannot spam it^^ + if (timestamps.has(message.member.id)) { + //if the user is on cooldown const expirationTime = timestamps.get(message.member.id) + cooldownAmount; //get the amount of time he needs to wait until he can run the cmd again - if (now < expirationTime) { //if he is still on cooldonw + if (now < expirationTime) { + //if he is still on cooldonw const timeLeft = (expirationTime - now) / 1000; //get the lefttime //return true - return timeLeft - } - else { + return timeLeft; + } else { //if he is not on cooldown, set it to the cooldown timestamps.set(message.member.id, now); //set a timeout function with the cooldown, so it gets deleted later on again @@ -95,8 +190,7 @@ function onCoolDown(message, command) { //return false aka not on cooldown return false; } - } - else { + } else { //if he is not on cooldown, set it to the cooldown timestamps.set(message.member.id, now); //set a timeout function with the cooldown, so it gets deleted later on again @@ -107,13 +201,13 @@ function onCoolDown(message, command) { } /** - * + * * @param {*} milliseconds NUMBER | TIME IN MILLISECONDS * @returns Object of Formatted Time in Days to nanoseconds */ function parseMilliseconds(milliseconds) { - if (typeof milliseconds !== 'number') { - throw new TypeError('Expected a number'); + if (typeof milliseconds !== "number") { + throw new TypeError("Expected a number"); } return { @@ -123,12 +217,12 @@ function parseMilliseconds(milliseconds) { seconds: Math.trunc(milliseconds / 1000) % 60, milliseconds: Math.trunc(milliseconds) % 1000, microseconds: Math.trunc(milliseconds * 1000) % 1000, - nanoseconds: Math.trunc(milliseconds * 1e6) % 1000 + nanoseconds: Math.trunc(milliseconds * 1e6) % 1000, }; } /** - * + * * @param {*} string A WHOLE TEXT, checks if there is a URL IN IT * @returns BOOLEAN/THE URL */ @@ -145,10 +239,10 @@ function isValidURL(string) { } } return url; -}; +} /** - * + * * @param {*} message a DISCORDMESSAGE with the Content and guild and client information * @param {*} arg //a argument, for search for example * @returns BOOLEAN/DISCORDUSER @@ -156,38 +250,55 @@ function isValidURL(string) { function GetUser(message, arg) { var errormessage = ":x: I failed finding that User..."; return new Promise(async (resolve, reject) => { - var args = arg, client = message.client; - if (!client || !message) return reject("CLIENT IS NOT DEFINED") - if (!args || args == null || args == undefined) args = message.content.trim().split(/ +/).slice(1); + var args = arg, + client = message.client; + if (!client || !message) return reject("CLIENT IS NOT DEFINED"); + if (!args || args == null || args == undefined) + args = message.content.trim().split(/ +/).slice(1); let user = message.mentions.users.first(); if (!user && args[0] && args[0].length == 18) { - user = await client.users.fetch(args[0]) - if (!user) return reject(errormessage) + user = await client.users.fetch(args[0]); + if (!user) return reject(errormessage); return resolve(user); - } - else if (!user && args[0]) { - let alluser = message.guild.members.cache.map(member => String(member.user.tag).toLowerCase()) - user = alluser.find(user => user.startsWith(args.join(" ").toLowerCase())) - user = message.guild.members.cache.find(me => String(me.user.tag).toLowerCase() == user) + } else if (!user && args[0]) { + let alluser = message.guild.members.cache.map((member) => + String(member.user.tag).toLowerCase() + ); + user = alluser.find((user) => + user.startsWith(args.join(" ").toLowerCase()) + ); + user = message.guild.members.cache.find( + (me) => String(me.user.tag).toLowerCase() == user + ); if (!user || user == null || !user.id) { - alluser = message.guild.members.cache.map(member => String(member.displayName + "#" + member.user.discriminator).toLowerCase()) - user = alluser.find(user => user.startsWith(args.join(" ").toLowerCase())) - user = message.guild.members.cache.find(me => String(me.displayName + "#" + me.user.discriminator).toLowerCase() == user) - if (!user || user == null || !user.id) return reject(errormessage) + alluser = message.guild.members.cache.map((member) => + String( + member.displayName + "#" + member.user.discriminator + ).toLowerCase() + ); + user = alluser.find((user) => + user.startsWith(args.join(" ").toLowerCase()) + ); + user = message.guild.members.cache.find( + (me) => + String( + me.displayName + "#" + me.user.discriminator + ).toLowerCase() == user + ); + if (!user || user == null || !user.id) return reject(errormessage); } - user = await client.users.fetch(user.user.id) - if (!user) return reject(errormessage) + user = await client.users.fetch(user.user.id); + if (!user) return reject(errormessage); return resolve(user); - } - else { + } else { user = message.mentions.users.first() || message.author; return resolve(user); } - }) + }); } /** - * + * * @param {*} message a DISCORDMESSAGE with the Content and guild and client information * @param {*} arg //a argument, for search for example * @returns BOOLEAN/GUILDROLE @@ -195,33 +306,42 @@ function GetUser(message, arg) { function GetRole(message, arg) { var errormessage = ":x: I failed finding that Role..."; return new Promise(async (resolve, reject) => { - var args = arg, client = message.client; - if (!client || !message) return reject("CLIENT IS NOT DEFINED") - if (!args || args == null || args == undefined) args = message.content.trim().split(/ +/).slice(1); - let user = message.mentions.roles.filter(role => role.guild.id == message.guild.id).first(); + var args = arg, + client = message.client; + if (!client || !message) return reject("CLIENT IS NOT DEFINED"); + if (!args || args == null || args == undefined) + args = message.content.trim().split(/ +/).slice(1); + let user = message.mentions.roles + .filter((role) => role.guild.id == message.guild.id) + .first(); if (!user && args[0] && args[0].length == 18) { - user = message.guild.roles.cache.get(args[0]) - if (!user) return reject(errormessage) + user = message.guild.roles.cache.get(args[0]); + if (!user) return reject(errormessage); return resolve(user); - } - else if (!user && args[0]) { - let alluser = message.guild.roles.cache.map(role => String(role.name).toLowerCase()) - user = alluser.find(r => r.split(" ").join("").includes(args.join("").toLowerCase())) - user = message.guild.roles.cache.find(role => String(role.name).toLowerCase() === user) - if (!user) return reject(errormessage) + } else if (!user && args[0]) { + let alluser = message.guild.roles.cache.map((role) => + String(role.name).toLowerCase() + ); + user = alluser.find((r) => + r.split(" ").join("").includes(args.join("").toLowerCase()) + ); + user = message.guild.roles.cache.find( + (role) => String(role.name).toLowerCase() === user + ); + if (!user) return reject(errormessage); return resolve(user); - } - else { - user = message.mentions.roles.filter(role => role.guild.id == message.guild.id).first(); - if (!user) return reject(errormessage) + } else { + user = message.mentions.roles + .filter((role) => role.guild.id == message.guild.id) + .first(); + if (!user) return reject(errormessage); return resolve(user); } - }) + }); } - /** - * + * * @param {*} message a DISCORDMESSAGE with the Content and guild and client information * @param {*} arg //a argument, for search for example * @returns BOOLEAN/DISCORDUSER @@ -229,43 +349,56 @@ function GetRole(message, arg) { function GetGlobalUser(message, arg) { var errormessage = ":x: I failed finding that User..."; return new Promise(async (resolve, reject) => { - var args = arg, client = message.client; - if (!client || !message) return reject("CLIENT IS NOT DEFINED") - if (!args || args == null || args == undefined) args = message.content.trim().split(/ +/).slice(1); + var args = arg, + client = message.client; + if (!client || !message) return reject("CLIENT IS NOT DEFINED"); + if (!args || args == null || args == undefined) + args = message.content.trim().split(/ +/).slice(1); let user = message.mentions.users.first(); if (!user && args[0] && args[0].length == 18) { - user = await client.users.fetch(args[0]) - if (!user) return reject(errormessage) + user = await client.users.fetch(args[0]); + if (!user) return reject(errormessage); return resolve(user); - } - else if (!user && args[0]) { - let alluser = [], allmembers = []; - var guilds = Array.from(client.guilds.cache.values()) + } else if (!user && args[0]) { + let alluser = [], + allmembers = []; + var guilds = Array.from(client.guilds.cache.values()); for (const g of guilds) { var members = Array.from(g.members.cache.values()); - for (const m of members) { alluser.push(m.user.tag); allmembers.push(m); } + for (const m of members) { + alluser.push(m.user.tag); + allmembers.push(m); + } } - user = alluser.find(user => user.startsWith(args.join(" ").toLowerCase())) - user = allmembers.find(me => String(me.user.tag).toLowerCase() == user) + user = alluser.find((user) => + user.startsWith(args.join(" ").toLowerCase()) + ); + user = allmembers.find((me) => String(me.user.tag).toLowerCase() == user); if (!user || user == null || !user.id) { - user = alluser.find(user => user.startsWith(args.join(" ").toLowerCase())) - user = allmembers.find(me => String(me.displayName + "#" + me.user.discriminator).toLowerCase() == user) - if (!user || user == null || !user.id) return reject(errormessage) + user = alluser.find((user) => + user.startsWith(args.join(" ").toLowerCase()) + ); + user = allmembers.find( + (me) => + String( + me.displayName + "#" + me.user.discriminator + ).toLowerCase() == user + ); + if (!user || user == null || !user.id) return reject(errormessage); } - user = await client.users.fetch(user.user.id) - if (!user) return reject(errormessage) + user = await client.users.fetch(user.user.id); + if (!user) return reject(errormessage); return resolve(user); - } - else { + } else { user = message.mentions.users.first() || message.author; return resolve(user); } - }) + }); } /** - * - * @param {*} array Shuffles a given array (mix) + * + * @param {*} array Shuffles a given array (mix) * @returns ARRAY */ function shuffle(array) { @@ -279,12 +412,12 @@ function shuffle(array) { } return array; } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } /** - * + * * @param {*} date Date format (Date.now()) * @returns Formatted Date */ @@ -292,102 +425,101 @@ function formatDate(date) { try { return new Intl.DateTimeFormat("en-US").format(date); } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); return false; } } /** - * + * * @param {*} duration Number | Time in Milliseconds * @returns Object of Formatted Time in Days to milliseconds */ function parseDuration(duration) { - let remain = duration - let days = Math.floor(remain / (1000 * 60 * 60 * 24)) - remain = remain % (1000 * 60 * 60 * 24) + let remain = duration; + let days = Math.floor(remain / (1000 * 60 * 60 * 24)); + remain = remain % (1000 * 60 * 60 * 24); - let hours = Math.floor(remain / (1000 * 60 * 60)) - remain = remain % (1000 * 60 * 60) + let hours = Math.floor(remain / (1000 * 60 * 60)); + remain = remain % (1000 * 60 * 60); - let minutes = Math.floor(remain / (1000 * 60)) - remain = remain % (1000 * 60) + let minutes = Math.floor(remain / (1000 * 60)); + remain = remain % (1000 * 60); - let seconds = Math.floor(remain / (1000)) - remain = remain % (1000) + let seconds = Math.floor(remain / 1000); + remain = remain % 1000; - let milliseconds = remain + let milliseconds = remain; return { days, hours, minutes, seconds, - milliseconds + milliseconds, }; } /** - * + * * @param {*} o Object of Time from days to nanoseconds/milliseconds * @param {*} useMilli Optional Boolean parameter, if it should use milliseconds or not in the showof * @returns Formatted Time */ function formatTime(o, useMilli = false) { - let parts = [] + let parts = []; if (o.days) { - let ret = o.days + ' Day' + let ret = o.days + " Day"; if (o.days !== 1) { - ret += 's' + ret += "s"; } - parts.push(ret) + parts.push(ret); } if (o.hours) { - let ret = o.hours + ' Hr' + let ret = o.hours + " Hr"; if (o.hours !== 1) { - ret += 's' + ret += "s"; } - parts.push(ret) + parts.push(ret); } if (o.minutes) { - let ret = o.minutes + ' Min' + let ret = o.minutes + " Min"; if (o.minutes !== 1) { - ret += 's' + ret += "s"; } - parts.push(ret) - + parts.push(ret); } if (o.seconds) { - let ret = o.seconds + ' Sec' + let ret = o.seconds + " Sec"; if (o.seconds !== 1) { - ret += 's' + ret += "s"; } - parts.push(ret) + parts.push(ret); } if (useMilli && o.milliseconds) { - let ret = o.milliseconds + ' ms' - parts.push(ret) + let ret = o.milliseconds + " ms"; + parts.push(ret); } if (parts.length === 0) { - return 'instantly' + return "instantly"; } else { - return parts + return parts; } } /** - * + * * @param {*} duration Number | Time in Millisceonds * @param {*} useMilli Optional Boolean parameter, if it should use milliseconds or not in the showof * @returns Formatted Time */ function duration(duration, useMilli = false) { - let time = parseDuration(duration) - return formatTime(time, useMilli) + let time = parseDuration(duration); + return formatTime(time, useMilli); } /** - * + * * @param {*} delayInms Number | Time in Milliseconds * @returns Promise, waiting for the given Milliseconds */ @@ -399,12 +531,12 @@ function delay(delayInms) { }, delayInms); }); } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } /** - * + * * @param {*} max Number | 0 - MAX * @returns Number */ @@ -412,28 +544,27 @@ function getRandomInt(max) { try { return Math.floor(Math.random() * Math.floor(max)); } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } /** - * + * * @param {*} min Number | min - max * @param {*} max Number | min - max * @returns Number */ function getRandomNum(min, max) { try { - return Math.floor(Math.random() * Math.floor((max - min) + min)); + return Math.floor(Math.random() * Math.floor(max - min + min)); } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } - /** - * - * @param {*} millis Number | Time in Milliseconds + * + * @param {*} millis Number | Time in Milliseconds * @returns Formatted time in: HH:MM:SS HH only if bigger then 0 */ function format(millis) { @@ -441,29 +572,52 @@ function format(millis) { var h = Math.floor(millis / 3600000), m = Math.floor(millis / 60000), s = ((millis % 60000) / 1000).toFixed(0); - if (h < 1) return (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s + " | " + (Math.floor(millis / 1000)) + " Seconds"; - else return (h < 10 ? "0" : "") + h + ":" + (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s + " | " + (Math.floor(millis / 1000)) + " Seconds"; + if (h < 1) + return ( + (m < 10 ? "0" : "") + + m + + ":" + + (s < 10 ? "0" : "") + + s + + " | " + + Math.floor(millis / 1000) + + " Seconds" + ); + else + return ( + (h < 10 ? "0" : "") + + h + + ":" + + (m < 10 ? "0" : "") + + m + + ":" + + (s < 10 ? "0" : "") + + s + + " | " + + Math.floor(millis / 1000) + + " Seconds" + ); } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } /** - * - * @param {*} str String of message, not replacing pings + * + * @param {*} str String of message, not replacing pings * @returns Only the Pinged message */ function escapeRegex(str) { try { return str.replace(/[.*+?^${}()|[\]\\]/g, `\\$&`); } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } /** - * - * @param {*} array ARRAY | Complete Array to work with + * + * @param {*} array ARRAY | Complete Array to work with * @param {*} from NUMBER | Position of first ITEM * @param {*} to NUMBER | Position where to move it to * @returns ARRAY | the Moved Array @@ -479,12 +633,12 @@ function arrayMove(array, from, to) { } return array; } catch (e) { - console.log(String(e.stack).bgRed) + console.log(e); } } /** - * + * * @param {*} num Number * @param {*} digits How many digits it should have: 10.231k == 3 * @returns Formatted Number @@ -497,13 +651,18 @@ function nFormatter(num, digits = 2) { { value: 1e9, symbol: "G" }, { value: 1e12, symbol: "T" }, { value: 1e15, symbol: "P" }, - { value: 1e18, symbol: "E" } + { value: 1e18, symbol: "E" }, ]; const rx = /\.0+$|(\.[0-9]*[1-9])0+$/; - var item = lookup.slice().reverse().find(function(item) { - return num >= item.value; - }); - return item ? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol : "0"; + var item = lookup + .slice() + .reverse() + .find(function (item) { + return num >= item.value; + }); + return item + ? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol + : "0"; } /** @@ -514,9 +673,16 @@ function nFormatter(num, digits = 2) { * @param {*} sliceamount If an Array is beeing used, it is the amount of items, per page, if a string then the amount of letters per page, Default Array: 15, Default String: 1000 | OPTIONAL * @returns VOID, works by itself */ -const { ButtonBuilder, ActionRowBuilder } = require('discord.js') -async function swap_pages(client, message, description, TITLE) { - let prefix = "/" +const { ButtonBuilder, ActionRowBuilder } = require("discord.js"); +async function swap_pages( + client, + message, + description, + TITLE, + reactionemojis = ["⬅️", "⏹", "➡️"], + sliceamount = 15 +) { + let prefix = client.config.prefix; let cmduser = message.author; let currentPage = 0; @@ -533,11 +699,11 @@ async function swap_pages(client, message, description, TITLE) { .setDescription(current) .setTitle(TITLE) .setColor(ee.color) - .setFooter({ text: ee.footertext, iconURL: ee.footericon }) + .setFooter({ text: ee.footertext, iconURL: ee.footericon }); embeds.push(embed); } embeds; - } catch { } + } catch {} } else { try { let k = 1000; @@ -548,46 +714,90 @@ async function swap_pages(client, message, description, TITLE) { .setDescription(current) .setTitle(TITLE) .setColor(ee.color) - .setFooter({ text: ee.footertext, iconURL: ee.footericon }) + .setFooter({ text: ee.footertext, iconURL: ee.footericon }); embeds.push(embed); } embeds; - } catch { } + } catch {} } - if (embeds.length === 0) return message.channel.send({ - embeds: [new EmbedBuilder() - .setTitle(`${emoji.msg.ERROR} No Content added to the SWAP PAGES Function`) - .setColor(ee.wrongcolor) - .setFooter({ text: ee.footertext, iconURL: ee.footericon })] - }).catch(e => console.log("THIS IS TO PREVENT A CRASH")) - if (embeds.length === 1) return message.channel.send({ embeds: [embeds[0]] }).catch(e => console.log("THIS IS TO PREVENT A CRASH")) - - let button_back = new ButtonBuilder().setStyle('SUCCESS').setCustomId('1').setEmoji("833802907509719130").setLabel("Back") - let button_home = new ButtonBuilder().setStyle('DANGER').setCustomId('2').setEmoji("🏠").setLabel("Home") - let button_forward = new ButtonBuilder().setStyle('SUCCESS').setCustomId('3').setEmoji('832598861813776394').setLabel("Forward") - const allbuttons = [new ActionRowBuilder().addComponents([button_back, button_home, button_forward])] + if (embeds.length === 0) + return message.channel + .send({ + embeds: [ + new EmbedBuilder() + .setTitle( + `${emoji.msg.ERROR} No Content added to the SWAP PAGES Function` + ) + .setColor(ee.wrongcolor) + .setFooter({ text: ee.footertext, iconURL: ee.footericon }), + ], + }) + .catch((e) => console.log("THIS IS TO PREVENT A CRASH")); + if (embeds.length === 1) + return message.channel + .send({ embeds: [embeds[0]] }) + .catch((e) => console.log("THIS IS TO PREVENT A CRASH")); + + let button_back = new ButtonBuilder() + .setStyle("SUCCESS") + .setCustomId("1") + .setEmoji("833802907509719130") + .setLabel("Back"); + let button_home = new ButtonBuilder() + .setStyle("DANGER") + .setCustomId("2") + .setEmoji("🏠") + .setLabel("Home"); + let button_forward = new ButtonBuilder() + .setStyle("SUCCESS") + .setCustomId("3") + .setEmoji("832598861813776394") + .setLabel("Forward"); + const allbuttons = [ + new ActionRowBuilder().addComponents([ + button_back, + button_home, + button_forward, + ]), + ]; //Send message with buttons - let swapmsg = await message.channel.send({ + let swapmsg = await message.channel.safeSend({ content: `***Click on the __Buttons__ to swap the Pages***`, embeds: [embeds[0]], - components: allbuttons + components: allbuttons, }); //create a collector for the thinggy - const collector = swapmsg.createMessageComponentCollector({ filter: (i) => i.isButton() && i.user && i.user.id == cmduser.id && i.message.author.id == client.user.id, time: 180e3 }); //collector for 5 seconds + const collector = swapmsg.createMessageComponentCollector({ + filter: (i) => + i.isButton() && + i.user && + i.user.id == cmduser.id && + i.message.author.id == client.user.id, + time: 180e3, + }); //collector for 5 seconds //array of all embeds, here simplified just 10 embeds with numbers 0 - 9 - collector.on('collect', async b => { + collector.on("collect", async (b) => { if (b.user.id !== message.author.id) - return b.reply(`<:declined:780403017160982538> **Only the one who typed ${prefix}help is allowed to react!**`, true) + return b.reply( + `<:declined:780403017160982538> **Only the one who typed ${prefix}help is allowed to react!**`, + true + ); //page forward if (b.customId == "1") { //b.reply("***Swapping a PAGE FORWARD***, *please wait 2 Seconds for the next Input*", true) if (currentPage !== 0) { - currentPage -= 1 - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + currentPage -= 1; + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } else { - currentPage = embeds.length - 1 - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + currentPage = embeds.length - 1; + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } } @@ -595,7 +805,10 @@ async function swap_pages(client, message, description, TITLE) { else if (b.customId == "2") { //b.reply("***Going Back home***, *please wait 2 Seconds for the next Input*", true) currentPage = 0; - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } //go forward @@ -603,50 +816,90 @@ async function swap_pages(client, message, description, TITLE) { //b.reply("***Swapping a PAGE BACK***, *please wait 2 Seconds for the next Input*", true) if (currentPage < embeds.length - 1) { currentPage++; - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } else { - currentPage = 0 - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + currentPage = 0; + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } - } }); - - } async function swap_pages2(client, message, embeds) { let currentPage = 0; let cmduser = message.author; - if (embeds.length === 1) return message.channel.send({ embeds: [embeds[0]] }).catch(e => console.log("THIS IS TO PREVENT A CRASH")) - let button_back = new ButtonBuilder().setStyle('SUCCESS').setCustomId('1').setEmoji("833802907509719130").setLabel("Back") - let button_home = new ButtonBuilder().setStyle('DANGER').setCustomId('2').setEmoji("🏠").setLabel("Home") - let button_forward = new ButtonBuilder().setStyle('SUCCESS').setCustomId('3').setEmoji('832598861813776394').setLabel("Forward") - const allbuttons = [new ActionRowBuilder().addComponents([button_back, button_home, button_forward])] - let prefix = "/" + if (embeds.length === 1) + return message.channel + .send({ embeds: [embeds[0]] }) + .catch((e) => console.log("THIS IS TO PREVENT A CRASH")); + let button_back = new ButtonBuilder() + .setStyle("SUCCESS") + .setCustomId("1") + .setEmoji("833802907509719130") + .setLabel("Back"); + let button_home = new ButtonBuilder() + .setStyle("DANGER") + .setCustomId("2") + .setEmoji("🏠") + .setLabel("Home"); + let button_forward = new ButtonBuilder() + .setStyle("SUCCESS") + .setCustomId("3") + .setEmoji("832598861813776394") + .setLabel("Forward"); + const allbuttons = [ + new ActionRowBuilder().addComponents([ + button_back, + button_home, + button_forward, + ]), + ]; + let prefix = "/"; //Send message with buttons - let swapmsg = await message.channel.send({ + let swapmsg = await message.channel.safeSend({ content: `***Click on the __Buttons__ to swap the Pages***`, embeds: [embeds[0]], - components: allbuttons + components: allbuttons, }); //create a collector for the thinggy - const collector = swapmsg.createMessageComponentCollector({ filter: (i) => i.isButton() && i.user && i.user.id == cmduser.id && i.message.author.id == client.user.id, time: 180e3 }); //collector for 5 seconds + const collector = swapmsg.createMessageComponentCollector({ + filter: (i) => + i.isButton() && + i.user && + i.user.id == cmduser.id && + i.message.author.id == client.user.id, + time: 180e3, + }); //collector for 5 seconds //array of all embeds, here simplified just 10 embeds with numbers 0 - 9 - collector.on('collect', async b => { + collector.on("collect", async (b) => { if (b.user.id !== message.author.id) - return b.reply(`<:declined:780403017160982538> **Only the one who typed ${prefix}help is allowed to react!**`, true) + return b.reply( + `<:declined:780403017160982538> **Only the one who typed ${prefix}help is allowed to react!**`, + true + ); //page forward if (b.customId == "1") { //b.reply("***Swapping a PAGE FORWARD***, *please wait 2 Seconds for the next Input*", true) if (currentPage !== 0) { - currentPage -= 1 - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + currentPage -= 1; + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } else { - currentPage = embeds.length - 1 - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + currentPage = embeds.length - 1; + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } } @@ -654,7 +907,10 @@ async function swap_pages2(client, message, embeds) { else if (b.customId == "2") { //b.reply("***Going Back home***, *please wait 2 Seconds for the next Input*", true) currentPage = 0; - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } //go forward @@ -662,18 +918,799 @@ async function swap_pages2(client, message, embeds) { //b.reply("***Swapping a PAGE BACK***, *please wait 2 Seconds for the next Input*", true) if (currentPage < embeds.length - 1) { currentPage++; - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } else { - currentPage = 0 - await swapmsg.edit({ embeds: [embeds[currentPage]], components: allbuttons }); + currentPage = 0; + await swapmsg.edit({ + embeds: [embeds[currentPage]], + components: allbuttons, + }); await b.deferUpdate(); } + } + }); +} +/** + * + * @param {*} message Discord Message + * @param {*} args Array of Message Arguments + * @returns Discord.User + */ + +function GetGlobalUser(message, arg) { + var errormessage = "<:no:833101993668771842> I failed finding that User..."; + return new Promise(async (resolve, reject) => { + var args = arg, + client = message.client; + if (!client || !message) return reject("CLIENT IS NOT DEFINED"); + if (!args || args == null || args == undefined) + args = message.content.trim().split(/ +/).slice(1); + let user = message.mentions.users.first(); + if (!user && args[0] && args[0].length == 18) { + user = await client.users.fetch(args[0]).catch(() => {}); + if (!user) return reject(errormessage); + return resolve(user); + } else if (!user && args[0]) { + let alluser = [], + allmembers = []; + var guilds = [...client.guilds.cache.values()]; + for (const g of guilds) { + var members = g.members.cache.map((NOVA) => NOVA); + for (const m of members) { + alluser.push(m.user.tag); + allmembers.push(m); + } + } + user = alluser.find((user) => + user.startsWith(args.join(" ").toLowerCase()) + ); + user = allmembers.find((me) => String(me.user.tag).toLowerCase() == user); + if (!user || user == null || !user.id) { + user = alluser.find((user) => + user.startsWith(args.join(" ").toLowerCase()) + ); + user = allmembers.find( + (me) => + String( + me.displayName + "#" + me.user.discriminator + ).toLowerCase() == user + ); + if (!user || user == null || !user.id) return reject(errormessage); + } + user = await client.users.fetch(user.user.id).catch(() => {}); + if (!user) return reject(errormessage); + return resolve(user); + } else { + user = message.mentions.users.first() || message.author; + return resolve(user); } }); +} + +/** + * @param {Discord.Channel} channel Discord Channel + * @param {Discord.Guild} guild Discord Guild + * @param {Number} limit Number of Messages to fetch + * @returns {Promise} Path to the html file + * @description Creates a Buffer of the Transcript + * @example create_transcript_buffer(channel, guild, 1000).then(async path => { + * const attachment = new Discord.AttachmentBuilder(path, {name: "transcript.html" description: "Transcript of the Channel""}); + * await message.channel.safeSend({ files: [attachment] }); + * await fs.unlinkSync(path); + * }); + */ +async function create_transcript_buffer(Channel, Guild, Limit) { + return new Promise(async (resolve, reject) => { + try { + let baseHTML = + `` + + `` + + `` + + `${Channel.name}` + + `` + + `` + + `` + + `` + + `` + + ``; + let messagesArray = []; + msglimit = Limit || 1000; + let messageCollection = new Collection(); //make a new collection + let channelMessages = await Channel.messages + .fetch({ + //fetch the last 100 messages + limit: 100, + }) + .catch(() => {}); //catch any error + messageCollection = messageCollection.concat(channelMessages); //add them to the Collection + let tomanymsgs = 1; //some calculation for the messagelimit + if (Number(msglimit) === 0) msglimit = 100; //if its 0 set it to 100 + let messagelimit = Number(msglimit) / 100; //devide it by 100 to get a counter + if (messagelimit < 1) messagelimit = 1; //set the counter to 1 if its under 1 + while (channelMessages.size === 100) { + //make a loop if there are more then 100 messages in this channel to fetch + if (tomanymsgs === messagelimit) break; //if the counter equals to the limit stop the loop + tomanymsgs += 1; //add 1 to the counter + let lastMessageId = channelMessages.lastKey(); //get key of the already fetched messages above + channelMessages = await Channel.messages + .fetch({ + limit: 100, + before: lastMessageId, + }) + .catch(() => {}); //Fetch again, 100 messages above the already fetched messages + if (channelMessages) + //if its true + messageCollection = messageCollection.concat(channelMessages); //add them to the collection + } + let Messages = [...messageCollection.values()]; + let messagescount = Messages.length; + let msgs = Messages.reverse(); //reverse the array to have it listed like the discord chat + //now for every message in the array make a new paragraph! + await msgs.forEach(async (msg) => { + //Aug 02, 2021 12:20 AM + if (msg.type == "DEFAULT") { + let time = moment(msg.createdTimestamp).format( + "MMM DD, YYYY HH:mm:ss" + ); + let subcontent = + `
` + + `
` + + `
` + + `${msg.author.tag}`; + if (msg.author.bot) subcontent += `BOT`; + subcontent += + `ID: ${msg.author.id} | ` + + `${time} ${ + msg.editedTimestamp ? `(edited)` : msg.editedAt ? `(edited)` : "" + }` + + `
`; + if (msg.content) { + subcontent += `
${markdowntohtml( + String(msg.cleanContent ? msg.cleanContent : msg.content).replace( + /\n/gi, + "
" + ) + )}
`; + } + if (msg.embeds[0]) { + subcontent += `
`; + + if (msg.embeds[0].author) { + subcontent += `
`; + if (msg.embeds[0].author.iconURL) { + subcontent += ``; + } + if (msg.embeds[0].author.name) { + subcontent += `
${markdowntohtml( + String(msg.embeds[0].author.name).replace(/\n/gi, "
") + )}
`; + } + subcontent += `
`; + } + if (msg.embeds[0].title) { + subcontent += `
${markdowntohtml( + String(msg.embeds[0].title).replace(/\n/gi, "
") + )}
`; + } + if (msg.embeds[0].description) { + subcontent += `
${markdowntohtml( + String(msg.embeds[0].description).replace(/\n/gi, "
") + )}
`; + } + if (msg.embeds[0].image) { + subcontent += `
`; + } + if (msg.embeds[0].fields && msg.embeds[0].fields.length > 0) { + subcontent += `
`; + for (let i = 0; i < msg.embeds[0].fields.length; i++) { + subcontent += `
`; + const field = msg.embeds[0].fields[i]; + if (field.key) { + subcontent += `
${markdowntohtml( + String(field.key).replace(/\n/gi, "
") + )}
`; + } + if (field.value) { + subcontent += `
${markdowntohtml( + String(field.value).replace(/\n/gi, "
") + )}
`; + } + subcontent += `
`; + } + subcontent += `
`; + } + if (msg.embeds[0].footer) { + subcontent += ``; + } + subcontent += `
`; + if (msg.embeds[0].thumbnail && msg.embeds[0].thumbnail.url) { + subcontent += ``; + } + subcontent += `
`; + } + if (msg.reactions && msg.reactions.cache.size > 0) { + subcontent += `
`; + for (const reaction of msg.reactions.cache.map((r) => r)) { + subcontent += `
${ + reaction.emoji?.url + ? `${
+                      " + }">` + : reaction.emoji?.name.toString() + }${reaction.count}
`; + } + subcontent += `
`; + } + subcontent += `
`; + messagesArray.push(subcontent); + } + if (msg.type == "PINS_ADD") { + let time = moment(msg.createdTimestamp).format( + "MMM DD, YYYY HH:mm:ss" + ); + let subcontent = + `
` + + `
` + + `
` + + `${msg.author.tag}`; + if (msg.author.bot) subcontent += `BOT`; + subcontent += `pinned a message to this channel.${time}
`; + messagesArray.push(subcontent); + } + }); + baseHTML += + `
` + + `
` + + `
`; + baseHTML += messagesArray.join("\n"); + baseHTML += `
TICKET LOG INFORMATION✓ SYSTEMMind this Information
If there are Files, Attachments, Videos or Images, they won't always be displayed cause they will be unknown and we don't want to spam an API like IMGUR!
`; + fs.writeFileSync(`${process.cwd()}/${Channel.name}.html`, baseHTML); //write everything in the docx file + resolve(`${process.cwd()}/${Channel.name}.html`); + return; + function markdowntohtml(tomarkdown) { + mentionReplace(tomarkdown.split(" ")); + function mentionReplace(splitted) { + for (arg of splitted) { + const memberatches = arg.match(/<@!?(\d+)>/); + const rolematches = arg.match(/<@&(\d+)>/); + const channelmatches = arg.match(/<#(\d+)>/); + if (rolematches) { + let role = Guild.roles.cache.get(rolematches[1]); + if (role) { + let torpleace = new RegExp(rolematches[0], "g"); + tomarkdown = tomarkdown.replace( + torpleace, + `@${role.name}` + ); + } + } + if (memberatches) { + let member = Guild.members.cache.get(memberatches[1]); + if (member) { + let torpleace = new RegExp(memberatches[0], "g"); + tomarkdown = tomarkdown.replace( + torpleace, + `@${member.user.username}` + ); + } + } + if (channelmatches) { + let channel = Guild.channels.cache.get(channelmatches[1]); + if (channel) { + let torpleace = new RegExp(channelmatches[0], "g"); + tomarkdown = tomarkdown.replace( + torpleace, + `@${channel.name}` + ); + } + } + } + } + var output = ""; + var BLOCK = "block"; + var INLINE = "inline"; + var parseMap = [ + { + //

+ pattern: /\n(?!<\/?\w+>|\s?\*|\s?[0-9]+|>|\>|-{5,})([^\n]+)/g, + replace: "$1
", + type: BLOCK, + }, + { + //

+ pattern: /\n(?:>|\>)\W*(.*)/g, + replace: "

$1

", + type: BLOCK, + }, + { + //
    + pattern: /\n\s?\*\s*(.*)/g, + replace: "
      \n\t
    • $1
    • \n
    ", + type: BLOCK, + }, + { + //
      + pattern: /\n\s?[0-9]+\.\s*(.*)/g, + replace: "
        \n\t
      1. $1
      2. \n
      ", + type: BLOCK, + }, + { + // + pattern: /(\*\*|__)(.*?)\1/g, + replace: "$2", + type: INLINE, + }, + { + // + pattern: /(\*)(.*?)\1/g, + replace: "$2", + type: INLINE, + }, + { + // + pattern: /([^!])\[([^\[]+)\]\(([^\)]+)\)/g, + replace: '$1$2', + type: INLINE, + }, + { + // + pattern: /!\[([^\[]+)\]\(([^\)]+)\)/g, + replace: '$1', + type: INLINE, + }, + { + // + pattern: /`(.*?)`/g, + replace: "$1", + type: INLINE, + }, + ]; + function parse(string) { + output = "\n" + string + "\n"; + parseMap.forEach(function (p) { + output = output.replace(p.pattern, function () { + return replace.call(this, arguments, p.replace, p.type); + }); + }); + output = clean(output); + output = output.trim(); + output = output.replace(/[\n]{1,}/g, "\n"); + return output; + } + function replace(matchList, replacement, type) { + var i, $$; + for (i in matchList) { + if (!matchList.hasOwnProperty(i)) { + continue; + } + replacement = replacement.split("$" + i).join(matchList[i]); + replacement = replacement.split("$L" + i).join(matchList[i].length); + } + if (type === BLOCK) { + replacement = replacement.trim() + "\n"; + } + return replacement; + } + function clean(string) { + var cleaningRuleArray = [ + { + match: /<\/([uo]l)>\s*<\1>/g, + replacement: "", + }, + { + match: /(<\/\w+>)<\/(blockquote)>\s*<\2>/g, + replacement: "$1", + }, + ]; + cleaningRuleArray.forEach(function (rule) { + string = string.replace(rule.match, rule.replacement); + }); + return string; + } + let output__ = parse(tomarkdown); + return output__; + } + } catch (e) { + reject(e); + return; + } + }); } +/** + * + * @param {*} title String | The title of the embed + * @param {*} text Array | The text to paginate + * @param {*} res Interaction/Message | The interaction or message that triggered the command + * @returns Null | does the work + */ + +async function createPaginationEmbed(title, text, res) { + const msg = await res + .reply({ embeds: [await createEmbed(0, 0, text, title, res)] }) + .then(async (msg) => { + if (text.length <= 10) return; + let button1 = new Discord.ButtonBuilder() + .setCustomId("back_button") + .setEmoji("⬅️") + .setStyle(Discord.ButtonStyle.Primary) + .setDisabled(true); + let button2 = new Discord.ButtonBuilder() + .setCustomId("forward_button") + .setEmoji("➡️") + .setStyle(Discord.ButtonStyle.Primary); + + let row = new Discord.ActionRowBuilder().addComponents(button1, button2); + + msg.edit({ + embeds: [await createEmbed(0, 0, text, title, res)], + components: [row], + }); + + let currentIndex = 0; + const collector = res.channel.createMessageComponentCollector({ + componentType: Discord.ComponentType.Button, + time: 60000, + }); + + collector.on("collect", async (btn) => { + if (btn.user.id == (res.user?.id || res.author?.id) && btn.message.id == msg.id) { + btn.customId === "back_button" + ? (currentIndex -= 10) + : (currentIndex += 10); + + let btn1 = new Discord.ButtonBuilder() + .setCustomId("back_button") + .setEmoji("⬅️") + .setStyle(Discord.ButtonStyle.Primary) + .setDisabled(true); + + let btn2 = new Discord.ButtonBuilder() + .setCustomId("forward_button") + .setEmoji("➡️") + .setStyle(Discord.ButtonStyle.Primary) + .setDisabled(true); + + if (currentIndex !== 0) btn1.setDisabled(false); + if (currentIndex + 10 < text.length) btn2.setDisabled(false); + + let row2 = new Discord.ActionRowBuilder().addComponents(btn1, btn2); + + msg.edit({ + embeds: [ + await createEmbed(currentIndex, currentIndex, text, title, res), + ], + components: [row2], + }); + btn.deferUpdate(); + } + }); + + collector.on("end", async (btn) => { + let btn1Disable = new Discord.ButtonBuilder() + .setCustomId("back_button") + .setEmoji("⬅️") + .setStyle(Discord.ButtonStyle.Primary) + .setDisabled(true); + + let btn2Disable = new Discord.ButtonBuilder() + .setCustomId("forward_button") + .setEmoji("➡️") + .setStyle(Discord.ButtonStyle.Primary) + .setDisabled(true); + + let rowDisable = new Discord.ActionRowBuilder().addComponents( + btn1Disable, + btn2Disable + ); + + msg.edit({ + embeds: [ + await createEmbed(currentIndex, currentIndex, text, title, res), + ], + components: [rowDisable], + }); + }); + }); +} + +/** + * + * + * @param {*} text Array | The text to paginate + * @param {*} title String | The title of the embed + * @param {*} res Interaction/Message | The interaction or message that triggered the command + * @returns Array of one embed + */ + +async function createEmbed(start, end, text, title, res, len = 10) { + result = (text.slice(start, end + len)).join("\n") + let embed = new Discord.EmbedBuilder() + .setTitle(title) + .setDescription(result) + .setFooter( + {text: `Page ${Math.floor(start / len) + 1} of ${Math.floor(text.length / len) + 1}`, iconURL: ee.iconURL} + ).setColor(ee.color); + + return embed; +} + +/** + * @param {String} str + * @param {Number} length + * @returns {String} + * @example + * smartSlice("Hello World", 5); + * // => "Hello" + * smartSlice("Hello World", 50); + * // => "Hello World" + * smartSlice("Hello World", 8); + * // => "Hello" + */ + +function smartSlice(str, length) { + if (str.length <= length) { + return str; + } + + let slicedText = str.slice(0, length); + const lastSpaceIndex = slicedText.lastIndexOf(" "); + + if (lastSpaceIndex !== -1) { + slicedText = slicedText.slice(0, lastSpaceIndex); + } + + return slicedText; +} + +/** + * + * @param {String} content | The content to post to sourcebin + * @param {String} title | The title of the sourcebin + * @param {String} language | The language of the sourcebin + * @param {String} name | The name of the sourcebin + * @param {String} description | The description of the sourcebin + * @returns {Object} | The sourcebin object + * @example + * await postToBin("Hello World", "Hello World", "js", "NOVA Bot", "This was created using NOVA Bot") + * // => { url: 'https://sourceb.in/xxxxxx', short: 'xxxxxx', raw: 'https://cdn.sourceb.in/bins/xxxxxx/0' } + */ + +async function postToBin(content, title, language = "js", name = "NOVA Bot", description = "This was created using NOVA Bot") { + try { + const response = await sourcebin.create( + [ + { + name: name, + content, + languageId: language, + }, + ], + { + title, + description: description, + } + ); + return { + url: response.url, + short: response.short, + raw: `https://cdn.sourceb.in/bins/${response.key}/0`, + }; + } catch (ex) { + console.log(ex); + } +} + +/** + * + * @param {String} text | The text to check + * @returns {Boolean} | Whether the text contains a link or not + */ + +function containsLink(text) { + return /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/.test( + text + ); +} + +/** + * + * @param {String} text | The text to check + * @returns {Boolean} | Whether the text contains a discord invite or not + */ + +function containsDiscordInvite(text) { + return /(https?:\/\/)?(www.)?(discord.(gg|io|me|li|link|plus)|discorda?p?p?.com\/invite|invite.gg|dsc.gg|urlcord.cf)\/[^\s/]+?(?=\b)/.test( + text + ); +} + +/** + * @param {Array} perms | The permissions to parse + * @returns {String} | The parsed permissions + */ +function parsePermissions(perms) { + const permissionWord = `permission${perms.length > 1 ? "s" : ""}`; + return "`" + perms.map((perm) => permissions[perm]).join(", ") + "` " + permissionWord; +} + +/** + * + * @param {Array} arr1 | The first array + * @param {Array} arr2 | The second array + * @returns {Array} | The array with the duplicates removed + */ +function removeDuplicatesPerms(arr1, arr2) { + if (arr1.includes("Administrator")) return []; + return arr1.filter((x) => !arr2.includes(x)); +} + +/** + +Generates a giveaway embed based on the provided data and options. +@param {EmbedBuilder} oldData - The old data of the giveaway embed. +@param {Object} options - The options for the giveaway embed. +@param {String} options.color - The color of the embed. Defaults to ee.color if not provided. +@param {String} options.EmbedAuthor - The author of the embed. Defaults to null if not provided. +@param {String} options.banner - The banner image of the embed. Defaults to null if not provided. +@param {String} options.prize - The prize of the giveaway. +@param {Number} options.winnerCount - The number of winners for the giveaway. +@param {String} options.host - The host of the giveaway. +@param {String} options.entriesLimit - The limit of entries for the giveaway. Defaults to "infinite" if not provided. +@param {Number} options.time - The time remaining for the giveaway. +@param {String[]} options.multi - An array of multipliers for the giveaway. Defaults to an empty array if not provided. +@param {String[]} options.requirements - An array of requirements for the giveaway. Defaults to an empty array if not provided. +@param {String} type - The type of the giveaway embed. +@returns {EmbedBuilder} - The generated giveaway embed. +*/ + +function generateGiveawayEmbed(oldData, options = { + color: ee.color, + EmbedAuthor: null, + banner: null, + prize: null, + winnerCount: null, + host: null, + entriesLimit: "infinte", + time: null, +}, type = "main") { + const embed = new EmbedBuilder(oldData) + if (type && !["noEntries", "End"].includes(type)) { + + embed.setColor(options.color ?? ee.color) + .setAuthor(options.EmbedAuthor || null) + .setImage(options.banner || null) + .setDescription(` + ${formatEmoji(allEmojis.Giveaway, false)} **Giveaway Details** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_prize, false)} Prize: **${options.prize}** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_winner, false)} No. of Winners: ${options.winnerCount} + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_host, false)} Host: ${options.host} ${options.entriesLimit != 'infinite' ? `\n ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_thumb_point, false)} Entry will stop at ${options.entriesLimit} Entries` : ``} + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_clock, false)} Ends: [] + ${options?.multi?.length == 0 ? `` : `\n${formatEmoji(allEmojis.nova_multiplier, false)} **Multiplier**\n`.concat(options.multi)} + ${options?.requirements?.length == 0 ? `` : `${formatEmoji(allEmojis.nova_requirments, false)} **Requirements**\n`.concat(options.requirements)} + `) + + return embed; + } + else if (type && type == "noEntries") { + embed.setColor(typeof oldData == "undefined" ? options.color ?? ee.color : oldData.color ?? ee.color) + .setAuthor(typeof oldData == "undefined" ? options.EmbedAuthor ?? null : oldData.author ?? null) + .setImage(typeof oldData == "undefined" ? options.banner ?? null : oldData.image ?? null) + .setDescription(` + ${formatEmoji(allEmojis.Giveaway, false)} **Giveaway Details** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_prize, false)} Prize: **${options.prize}** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_winner, false)} Winners: **No Winners** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_host, false)} Host: ${userMention(options.host)} ${options.entriesLimit != 'infinite' ? `\n ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_thumb_point, false)} Entry stopped at ${options.entriesLimit} Entries` : ``} + ${formatEmoji(allEmojis.blankspace, false)}${allEmojis.nova_no} Ends: Giveaway Cancelled + ${options.multi.length == 0 ? `` : `\n${formatEmoji(allEmojis.nova_multiplier, false)} **Multiplier**\n`.concat(options.multi)} + ${options.requirements.length == 0 ? `` : `${formatEmoji(allEmojis.nova_requirments, false)} **Requirements**\n`.concat(options.requirements)} + `).setFooter(typeof oldData == "undefined" ? options.footer ?? { text: "Giveaway has been cancelled due to no participation" } : oldData.footer ?? { text: "Giveaway has been cancelled due to no participation" }) + + return embed; + } + else if (type && type == "End") { + embed.setColor(options.color ?? ee.color) + .setAuthor(typeof oldData == "undefined" ? options.EmbedAuthor ?? null : oldData.author ?? null) + .setImage(typeof oldData == "undefined" ? options.banner ?? null : oldData.image ?? null) + .setDescription(` + ${formatEmoji(allEmojis.Giveaway, false)} **Giveaway Details** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_prize, false)} Prize: **${options.prize}** + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_winner, false)} Winners: ${options.winners.length != 0 ? options.winners : '\`Error came\` :skull:'} + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_host, false)} Host: ${userMention(options.host)} ${options.entriesLimit != 'infinite' ? `\n ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_thumb_point, false)} Entry stopped at ${options.entriesLimit} Entries` : ``} + ${formatEmoji(allEmojis.blankspace, false)}${formatEmoji(allEmojis.nova_clock, false)} Ended At: [] + ${options.multi.length == 0 ? `` : `\n${formatEmoji(allEmojis.nova_multiplier, false)} **Multiplier**\n`.concat(options.multi)} + ${options.requirements.length == 0 ? `` : `${formatEmoji(allEmojis.nova_requirments, false)} **Requirements**\n`.concat(options.requirements)} + `).setFooter(typeof oldData == "undefined" ? options.footer ?? { text: "Giveaway has been ended." } : oldData.footer ?? { text: "Giveaway has been ended." }) + + return embed + } +} +/** + * + * @param {Array} entries | The entries array + * @param {Number} winnerCount | The number of winner to be selected + * @returns {Object} | The object containing the new entries, winnerId and winners + */ + +function gReRoll(entries, winnerCount) { + let winnerId = `` + let winners = [] + try { + for (let i = 0; i < winnerCount && entries?.length != 0; i++) { + let rid = entries[Math.floor(Math.random() * entries?.length)]; + if (winnerId.length == 0) winnerId = winnerId + `<@${rid}>`; + else winnerId = winnerId + `, <@${rid}>`; + + winners.push(rid); + + let r = []; + entries.forEach(x => { + if (x != rid) r.push(x) + }); + entries = r; + }; + } catch (error) { }; + + return { entries, winnerId, winners } +} + + +/** + +Disables all buttons in the given array of components. +@param {Array} msg - Message Data. +@returns {Array} - The updated array of components with disabled buttons. +*/ + +function disableButtons(msg) { + const components = msg.components; + for (let x = 0; x < components.length; x++) { + for (let y = 0; y < components[x].components.length; y++) { + components[x].components[y].data.disabled = true; + } + } + return components; +} \ No newline at end of file diff --git a/handlers/messageCommands.js b/handlers/messageCommands.js new file mode 100644 index 0000000..8da85b6 --- /dev/null +++ b/handlers/messageCommands.js @@ -0,0 +1,30 @@ +const { + readdirSync + } = require("fs"); + module.exports = (client) => { + let dateNow = Date.now(); + console.log(`${String("[x] :: ".magenta)}Now loading the Commands ...`.brightGreen) + try { + readdirSync("./commands/").forEach((dir) => { + const commands = readdirSync(`./commands/${dir}/`).filter((file) => file.endsWith(".js")); + for (let file of commands) { + try{ + let pull = require(`../commands/${dir}/${file}`); + if (pull.name) { + client.commands.set(pull.name, pull); + //console.log(` | ${file} :: Ready`.brightGreen) + } else { + //console.log(` | ${file} :: error -> missing a help.name,or help.name is not a string.`.brightRed) + continue; + } + if (pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach((alias) => client.aliases.set(alias, pull.name)); + }catch(e){ + console.log(String(e.stack).grey.bgRed) + } + } + }); + } catch (e) { + console.log(String(e.stack).grey.bgRed) + } + console.log(`[x] :: `.magenta + `LOADED THE ${client.commands.size} COMMANDS after: `.brightGreen + `${Date.now() - dateNow}ms`.green) + }; \ No newline at end of file diff --git a/handlers/slashCommands.js b/handlers/slashCommands.js index 6db3085..1ce572f 100644 --- a/handlers/slashCommands.js +++ b/handlers/slashCommands.js @@ -1,171 +1,407 @@ const { readdirSync, lstatSync } = require("fs"); -const { SlashCommandBuilder } = require('discord.js'); +const { SlashCommandBuilder } = require("discord.js"); const config = require("../botconfig/config.js"); const dirSetup = config.dirSetup; + module.exports = (client) => { - try { - let allCommands = []; - readdirSync("./slashCommands/").forEach((dir) => { - if(lstatSync(`./slashCommands/${dir}`).isDirectory()) { - const cmdSetup = dirSetup.find(d=>d.Folder == dir); - //If its a valid cmdsetup - if(cmdSetup && cmdSetup.Folder) { - //Set the SubCommand as a Slash Builder - const subCommand = new SlashCommandBuilder().setName(String(cmdSetup.CmdName).replace(/\s+/g, '_').toLowerCase()).setDescription(String(cmdSetup.CmdDescription)); - //Now for each file in that subcommand, add a command! - const slashCommands = readdirSync(`./slashCommands/${dir}/`).filter((file) => file.endsWith(".js")); - for (let file of slashCommands) { - let pull = require(`../slashCommands/${dir}/${file}`); - if (pull.name && pull.description) { - subCommand - .addSubcommand((subcommand) => { - subcommand.setName(String(pull.name).toLowerCase()).setDescription(pull.description) - if(pull.options && pull.options.length > 0){ - for(const option of pull.options){ - if(option.User && option.User.name && option.User.description){ - subcommand.addUserOption((op) => - op.setName(String(option.User.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.User.description).setRequired(option.User.required).setAutocomplete(option.User.autocomplete? true: false) - ) - } else if(option.Integer && option.Integer.name && option.Integer.description){ - subcommand.addIntegerOption((op) => - op.setName(String(option.Integer.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Integer.description).setRequired(option.Integer.required).setAutocomplete(option.Integer.autocomplete? true: false) - ) - } else if(option.String && option.String.name && option.String.description){ - subcommand.addStringOption((op) => - op.setName(String(option.String.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.String.description).setRequired(option.String.required).setAutocomplete(option.String.autocomplete? true: false) - ) - } else if(option.Channel && option.Channel.name && option.Channel.description){ - subcommand.addChannelOption((op) => - op.setName(String(option.Channel.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Channel.description).setRequired(option.Channel.required) - ) - } else if(option.Role && option.Role.name && option.Role.description){ - subcommand.addRoleOption((op) => - op.setName(String(option.Role.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Role.description).setRequired(option.Role.required) - ) - } else if(option.StringChoices && option.StringChoices.name && option.StringChoices.description && option.StringChoices.choices && option.StringChoices.choices.length > 0){ - const choices = option.StringChoices.choices.map(c => ({ name: String(c[0]).replace(/\s+/g, '_').toLowerCase(), value: c[1] })); - subcommand.addStringOption((op) => - op.setName(String(option.StringChoices.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.StringChoices.description).setRequired(option.StringChoices.required).setAutocomplete(option.StringChoices.autocomplete? true: false) - .addChoices(...choices), - ) - } else if(option.IntChoices && option.IntChoices.name && option.IntChoices.description && option.IntChoices.choices && option.IntChoices.choices.length > 0){ - subcommand.addStringOption((op) => - op.setName(String(option.IntChoices.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.IntChoices.description).setRequired(option.IntChoices.required).setAutocomplete(option.IntChoices.autocomplete? true: false) - .addChoices(option.IntChoices.choices.map(c=> [String(c[0]).replace(/\s+/g, '_').toLowerCase(),parseInt(c[1])] )), - ) - } else if(option.Attachment && option.Attachment.name && option.Attachment.description) { + let dateNow = Date.now(); + try { + console.log(`${String("[x] :: ".cyan)}Now loading the Slash Commands ...`.brightBlue) + let allCommands = []; + readdirSync("./commands/").forEach((dir) => { + if (lstatSync(`./commands/${dir}`).isDirectory()) { + const cmdSetup = dirSetup.find((d) => d.Folder == dir); + //If its a valid cmdsetup + if (cmdSetup && cmdSetup.Folder) { + //Set the SubCommand as a Slash Builder + const subCommand = new SlashCommandBuilder() + .setName( + String(cmdSetup.CmdName).replace(/\s+/g, "_").toLowerCase() + ) + .setDescription(String(cmdSetup.CmdDescription)); + //Now for each file in that subcommand, add a command! + const slashCommands = readdirSync(`./commands/${dir}/`).filter( + (file) => file.endsWith(".js") + ); + for (let file of slashCommands) { + let pull = require(`../commands/${dir}/${file}`); + if (pull.slashName && pull.description) { + subCommand.addSubcommand((subcommand) => { + subcommand + .setName(String(pull.slashName).toLowerCase()) + .setDescription(pull.description); + if (pull.options && pull.options.length > 0) { + for (const option of pull.options) { + if ( + option.User && + option.User.name && + option.User.description + ) { + subcommand.addUserOption((op) => + op + .setName( + String(option.User.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.User.description) + .setRequired(option.User.required) + ); + } else if ( + option.Integer && + option.Integer.name && + option.Integer.description + ) { + subcommand.addIntegerOption((op) => + op + .setName( + String(option.Integer.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Integer.description) + .setRequired(option.Integer.required) + ); + } else if ( + option.String && + option.String.name && + option.String.description + ) { + subcommand.addStringOption((op) => + op + .setName( + String(option.String.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.String.description) + .setRequired(option.String.required) + .setAutocomplete( + option.String.autocomplete ? true : false + ) + ); + } else if ( + option.Channel && + option.Channel.name && + option.Channel.description + ) { + subcommand.addChannelOption((op) => + op + .setName( + String(option.Channel.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Channel.description) + .setRequired(option.Channel.required) + ); + } else if ( + option.Role && + option.Role.name && + option.Role.description + ) { + subcommand.addRoleOption((op) => + op + .setName( + String(option.Role.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Role.description) + .setRequired(option.Role.required) + ); + } else if ( + option.StringChoices && + option.StringChoices.name && + option.StringChoices.description && + option.StringChoices.choices && + option.StringChoices.choices.length > 0 + ) { + const choices = option.StringChoices.choices.map((c) => ({ + name: String(c[0]).replace(/\s+/g, "_").toLowerCase(), + value: c[1], + })); + subcommand.addStringOption((op) => + op + .setName( + String(option.StringChoices.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.StringChoices.description) + .setRequired(option.StringChoices.required) + .addChoices(...choices) + ); + } else if ( + option.IntChoices && + option.IntChoices.name && + option.IntChoices.description && + option.IntChoices.choices && + option.IntChoices.choices.length > 0 + ) { + subcommand.addStringOption((op) => + op + .setName( + String(option.IntChoices.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.IntChoices.description) + .setRequired(option.IntChoices.required) + .setAutocomplete( + option.IntChoices.autocomplete ? true : false + ) + .addChoices( + option.IntChoices.choices.map((c) => [ + String(c[0]).replace(/\s+/g, "_").toLowerCase(), + parseInt(c[1]), + ]) + ) + ); + } else if ( + option.Attachment && + option.Attachment.name && + option.Attachment.description + ) { subcommand.addAttachmentOption((op) => - op.setName(String(option.Attachment.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Attachment.description).setRequired(option.Attachment.required).setAutocomplete(option.Attachment.autocomplete? true: false) - ) + op + .setName( + String(option.Attachment.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Attachment.description) + .setRequired(option.Attachment.required) + ); } else { - console.log(`A Option is missing the Name or/and the Description of ${pull.name}`) - } - } - } - return subcommand; - }) - client.slashCommands.set(String(cmdSetup.CmdName).replace(/\s+/g, '_').toLowerCase() + pull.name, pull) - } else { - console.log(file, `error -> missing a help.name, or help.name is not a string.`.brightRed); - continue; - } - } - //add the subcommand to the array - allCommands.push(subCommand.toJSON()); - } - else { - return console.log(`The Subcommand-Folder ${dir} is not in the dirSetup Configuration!`); - } - } else { - let pull = require(`../slashCommands/${dir}`); - if (pull.name && pull.description) { - let Command = new SlashCommandBuilder().setName(String(pull.name).toLowerCase()).setDescription(pull.description); - if(pull.options && pull.options.length > 0){ - for(const option of pull.options){ - if(option.User && option.User.name && option.User.description){ - Command.addUserOption((op) => - op.setName(String(option.User.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.User.description).setRequired(option.User.required).setAutocomplete(option.User.autocomplete? true: false) - ) - } else if(option.Integer && option.Integer.name && option.Integer.description){ - Command.addIntegerOption((op) => - op.setName(String(option.Integer.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Integer.description).setRequired(option.Integer.required).setAutocomplete(option.Integer.autocomplete? true: false) - ) - } else if(option.String && option.String.name && option.String.description){ - Command.addStringOption((op) => - op.setName(String(option.String.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.String.description).setRequired(option.String.required).setAutocomplete(option.String.autocomplete? true: false) - ) - } else if(option.Channel && option.Channel.name && option.Channel.description){ - Command.addChannelOption((op) => - op.setName(String(option.Channel.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Channel.description).setRequired(option.Channel.required).setAutocomplete(option.Channel.autocomplete? true: false) - ) - } else if(option.Role && option.Role.name && option.Role.description){ - Command.addRoleOption((op) => - op.setName(String(option.Role.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.Role.description).setRequired(option.Role.required).setAutocomplete(option.Role.autocomplete? true: false) - ) - } else if(option.StringChoices && option.StringChoices.name && option.StringChoices.description && option.StringChoices.choices && option.StringChoices.choices.length > 0){ - Command.addStringOption((op) => - op.setName(String(option.StringChoices.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.StringChoices.description).setRequired(option.StringChoices.required).setAutocomplete(option.StringChoices.autocomplete? true: false) - .addChoices(option.StringChoices.choices.map(c=> [String(c[0]).replace(/\s+/g, '_').toLowerCase(),String(c[1])] )), - ) - } else if(option.IntChoices && option.IntChoices.name && option.IntChoices.description && option.IntChoices.choices && option.IntChoices.choices.length > 0){ - Command.addStringOption((op) => - op.setName(String(option.IntChoices.name).replace(/\s+/g, '_').toLowerCase()).setDescription(option.IntChoices.description).setRequired(option.IntChoices.required).setAutocomplete(option.IntChoices.autocomplete? true: false) - .addChoices(option.IntChoices.choices.map(c=> [String(c[0]).replace(/\s+/g, '_').toLowerCase(),parseInt(c[1])] )), - ) - } else { - console.log(`A Option is missing the Name or/and the Description of ${pull.name}`) - } - } - } - allCommands.push(Command.toJSON()); - client.slashCommands.set("normal" + pull.name, pull) - } - else { - console.log(file, `error -> missing a help.name, or help.name is not a string.`.brightRed); - } - } - }); + console.log( + `A Option is missing the Name or/and the Description of ${pull.slashName}` + ); + } + } + } + return subcommand; + }); + client.slashCommands.set( + String(cmdSetup.CmdName).replace(/\s+/g, "_").toLowerCase() + + pull.slashName, + pull + ); + } else { + console.log( + file, + `error -> missing a help.name, or help.name is not a string.` + .brightRed + ); + continue; + } + } + //add the subcommand to the array + allCommands.push(subCommand.toJSON()); + } else { + return console.log( + `The Subcommand-Folder ${dir} is not in the dirSetup Configuration!` + ); + } + } else { + let pull = require(`../commands/${dir}`); + if (pull.slashName && pull.description) { + let Command = new SlashCommandBuilder() + .setName(String(pull.slashName).toLowerCase()) + .setDescription(pull.description); + if (pull.options && pull.options.length > 0) { + for (const option of pull.options) { + if (option.User && option.User.name && option.User.description) { + Command.addUserOption((op) => + op + .setName( + String(option.User.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.User.description) + .setRequired(option.User.required) + ); + } else if ( + option.Integer && + option.Integer.name && + option.Integer.description + ) { + Command.addIntegerOption((op) => + op + .setName( + String(option.Integer.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Integer.description) + .setRequired(option.Integer.required) + ); + } else if ( + option.String && + option.String.name && + option.String.description + ) { + Command.addStringOption((op) => + op + .setName( + String(option.String.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.String.description) + .setRequired(option.String.required) + .setAutocomplete(option.String.autocomplete ? true : false) + ); + } else if ( + option.Channel && + option.Channel.name && + option.Channel.description + ) { + Command.addChannelOption((op) => + op + .setName( + String(option.Channel.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Channel.description) + .setRequired(option.Channel.required) + ); + } else if ( + option.Role && + option.Role.name && + option.Role.description + ) { + Command.addRoleOption((op) => + op + .setName( + String(option.Role.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.Role.description) + .setRequired(option.Role.required) + ); + } else if ( + option.StringChoices && + option.StringChoices.name && + option.StringChoices.description && + option.StringChoices.choices && + option.StringChoices.choices.length > 0 + ) { + Command.addStringOption((op) => + op + .setName( + String(option.StringChoices.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.StringChoices.description) + .setRequired(option.StringChoices.required) + .setAutocomplete( + option.StringChoices.autocomplete ? true : false + ) + .addChoices( + option.StringChoices.choices.map((c) => [ + String(c[0]).replace(/\s+/g, "_").toLowerCase(), + String(c[1]), + ]) + ) + ); + } else if ( + option.IntChoices && + option.IntChoices.name && + option.IntChoices.description && + option.IntChoices.choices && + option.IntChoices.choices.length > 0 + ) { + Command.addStringOption((op) => + op + .setName( + String(option.IntChoices.name) + .replace(/\s+/g, "_") + .toLowerCase() + ) + .setDescription(option.IntChoices.description) + .setRequired(option.IntChoices.required) + .addChoices( + option.IntChoices.choices.map((c) => [ + String(c[0]).replace(/\s+/g, "_").toLowerCase(), + parseInt(c[1]), + ]) + ) + ); + } else { + console.log( + `A Option is missing the Name or/and the Description of ${pull.slashName}` + ); + } + } + } + allCommands.push(Command.toJSON()); + client.slashCommands.set("normal" + pull.slashName, pull); + } else { + console.log( + file, + `error -> missing a help.name, or help.name is not a string.` + .brightRed + ); + } + } + + }); + + //Once the Bot is ready, add all Slas Commands to each guild + client.on("ready", () => { + if (config.loadSlashsGlobal) { + client.application.commands + .set(allCommands) + .then((slashCommandsData) => { + console.log(`[x] :: `.cyan + `LOADED ${slashCommandsData.size} SLASH COMMANDS (with ${slashCommandsData.map((d) => d.options).flat().length} subcmds in total) after: `.brightBlue + `${Date.now() - dateNow}ms`.green) + console.log( + `Because u are Using Global Settings, it can take up to 1 hour until the Commands are changed!` + .bold.yellow + ); + }) + .catch(console.error); + } else { + client.guilds.cache + .map((g) => g) + .forEach(async (guild) => { + try { + await guild.commands.set([]).catch((e) => {}); + guild.commands + .set(allCommands) + .then((slashCommandsData) => { + console.log(`[x] :: `.cyan + `LOADED ${slashCommandsData.size} SLASH COMMANDS (with ${slashCommandsData.map((d) => d.options).flat().length} subcmds in total) Loaded for: ${`${guild.name}`.underline} after: `.brightBlue + `${Date.now() - dateNow}ms`.green) + }) + .catch(console.error); + } catch (e) { + console.log(String(e).grey); + } + }); + } + }); + if (!config.loadSlashsGlobal) { + client.on("guildCreate", async (guild) => { + try { + if (!config.loadSlashsGlobal) { + await guild.commands.set([]).catch((e) => {}); + guild.commands + .set(allCommands) + .then((slashCommandsData) => { + console.log(`[x] :: `.cyan + `LOADED ${slashCommandsData.size} SLASH COMMANDS (with ${slashCommandsData.map((d) => d.options).flat().length} subcmds in total) Loaded for: ${`${guild.name}`.underline} after: `.brightBlue + `${Date.now() - dateNow}ms`.green) + }) + .catch((e) => {}); + } - //Once the Bot is ready, add all Slas Commands to each guild - client.on("ready", () => { - if(config.loadSlashsGlobal){ - client.application.commands.set(allCommands) - .then(slashCommandsData => { - client.slashCommandsData = slashCommandsData; - console.log(`${slashCommandsData.size} slashCommands ${`(With ${slashCommandsData.map(d => d.options).flat().length} Subcommands)`.green} Loaded for all: ${`All possible Guilds`.underline}`.brightGreen); - console.log(`Because u are Using Global Settings, it can take up to 1 hour until the Commands are changed!`.bold.yellow) - }).catch(console.error); - } else { - client.guilds.cache.map(g => g).forEach(async (guild) => { - try{ - await guild.commands.set([]).catch((e)=>{}); - guild.commands.set(allCommands) - .then(slashCommandsData => { - client.slashCommandsData = slashCommandsData; - console.log(`${slashCommandsData.size} slashCommands ${`(With ${slashCommandsData.map(d => d.options).flat().length} Subcommands)`.green} Loaded for: ${`${guild.name}`.underline}`.brightGreen); - }).catch(console.error); - }catch (e){ - console.log(String(e).grey) - } - }); - } - }) - //DISABLE WHEN USING GLOBAL! - client.on("guildCreate", async (guild) => { - try{ - if(!config.loadSlashsGlobal){ - await guild.commands.set([]).catch((e)=>{}); - guild.commands.set(allCommands) - .then(slashCommandsData => { - console.log(`${slashCommandsData.size} slashCommands ${`(With ${slashCommandsData.map(d => d.options).flat().length} Subcommands)`.green} Loaded for: ${`${guild.name}`.underline}`.brightGreen); - }).catch((e)=>{}); - } - }catch (e){ - console.log(String(e).grey) - } - }) - - } catch (e) { - console.log(String(e.stack).bgRed) - } + } catch (e) { + console.log(String(e).grey); + } + }); + } + } catch (e) { + console.log(e); + } }; diff --git a/slashCommands/Info/botinfo.js b/slashCommands/Info/botinfo.js deleted file mode 100644 index cbc359e..0000000 --- a/slashCommands/Info/botinfo.js +++ /dev/null @@ -1,303 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const Discord = require("discord.js"); -const config = require("../../botconfig/config.js"); -var ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); -let cpuStat = require("cpu-stat"); -let os = require("os"); -module.exports = { - - name: "botinfo", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 1, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Shows Bot Information", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - run: async (client, interaction) => { - try { - - cpuStat.usagePercent(function (e, percent, seconds) { - try { - if (e) return console.log(String(e.stack).red); - - let connectedchannelsamount = 0; - let guilds = client.guilds.cache.map((guild) => guild); - for (let i = 0; i < guilds.length; i++) { - if (guilds[i].members.me.voice.channel) connectedchannelsamount += 1; - } - if (connectedchannelsamount > client.guilds.cache.size) connectedchannelsamount = client.guilds.cache.size; - - const botinfo = new EmbedBuilder() - .setAuthor({name: client.user.username, iconURL: client.user.displayAvatarURL()}) - .setTitle("__**Stats:**__") - .setColor(ee.color) - .addFields({ - name: '⏳ Memory Usage', - value: `\`${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)}/ ${(os.totalmem() / 1024 / 1024).toFixed(2)}MB\``, - inline: true - }, - { - name: '⌚️ Uptime', - value: `${duration(client.uptime).map(i => `\`${i}\``).join(', ')}`, - inline: true - }, - { - name: '\u200b', - value: '\u200b', - inline: true - }, - { - name: '📁 Users', - value: `\`Total: ${client.users.cache.size} Users\``, - inline: true - }, - { - name: '📁 Servers', - value: `\`Total: ${client.guilds.cache.size} Servers\``, - inline: true - }, - { - name: '\u200b', - value: '\u200b', - inline: true - }, - { - name: '📁 Voice-Channels', - value: `\`${client.channels.cache.filter((ch) => ch.type === "GUILD_VOICE" || ch.type === "GUILD_STAGE_VOICE").size}\``, - inline: true - }, - { - name: '🔊 Connections', - value: `\`${connectedchannelsamount} Connections\``, - inline: true - }, - { - name: '\u200b', - value: '\u200b', - inline: true - }, - { - name: '👾 Discord.js', - value: `\`v${Discord.version}\``, - inline: true - }, - { - name: '🤖 Node', - value: `\`${process.version}\``, - inline: true - }, - { - name: '\u200b', - value: '\u200b', - inline: true - }, - { - name: '🤖 CPU', - value: `\`\`\`md\n${os.cpus().map((i) => `${i.model}`)[0]}\`\`\``, - inline: false - }, - { - name: '🤖 CPU usage', - value: `\`${percent.toFixed(2)}%\``, - inline: true - }, - { - name: '🤖 Arch', - value: `\`${os.arch()}\``, - inline: true - }, - { - name: '\u200b', - value: '\u200b', - inline: true - }, - { - name: '💻 Platform', - value: `\`\`${os.platform()}\`\``, - inline: true - }, - { - name: 'API Latency', - value: `\`${client.ws.ping}ms\``, - inline: true - }) - .setFooter({text: "Coded by: Tejas Lamba#1924", iconURL: "https://cdn.discordapp.com/avatars/502406420453654529/d6d53ede023831dc96694de6c3de8c23.png?size=512"}); - interaction.reply({ - embeds: [botinfo] - }); - - } catch (e) { - console.log(e) - let connectedchannelsamount = 0; - let guilds = client.guilds.cache.map((guild) => guild); - for (let i = 0; i < guilds.length; i++) { - if (guilds[i].members.me.voice.channel) connectedchannelsamount += 1; - } - if (connectedchannelsamount > client.guilds.cache.size) connectedchannelsamount = client.guilds.cache.size; - const botinfo = new EmbedBuilder() - .setAuthor({text: client.user.username, iconURL: client.user.displayAvatarURL()}) - .setTitle("__**Stats:**__") - .setColor(ee.color) - .addFields({ - name: "⏳ Memory Usage", - value: `\`${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)}/ ${(os.totalmem() / 1024 / 1024).toFixed(2)}MB\``, - inline: true - }, - { - name: "⌚️ Uptime", - value: `${duration(client.uptime).map(i=>`\`${i}\``).join(", ")}`, - inline: true - }, - { - name: "\u200b", - value: "\u200b", - inline: true - }, - { - name: "📁 Users", - value: `\`Total: ${client.users.cache.size} Users\``, - inline: true - }, - { - name: "📁 Servers", - value: `\`Total: ${client.guilds.cache.size} Servers\``, - inline: true - }, - { - name: "\u200b", - value: "\u200b", - inline: true - }, - { - name: "📁 Voice-Channels", - value: `\`${client.channels.cache.filter((ch) => ch.type === "GUILD_VOICE" || ch.type === "GUILD_STAGE_VOICE").size}\``, - inline: true - }, - { - name: "🔊 Connections", - value: `\`${connectedchannelsamount} Connections\``, - inline: true - }, - { - name: "\u200b", - value: "\u200b", - inline: true - }, - { - name: "👾 Discord.js", - value: `\`v${Discord.version}\``, - inline: true - }, - { - name: "🤖 Node", - value: `\`${process.version}\``, - inline: true - }, - { - name: "\u200b", - value: "\u200b", - inline: true - }, - { - name: "🤖 CPU", - value: `\`\`\`md\n${os.cpus().map((i) => `${i.model}`)[0]}\`\`\`` - }, - { - name: "🤖 CPU usage", - value: `\`${percent.toFixed(2)}%\``, - inline: true - }, - { - name: "🤖 Arch", - value: `\`${os.arch()}\``, - inline: true - }, - { - name: "\u200b", - value: "\u200b", - inline: true - }, - { - name: "💻 Platform", - value: `\`\`${os.platform()}\`\``, - inline: true - }, - { - name: "API Latency", - value: `\`${client.ws.ping}ms\``, - inline: true - }) - .setFooter({text: "Coded by: Tejas Lamba#1924", iconURL: "https://cdn.discordapp.com/avatars/502406420453654529/d6d53ede023831dc96694de6c3de8c23.png?size=512"}); - interaction.reply({ - embeds: [botinfo] - }); - } - }) - - function duration(duration, useMilli = false) { - let remain = duration; - let days = Math.floor(remain / (1000 * 60 * 60 * 24)); - remain = remain % (1000 * 60 * 60 * 24); - let hours = Math.floor(remain / (1000 * 60 * 60)); - remain = remain % (1000 * 60 * 60); - let minutes = Math.floor(remain / (1000 * 60)); - remain = remain % (1000 * 60); - let seconds = Math.floor(remain / (1000)); - remain = remain % (1000); - let milliseconds = remain; - let time = { - days, - hours, - minutes, - seconds, - milliseconds - }; - let parts = [] - if (time.days) { - let ret = time.days + ' Day' - if (time.days !== 1) { - ret += 's' - } - parts.push(ret) - } - if (time.hours) { - let ret = time.hours + ' Hr' - if (time.hours !== 1) { - ret += 's' - } - parts.push(ret) - } - if (time.minutes) { - let ret = time.minutes + ' Min' - if (time.minutes !== 1) { - ret += 's' - } - parts.push(ret) - - } - if (time.seconds) { - let ret = time.seconds + ' Sec' - if (time.seconds !== 1) { - ret += 's' - } - parts.push(ret) - } - if (useMilli && time.milliseconds) { - let ret = time.milliseconds + ' ms' - parts.push(ret) - } - if (parts.length === 0) { - return ['instantly'] - } else { - return parts - } - } - return; - } catch (e) { - console.log(String(e.stack).bgRed) - } - } -} diff --git a/slashCommands/Info/commandcount.js b/slashCommands/Info/commandcount.js deleted file mode 100644 index df15acb..0000000 --- a/slashCommands/Info/commandcount.js +++ /dev/null @@ -1,47 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -var ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); -module.exports = { - name: "commandcount", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 1, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Shows the Amount of Commands an Categories", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - run: async (client, interaction) => { - try { - //things u can directly access in an interaction! - const { - member, - channelId, - guildId, - applicationId, - commandName, - deferred, - replied, - ephemeral, - options, - id, - createdTimestamp - } = interaction; - const { - guild - } = member; - interaction.reply({ - ephemeral: true, - embeds: [new EmbedBuilder() - .setColor(ee.color) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setDescription(`:gear: **[${client.categories.length}] Categories**\n\n:gear: **[${client.slashCommands.size + client.slashCommands.map(d => d.options).flat().length}] Slash Commands**\n\n`) - ] - }); - } catch (e) { - console.log(String(e.stack).bgRed) - } - } -} - diff --git a/slashCommands/Info/help.js b/slashCommands/Info/help.js deleted file mode 100644 index 993c85e..0000000 --- a/slashCommands/Info/help.js +++ /dev/null @@ -1,112 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -const ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); -module.exports = { - name: "help", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 1, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Returns all Commmands, or one specific command", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - options: [ //OPTIONAL OPTIONS, make the array empty / dont add this option if you don't need options! - //INFORMATIONS! You can add Options, but mind that the NAME MUST BE LOWERCASED! AND NO SPACES!!!, for the CHOCIES you need to add a array of arrays; [ ["",""] , ["",""] ] - //{"Integer": { name: "ping_amount", description: "How many times do you want to ping?", required: true }}, //to use in the code: interacton.getInteger("ping_amount") - { - "String": { - name: "specific_cmd", - description: "Want details of a Specific Command?", - required: false - } - }, //to use in the code: interacton.getString("ping_amount") - //{"User": { name: "ping_a_user", description: "To Ping a user lol", required: false }}, //to use in the code: interacton.getUser("ping_a_user") - //{"Channel": { name: "what_channel", description: "To Ping a Channel lol", required: false }}, //to use in the code: interacton.getChannel("what_channel") - //{"Role": { name: "what_role", description: "To Ping a Role lol", required: false }}, //to use in the code: interacton.getRole("what_role") - //{"IntChoices": { name: "what_ping", description: "What Ping do you want to get?", required: true, choices: [["Bot", 1], ["Discord Api", 2]] }, //here the second array input MUST BE A NUMBER // TO USE IN THE CODE: interacton.getInteger("what_ping") - //{"StringChoices": { name: "what_ping", description: "What Ping do you want to get?", required: false, choices: [["Bot", "botping"], ["Discord Api", "api"]] }}, //here the second array input MUST BE A STRING // TO USE IN THE CODE: interacton.getString("what_ping") - ], - run: async (client, interaction) => { - try { - //things u can directly access in an interaction! - const { - member, - channelId, - guildId, - applicationId, - commandName, - deferred, - replied, - ephemeral, - options, - id, - createdTimestamp - } = interaction; - const { - guild - } = member; - let prefix = '/' - let args = options.getString("specific_cmd"); - if (args && args.length > 0) { - const embed = new EmbedBuilder(); - const cmd = client.commands.get(args.toLowerCase()) || client.commands.get(client.aliases.get(args.toLowerCase())); - if (!cmd) { - return interaction.reply({ - ephemeral: true, - embeds: [embed.setColor(ee.wrongcolor).setDescription(`No Information found for command **${args.toLowerCase()}**`)] - }); - } - if (cmd.name) embed.addFields({ name: "**Command name**", value: `\`${cmd.name}\`` }); - if (cmd.name) embed.setTitle(`Detailed Information about:\`${cmd.name}\``); - if (cmd.description) embed.addFields({ name: "**Description**", value: `\`${cmd.description}\`` }); - if (cmd.aliases) embed.addFields({ name: "**Aliases**", value: `\`${cmd.aliases.map((a) => `${a}`).join("`, `")}\`` }); - embed.addFields({ name: "**Cooldown**", value: `\`${cmd.cooldown ? cmd.cooldown + " Seconds" : settings.default_cooldown_in_sec + " Second"}\`` }); - if (cmd.usage) { - embed.addFields({ name: "**Usage**", value: `\`${prefix}${cmd.usage}\`` }); - embed.setFooter({text: "Syntax: <> = required, [] = optional"}); - } - return interaction.reply({ - ephemeral: true, - embeds: [embed.setColor(ee.color)] - }); - } else { - const embed = new EmbedBuilder() - .setColor(ee.color) - .setThumbnail(client.user.displayAvatarURL()) - .setTitle("HELP MENU 🔰 Commands") - .setDescription(`**[Invite me with __Slash Commands__ Permissions](https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot%20applications.commands), cause all of my Commands are Slash Commands!**`) - .setFooter({text: `To see command Descriptions and Information, type: ${prefix}help [CMD NAME]`, iconURL: client.user.displayAvatarURL()}); - const commands = (category) => { - return client.slashCommands.filter((cmd) => cmd.category === category).map((cmd) => `\`${cmd.name}\``); - }; - try { - for (let i = 0; i < client.categories.length; i += 1) { - const current = client.categories[i]; - const items = commands(current); - embed.addFields({name: `**${current.toUpperCase()} [${items.length}]**`, value: `> ${items.join(", ")}`}); - } - } catch (e) { - console.log(String(e.stack).red); - } - interaction.reply({ - ephemeral: true, - embeds: [embed] - }); - } - } catch (e) { - console.log(String(e.stack).bgRed) - return interaction.reply({ - ephemeral: true, - embeds: [new EmbedBuilder() - .setColor(ee.wrongcolor) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setTitle(`${client.allEmojis.x} ERROR | An error occurred`) - .setDescription(`\`\`\`${e.message ? String(e.message).substr(0, 2000) : String(e).substr(0, 2000)}\`\`\``) - ] - }); - } - } -} - diff --git a/slashCommands/Info/invite.js b/slashCommands/Info/invite.js deleted file mode 100644 index b424a3b..0000000 --- a/slashCommands/Info/invite.js +++ /dev/null @@ -1,47 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -var ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); -module.exports = { - name: "invite", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 5, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Sends you an invite link", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - run: async (client, interaction) => { - try { - //things u can directly access in an interaction! - const { - member, - channelId, - guildId, - applicationId, - commandName, - deferred, - replied, - ephemeral, - options, - id, - createdTimestamp - } = interaction; - const { - guild - } = member; - interaction.reply({ - ephemeral: true, - embeds: [ - new EmbedBuilder().setColor(ee.color) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setDescription(`[**Click here to invite me!**](https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot%20applications.commands)\n\n||[**Click here to invite me __without__ Slash Commands!**](https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot)||`) - ] - }); - } catch (e) { - console.log(String(e.stack).bgRed) - } - } -} - diff --git a/slashCommands/Info/source.js b/slashCommands/Info/source.js deleted file mode 100644 index 547bef3..0000000 --- a/slashCommands/Info/source.js +++ /dev/null @@ -1,47 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -var ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); -module.exports = { - name: "source", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 5, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Sends you Source Code Information", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - run: async (client, interaction) => { - try { - //things u can directly access in an interaction! - const { - member, - channelId, - guildId, - applicationId, - commandName, - deferred, - replied, - ephemeral, - options, - id, - createdTimestamp - } = interaction; - const { - guild - } = member; - interaction.reply({ - ephemeral: true, - embeds: [ - new EmbedBuilder().setColor(ee.color) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setDescription(`**WHEN YOU USE THE SOURCE CODE, __GIVE CREDITS__!** :heart:\n\n[Link to Source](https://github.com/The-Rainbow-Studios/discord.js-v14-handler)\n\n[Youtube Tutorial]()`) - ] - }); - } catch (e) { - console.log(String(e.stack).bgRed) - } - } -} - diff --git a/slashCommands/Info/support.js b/slashCommands/Info/support.js deleted file mode 100644 index da0972d..0000000 --- a/slashCommands/Info/support.js +++ /dev/null @@ -1,43 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -var ee = require("../../botconfig/embed.js"); -const settings = require("../../botconfig/settings.js"); -module.exports = { - name: "support", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 1, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Sends a Link of the Support Server", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - run: async (client, interaction) => { - try { - //things u can directly access in an interaction! - const { - member, - channelId, - guildId, - applicationId, - commandName, - deferred, - replied, - ephemeral, - options, - id, - createdTimestamp - } = interaction; - const { - guild - } = member; - interaction.reply({ - ephemeral: true, - content: "https://discord.gg/rainbow-studios-free-codes-869916537610448897" - }); - } catch (e) { - console.log(String(e.stack).bgRed) - } - } -} - diff --git a/slashCommands/Info/uptime.js b/slashCommands/Info/uptime.js deleted file mode 100644 index 2769bbe..0000000 --- a/slashCommands/Info/uptime.js +++ /dev/null @@ -1,50 +0,0 @@ -const { - EmbedBuilder -} = require("discord.js"); -const config = require("../../botconfig/config.js"); -const ee = require("../../botconfig/embed.js"); -const { - duration -} = require("../../handlers/functions") -const settings = require("../../botconfig/settings.js"); -module.exports = { - name: "uptime", //the command name for execution & for helpcmd [OPTIONAL] - category: "Info", - cooldown: 1, //the command cooldown for execution & for helpcmd [OPTIONAL] - description: "Returns the duration on how long the Bot is online", //the command description for helpcmd [OPTIONAL] - memberpermissions: [], //Only allow members with specific Permissions to execute a Commmand [OPTIONAL] - requiredroles: [], //Only allow specific Users with a Role to execute a Command [OPTIONAL] - alloweduserids: [], //Only allow specific Users to execute a Command [OPTIONAL] - run: async (client, interaction) => { - try { - //things u can directly access in an interaction! - const { - member, - channelId, - guildId, - applicationId, - commandName, - deferred, - replied, - ephemeral, - options, - id, - createdTimestamp - } = interaction; - const { - guild - } = member; - interaction.reply({ - ephemeral: true, - embeds: [new EmbedBuilder() - .setColor(ee.color) - .setFooter({ text: ee.footertext, iconURL: ee.footericon}) - .setTitle(`:white_check_mark: **${client.user.username}** is since:\n ${duration(client.uptime).map(t=>`\`${t}\``).join(", ")} online`) - ] - }); - } catch (e) { - console.log(String(e.stack).bgRed) - } - } -} -