diff --git a/.env.example b/.env.example index 063b7f2..9362bc7 100644 --- a/.env.example +++ b/.env.example @@ -2,4 +2,5 @@ TOKEN= CLIENT_ID= GUILD_ID= SOURCEJUMP_API_KEY= -SOURCEJUMP_API_URL= \ No newline at end of file +SOURCEJUMP_API_URL= +CHANNEL diff --git a/index.js b/index.js index 40380b9..8f30275 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,8 @@ const fs = require('fs'); const path = require('path'); const { REST } = require('@discordjs/rest'); const { Routes } = require('discord-api-types/v9'); -const { Client, Collection, Intents } = require('discord.js'); +const { Client, Collection, Intents, MessageEmbed } = require('discord.js'); +const { modalSubmitGiveaway } = require('./src/events/giveaway.js'); const token = process.env.TOKEN; const clientId = process.env.CLIENT_ID; @@ -59,11 +60,13 @@ const rest = new REST({ version: '9' }).setToken(token); } })(); -client.once('ready', () => { - console.log('Ready!'); -}); - client.on('interactionCreate', async (interaction) => { + if (interaction.isModalSubmit()) { + if (interaction.customId == 'giveaway') { + modalSubmitGiveaway(interaction); + } + } + if (!interaction.isCommand()) { return; } @@ -85,4 +88,8 @@ client.on('interactionCreate', async (interaction) => { } }); +client.once('ready', () => { + console.log('Ready!'); +}); + client.login(token); diff --git a/src/commands/giveaway.js b/src/commands/giveaway.js new file mode 100644 index 0000000..bdbc368 --- /dev/null +++ b/src/commands/giveaway.js @@ -0,0 +1,52 @@ +const { SlashCommandBuilder } = require('@discordjs/builders'); +const { Modal, MessageActionRow, TextInputComponent } = require('discord.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName('giveaway') + .setDescription('An admin command for creating giveaways'), + async execute(interaction) { + const modal = new Modal() + .setCustomId('giveaway') + .setTitle('Create a giveaway') + .addComponents([ + new MessageActionRow().addComponents( + new TextInputComponent() + .setCustomId('gameKey') + .setLabel('Game Key') + .setStyle('SHORT') + .setRequired(true), + ), + new MessageActionRow().addComponents( + new TextInputComponent() + .setCustomId('description') + .setLabel('Description') + .setStyle('SHORT') + .setRequired(true), + ), + new MessageActionRow().addComponents( + new TextInputComponent() + .setCustomId('timeLimit') + .setLabel('Time Limit (In Minutes)') + .setStyle('SHORT') + .setRequired(true), + ), + new MessageActionRow().addComponents( + new TextInputComponent() + .setCustomId('emoji') + .setLabel('Emoji (To React With, without ::)') + .setStyle('SHORT') + .setRequired(true), + ), + new MessageActionRow().addComponents( + new TextInputComponent() + .setCustomId('imageUrl') + .setLabel('Image URL') + .setStyle('SHORT') + .setRequired(false), + ), + ]); + + await interaction.showModal(modal); + }, +}; diff --git a/src/events/giveaway.js b/src/events/giveaway.js new file mode 100644 index 0000000..cf42e23 --- /dev/null +++ b/src/events/giveaway.js @@ -0,0 +1,130 @@ +const { MessageEmbed } = require('discord.js'); + +function createGiveawayEmbed(description, timelimit, emoji, image, winner) { + let standardEmbedFields = [ + { + name: '🎁 Item', + value: description, + }, + { + name: '➡️ How to enter', + value: 'React to this message with ' + emoji, + }, + { + name: '🏆 Winners', + value: 'Winners are picked at random, and prizes are sent automatically through a direct message here on Discord when the giveaway concludes. Make sure you allow direct messages from other members!', + }, + ]; + if (winner != '') { + let embed = new MessageEmbed() + .setColor('GREEN') + .addFields( + standardEmbedFields[0], + standardEmbedFields[1], + standardEmbedFields[2], + { + name: '🏁 Giveaway ended', + value: 'Winner: ' + winner, + }, + ) + .setImage(image) + .setFooter({ text: `Giveaway ended` }); + return embed; + } + let embed = new MessageEmbed() + .setColor('YELLOW') + .addFields( + standardEmbedFields[0], + standardEmbedFields[1], + standardEmbedFields[2], + ) + .setImage(image) + .setFooter({ + text: `Ending in ${Math.ceil(timelimit / 60)} ${ + Math.ceil(timelimit / 60) < 2 ? 'hour' : 'hours' + }`, + }); + return embed; +} + +async function modalSubmitGiveaway(interaction) { + //const channel = '838711380076396574'; + const channel = process.env.CHANNEL; + const gamekey = interaction.fields.getTextInputValue('gameKey'); + const description = interaction.fields.getTextInputValue('description'); + let timelimit = interaction.fields.getTextInputValue('timeLimit'); + if (isNaN(timelimit)) { + await interaction.reply({ + content: 'Timelimit has to be integer.', + ephemeral: true, + }); + return; + } + const emoji = `${interaction.client.emojis.cache.find( + (emoji) => emoji.name == interaction.fields.getTextInputValue('emoji'), + )}`; + if (emoji == 'undefined') { + await interaction.reply({ + content: 'Emoji not found. Only custom server-emojis work.', + ephemeral: true, + }); + return; + } + let image = ''; + if (interaction.fields.getTextInputValue('imageUrl') != null) { + image = interaction.fields.getTextInputValue('imageUrl'); + } + + let embed = createGiveawayEmbed(description, timelimit, emoji, image, ''); + + let msg = await interaction.client.channels.cache + .get(channel) + .send({ embeds: [embed] }); + msg.react(emoji); + + let interval = setInterval(() => { + timelimit -= 1; + embed = createGiveawayEmbed(description, timelimit, emoji, image, ''); + msg.edit({ embeds: [embed] }); + if (timelimit < 1) { + clearInterval(interval); + let winner; + msg.reactions.cache.map(async (reaction) => { + let emojiName = emoji.split(':')[1]; + if (reaction.emoji.name !== emojiName) return; + let usersThatReacted = []; + let reactedUsers = await reaction.users.fetch(); + reactedUsers.map((user) => { + if (user != msg.author) { + usersThatReacted.push(user); + } + }); + if (usersThatReacted.length == 0) { + winner = 'No one reacted! :('; + } else { + winner = + usersThatReacted[ + Math.floor(Math.random() * usersThatReacted.length) + ]; + winner.send( + `Congratulations! You won the giveaway for ${description}. \nYour Game key: ${gamekey}`, + ); + } + + embed = createGiveawayEmbed( + description, + timelimit, + emoji, + image, + winner.toString(), + ); + msg.edit({ embeds: [embed] }); + }); + } + }, 60000); + await interaction.reply({ content: 'Giveaway created.', ephemeral: true }); +} + +module.exports = { + modalSubmitGiveaway, +};