UNPKG

discord-giveaway-easy

Version:

A module allowing the simple creation of a discord giveaway with your bot supported by Discord.js^14.0.0

548 lines (399 loc) 21.2 kB
/* A giveaway system for discord.js. */ const Discord = require("discord.js"); const {customID} = require("discord-giveaway-easy/src/Giveaway-Discord/system/customId") module.exports = class Giveaway { constructor() { this.language = null, this.interaction = null, this.embedColor = null, this.Title = null, this.footer = null, this.winnerNumber = null, this.buttonType = null, this.buttonEmoji = null, this.time = null, this.bot = null, this.status = null this.customID = customID() } /** * @param {Discord.Message} value */ setInteraction(value) { this.interaction = value return this; } /** * @param {String} value */ setLanguage(value) { this.language = value return this; } /** * @param {Number} value */ setWinnerNumber(value) { this.winnerNumber = value return this; } /** * @param {String} value */ setEmbedColor(value) { this.embedColor = value return this; } /** * @param {String} value */ setTitle(value) { this.Title = value return this; } /** * @param {String} value */ setFooter(value) { this.footer = value return this; } /** * @param {Discord.ButtonStyle} value */ setButtonType(value) { this.buttonType = value return this; } /** * @param {String} value */ setButtonEmoji(value) { this.buttonEmoji = value return this; } /** * @param {String} value */ setTime(value) { this.time = value return this; } /** * @param {Discord.Client} value */ setBot(value) { this.bot = value return this; } CreateGiveaway() { this.status = "In progress" //Discord-giveaway-easy cannot support languages ​​other than 'fr' and 'en' let language1 = "fren" // globad error if (this.language === null || !this.language) this.language = "en" if (this.footer === null || typeof this.footer !== "string") this.footer = "Discord-Giveaway-Easy" if (this.embedColor === null || typeof this.embedColor !== "string") this.embedColor = "#ffffff" if (this.disableShareButton === null || typeof this.disableShareButton !== "boolean") this.disableShareButton = false if (this.winnerNumber === null || typeof this.winnerNumber !== "number") throw new Error("setWinnerNumber must be a number."); if (this.interaction === null || !this.interaction.channel || this.interaction.channel === null) throw new Error("setInteraction must be a Discord Interaction."); if (this.buttonType === null) this.buttonType = Discord.ButtonStyle.Primary if (this.buttonEmoji === null || typeof this.buttonEmoji !== "string") this.buttonEmoji = "🎉" if (this.Title === null || typeof this.Title !== "string") throw new Error("setTitle must be a string."); if (this.time === null || typeof this.time !== "string") throw new Error("setTime must be a string."); if (this.bot === null || !this.bot.token || this.bot.token === null) throw new Error("setBot must be a Discord Client and must have a token."); if (!language1.includes(this.language)) throw new Error("You can enter 2 languages: 'fr' and 'en'. No other languages translated."); // time system if (this.language === "en") { //initialisation of setWinner's and setButtonType's error let keyButtonType = [ '1', '2', '3', '4', '5' ]; // button type error if (!keyButtonType.includes(String(this.buttonType))) throw new Error("Pls, enter 'Primary', 'Secondary', 'Success', 'Danger' or 'Link' on setButtonType argument.") if (typeof this.winnerNumber !== "number") throw new Error("Pls, enter a number in setWninnerNumber.") //initialisation of time error let timeString = "mhj" //time error for type of time if (!timeString.includes(this.time.slice(this.time.length - 1))) throw new Error("Pls, include in setTime argument 'm', 'h' or 'j' after you number.") //time error for check if there is a number before the type of time. let numebrTime = this.time.replace(this.time.slice(this.time.length - 1), "") if (numebrTime === "") numebrTime = null if (numebrTime === null) throw new Error("Pls, enter a number before your type of time in setTime argument.") if (Number(numebrTime) < 1 && Number(numebrTime) > 0) throw new Error("Pls, enter a whole number before your type of time in setTime argument.") if (!Number.isInteger(Number(numebrTime))) throw new Error("Pls, enter a whole number before your type of time in setTime argument.") //time system for filter type of time and number for initialised it in a let variable if (this.time?.includes("m")) { let m = this.time var time = parseInt(Number(m?.replace("m", "")) * 60) } if (this.time?.includes("h")) { let m = this.time var time = parseInt(Number(m?.replace("h", "")) * 3600) } if (this.time?.includes("d")) { let m = this.time var time = parseInt(Number(m?.replace("d", "")) * 86400) } let secondes = Math.floor((Date.now() / 1000) + (time)) if (typeof time !== "number") throw new Error("Pls, enter Number for setTime argument.") //convert a time in second to millisecond let ms = time * 1000 if (ms > 2147483647) throw new Error("You cannot enter a value with milliseconds greater than 2,147,483,647. Or, you cannot enter a value superior to 3 weeks and 5 days.") //interaction button /** * @param {Discord.Interaction} interaction */ let giveawayRamdom = [] //system global bot command let messageId; this.bot?.on("interactionCreate", async (interaction) => { if (interaction.type = Discord.InteractionType.MessageComponent) { if (interaction.customId === this.customID) { messageId = interaction.message.id if (giveawayRamdom.includes(`${interaction.user.id}`)) { return interaction?.reply({content: 'You are already in the list for this giveaway!', ephemeral: true}) } else { await interaction?.reply({content: 'You have been queued for this giveaway. Good luck!', ephemeral: true}) giveawayRamdom.push(interaction.user.id) let Embed = new Discord.EmbedBuilder() .setTitle(this.Title) .setDescription(`Please click on the button ${this.buttonEmoji} to participate in the giveaway.\nEnd of the giveaway: <t:${secondes}:R>\nPosted by: **<@${this.interaction?.user?.id}>**\nNumber of winners: **${this.winnerNumber}**`) .setColor(this.embedColor) .setFooter({text: `Attendees: ${giveawayRamdom.length} | ${this.footer}`}) .setTimestamp() return this.interaction.channel.messages.fetch(messageId).then(mess => mess.edit({embeds: [Embed], components: [this.getButton()]})); } } } }) //save data in local database let guild; let timeArray; let winnernumber; if (this.time && this.winnerNumber) { timeArray = time winnernumber = this.winnerNumber } else { guild = undefined timeArray = undefined winnernumber = undefined } // start timeOut of the time corresponding at the time of the giveaway for choice a winners after it. let WinnerTimeOut = setTimeout(() => { if (messageId === null || !messageId || giveawayRamdom.length < 1) return this.interaction.channel.send("Error ❌ : this giveaway can't be finished.") function randomWinner(number) { // const toDeleteDuplicates = arry => arry.filter((item, index) => arry.indexOf(item) == index) const toFindDuplicates = arry => arry.filter((item, index) => arry.indexOf(item) !== index) let arryDuplicate = toFindDuplicates(giveawayRamdom) let tirage = [] if (number === giveawayRamdom.length || number > giveawayRamdom.length) { tirage.push(`<@${giveawayRamdom.join(">, <@")}>`) return tirage } for(let i = 0; i < (number + arryDuplicate); i++) { tirage.push(`<@${giveawayRamdom[Math.floor(Math.random() * giveawayRamdom.length)]}>`) } return tirage.join(", ") } let EmbedsEnding = new Discord.EmbedBuilder() .setTitle(`${this.Title}`) .setDescription(`The winner is ${randomWinner(winnernumber)}!\nThe giveaway **${this.Title}** has been closed.`) .setFooter({text : `Attendees: ${giveawayRamdom.length} | winners: ${this.winnerNumber}`}) .setColor(this.embedColor) .setTimestamp() this.interaction.channel.messages.fetch(messageId).then(mess => mess.edit({content: "🎉🎉 **GIVEAWAY ENDED** 🎉🎉", embeds: [EmbedsEnding], components: []})) giveawayRamdom = []; this.status = "To end" // clear that timeOut clearTimeout(WinnerTimeOut); }, ms) } //======================== //======================== //======================== //======================== //======================== //======================== if (this.language === "fr") { //initialisation of setWinner's and setButtonType's error let keyButtonType = [ '1', '2', '3', '4', '5' ]; // button type error if (!keyButtonType.includes(String(this.buttonType))) throw new Error("Svp, entrer 'Primary', 'Secondary', 'Success', 'Danger' ou 'Link' dans l'argument setButtonType.") if (typeof this.winnerNumber !== "number") throw new Error("Svp, entrer un nombre dans setWninnerNumber.") //initialisation of time error let timeString = "mhj" //time error for type of time if (!timeString.includes(this.time.slice(this.time.length - 1))) throw new Error("Svp, veuillez inclure dans l'argument setTime 'm', 'h' or 'j' après votre nombre.") //time error for check if there is a number before the type of time. let numebrTime = this.time.replace(this.time.slice(this.time.length - 1), "") if (numebrTime === "") numebrTime = null if (numebrTime === null) throw new Error("Svp, entrer un numbre avant votre type de temps dans l'argument setTime.") if (Number(numebrTime) < 1 && Number(numebrTime) > 0) throw new Error("Svp, entrer un nombre entier avant votre type de temps dans l'argument setTime.") if (!Number.isInteger(Number(numebrTime))) throw new Error("Svp, entrer un nombre entier avant votre type de temps dans l'argument setTime.") //time system for filter type of time and number for initialised it in a let variable if (this.time?.includes("m")) { let m = this.time var time = parseInt(Number(m?.replace("m", "")) * 60) } if (this.time?.includes("h")) { let m = this.time var time = parseInt(Number(m?.replace("h", "")) * 3600) } if (this.time?.includes("j")) { let m = this.time var time = parseInt(Number(m?.replace("j", "")) * 86400) } let secondes = Math.floor((Date.now() / 1000) + (time)) if (typeof time !== "number") throw new Error("Svp, entrer un nombre pour l'argument setTime.") //convert a time in second to millisecond let ms = time * 1000 if (ms > 2147483647) throw new Error("Vous ne pouvez pas entrer une valeur avec des millisecondes supérieures à 2 147 483 647. Ou, vous ne pouvez pas entrer une valeur supérieure à 3 semaines et 5 jours.") //interaction button /** * @param {Discord.Interaction} interaction */ let giveawayRamdom = [] //system global bot command let messageId; this.bot?.on("interactionCreate", async (interaction) => { if (interaction.type = Discord.InteractionType.MessageComponent) { if (interaction.customId === this.customID) { messageId = interaction.message.id if (giveawayRamdom.includes(`${interaction.user.id}`)) { interaction?.reply({content: 'Vous êtes déjà dans la liste pour ce giveaway!', ephemeral: true}) } else { await interaction?.reply({content: "Vous avez été mis en file d'attente pour ce giveaway. Bonne chance!", ephemeral: true}) giveawayRamdom.push(interaction.user.id) let Embed = new Discord.EmbedBuilder() .setTitle(this.Title) .setDescription(`Cliquer sur le button ${this.buttonEmoji} pour participer au giveaway.\nFin du giveaway : <t:${secondes}:R>\nPosté par : **<@${this.interaction?.user?.id}>**\nNombre de gagnant.e.s : **${this.winnerNumber}**`) .setColor(this.embedColor) .setFooter({text: `Participants : ${giveawayRamdom.length} | ${this.footer}`}) .setTimestamp() return this.interaction.channel.messages.fetch(messageId).then(mess => mess.edit({embeds: [Embed], components: [this.getButton()]})); } } } }) //save data in local database let guild; let timeArray; let winnernumber; if (this.time && this.winnerNumber) { timeArray = time winnernumber = this.winnerNumber } else { guild = undefined timeArray = undefined winnernumber = undefined messageId = undefined } // start timeOut of the time corresponding at the time of the giveaway for choice a winners after it. let WinnerTimeOut = setTimeout(() => { if (messageId === null || !messageId || giveawayRamdom.length < 1) return this.interaction.channel.send("Erreur ❌ : ce giveaway ne peut pas être terminé.") function randomWinner(number) { // const toDeleteDuplicates = arry => arry.filter((item, index) => arry.indexOf(item) == index) const toFindDuplicates = arry => arry.filter((item, index) => arry.indexOf(item) !== index) let arryDuplicate = toFindDuplicates(giveawayRamdom) let tirage = [] if (number === giveawayRamdom.length || number > giveawayRamdom.length) { tirage.push(`<@${giveawayRamdom.join(">, <@")}>`) return tirage } for(let i = 0; i < (number + arryDuplicate); i++) { tirage.push(`<@${giveawayRamdom[Math.floor(Math.random() * giveawayRamdom.length)]}>`) } return tirage.join(", ") } let EmbedsEnding = new Discord.EmbedBuilder() .setTitle(`${this.Title}`) .setDescription(`Le gagnant est ${randomWinner(winnernumber)}!\nLe giveaway **${this.Title}** a été fermer.`) .setFooter({text : `Participants : ${giveawayRamdom.length} | gagnants : ${this.winnerNumber}`}) .setColor(this.embedColor) .setTimestamp() this.interaction.channel.messages.fetch(messageId).then(mess => mess.edit({content: "🎉🎉 **GIVEAWAY TERMINE** 🎉🎉", embeds: [EmbedsEnding], components: []})) giveawayRamdom = []; this.status = "To end" // clear that timeOut clearTimeout(WinnerTimeOut); }, ms) } return this; } getEmbed() { if (!this.Title) throw new Error("setTitle must be a string.") if (!this.buttonEmoji) throw new Error("setButtonEmoji must be a string.") if (!this.interaction) throw new Error("setInteraction must be a Discord Interaction.") if (!this.embedColor) throw new Error("setEmbedColor must be a String.") if (!this.footer) throw new Error("setFooter must be a String.") if (this.language === "en") { if (this.time?.includes("m")) { let m = this.time var time = parseInt(Number(m?.replace("m", "")) * 60) } if (this.time?.includes("h")) { let m = this.time var time = parseInt(Number(m?.replace("h", "")) * 3600) } if (this.time?.includes("d")) { let m = this.time var time = parseInt(Number(m?.replace("d", "")) * 86400) } let secondes = Math.floor((Date.now() / 1000) + (time)) let Embed = new Discord.EmbedBuilder() .setTitle(this.Title) .setDescription(`Please click on the button ${this.buttonEmoji} to participate in the giveaway.\nEnd of the giveaway: <t:${secondes}:R>\nPosted by: **<@${this.interaction?.user?.id}>**\nNumber of winners: **${this.winnerNumber}**`) .setColor(this.embedColor) .setFooter({text: `Attendees: 0 | ${this.footer}`}) .setTimestamp() return Embed; } if (this.language === "fr") { if (this.time?.includes("m")) { let m = this.time var time = parseInt(Number(m?.replace("m", "")) * 60) } if (this.time?.includes("h")) { let m = this.time var time = parseInt(Number(m?.replace("h", "")) * 3600) } if (this.time?.includes("j")) { let m = this.time var time = parseInt(Number(m?.replace("j", "")) * 86400) } let secondes = Math.floor((Date.now() / 1000) + (time)) let Embed = new Discord.EmbedBuilder() .setTitle(this.Title) .setDescription(`Cliquer sur le button ${this.buttonEmoji} pour participer au giveaway.\nFin du giveaway : <t:${secondes}:R>\nPosté par : **<@${this.interaction?.user?.id}>**\nNombre de gagnant.e.s : **${this.winnerNumber}**`) .setColor(this.embedColor) .setFooter({text: `Participants : 0 | ${this.footer}`}) .setTimestamp() return Embed; } } getButton() { if (!this.buttonEmoji) throw new Error("setButtonEmoji must be a string.") if (!this.buttonType) throw new Error("setButtonType must be a string.") if (this.language === "en") { const button = new Discord.ActionRowBuilder() .addComponents( new Discord.ButtonBuilder() .setCustomId(this.customID) .setLabel('Participate') .setEmoji(this.buttonEmoji) .setStyle(this.buttonType) ) return button; } if (this.language === "fr") { const button = new Discord.ActionRowBuilder() .addComponents( new Discord.ButtonBuilder() .setCustomId(this.customID) .setLabel('Participer') .setEmoji(this.buttonEmoji) .setStyle(this.buttonType) ) return button; } } }