242 lines
7 KiB
TypeScript
242 lines
7 KiB
TypeScript
// Dependencies
|
|
import { CommandInteraction, ColorResolvable } from "discord.js";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
import axios from "axios";
|
|
|
|
// Configurations
|
|
import config from "../../../../config.json";
|
|
|
|
// Handlers
|
|
import logger from "../../../logger";
|
|
import encryption from "../../../handlers/encryption";
|
|
|
|
// Helpers
|
|
import pluralize from "../../../helpers/pluralize";
|
|
|
|
// Models
|
|
import apiSchema from "../../../database/schemas/api";
|
|
import fetchUser from "../../../helpers/fetchUser";
|
|
|
|
// Function
|
|
export default async (interaction: CommandInteraction) => {
|
|
const { options, guild, user, client } = interaction;
|
|
|
|
// Get options
|
|
const optionAmount = options?.getInteger("amount");
|
|
|
|
// If amount is null
|
|
if (optionAmount === null) {
|
|
// Embed object
|
|
const embed = {
|
|
title: ":dollar: Credits [Gift]" as string,
|
|
description: "We could not read your requested amount." as string,
|
|
color: config?.colors?.error as ColorResolvable,
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
|
|
// Send interaction reply
|
|
return interaction?.editReply({ embeds: [embed] });
|
|
}
|
|
|
|
if (guild === null) return;
|
|
|
|
// Get user object
|
|
const userDB = await fetchUser(user, guild);
|
|
|
|
if (userDB === null) return;
|
|
|
|
// Get DM user object
|
|
const dmUser = client?.users?.cache?.get(user?.id);
|
|
|
|
// Stop if amount or user credits is below 100
|
|
if ((optionAmount || userDB?.credits) < 100) {
|
|
const embed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description:
|
|
`You **can't** withdraw for __Pterodactyl__ below **100**.` as string,
|
|
color: config?.colors?.error as ColorResolvable,
|
|
fields: [
|
|
{
|
|
name: "Your balance" as string,
|
|
value: `${pluralize(userDB?.credits, "credit")}` as string,
|
|
},
|
|
],
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
return interaction?.editReply({ embeds: [embed] });
|
|
}
|
|
|
|
// Stop if amount or user credits is above 1.000.000
|
|
if ((optionAmount || userDB?.credits) > 1000000) {
|
|
const embed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description:
|
|
`You **can't** withdraw for __Pterodactyl__ above **1.000.000**.` as string,
|
|
color: config?.colors?.error as ColorResolvable,
|
|
fields: [
|
|
{
|
|
name: "Your balance" as string,
|
|
value: `${pluralize(userDB?.credits, "credit")}` as string,
|
|
},
|
|
],
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
return interaction?.editReply({ embeds: [embed] });
|
|
}
|
|
|
|
// Stop if user credits is below amount
|
|
if (userDB?.credits < optionAmount) {
|
|
const embed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description: `You have **insufficient** credits.` as string,
|
|
color: config.colors.error as ColorResolvable,
|
|
fields: [
|
|
{
|
|
name: "Your balance" as string,
|
|
value: `${pluralize(userDB?.credits, "credit")}` as string,
|
|
},
|
|
],
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
return interaction?.editReply({ embeds: [embed] });
|
|
}
|
|
|
|
// Generate a unique voucher for the user
|
|
const code = uuidv4();
|
|
|
|
// Get api object
|
|
const apiCredentials = await apiSchema?.findOne({
|
|
guildId: guild?.id,
|
|
});
|
|
|
|
// Create a api instance
|
|
const api = axios?.create({
|
|
baseURL: apiCredentials?.url,
|
|
headers: {
|
|
Authorization: `Bearer ${encryption.decrypt(apiCredentials?.token)}`,
|
|
},
|
|
});
|
|
|
|
// Get shop URL
|
|
const shopUrl = apiCredentials?.url?.replace("/api", "/store");
|
|
|
|
// Make API request
|
|
await api
|
|
|
|
// Make a post request to the API
|
|
?.post("vouchers", {
|
|
uses: 1,
|
|
code,
|
|
credits: optionAmount || userDB?.credits,
|
|
memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`,
|
|
})
|
|
|
|
// If successful
|
|
?.then(async () => {
|
|
// Create DM embed object
|
|
const dmEmbed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description: `Redeem this voucher [here](${shopUrl})!` as string,
|
|
fields: [
|
|
{ name: "Code" as string, value: `${code}` as string, inline: true },
|
|
{
|
|
name: "Credits" as string,
|
|
value: `${optionAmount || userDB?.credits}` as string,
|
|
inline: true,
|
|
},
|
|
],
|
|
color: config?.colors?.success as ColorResolvable,
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
|
|
// Create interaction embed object
|
|
const interactionEmbed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description: "I have sent you the code in DM!" as string,
|
|
color: config?.colors?.success as ColorResolvable,
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
|
|
// Withdraw amount from user credits
|
|
userDB.credits -= optionAmount || userDB?.credits;
|
|
|
|
// Save new credits
|
|
await userDB
|
|
?.save()
|
|
// If successful
|
|
?.then(async () => {
|
|
// Send debug message
|
|
logger?.debug(
|
|
`User: ${user?.username} redeemed: ${pluralize(
|
|
optionAmount,
|
|
"credit"
|
|
)}`
|
|
);
|
|
|
|
// Send DM message
|
|
await dmUser?.send({ embeds: [dmEmbed] });
|
|
|
|
// Send interaction reply
|
|
await interaction?.editReply({
|
|
embeds: [interactionEmbed],
|
|
});
|
|
})
|
|
|
|
// If error occurs
|
|
.catch(async (e: any) => {
|
|
logger?.error(e);
|
|
const embed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description:
|
|
"Something went wrong, please try again later." as string,
|
|
color: config?.colors?.error as ColorResolvable,
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
return interaction?.editReply({ embeds: [embed] });
|
|
});
|
|
})
|
|
|
|
// If error occurs
|
|
.catch(async (e) => {
|
|
logger?.error(e);
|
|
const embed = {
|
|
title: ":shopping_cart: Shop [Pterodactyl]" as string,
|
|
description: "Something went wrong, please try again later." as string,
|
|
color: config?.colors?.error as ColorResolvable,
|
|
timestamp: new Date(),
|
|
footer: {
|
|
iconURL: config?.footer?.icon as string,
|
|
text: config?.footer?.text as string,
|
|
},
|
|
};
|
|
return interaction?.editReply({ embeds: [embed] });
|
|
});
|
|
};
|