xyter/src/commands/manage/groups/credits/subcommands/giveaway/index.ts

168 lines
4.6 KiB
TypeScript

// 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<ButtonBuilder>().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],
});
});
};