UNPKG

giftcord

Version:

Giveaway discord.js Package

265 lines (211 loc) 9.5 kB
const mongoose = require('mongoose'); const Discord = require('discord.js'); const Giveaway = require('./Giveaway'); const moment = require('moment'); const ms = require("ms") const { schedule } = require('../Functions/Schedule.js'); const { getWinner } = require('../Functions/getWinner.js'); const { endGiveaway } = require('../Functions/endGiveaway.js'); const GiveawayModel = require('../models/Giveaway'); const scheduler = require('node-schedule'); const { EventEmitter } = require('events'); class GiveawayCreator extends EventEmitter { /** * * @param {Discord.Client} client - A discord.js client. * @param {string} url - A MongoDB connection string. */ constructor(client, url = '', color = 0x7289da) { super(); if (!client) throw new Error("A client wasn't provided."); if (!url) throw new Error("A connection string wasn't provided."); this.client = client; this.mongoUrl = url; this.color = color; mongoose.connect(this.mongoUrl); this.client.on('ready', async () => { const now = new Date(); const giveaways = await GiveawayModel.find({ endsOn: { $gt: now }, hasEnded: 'False' }); await schedule(this, giveaways); }); } /** * * @param {GiveawayOptions} options - Options for the giveaway. */ async startGiveaway(options) { if (!options.duration) throw new Error("You didn't provide a duration."); let validDuration = false; if (options.duration.endsWith("s") || options.duration.endsWith("m") || options.duration.endsWith("h") || options.duration.endsWith("d")) { validDuration = true; } if (!validDuration) { throw new Error("Please provide a correct duration format (e.g., 1s, 1m, 1h, 1d)"); } if (!options.emoji) throw new Error("You didn't provide a emoji."); if(options.emoji.length > 2) throw new Error("Please Provide one Emoji.") if (!options.channelId) throw new Error("You didn't provide a channel ID."); if (!options.guildId) throw new Error("You didn't provide a guild ID."); if (!options.prize) throw new Error("You didn't provide a prize."); if (!options.winners || isNaN(options.winners)) throw new Error("You didn't provide an amount of winners OR winners is not a number."); if (!options.hostedBy) throw new Error("Please provide a user ID for the person who hosted the giveaway."); const guild = this.client.guilds.cache.get(options.guildId); const channel = guild.channels.cache.get(options.channelId); const user = this.client.users.cache.get(options.hostedBy) const giveawayEmbed = new Discord.EmbedBuilder() .setTitle(options.prize) .setThumbnail(guild.iconURL({dynamic: true})) .setColor(this.color) .setDescription(`** ・Winners: ${options.winners} ・Ends: <t:${Math.floor((Date.now() + ms(options.duration)) / 1000)}:R> ・Hosted By: ${user.toString()} ・React with ${options.emoji} to participate! **`) .setFooter({text: `Ends `}) .setTimestamp(new Date(Date.now() + ms(options.duration))); const msg = await channel.send({ embeds: [giveawayEmbed] }); await msg.react(options.emoji); const newGiveaway = new Giveaway({ prize: options.prize, emoji: options.emoji, duration: ms(options.duration), channelId: options.channelId, guildId: options.guildId, endsOn: new Date(Date.now() + ms(options.duration)), startsOn: new Date(), messageId: msg.id, winners: options.winners, hostedBy: options.hostedBy }); await schedule(this, [newGiveaway]); this.emit('giveawayStart', newGiveaway); return newGiveaway; } /** * * @param {string} messageId - A discord message ID. */ async endGiveaway(messageId) { let data = await GiveawayModel.findOne({ messageId: messageId }); if (!data) return false; if (data.hasEnded === 'True') return false; const job = scheduler.scheduledJobs[`${messageId}`]; if (!job) return false; job.cancel(); const channel = this.client.channels.cache.get(data.channelId); if (channel) { const message = await channel.messages.fetch(messageId); if (message) { const { embeds, reactions } = message; const reaction = reactions.cache.get(data.emoji); const users = await reaction.users.fetch(); const entries = users.filter(user => !user.bot); if (embeds.length === 1) { const usersArray = Array.from(entries.values()); const winner = getWinner(usersArray, data.winners); let finalWinners; if (!winner) { finalWinners = 'Nobody Reacted'; } else { finalWinners = winner.map(user => user.toString()).join(', '); } let embed = new Discord.EmbedBuilder() embed.setDescription(`**🎖️ Winner(s): ${finalWinners}**`); embed.setFooter({text: this.client.user.username, iconURL: this.client.user.displayAvatarURL({ extension: 'png', size: 512 })}); embed.setTimestamp(); await message.edit({ embeds: [embed] }); if (!winner) { message.channel.send(`Nobody reacted to the **${data.prize}** giveaway. `); } else { message.channel.send(`**Congratulations ${finalWinners}, you won the ${data.prize}!**`); const wins = winner for (const win of wins) { win.send(`### Congratulations ${win}, you won the ${data.prize}!\n **MSG LINK: **${message.url}`).catch(() => {}) } const ended = await endGiveaway(messageId); this.emit('giveawayEnd', ended); } } } return data; } } /** * * @param {string} messageId - A discord message ID. */ async fetchGiveaway(messageId) { const giveaway = await GiveawayModel.findOne({ messageId: messageId }); if (!giveaway) return false; return giveaway; } /** * * @param {string} messageId - A discord message ID. */ async rerollGiveaway(messageId) { const giveaway = await GiveawayModel.findOne({ messageId: messageId }); if (!giveaway) return false; if (giveaway.hasEnded === 'False') return false; const channel = this.client.channels.cache.get(giveaway.channelId); if (channel) { const message = await channel.messages.fetch(messageId); if (message) { const { embeds, reactions } = message; const reaction = reactions.cache.get(giveaway.emoji); if (!reaction || reaction.count < 2) { return message.channel.send("**Nobody Reacted, I Can't Reroll Giveaway**"); } const users = await reaction.users.fetch(); const entries = users.filter(user => !user.bot); const usersArray = Array.from(entries.values()); const winner = getWinner(usersArray, giveaway.winners); let finalWinners; if (!winner) { finalWinners = 'Nobody Reacted'; message.channel.send(`Nobody reacted to the **${giveaway.prize}** giveaway. **ID**: \`${messageId}\`\n${message.url}`); } else { finalWinners = winner.map(user => user.toString()).join(', '); message.channel.send(`**Congratulations ${finalWinners}, you won the ${giveaway.prize}!**`); const wins = winner for (const win of wins) { win.send(`### Congratulations ${win}, you won the ${giveaway.prize}!\n **MSG LINK: **${message.url}`).catch(() => {}) } if (embeds.length === 1) { const embed = new Discord.EmbedBuilder() embed.setDescription(`🎖️ Winner(s): ${finalWinners}`); await message.edit({ embeds: [embed] }); } } } this.emit('giveawayReroll', giveaway); return giveaway; } } /** * * @param {string} guildId - A discord guild ID. */ async listGiveaways(guildId) { if (!guildId) throw new Error("Please provide a guild ID."); const Giveaways = await GiveawayModel.find({ guildId: guildId, hasEnded: 'False' }); if (Giveaways.length < 1) return false; const array = []; Giveaways.map(async (i) => { const user = this.client.users.get(i.hostedBy) if(!user) user = "Unknown" array.push({ hostedBy:user.displayName, timeRemaining: i.endsOn - Date.now(), messageId: i.messageId, prize: i.prize }); return array; }) } } module.exports = GiveawayCreator;