// Dependencies import axios from "axios"; import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, ChatInputCommandInteraction, EmbedBuilder, PermissionsBitField, SlashCommandSubcommandBuilder, } from "discord.js"; import { v4 as uuidv4 } from "uuid"; import encryption from "../../../../../../helpers/encryption"; // Configurations import prisma from "../../../../../../handlers/database"; import deferReply from "../../../../../../handlers/deferReply"; import checkPermission from "../../../../../../helpers/checkPermission"; import getEmbedConfig from "../../../../../../helpers/getEmbedData"; import logger from "../../../../../../middlewares/logger"; // Function export const builder = (command: SlashCommandSubcommandBuilder) => { return command .setName("giveaway") .setDescription("Giveaway some credits for specified amount of users.") .addIntegerOption((option) => option .setName("uses") .setDescription("How many users should be able to use this.") .setRequired(true) ) .addIntegerOption((option) => option .setName("credit") .setDescription(`How much credits provided per use.`) .setRequired(true) ) .addChannelOption((option) => option .setName("channel") .setDescription("The channel to send the message to.") .setRequired(true) .addChannelTypes(ChannelType.GuildText) ); }; export const execute = async (interaction: ChatInputCommandInteraction) => { await deferReply(interaction, true); checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); const { successColor, footerText, footerIcon } = await getEmbedConfig( interaction.guild ); // Destructure const { guild, user, options } = interaction; const uses = options?.getInteger("uses"); const creditAmount = options?.getInteger("credit"); const channel = options?.getChannel("channel"); if (!uses) throw new Error("Amount of uses is required."); if (!creditAmount) throw new Error("Amount of credits is required."); if (!channel) throw new Error("Channel is required."); if (!guild) throw new Error("Guild is required."); const embed = new EmbedBuilder() .setTitle("[:toolbox:] Giveaway") .setFooter({ text: footerText, iconURL: footerIcon }); const code = uuidv4(); const createGuildMember = await prisma.guildConfigApisCpgg.upsert({ where: { id: guild.id, }, update: {}, create: { guild: { connectOrCreate: { create: { id: guild.id, }, where: { id: guild.id, }, }, }, }, include: { guild: true, }, }); logger.silly(createGuildMember); if (!createGuildMember.urlIv || !createGuildMember.urlContent) throw new Error("No API url available"); if (!createGuildMember.tokenIv || !createGuildMember.tokenContent) throw new Error("No API token available"); const url = encryption.decrypt({ iv: createGuildMember.urlIv, content: createGuildMember.urlContent, }); const api = axios?.create({ baseURL: `${url}/api/`, headers: { Authorization: `Bearer ${encryption.decrypt({ iv: createGuildMember.tokenIv, content: createGuildMember.tokenContent, })}`, }, }); const shopUrl = `${url}/store`; await api .post("vouchers", { uses, code, credits: creditAmount, memo: `[GIVEAWAY] ${interaction?.createdTimestamp} - ${interaction?.user?.id}`, }) .then(async () => { await interaction.editReply({ embeds: [ embed .setColor(successColor) .setDescription(`Successfully created code: ${code}`), ], }); const buttons = new ActionRowBuilder().addComponents( new ButtonBuilder() .setLabel("Redeem it here") .setStyle(ButtonStyle.Link) .setEmoji("🏦") .setURL(`${shopUrl}?voucher=${code}`) ); const discordChannel = guild?.channels.cache.get(channel.id); if (!discordChannel) return; if (discordChannel.type !== ChannelType.GuildText) return; discordChannel.send({ embeds: [ new EmbedBuilder() .setTitle("[:parachute:] Credits!") .addFields([ { name: "💶 Credits", value: `${creditAmount}`, inline: true, }, ]) .setDescription( `${interaction.user} dropped a voucher for a maximum **${uses}** members!` ) .setColor(successColor), ], components: [buttons], }); }); };