refactor: 🧑💻 modules are called subcommands and groups
It makes more sense to use subcommands and groups as names instead of modules
This commit is contained in:
parent
9687f617b6
commit
3c079943b0
70 changed files with 2902 additions and 2843 deletions
|
@ -1,51 +1,72 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleAudits from "./modules/audits";
|
||||
import moduleCpgg from "./modules/cpgg";
|
||||
import moduleCredits from "./modules/credits";
|
||||
import moduleEmbeds from "./modules/embeds";
|
||||
import modulePoints from "./modules/points";
|
||||
import moduleShop from "./modules/shop";
|
||||
import moduleWelcome from "./modules/welcome";
|
||||
// Subcommands
|
||||
import {
|
||||
builder as AuditsBuilder,
|
||||
execute as AuditsExecute,
|
||||
} from "./subcommands/audits";
|
||||
import {
|
||||
builder as CpggBuilder,
|
||||
execute as CpggExecute,
|
||||
} from "./subcommands/cpgg";
|
||||
import {
|
||||
builder as CreditsBuilder,
|
||||
execute as CreditsExecute,
|
||||
} from "./subcommands/credits";
|
||||
import {
|
||||
builder as EmbedsBuilder,
|
||||
execute as EmbedsExecute,
|
||||
} from "./subcommands/embeds";
|
||||
import {
|
||||
builder as PointsBuilder,
|
||||
execute as PointsExecute,
|
||||
} from "./subcommands/points";
|
||||
import {
|
||||
builder as ShopBuilder,
|
||||
execute as ShopExecute,
|
||||
} from "./subcommands/shop";
|
||||
import {
|
||||
builder as WelcomeBuilder,
|
||||
execute as WelcomeExecute,
|
||||
} from "./subcommands/welcome";
|
||||
|
||||
export const builder = new SlashCommandBuilder()
|
||||
.setName("config")
|
||||
.setDescription("Manage guild configurations.")
|
||||
.setDMPermission(false)
|
||||
|
||||
// Modules
|
||||
.addSubcommand(moduleAudits.builder)
|
||||
.addSubcommand(moduleCpgg.builder)
|
||||
.addSubcommand(moduleCredits.builder)
|
||||
.addSubcommand(moduleEmbeds.builder)
|
||||
.addSubcommand(modulePoints.builder)
|
||||
.addSubcommand(moduleShop.builder)
|
||||
.addSubcommand(moduleWelcome.builder);
|
||||
// Subcommands
|
||||
.addSubcommand(AuditsBuilder)
|
||||
.addSubcommand(CpggBuilder)
|
||||
.addSubcommand(CreditsBuilder)
|
||||
.addSubcommand(EmbedsBuilder)
|
||||
.addSubcommand(PointsBuilder)
|
||||
.addSubcommand(ShopBuilder)
|
||||
.addSubcommand(WelcomeBuilder);
|
||||
|
||||
// Execute function
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "audits":
|
||||
await moduleAudits.execute(interaction);
|
||||
await AuditsExecute(interaction);
|
||||
break;
|
||||
case "cpgg":
|
||||
await moduleCpgg.execute(interaction);
|
||||
await CpggExecute(interaction);
|
||||
break;
|
||||
case "credits":
|
||||
await moduleCredits.execute(interaction);
|
||||
await CreditsExecute(interaction);
|
||||
break;
|
||||
case "embeds":
|
||||
await moduleEmbeds.execute(interaction);
|
||||
await EmbedsExecute(interaction);
|
||||
break;
|
||||
case "points":
|
||||
await modulePoints.execute(interaction);
|
||||
await PointsExecute(interaction);
|
||||
break;
|
||||
case "shop":
|
||||
await moduleShop.execute(interaction);
|
||||
await ShopExecute(interaction);
|
||||
break;
|
||||
case "welcome":
|
||||
await moduleWelcome.execute(interaction);
|
||||
await WelcomeExecute(interaction);
|
||||
break;
|
||||
default:
|
||||
throw new Error("No module found for that specific command.");
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("audits")
|
||||
.setDescription("Audits")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("status")
|
||||
.setDescription("Should audits be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("Channel for audit messages.")
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { guild, options } = interaction;
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
guild
|
||||
);
|
||||
const status = options.getBoolean("status");
|
||||
const channel = options.getChannel("channel");
|
||||
|
||||
if (!guild) throw new Error("Guild not found.");
|
||||
if (!channel) throw new Error("Channel not found.");
|
||||
if (status === null) throw new Error("Status not found.");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
auditsEnabled: status,
|
||||
auditsChannelId: channel.id,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
auditsEnabled: status,
|
||||
auditsChannelId: channel.id,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const embedSuccess = new EmbedBuilder()
|
||||
.setTitle("[:hammer:] Audits")
|
||||
.setDescription("Guild configuration updated successfully.")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Status",
|
||||
value: `${
|
||||
createGuild.auditsEnabled
|
||||
? ":white_check_mark: Enabled"
|
||||
: ":x: Disabled"
|
||||
}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Channel",
|
||||
value: `<#${createGuild.auditsChannelId}>`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [embedSuccess],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
|
@ -1,106 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../helpers/checkPermission";
|
||||
import encryption from "../../../../helpers/encryption";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cpgg")
|
||||
.setDescription("Controlpanel.gg")
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("scheme")
|
||||
.setDescription(`Controlpanel.gg Scheme`)
|
||||
.setRequired(true)
|
||||
.setChoices(
|
||||
{ name: "HTTPS (secure)", value: "https" },
|
||||
{ name: "HTTP (insecure)", value: "http" }
|
||||
)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("domain")
|
||||
.setDescription(`Controlpanel.gg Domain`)
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("token")
|
||||
.setDescription(`Controlpanel.gg Application API`)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const tokenData = options.getString("token");
|
||||
const scheme = options.getString("scheme");
|
||||
const domain = options.getString("domain");
|
||||
const token = tokenData && encryption.encrypt(tokenData);
|
||||
const url = scheme && domain && encryption.encrypt(`${scheme}://${domain}`);
|
||||
|
||||
if (!guild) throw new Error("No guild found");
|
||||
if (!token) throw new Error("Token not found");
|
||||
if (!url) throw new Error("URL not found");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
apiCpggTokenIv: token.iv,
|
||||
apiCpggTokenContent: token.content,
|
||||
apiCpggUrlIv: url.iv,
|
||||
apiCpggUrlContent: url.content,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
apiCpggTokenIv: token.iv,
|
||||
apiCpggTokenContent: token.content,
|
||||
apiCpggUrlIv: url.iv,
|
||||
apiCpggUrlContent: url.content,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
logger?.silly(`Updated API credentials.`);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] CPGG")
|
||||
.setDescription(
|
||||
`The following configuration will be used.
|
||||
|
||||
**Scheme**: ${scheme}
|
||||
**Domain**: ${domain}
|
||||
**Token**: ends with ${tokenData?.slice(-4)}`
|
||||
)
|
||||
.setColor(successColor)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
|
@ -1,165 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("credits")
|
||||
.setDescription(`Configure this guild's credits module.`)
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("enabled")
|
||||
.setDescription("Do you want to activate the credit module?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("rate")
|
||||
.setDescription("Credit rate per message.")
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("minimum-length")
|
||||
.setDescription("Minimum message length to receive credit.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("work-rate")
|
||||
.setDescription(
|
||||
"The maximum amount of credit that can be obtained within a working day."
|
||||
)
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("work-timeout")
|
||||
.setDescription(
|
||||
"How long you need to wait before you can work again provided in seconds."
|
||||
)
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("timeout")
|
||||
.setDescription(
|
||||
"How long you need to wait before you can earn more credits."
|
||||
)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { guild, options } = interaction;
|
||||
|
||||
const enabled = options.getBoolean("enabled");
|
||||
const rate = options.getNumber("rate");
|
||||
const timeout = options.getNumber("timeout");
|
||||
const minimumLength = options.getNumber("minimum-length");
|
||||
const workRate = options.getNumber("work-rate");
|
||||
const workTimeout = options.getNumber("work-timeout");
|
||||
|
||||
if (!guild) throw new Error("Guild not found.");
|
||||
if (typeof enabled !== "boolean")
|
||||
throw new Error("Enabled option is not a boolean.");
|
||||
if (typeof rate !== "number") throw new Error("Rate is not a number.");
|
||||
if (typeof workRate !== "number")
|
||||
throw new Error("Work rate is not a number.");
|
||||
if (typeof workTimeout !== "number")
|
||||
throw new Error("Work timeout is not a number.");
|
||||
if (typeof timeout !== "number")
|
||||
throw new Error("Timeout is not a number.");
|
||||
if (typeof minimumLength !== "number")
|
||||
throw new Error("Minimum length is not a number.");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
creditsEnabled: enabled,
|
||||
creditsRate: rate,
|
||||
creditsTimeout: timeout,
|
||||
creditsWorkRate: workRate,
|
||||
creditsWorkTimeout: workTimeout,
|
||||
creditsMinimumLength: minimumLength,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
creditsEnabled: enabled,
|
||||
creditsRate: rate,
|
||||
creditsTimeout: timeout,
|
||||
creditsWorkRate: workRate,
|
||||
creditsWorkTimeout: workTimeout,
|
||||
creditsMinimumLength: minimumLength,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Credits")
|
||||
.setDescription("Credits settings updated")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Enabled?",
|
||||
value: `${createGuild.creditsEnabled}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📈 Rate",
|
||||
value: `${createGuild.creditsRate}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📈 Work Rate",
|
||||
value: `${createGuild.creditsWorkRate}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🔨 Minimum Length",
|
||||
value: `${createGuild.creditsMinimumLength}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Timeout",
|
||||
value: `${createGuild.creditsTimeout}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Work Timeout",
|
||||
value: `${createGuild.creditsWorkTimeout}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
|
@ -1,100 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../helpers/checkPermission";
|
||||
import getValues from "./components/getValues";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("embeds")
|
||||
.setDescription(`Embeds`)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("success-color")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("wait-color")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("error-color")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("footer-icon")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("footer-text")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { guild } = interaction;
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
|
||||
const { successColor, waitColor, errorColor, footerText, footerIcon } =
|
||||
await getValues(interaction);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Embeds")
|
||||
.setFooter({ text: footerText, iconURL: footerIcon })
|
||||
.setTimestamp(new Date());
|
||||
|
||||
embed
|
||||
.setDescription("Following embed configuration will be used.")
|
||||
.setColor(successColor)
|
||||
.addFields([
|
||||
{
|
||||
name: "🟢 Success Color",
|
||||
value: `${successColor}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🟡 Wait Color",
|
||||
value: `${waitColor}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🔴 Error Color",
|
||||
value: `${errorColor}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🖼️ Footer Icon",
|
||||
value: `${footerIcon}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📄 Footer Text",
|
||||
value: `${footerText}`,
|
||||
inline: true,
|
||||
},
|
||||
]);
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [embed],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
|
@ -1,123 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("points")
|
||||
.setDescription("Points")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("status")
|
||||
.setDescription("Should credits be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("rate")
|
||||
.setDescription("Amount of credits per message.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("minimum-length")
|
||||
.setDescription("Minimum length of message to earn credits.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("timeout")
|
||||
.setDescription("Timeout between earning credits (milliseconds).")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const status = options?.getBoolean("status");
|
||||
const rate = options?.getNumber("rate");
|
||||
const timeout = options?.getNumber("timeout");
|
||||
const minimumLength = options?.getNumber("minimum-length");
|
||||
|
||||
if (!guild) throw new Error("Guild is required");
|
||||
if (status === null) throw new Error("Status must be specified");
|
||||
if (!rate) throw new Error("Rate must be specified");
|
||||
if (!timeout) throw new Error("Timeout must be specified");
|
||||
if (!minimumLength) throw new Error("Minimum length must be specified");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
pointsEnabled: status,
|
||||
pointsRate: rate,
|
||||
pointsTimeout: timeout,
|
||||
pointsMinimumLength: minimumLength,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
pointsEnabled: status,
|
||||
pointsRate: rate,
|
||||
pointsTimeout: timeout,
|
||||
pointsMinimumLength: minimumLength,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Points")
|
||||
.setDescription("Points settings updated")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Status",
|
||||
value: `${createGuild.pointsEnabled}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📈 Rate",
|
||||
value: `${createGuild.pointsRate}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🔨 Minimum Length",
|
||||
value: `${createGuild.pointsMinimumLength}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Timeout",
|
||||
value: `${createGuild.pointsTimeout}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
|
@ -1,93 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("shop")
|
||||
.setDescription("Shop")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("roles-status")
|
||||
.setDescription("Should roles be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("roles-price-per-hour")
|
||||
.setDescription("Price per hour for roles.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const rolesStatus = options?.getBoolean("roles-status");
|
||||
const rolesPricePerHour = options?.getNumber("roles-price-per-hour");
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (rolesStatus === null) throw new Error("Status must be provided");
|
||||
if (!rolesPricePerHour)
|
||||
throw new Error("Roles price per hour must be provided");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
shopRolesEnabled: rolesStatus,
|
||||
shopRolesPricePerHour: rolesPricePerHour,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
shopRolesEnabled: rolesStatus,
|
||||
shopRolesPricePerHour: rolesPricePerHour,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Shop")
|
||||
.setDescription("Shop settings updated")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Roles Status",
|
||||
value: `${createGuild.shopRolesEnabled}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Roles Price Per Hour",
|
||||
value: `${createGuild.shopRolesPricePerHour}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
},
|
||||
};
|
|
@ -1,147 +0,0 @@
|
|||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("welcome")
|
||||
.setDescription("Welcome")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("status")
|
||||
.setDescription("Should welcome be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("join-channel")
|
||||
.setDescription("Channel for join messages.")
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
.setRequired(true)
|
||||
)
|
||||
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("leave-channel")
|
||||
.setDescription("Channel for leave messages.")
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
.setRequired(true)
|
||||
)
|
||||
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("leave-message")
|
||||
.setDescription("Message for leave messages.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("join-message")
|
||||
.setDescription("Message for join messages.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const status = options?.getBoolean("status");
|
||||
const joinChannel = options?.getChannel("join-channel");
|
||||
const leaveChannel = options?.getChannel("leave-channel");
|
||||
const joinChannelMessage = options?.getString("join-message");
|
||||
const leaveChannelMessage = options?.getString("leave-message");
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (status === null) throw new Error("Status not specified");
|
||||
if (!joinChannel) throw new Error("Join channel not specified");
|
||||
if (!joinChannelMessage)
|
||||
throw new Error("Join channel message not specified");
|
||||
if (!leaveChannel) throw new Error("Leave channel not specified");
|
||||
if (!leaveChannelMessage)
|
||||
throw new Error("Leave channel message not specified");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
welcomeEnabled: status,
|
||||
welcomeJoinChannelId: joinChannel.id,
|
||||
welcomeJoinChannelMessage: joinChannelMessage,
|
||||
welcomeLeaveChannelId: leaveChannel.id,
|
||||
welcomeLeaveChannelMessage: leaveChannelMessage,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
welcomeEnabled: status,
|
||||
welcomeJoinChannelId: joinChannel.id,
|
||||
welcomeJoinChannelMessage: joinChannelMessage,
|
||||
welcomeLeaveChannelId: leaveChannel.id,
|
||||
welcomeLeaveChannelMessage: leaveChannelMessage,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbedDisabled = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Welcome")
|
||||
.setDescription(
|
||||
"This module is currently disabled, please enable it to continue."
|
||||
)
|
||||
.setColor(successColor)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
if (!createGuild.welcomeEnabled) {
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbedDisabled],
|
||||
});
|
||||
}
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Welcome")
|
||||
.setDescription(
|
||||
`The following configuration will be used.
|
||||
|
||||
[👋] **Welcome**
|
||||
|
||||
ㅤ**Channel**: <#${createGuild.welcomeJoinChannelId}>
|
||||
ㅤ**Message**: ${createGuild.welcomeJoinChannelMessage}
|
||||
|
||||
[🚪] **Leave**
|
||||
|
||||
ㅤ**Channel**: <#${createGuild.welcomeLeaveChannelId}>
|
||||
ㅤ**Message**: ${createGuild.welcomeLeaveChannelMessage}`
|
||||
)
|
||||
.setColor(successColor)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return true;
|
||||
},
|
||||
};
|
94
src/commands/config/subcommands/audits/index.ts
Normal file
94
src/commands/config/subcommands/audits/index.ts
Normal file
|
@ -0,0 +1,94 @@
|
|||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("audits")
|
||||
.setDescription("Audits")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("status")
|
||||
.setDescription("Should audits be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("Channel for audit messages.")
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { guild, options } = interaction;
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(guild);
|
||||
const status = options.getBoolean("status");
|
||||
const channel = options.getChannel("channel");
|
||||
|
||||
if (!guild) throw new Error("Guild not found.");
|
||||
if (!channel) throw new Error("Channel not found.");
|
||||
if (status === null) throw new Error("Status not found.");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
auditsEnabled: status,
|
||||
auditsChannelId: channel.id,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
auditsEnabled: status,
|
||||
auditsChannelId: channel.id,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const embedSuccess = new EmbedBuilder()
|
||||
.setTitle("[:hammer:] Audits")
|
||||
.setDescription("Guild configuration updated successfully.")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Status",
|
||||
value: `${
|
||||
createGuild.auditsEnabled
|
||||
? ":white_check_mark: Enabled"
|
||||
: ":x: Disabled"
|
||||
}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Channel",
|
||||
value: `<#${createGuild.auditsChannelId}>`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [embedSuccess],
|
||||
});
|
||||
return;
|
||||
};
|
105
src/commands/config/subcommands/cpgg/index.ts
Normal file
105
src/commands/config/subcommands/cpgg/index.ts
Normal file
|
@ -0,0 +1,105 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../helpers/checkPermission";
|
||||
import encryption from "../../../../helpers/encryption";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cpgg")
|
||||
.setDescription("Controlpanel.gg")
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("scheme")
|
||||
.setDescription(`Controlpanel.gg Scheme`)
|
||||
.setRequired(true)
|
||||
.setChoices(
|
||||
{ name: "HTTPS (secure)", value: "https" },
|
||||
{ name: "HTTP (insecure)", value: "http" }
|
||||
)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("domain")
|
||||
.setDescription(`Controlpanel.gg Domain`)
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("token")
|
||||
.setDescription(`Controlpanel.gg Application API`)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const tokenData = options.getString("token");
|
||||
const scheme = options.getString("scheme");
|
||||
const domain = options.getString("domain");
|
||||
const token = tokenData && encryption.encrypt(tokenData);
|
||||
const url = scheme && domain && encryption.encrypt(`${scheme}://${domain}`);
|
||||
|
||||
if (!guild) throw new Error("No guild found");
|
||||
if (!token) throw new Error("Token not found");
|
||||
if (!url) throw new Error("URL not found");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
apiCpggTokenIv: token.iv,
|
||||
apiCpggTokenContent: token.content,
|
||||
apiCpggUrlIv: url.iv,
|
||||
apiCpggUrlContent: url.content,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
apiCpggTokenIv: token.iv,
|
||||
apiCpggTokenContent: token.content,
|
||||
apiCpggUrlIv: url.iv,
|
||||
apiCpggUrlContent: url.content,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
logger?.silly(`Updated API credentials.`);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] CPGG")
|
||||
.setDescription(
|
||||
`The following configuration will be used.
|
||||
|
||||
**Scheme**: ${scheme}
|
||||
**Domain**: ${domain}
|
||||
**Token**: ends with ${tokenData?.slice(-4)}`
|
||||
)
|
||||
.setColor(successColor)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
};
|
163
src/commands/config/subcommands/credits/index.ts
Normal file
163
src/commands/config/subcommands/credits/index.ts
Normal file
|
@ -0,0 +1,163 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("credits")
|
||||
.setDescription(`Configure this guild's credits module.`)
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("enabled")
|
||||
.setDescription("Do you want to activate the credit module?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("rate")
|
||||
.setDescription("Credit rate per message.")
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("minimum-length")
|
||||
.setDescription("Minimum message length to receive credit.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("work-rate")
|
||||
.setDescription(
|
||||
"The maximum amount of credit that can be obtained within a working day."
|
||||
)
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("work-timeout")
|
||||
.setDescription(
|
||||
"How long you need to wait before you can work again provided in seconds."
|
||||
)
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("timeout")
|
||||
.setDescription(
|
||||
"How long you need to wait before you can earn more credits."
|
||||
)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { guild, options } = interaction;
|
||||
|
||||
const enabled = options.getBoolean("enabled");
|
||||
const rate = options.getNumber("rate");
|
||||
const timeout = options.getNumber("timeout");
|
||||
const minimumLength = options.getNumber("minimum-length");
|
||||
const workRate = options.getNumber("work-rate");
|
||||
const workTimeout = options.getNumber("work-timeout");
|
||||
|
||||
if (!guild) throw new Error("Guild not found.");
|
||||
if (typeof enabled !== "boolean")
|
||||
throw new Error("Enabled option is not a boolean.");
|
||||
if (typeof rate !== "number") throw new Error("Rate is not a number.");
|
||||
if (typeof workRate !== "number")
|
||||
throw new Error("Work rate is not a number.");
|
||||
if (typeof workTimeout !== "number")
|
||||
throw new Error("Work timeout is not a number.");
|
||||
if (typeof timeout !== "number") throw new Error("Timeout is not a number.");
|
||||
if (typeof minimumLength !== "number")
|
||||
throw new Error("Minimum length is not a number.");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
creditsEnabled: enabled,
|
||||
creditsRate: rate,
|
||||
creditsTimeout: timeout,
|
||||
creditsWorkRate: workRate,
|
||||
creditsWorkTimeout: workTimeout,
|
||||
creditsMinimumLength: minimumLength,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
creditsEnabled: enabled,
|
||||
creditsRate: rate,
|
||||
creditsTimeout: timeout,
|
||||
creditsWorkRate: workRate,
|
||||
creditsWorkTimeout: workTimeout,
|
||||
creditsMinimumLength: minimumLength,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Credits")
|
||||
.setDescription("Credits settings updated")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Enabled?",
|
||||
value: `${createGuild.creditsEnabled}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📈 Rate",
|
||||
value: `${createGuild.creditsRate}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📈 Work Rate",
|
||||
value: `${createGuild.creditsWorkRate}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🔨 Minimum Length",
|
||||
value: `${createGuild.creditsMinimumLength}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Timeout",
|
||||
value: `${createGuild.creditsTimeout}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Work Timeout",
|
||||
value: `${createGuild.creditsWorkTimeout}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
};
|
99
src/commands/config/subcommands/embeds/index.ts
Normal file
99
src/commands/config/subcommands/embeds/index.ts
Normal file
|
@ -0,0 +1,99 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../helpers/checkPermission";
|
||||
import getValues from "./components/getValues";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("embeds")
|
||||
.setDescription(`Embeds`)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("success-color")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("wait-color")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("error-color")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("footer-icon")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("footer-text")
|
||||
.setDescription("No provided description")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { guild } = interaction;
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
|
||||
const { successColor, waitColor, errorColor, footerText, footerIcon } =
|
||||
await getValues(interaction);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Embeds")
|
||||
.setFooter({ text: footerText, iconURL: footerIcon })
|
||||
.setTimestamp(new Date());
|
||||
|
||||
embed
|
||||
.setDescription("Following embed configuration will be used.")
|
||||
.setColor(successColor)
|
||||
.addFields([
|
||||
{
|
||||
name: "🟢 Success Color",
|
||||
value: `${successColor}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🟡 Wait Color",
|
||||
value: `${waitColor}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🔴 Error Color",
|
||||
value: `${errorColor}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🖼️ Footer Icon",
|
||||
value: `${footerIcon}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📄 Footer Text",
|
||||
value: `${footerText}`,
|
||||
inline: true,
|
||||
},
|
||||
]);
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [embed],
|
||||
});
|
||||
return;
|
||||
};
|
122
src/commands/config/subcommands/points/index.ts
Normal file
122
src/commands/config/subcommands/points/index.ts
Normal file
|
@ -0,0 +1,122 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("points")
|
||||
.setDescription("Points")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("status")
|
||||
.setDescription("Should credits be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("rate")
|
||||
.setDescription("Amount of credits per message.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("minimum-length")
|
||||
.setDescription("Minimum length of message to earn credits.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("timeout")
|
||||
.setDescription("Timeout between earning credits (milliseconds).")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const status = options?.getBoolean("status");
|
||||
const rate = options?.getNumber("rate");
|
||||
const timeout = options?.getNumber("timeout");
|
||||
const minimumLength = options?.getNumber("minimum-length");
|
||||
|
||||
if (!guild) throw new Error("Guild is required");
|
||||
if (status === null) throw new Error("Status must be specified");
|
||||
if (!rate) throw new Error("Rate must be specified");
|
||||
if (!timeout) throw new Error("Timeout must be specified");
|
||||
if (!minimumLength) throw new Error("Minimum length must be specified");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
pointsEnabled: status,
|
||||
pointsRate: rate,
|
||||
pointsTimeout: timeout,
|
||||
pointsMinimumLength: minimumLength,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
pointsEnabled: status,
|
||||
pointsRate: rate,
|
||||
pointsTimeout: timeout,
|
||||
pointsMinimumLength: minimumLength,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Points")
|
||||
.setDescription("Points settings updated")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Status",
|
||||
value: `${createGuild.pointsEnabled}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📈 Rate",
|
||||
value: `${createGuild.pointsRate}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🔨 Minimum Length",
|
||||
value: `${createGuild.pointsMinimumLength}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "⏰ Timeout",
|
||||
value: `${createGuild.pointsTimeout}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
};
|
92
src/commands/config/subcommands/shop/index.ts
Normal file
92
src/commands/config/subcommands/shop/index.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("shop")
|
||||
.setDescription("Shop")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("roles-status")
|
||||
.setDescription("Should roles be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("roles-price-per-hour")
|
||||
.setDescription("Price per hour for roles.")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const rolesStatus = options?.getBoolean("roles-status");
|
||||
const rolesPricePerHour = options?.getNumber("roles-price-per-hour");
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (rolesStatus === null) throw new Error("Status must be provided");
|
||||
if (!rolesPricePerHour)
|
||||
throw new Error("Roles price per hour must be provided");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
shopRolesEnabled: rolesStatus,
|
||||
shopRolesPricePerHour: rolesPricePerHour,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
shopRolesEnabled: rolesStatus,
|
||||
shopRolesPricePerHour: rolesPricePerHour,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Shop")
|
||||
.setDescription("Shop settings updated")
|
||||
.setColor(successColor)
|
||||
.addFields(
|
||||
{
|
||||
name: "🤖 Roles Status",
|
||||
value: `${createGuild.shopRolesEnabled}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Roles Price Per Hour",
|
||||
value: `${createGuild.shopRolesPricePerHour}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
};
|
146
src/commands/config/subcommands/welcome/index.ts
Normal file
146
src/commands/config/subcommands/welcome/index.ts
Normal file
|
@ -0,0 +1,146 @@
|
|||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
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";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("welcome")
|
||||
.setDescription("Welcome")
|
||||
.addBooleanOption((option) =>
|
||||
option
|
||||
.setName("status")
|
||||
.setDescription("Should welcome be enabled?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("join-channel")
|
||||
.setDescription("Channel for join messages.")
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
.setRequired(true)
|
||||
)
|
||||
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("leave-channel")
|
||||
.setDescription("Channel for leave messages.")
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
.setRequired(true)
|
||||
)
|
||||
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("leave-message")
|
||||
.setDescription("Message for leave messages.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("join-message")
|
||||
.setDescription("Message for join messages.")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const status = options?.getBoolean("status");
|
||||
const joinChannel = options?.getChannel("join-channel");
|
||||
const leaveChannel = options?.getChannel("leave-channel");
|
||||
const joinChannelMessage = options?.getString("join-message");
|
||||
const leaveChannelMessage = options?.getString("leave-message");
|
||||
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
if (status === null) throw new Error("Status not specified");
|
||||
if (!joinChannel) throw new Error("Join channel not specified");
|
||||
if (!joinChannelMessage)
|
||||
throw new Error("Join channel message not specified");
|
||||
if (!leaveChannel) throw new Error("Leave channel not specified");
|
||||
if (!leaveChannelMessage)
|
||||
throw new Error("Leave channel message not specified");
|
||||
|
||||
const createGuild = await prisma.guild.upsert({
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
update: {
|
||||
welcomeEnabled: status,
|
||||
welcomeJoinChannelId: joinChannel.id,
|
||||
welcomeJoinChannelMessage: joinChannelMessage,
|
||||
welcomeLeaveChannelId: leaveChannel.id,
|
||||
welcomeLeaveChannelMessage: leaveChannelMessage,
|
||||
},
|
||||
create: {
|
||||
id: guild.id,
|
||||
welcomeEnabled: status,
|
||||
welcomeJoinChannelId: joinChannel.id,
|
||||
welcomeJoinChannelMessage: joinChannelMessage,
|
||||
welcomeLeaveChannelId: leaveChannel.id,
|
||||
welcomeLeaveChannelMessage: leaveChannelMessage,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuild);
|
||||
|
||||
const interactionEmbedDisabled = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Welcome")
|
||||
.setDescription(
|
||||
"This module is currently disabled, please enable it to continue."
|
||||
)
|
||||
.setColor(successColor)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
if (!createGuild.welcomeEnabled) {
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbedDisabled],
|
||||
});
|
||||
}
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:tools:] Welcome")
|
||||
.setDescription(
|
||||
`The following configuration will be used.
|
||||
|
||||
[👋] **Welcome**
|
||||
|
||||
ㅤ**Channel**: <#${createGuild.welcomeJoinChannelId}>
|
||||
ㅤ**Message**: ${createGuild.welcomeJoinChannelMessage}
|
||||
|
||||
[🚪] **Leave**
|
||||
|
||||
ㅤ**Channel**: <#${createGuild.welcomeLeaveChannelId}>
|
||||
ㅤ**Message**: ${createGuild.welcomeLeaveChannelMessage}`
|
||||
)
|
||||
.setColor(successColor)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
});
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return true;
|
||||
};
|
|
@ -1,7 +1,10 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import { builder as ViewBuilder, execute as ViewExecute } from "./modules/view";
|
||||
// Subcommands
|
||||
import {
|
||||
builder as ViewBuilder,
|
||||
execute as ViewExecute,
|
||||
} from "./subcommands/view";
|
||||
|
||||
//
|
||||
export const builder = new SlashCommandBuilder()
|
||||
|
@ -9,7 +12,7 @@ export const builder = new SlashCommandBuilder()
|
|||
.setDescription("View guild counters")
|
||||
.setDMPermission(false)
|
||||
|
||||
// Modules
|
||||
// Subcommands
|
||||
.addSubcommand(ViewBuilder);
|
||||
|
||||
// Execute function
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
// Subcommands
|
||||
import {
|
||||
builder as BalanceBuilder,
|
||||
execute as BalanceExecute,
|
||||
} from "./modules/balance";
|
||||
import { builder as GiftBuilder, execute as GiftExecute } from "./modules/gift";
|
||||
import { builder as TopBuilder, execute as TopExecute } from "./modules/top";
|
||||
import { builder as WorkBuilder, execute as WorkExecute } from "./modules/work";
|
||||
} from "./subcommands/balance";
|
||||
import {
|
||||
builder as GiftBuilder,
|
||||
execute as GiftExecute,
|
||||
} from "./subcommands/gift";
|
||||
import {
|
||||
builder as TopBuilder,
|
||||
execute as TopExecute,
|
||||
} from "./subcommands/top";
|
||||
import {
|
||||
builder as WorkBuilder,
|
||||
execute as WorkExecute,
|
||||
} from "./subcommands/work";
|
||||
|
||||
// 1. Export a builder function.
|
||||
export const builder = new SlashCommandBuilder()
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleLookup from "./modules/lookup";
|
||||
// Subcommands
|
||||
import {
|
||||
builder as LookupBuilder,
|
||||
execute as LookupExecute,
|
||||
} from "./subcommands/lookup";
|
||||
|
||||
export const builder = new SlashCommandBuilder()
|
||||
.setName("dns")
|
||||
.setDescription("DNS commands.")
|
||||
|
||||
// Modules
|
||||
.addSubcommand(moduleLookup.builder);
|
||||
// Subcommands
|
||||
.addSubcommand(LookupBuilder);
|
||||
|
||||
// Execute the command
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "lookup":
|
||||
await moduleLookup.execute(interaction);
|
||||
await LookupExecute(interaction);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
import axios from "axios";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("lookup")
|
||||
.setDescription(
|
||||
"Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)"
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("query")
|
||||
.setDescription("The query you want to look up.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
const { errorColor, successColor, footerText, footerIcon } =
|
||||
await getEmbedConfig(interaction.guild);
|
||||
const embedTitle = "[:hammer:] Utility (Lookup)";
|
||||
|
||||
const { options } = interaction;
|
||||
const query = options.getString("query");
|
||||
|
||||
await axios
|
||||
.get(`http://ip-api.com/json/${query}`)
|
||||
.then(async (response) => {
|
||||
if (response.data.status !== "success") {
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle(embedTitle)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon })
|
||||
.setDescription(
|
||||
`${response?.data?.message}: ${response?.data?.query}`
|
||||
),
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle(embedTitle)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFields([
|
||||
{
|
||||
name: ":classical_building: AS",
|
||||
value: `${response.data.as || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":classical_building: ISP",
|
||||
value: `${response.data.isp || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":classical_building: Organization",
|
||||
value: `${response.data.org || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":compass: Latitude",
|
||||
value: `${response.data.lat || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":compass: Longitude",
|
||||
value: `${response.data.lon || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":clock4: Timezone",
|
||||
value: `${response.data.timezone || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Country",
|
||||
value: `${response.data.country || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Region",
|
||||
value: `${response.data.regionName || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: City",
|
||||
value: `${response.data.city || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Country Code",
|
||||
value: `${response.data.countryCode || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Region Code",
|
||||
value: `${response.data.region || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: ZIP",
|
||||
value: `${response.data.zip || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
130
src/commands/dns/subcommands/lookup/index.ts
Normal file
130
src/commands/dns/subcommands/lookup/index.ts
Normal file
|
@ -0,0 +1,130 @@
|
|||
import axios from "axios";
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("lookup")
|
||||
.setDescription(
|
||||
"Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)"
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("query")
|
||||
.setDescription("The query you want to look up.")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
const { errorColor, successColor, footerText, footerIcon } =
|
||||
await getEmbedConfig(interaction.guild);
|
||||
const embedTitle = "[:hammer:] Utility (Lookup)";
|
||||
|
||||
const { options } = interaction;
|
||||
const query = options.getString("query");
|
||||
|
||||
await axios.get(`http://ip-api.com/json/${query}`).then(async (response) => {
|
||||
if (response.data.status !== "success") {
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle(embedTitle)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setTimestamp(new Date())
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon })
|
||||
.setDescription(
|
||||
`${response?.data?.message}: ${response?.data?.query}`
|
||||
),
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle(embedTitle)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
})
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFields([
|
||||
{
|
||||
name: ":classical_building: AS",
|
||||
value: `${response.data.as || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":classical_building: ISP",
|
||||
value: `${response.data.isp || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":classical_building: Organization",
|
||||
value: `${response.data.org || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":compass: Latitude",
|
||||
value: `${response.data.lat || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":compass: Longitude",
|
||||
value: `${response.data.lon || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":clock4: Timezone",
|
||||
value: `${response.data.timezone || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Country",
|
||||
value: `${response.data.country || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Region",
|
||||
value: `${response.data.regionName || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: City",
|
||||
value: `${response.data.city || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Country Code",
|
||||
value: `${response.data.countryCode || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: Region Code",
|
||||
value: `${response.data.region || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: ":globe_with_meridians: ZIP",
|
||||
value: `${response.data.zip || "Unknown"}`,
|
||||
inline: true,
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
});
|
||||
};
|
|
@ -1,21 +1,24 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
import logger from "../../middlewares/logger";
|
||||
|
||||
// Modules
|
||||
import moduleMeme from "./modules/meme";
|
||||
// Subcommands
|
||||
import {
|
||||
builder as MemeBuilder,
|
||||
execute as MemeExecute,
|
||||
} from "./subcommands/meme";
|
||||
|
||||
export const builder = new SlashCommandBuilder()
|
||||
.setName("fun")
|
||||
.setDescription("Fun commands.")
|
||||
|
||||
.addSubcommand(moduleMeme.builder);
|
||||
.addSubcommand(MemeBuilder);
|
||||
|
||||
// Execute function
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
|
||||
if (options.getSubcommand() === "meme") {
|
||||
await moduleMeme.execute(interaction);
|
||||
await MemeExecute(interaction);
|
||||
} else {
|
||||
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import axios from "axios";
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
CommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("meme").setDescription("Random memes from r/memes");
|
||||
},
|
||||
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
const { guild, user, commandId } = interaction;
|
||||
if (!guild) throw new Error("Server unavailable");
|
||||
if (!user) throw new Error("User unavailable");
|
||||
|
||||
await cooldown(guild, user, commandId, 15);
|
||||
|
||||
const embedConfig = await getEmbedConfig(guild);
|
||||
|
||||
await axios
|
||||
.get("https://www.reddit.com/r/memes/random/.json")
|
||||
.then(async (res) => {
|
||||
const response = res.data[0].data.children;
|
||||
const content = response[0].data;
|
||||
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel("View post")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("🔗")
|
||||
.setURL(`https://reddit.com${content.permalink}`)
|
||||
);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`😆︱Meme`)
|
||||
.setDescription(`**${content.title}**`)
|
||||
.setTimestamp(new Date())
|
||||
.setImage(content.url)
|
||||
.setFooter({
|
||||
text: `👍 ${content.ups}︱👎 ${content.downs}`,
|
||||
})
|
||||
.setColor(embedConfig.successColor);
|
||||
|
||||
await interaction.editReply({ embeds: [embed], components: [buttons] });
|
||||
return;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw new Error(error.message);
|
||||
});
|
||||
},
|
||||
};
|
59
src/commands/fun/subcommands/meme/index.ts
Normal file
59
src/commands/fun/subcommands/meme/index.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import axios from "axios";
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
CommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command.setName("meme").setDescription("Random memes from r/memes");
|
||||
};
|
||||
|
||||
export const execute = async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
const { guild, user, commandId } = interaction;
|
||||
if (!guild) throw new Error("Server unavailable");
|
||||
if (!user) throw new Error("User unavailable");
|
||||
|
||||
await cooldown(guild, user, commandId, 15);
|
||||
|
||||
const embedConfig = await getEmbedConfig(guild);
|
||||
|
||||
await axios
|
||||
.get("https://www.reddit.com/r/memes/random/.json")
|
||||
.then(async (res) => {
|
||||
const response = res.data[0].data.children;
|
||||
const content = response[0].data;
|
||||
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel("View post")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("🔗")
|
||||
.setURL(`https://reddit.com${content.permalink}`)
|
||||
);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`😆︱Meme`)
|
||||
.setDescription(`**${content.title}**`)
|
||||
.setTimestamp(new Date())
|
||||
.setImage(content.url)
|
||||
.setFooter({
|
||||
text: `👍 ${content.ups}︱👎 ${content.downs}`,
|
||||
})
|
||||
.setColor(embedConfig.successColor);
|
||||
|
||||
await interaction.editReply({ embeds: [embed], components: [buttons] });
|
||||
return;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw new Error(error.message);
|
||||
});
|
||||
};
|
41
src/commands/manage/groups/counters/index.ts
Normal file
41
src/commands/manage/groups/counters/index.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
// Modules
|
||||
import {
|
||||
builder as AddBuilder,
|
||||
execute as AddExecute,
|
||||
} from "./subcommands/add";
|
||||
import {
|
||||
builder as RemoveBuilder,
|
||||
execute as RemoveExecute,
|
||||
} from "./subcommands/remove";
|
||||
|
||||
export const builder = (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("counters")
|
||||
.setDescription("Manage guild counters.")
|
||||
.addSubcommand(AddBuilder)
|
||||
.addSubcommand(RemoveBuilder);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
|
||||
switch (options.getSubcommand()) {
|
||||
case "add": {
|
||||
await AddExecute(interaction);
|
||||
break;
|
||||
}
|
||||
case "remove": {
|
||||
await RemoveExecute(interaction);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error("Could not found a module for that command.");
|
||||
}
|
||||
}
|
||||
};
|
112
src/commands/manage/groups/counters/subcommands/add/index.ts
Normal file
112
src/commands/manage/groups/counters/subcommands/add/index.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
// Configurations
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
|
||||
// Function
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("add")
|
||||
.setDescription("Add a counter to your guild.")
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("The channel to send the counter to.")
|
||||
.setRequired(true)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("word")
|
||||
.setDescription("The word to use for the counter.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("start")
|
||||
.setDescription("The starting value of the counter.")
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
const triggerWord = options?.getString("word");
|
||||
const startValue = options?.getNumber("start");
|
||||
|
||||
if (!guild) throw new Error("We could not find a guild");
|
||||
if (!discordChannel) throw new Error("We could not find a channel");
|
||||
if (!triggerWord) throw new Error("We could not find a word");
|
||||
|
||||
const channelCounter = await prisma.guildCounter.findUnique({
|
||||
where: {
|
||||
guildId_channelId: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (channelCounter)
|
||||
throw new Error("A counter already exists for this channel.");
|
||||
|
||||
const createGuildCounter = await prisma.guildCounter.upsert({
|
||||
where: {
|
||||
guildId_channelId: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
channelId: discordChannel.id,
|
||||
triggerWord,
|
||||
count: startValue || 0,
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildCounter);
|
||||
|
||||
if (createGuildCounter) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Counters - Add")
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(":white_check_mark: Counter created successfully.")
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
// Configurations
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("remove")
|
||||
.setDescription(`Delete a counter from your guild.`)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("The channel to delete the counter from.")
|
||||
.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
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
|
||||
if (!guild) throw new Error("We could not find a guild");
|
||||
if (!discordChannel) throw new Error("We could not find a channel");
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Counters - Remove")
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
const channelCounter = await prisma.guildCounter.findUnique({
|
||||
where: {
|
||||
guildId_channelId: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!channelCounter)
|
||||
throw new Error(
|
||||
"There is no counter sin this channel, please add one first."
|
||||
);
|
||||
|
||||
const deleteGuildCounter = await prisma.guildCounter.deleteMany({
|
||||
where: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!deleteGuildCounter)
|
||||
throw new Error("We could not find a counter for this guild");
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(":white_check_mark: Counter deleted successfully.")
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
};
|
58
src/commands/manage/groups/credits/index.ts
Normal file
58
src/commands/manage/groups/credits/index.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
// Modules
|
||||
import {
|
||||
builder as GiveBuilder,
|
||||
execute as GiveExecute,
|
||||
} from "./subcommands/give";
|
||||
import {
|
||||
builder as GiveawayBuilder,
|
||||
execute as GiveawayExecute,
|
||||
} from "./subcommands/giveaway";
|
||||
import {
|
||||
builder as SetBuilder,
|
||||
execute as SetExecute,
|
||||
} from "./subcommands/set";
|
||||
import {
|
||||
builder as TakeBuilder,
|
||||
execute as TakeExecute,
|
||||
} from "./subcommands/take";
|
||||
import {
|
||||
builder as TransferBuilder,
|
||||
execute as TransferExecute,
|
||||
} from "./subcommands/transfer";
|
||||
|
||||
export const builder = (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("credits")
|
||||
.setDescription("Manage the credits of a user.")
|
||||
.addSubcommand(GiveBuilder)
|
||||
.addSubcommand(SetBuilder)
|
||||
.addSubcommand(TakeBuilder)
|
||||
.addSubcommand(TransferBuilder)
|
||||
.addSubcommand(GiveawayBuilder);
|
||||
};
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "give":
|
||||
await GiveExecute(interaction);
|
||||
break;
|
||||
case "set":
|
||||
await SetExecute(interaction);
|
||||
break;
|
||||
case "take":
|
||||
await TakeExecute(interaction);
|
||||
break;
|
||||
case "transfer":
|
||||
await TransferExecute(interaction);
|
||||
break;
|
||||
case "giveaway":
|
||||
await GiveawayExecute(interaction);
|
||||
break;
|
||||
default:
|
||||
throw new Error("No module found for that specific command");
|
||||
}
|
||||
};
|
70
src/commands/manage/groups/credits/subcommands/give/index.ts
Normal file
70
src/commands/manage/groups/credits/subcommands/give/index.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
// Configurations
|
||||
// Helpers../../../../../../../helpers/userData
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
// Models
|
||||
// Handlers
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsGive from "../../../../../../helpers/credits/give";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("give")
|
||||
.setDescription("Give credits to a user.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to give credits to.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to give.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the MANAGE_GUILD permission.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
// 3. Destructure interaction object.
|
||||
const { guild, options } = interaction;
|
||||
if (!guild)
|
||||
throw new Error("We could not get the current guild from discord.");
|
||||
if (!options) throw new Error("We could not get the options from discord.");
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordReceiver = options.getUser("user");
|
||||
const creditsAmount = options.getInteger("amount");
|
||||
if (typeof creditsAmount !== "number")
|
||||
throw new Error("You need to provide a credit amount.");
|
||||
if (!discordReceiver)
|
||||
throw new Error("We could not get the receiving user from Discord");
|
||||
|
||||
// 5. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Give");
|
||||
|
||||
// 6. Give the credits.
|
||||
await creditsGive(guild, discordReceiver, creditsAmount);
|
||||
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
embedSuccess.setDescription(
|
||||
`Successfully gave ${pluralize(creditsAmount, "credit")}`
|
||||
),
|
||||
],
|
||||
});
|
||||
};
|
188
src/commands/manage/groups/credits/subcommands/giveaway/index.ts
Normal file
188
src/commands/manage/groups/credits/subcommands/giveaway/index.ts
Normal file
|
@ -0,0 +1,188 @@
|
|||
// 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.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggUrlIv ||
|
||||
!createGuildMember.guild.apiCpggUrlContent
|
||||
)
|
||||
throw new Error("No API url available");
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggTokenIv ||
|
||||
!createGuildMember.guild.apiCpggTokenContent
|
||||
)
|
||||
throw new Error("No API token available");
|
||||
|
||||
const url = encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggUrlIv,
|
||||
content: createGuildMember.guild.apiCpggUrlContent,
|
||||
});
|
||||
const api = axios?.create({
|
||||
baseURL: `${url}/api/`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggTokenIv,
|
||||
content: createGuildMember.guild.apiCpggTokenContent,
|
||||
})}`,
|
||||
},
|
||||
});
|
||||
|
||||
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],
|
||||
});
|
||||
});
|
||||
};
|
65
src/commands/manage/groups/credits/subcommands/set/index.ts
Normal file
65
src/commands/manage/groups/credits/subcommands/set/index.ts
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
// Models
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsSet from "../../../../../../helpers/credits/set";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("set")
|
||||
.setDescription("Set the amount of credits a user has.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to set the amount of credits for.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to set.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the permission to manage the guild.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
// 3. Destructure interaction object.
|
||||
const { options, guild } = interaction;
|
||||
if (!guild) throw new Error(`We could not find this guild.`);
|
||||
if (!options) throw new Error(`We could not find the options.`);
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordUser = options.getUser("user");
|
||||
const creditAmount = options.getInteger("amount");
|
||||
if (typeof creditAmount !== "number") throw new Error("Amount is not set.");
|
||||
if (!discordUser) throw new Error("User is not specified");
|
||||
|
||||
// 5. Set the credits.
|
||||
await creditsSet(guild, discordUser, creditAmount);
|
||||
|
||||
// 6. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Set");
|
||||
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
embedSuccess.setDescription(
|
||||
`Set **${discordUser}**'s credits to **${creditAmount}**.`
|
||||
),
|
||||
],
|
||||
});
|
||||
};
|
65
src/commands/manage/groups/credits/subcommands/take/index.ts
Normal file
65
src/commands/manage/groups/credits/subcommands/take/index.ts
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsTake from "../../../../../../helpers/credits/take";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("take")
|
||||
.setDescription("Take credits from a user.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to take credits from.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to take.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the MANAGE_GUILD permission.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
// 3. Destructure interaction object.
|
||||
const { guild, options } = interaction;
|
||||
if (!guild) throw new Error("Invalid guild.");
|
||||
if (!options) throw new Error("Invalid options.");
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordReceiver = options.getUser("user");
|
||||
const optionAmount = options.getInteger("amount");
|
||||
if (typeof optionAmount !== "number") throw new Error("Invalid amount.");
|
||||
if (!discordReceiver) throw new Error("Invalid user.");
|
||||
|
||||
// 5. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Take");
|
||||
|
||||
// 6. Take the credits.
|
||||
await creditsTake(guild, discordReceiver, optionAmount);
|
||||
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
embedSuccess.setDescription(
|
||||
`Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.`
|
||||
),
|
||||
],
|
||||
});
|
||||
};
|
|
@ -0,0 +1,79 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import creditsTransfer from "../../../../../../helpers/credits/transfer";
|
||||
// Configurations
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("transfer")
|
||||
.setDescription("Transfer credits from one user to another.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("from")
|
||||
.setDescription("The user to transfer credits from.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("to")
|
||||
.setDescription("The user to transfer credits to.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to transfer.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
); // Destructure member
|
||||
const { guild, options } = interaction;
|
||||
|
||||
// Get options
|
||||
const optionFromUser = options?.getUser("from");
|
||||
const optionToUser = options?.getUser("to");
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
|
||||
if (optionAmount === null) throw new Error("Amount is not specified");
|
||||
|
||||
if (optionAmount <= 0)
|
||||
throw new Error("You need to set amount above zero to transfer.");
|
||||
|
||||
if (!guild) throw new Error(`We could not find this guild.`);
|
||||
|
||||
if (!optionFromUser)
|
||||
throw new Error("You must provide a user to transfer from.");
|
||||
|
||||
if (!optionToUser) throw new Error("You must provide a user to transfer to.");
|
||||
|
||||
await creditsTransfer(guild, optionFromUser, optionToUser, optionAmount);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
|
||||
.setDescription(`Transferred ${optionAmount} credits.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
};
|
|
@ -2,8 +2,14 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleCounters from "./modules/counters";
|
||||
import moduleCredits from "./modules/credits";
|
||||
import {
|
||||
builder as CountersBuilder,
|
||||
execute as CountersExecute,
|
||||
} from "./groups/counters";
|
||||
import {
|
||||
builder as CreditsBuilder,
|
||||
execute as CreditsExecute,
|
||||
} from "./groups/credits";
|
||||
|
||||
// Function
|
||||
export const builder = new SlashCommandBuilder()
|
||||
|
@ -12,8 +18,8 @@ export const builder = new SlashCommandBuilder()
|
|||
.setDMPermission(false)
|
||||
|
||||
// Modules
|
||||
.addSubcommandGroup(moduleCounters.builder)
|
||||
.addSubcommandGroup(moduleCredits.builder);
|
||||
.addSubcommandGroup(CountersBuilder)
|
||||
.addSubcommandGroup(CreditsBuilder);
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
// Destructure
|
||||
|
@ -21,11 +27,11 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
|
||||
switch (options.getSubcommandGroup()) {
|
||||
case "credits": {
|
||||
await moduleCredits.execute(interaction);
|
||||
await CreditsExecute(interaction);
|
||||
break;
|
||||
}
|
||||
case "counters": {
|
||||
await moduleCounters.execute(interaction);
|
||||
await CountersExecute(interaction);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleAdd from "./modules/add";
|
||||
import moduleRemove from "./modules/remove";
|
||||
|
||||
export default {
|
||||
builder: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("counters")
|
||||
.setDescription("Manage guild counters.")
|
||||
.addSubcommand(moduleAdd.builder)
|
||||
.addSubcommand(moduleRemove.builder);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
const { options } = interaction;
|
||||
|
||||
switch (options.getSubcommand()) {
|
||||
case "add": {
|
||||
await moduleAdd.execute(interaction);
|
||||
break;
|
||||
}
|
||||
case "remove": {
|
||||
await moduleRemove.execute(interaction);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error("Could not found a module for that command.");
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
|
@ -1,113 +0,0 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
// Configurations
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("add")
|
||||
.setDescription("Add a counter to your guild.")
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("The channel to send the counter to.")
|
||||
.setRequired(true)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("word")
|
||||
.setDescription("The word to use for the counter.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addNumberOption((option) =>
|
||||
option
|
||||
.setName("start")
|
||||
.setDescription("The starting value of the counter.")
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
const triggerWord = options?.getString("word");
|
||||
const startValue = options?.getNumber("start");
|
||||
|
||||
if (!guild) throw new Error("We could not find a guild");
|
||||
if (!discordChannel) throw new Error("We could not find a channel");
|
||||
if (!triggerWord) throw new Error("We could not find a word");
|
||||
|
||||
const channelCounter = await prisma.guildCounter.findUnique({
|
||||
where: {
|
||||
guildId_channelId: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (channelCounter)
|
||||
throw new Error("A counter already exists for this channel.");
|
||||
|
||||
const createGuildCounter = await prisma.guildCounter.upsert({
|
||||
where: {
|
||||
guildId_channelId: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
channelId: discordChannel.id,
|
||||
triggerWord,
|
||||
count: startValue || 0,
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildCounter);
|
||||
|
||||
if (createGuildCounter) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Counters - Add")
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(":white_check_mark: Counter created successfully.")
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
|
@ -1,82 +0,0 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
// Configurations
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("remove")
|
||||
.setDescription(`Delete a counter from your guild.`)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("The channel to delete the counter from.")
|
||||
.setRequired(true)
|
||||
.addChannelTypes(ChannelType.GuildText)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const discordChannel = options?.getChannel("channel");
|
||||
|
||||
if (!guild) throw new Error("We could not find a guild");
|
||||
if (!discordChannel) throw new Error("We could not find a channel");
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Counters - Remove")
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
const channelCounter = await prisma.guildCounter.findUnique({
|
||||
where: {
|
||||
guildId_channelId: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!channelCounter)
|
||||
throw new Error(
|
||||
"There is no counter sin this channel, please add one first."
|
||||
);
|
||||
|
||||
const deleteGuildCounter = await prisma.guildCounter.deleteMany({
|
||||
where: {
|
||||
guildId: guild.id,
|
||||
channelId: discordChannel.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!deleteGuildCounter)
|
||||
throw new Error("We could not find a counter for this guild");
|
||||
|
||||
await interaction?.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(":white_check_mark: Counter deleted successfully.")
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleGive from "./modules/give";
|
||||
import moduleGiveaway from "./modules/giveaway";
|
||||
import moduleSet from "./modules/set";
|
||||
import moduleTake from "./modules/take";
|
||||
import moduleTransfer from "./modules/transfer";
|
||||
|
||||
export default {
|
||||
builder: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return group
|
||||
.setName("credits")
|
||||
.setDescription("Manage the credits of a user.")
|
||||
.addSubcommand(moduleGive.builder)
|
||||
.addSubcommand(moduleSet.builder)
|
||||
.addSubcommand(moduleTake.builder)
|
||||
.addSubcommand(moduleTransfer.builder)
|
||||
.addSubcommand(moduleGiveaway.builder);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "give":
|
||||
await moduleGive.execute(interaction);
|
||||
break;
|
||||
case "set":
|
||||
await moduleSet.execute(interaction);
|
||||
break;
|
||||
case "take":
|
||||
await moduleTake.execute(interaction);
|
||||
break;
|
||||
case "transfer":
|
||||
await moduleTransfer.execute(interaction);
|
||||
break;
|
||||
case "giveaway":
|
||||
await moduleGiveaway.execute(interaction);
|
||||
break;
|
||||
default:
|
||||
throw new Error("No module found for that specific command");
|
||||
}
|
||||
},
|
||||
};
|
|
@ -1,72 +0,0 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
// Configurations
|
||||
// Helpers../../../../../../../helpers/userData
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
// Models
|
||||
// Handlers
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsGive from "../../../../../../helpers/credits/give";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("give")
|
||||
.setDescription("Give credits to a user.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to give credits to.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to give.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the MANAGE_GUILD permission.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
// 3. Destructure interaction object.
|
||||
const { guild, options } = interaction;
|
||||
if (!guild)
|
||||
throw new Error("We could not get the current guild from discord.");
|
||||
if (!options) throw new Error("We could not get the options from discord.");
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordReceiver = options.getUser("user");
|
||||
const creditsAmount = options.getInteger("amount");
|
||||
if (typeof creditsAmount !== "number")
|
||||
throw new Error("You need to provide a credit amount.");
|
||||
if (!discordReceiver)
|
||||
throw new Error("We could not get the receiving user from Discord");
|
||||
|
||||
// 5. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Give");
|
||||
|
||||
// 6. Give the credits.
|
||||
await creditsGive(guild, discordReceiver, creditsAmount);
|
||||
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
embedSuccess.setDescription(
|
||||
`Successfully gave ${pluralize(creditsAmount, "credit")}`
|
||||
),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,189 +0,0 @@
|
|||
// 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 default {
|
||||
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)
|
||||
);
|
||||
},
|
||||
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.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggUrlIv ||
|
||||
!createGuildMember.guild.apiCpggUrlContent
|
||||
)
|
||||
throw new Error("No API url available");
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggTokenIv ||
|
||||
!createGuildMember.guild.apiCpggTokenContent
|
||||
)
|
||||
throw new Error("No API token available");
|
||||
|
||||
const url = encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggUrlIv,
|
||||
content: createGuildMember.guild.apiCpggUrlContent,
|
||||
});
|
||||
const api = axios?.create({
|
||||
baseURL: `${url}/api/`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggTokenIv,
|
||||
content: createGuildMember.guild.apiCpggTokenContent,
|
||||
})}`,
|
||||
},
|
||||
});
|
||||
|
||||
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],
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
// Models
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsSet from "../../../../../../helpers/credits/set";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("set")
|
||||
.setDescription("Set the amount of credits a user has.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to set the amount of credits for.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to set.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the permission to manage the guild.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
// 3. Destructure interaction object.
|
||||
const { options, guild } = interaction;
|
||||
if (!guild) throw new Error(`We could not find this guild.`);
|
||||
if (!options) throw new Error(`We could not find the options.`);
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordUser = options.getUser("user");
|
||||
const creditAmount = options.getInteger("amount");
|
||||
if (typeof creditAmount !== "number") throw new Error("Amount is not set.");
|
||||
if (!discordUser) throw new Error("User is not specified");
|
||||
|
||||
// 5. Set the credits.
|
||||
await creditsSet(guild, discordUser, creditAmount);
|
||||
|
||||
// 6. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Set");
|
||||
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
embedSuccess.setDescription(
|
||||
`Set **${discordUser}**'s credits to **${creditAmount}**.`
|
||||
),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import creditsTake from "../../../../../../helpers/credits/take";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("take")
|
||||
.setDescription("Take credits from a user.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to take credits from.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to take.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
// 1. Defer reply as ephemeral.
|
||||
await deferReply(interaction, true);
|
||||
|
||||
// 2. Check if the user has the MANAGE_GUILD permission.
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
// 3. Destructure interaction object.
|
||||
const { guild, options } = interaction;
|
||||
if (!guild) throw new Error("Invalid guild.");
|
||||
if (!options) throw new Error("Invalid options.");
|
||||
|
||||
// 4. Get the user and amount from the options.
|
||||
const discordReceiver = options.getUser("user");
|
||||
const optionAmount = options.getInteger("amount");
|
||||
if (typeof optionAmount !== "number") throw new Error("Invalid amount.");
|
||||
if (!discordReceiver) throw new Error("Invalid user.");
|
||||
|
||||
// 5. Create base embeds.
|
||||
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Take");
|
||||
|
||||
// 6. Take the credits.
|
||||
await creditsTake(guild, discordReceiver, optionAmount);
|
||||
|
||||
// 7. Send embed.
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
embedSuccess.setDescription(
|
||||
`Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.`
|
||||
),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,81 +0,0 @@
|
|||
// Dependencies
|
||||
// Models
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import creditsTransfer from "../../../../../../helpers/credits/transfer";
|
||||
// Configurations
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../../../helpers/checkPermission";
|
||||
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("transfer")
|
||||
.setDescription("Transfer credits from one user to another.")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("from")
|
||||
.setDescription("The user to transfer credits from.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("to")
|
||||
.setDescription("The user to transfer credits to.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription(`The amount of credits to transfer.`)
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageGuild);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
); // Destructure member
|
||||
const { guild, options } = interaction;
|
||||
|
||||
// Get options
|
||||
const optionFromUser = options?.getUser("from");
|
||||
const optionToUser = options?.getUser("to");
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
|
||||
if (optionAmount === null) throw new Error("Amount is not specified");
|
||||
|
||||
if (optionAmount <= 0)
|
||||
throw new Error("You need to set amount above zero to transfer.");
|
||||
|
||||
if (!guild) throw new Error(`We could not find this guild.`);
|
||||
|
||||
if (!optionFromUser)
|
||||
throw new Error("You must provide a user to transfer from.");
|
||||
|
||||
if (!optionToUser)
|
||||
throw new Error("You must provide a user to transfer to.");
|
||||
|
||||
await creditsTransfer(guild, optionFromUser, optionToUser, optionAmount);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
|
||||
.setDescription(`Transferred ${optionAmount} credits.`)
|
||||
.setTimestamp(new Date())
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon }),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,20 +1,23 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import modulePrune from "./modules/prune";
|
||||
import {
|
||||
builder as PruneBuilder,
|
||||
execute as PruneExecute,
|
||||
} from "./subcommands/prune";
|
||||
|
||||
export const builder = new SlashCommandBuilder()
|
||||
.setName("moderation")
|
||||
.setDescription("Moderation.")
|
||||
.setDMPermission(false)
|
||||
|
||||
.addSubcommand(modulePrune.builder);
|
||||
.addSubcommand(PruneBuilder);
|
||||
|
||||
// Execute the command
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "prune": {
|
||||
await modulePrune.execute(interaction);
|
||||
await PruneExecute(interaction);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../helpers/checkPermission";
|
||||
// Configurations
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("prune")
|
||||
.setDescription("Prune messages!")
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("count")
|
||||
.setDescription("How many messages you want to prune.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addBooleanOption((option) =>
|
||||
option.setName("bots").setDescription("Include bots.")
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageMessages);
|
||||
|
||||
const { errorColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
const count = interaction.options.getInteger("count");
|
||||
if (count === null) return;
|
||||
const bots = interaction.options.getBoolean("bots");
|
||||
|
||||
if (count < 1 || count > 100) {
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:police_car:] Prune")
|
||||
.setDescription(`You can only prune between 1 and 100 messages.`)
|
||||
.setTimestamp()
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (interaction?.channel?.type !== ChannelType.GuildText) return;
|
||||
await interaction.channel.messages.fetch().then(async (messages) => {
|
||||
const messagesToDelete = (
|
||||
bots
|
||||
? messages.filter((m) => m?.interaction?.id !== interaction.id)
|
||||
: messages.filter(
|
||||
(m) =>
|
||||
m?.interaction?.id !== interaction.id && m?.author?.bot !== true
|
||||
)
|
||||
).first(count);
|
||||
|
||||
if (interaction?.channel?.type !== ChannelType.GuildText) return;
|
||||
await interaction.channel
|
||||
.bulkDelete(messagesToDelete, true)
|
||||
.then(async () => {
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:police_car:] Prune")
|
||||
.setDescription(`Successfully pruned \`${count}\` messages.`)
|
||||
.setTimestamp()
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
84
src/commands/moderation/subcommands/prune/index.ts
Normal file
84
src/commands/moderation/subcommands/prune/index.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChannelType,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
PermissionsBitField,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import checkPermission from "../../../../helpers/checkPermission";
|
||||
// Configurations
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("prune")
|
||||
.setDescription("Prune messages!")
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("count")
|
||||
.setDescription("How many messages you want to prune.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addBooleanOption((option) =>
|
||||
option.setName("bots").setDescription("Include bots.")
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
checkPermission(interaction, PermissionsBitField.Flags.ManageMessages);
|
||||
|
||||
const { errorColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
const count = interaction.options.getInteger("count");
|
||||
if (count === null) return;
|
||||
const bots = interaction.options.getBoolean("bots");
|
||||
|
||||
if (count < 1 || count > 100) {
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:police_car:] Prune")
|
||||
.setDescription(`You can only prune between 1 and 100 messages.`)
|
||||
.setTimestamp()
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (interaction?.channel?.type !== ChannelType.GuildText) return;
|
||||
await interaction.channel.messages.fetch().then(async (messages) => {
|
||||
const messagesToDelete = (
|
||||
bots
|
||||
? messages.filter((m) => m?.interaction?.id !== interaction.id)
|
||||
: messages.filter(
|
||||
(m) =>
|
||||
m?.interaction?.id !== interaction.id && m?.author?.bot !== true
|
||||
)
|
||||
).first(count);
|
||||
|
||||
if (interaction?.channel?.type !== ChannelType.GuildText) return;
|
||||
await interaction.channel
|
||||
.bulkDelete(messagesToDelete, true)
|
||||
.then(async () => {
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:police_car:] Prune")
|
||||
.setDescription(`Successfully pruned \`${count}\` messages.`)
|
||||
.setTimestamp()
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -2,8 +2,14 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleCheck from "./modules/check";
|
||||
import moduleRepute from "./modules/repute";
|
||||
import {
|
||||
builder as CheckBuilder,
|
||||
execute as CheckExecute,
|
||||
} from "./subcommands/check";
|
||||
import {
|
||||
builder as ReputeBuilder,
|
||||
execute as ReputeExecute,
|
||||
} from "./subcommands/repute";
|
||||
|
||||
// Function
|
||||
export const builder = new SlashCommandBuilder()
|
||||
|
@ -12,17 +18,17 @@ export const builder = new SlashCommandBuilder()
|
|||
.setDMPermission(false)
|
||||
|
||||
// Modules
|
||||
.addSubcommand(moduleRepute.builder)
|
||||
.addSubcommand(moduleCheck.builder);
|
||||
.addSubcommand(ReputeBuilder)
|
||||
.addSubcommand(CheckBuilder);
|
||||
|
||||
// Execute function
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
if (interaction.options.getSubcommand() === "repute") {
|
||||
await moduleRepute.execute(interaction);
|
||||
await ReputeExecute(interaction);
|
||||
return;
|
||||
}
|
||||
if (interaction.options.getSubcommand() === "check") {
|
||||
await moduleCheck.execute(interaction);
|
||||
await CheckExecute(interaction);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("check")
|
||||
.setDescription("Check reputation")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("account")
|
||||
.setDescription("The account you checking")
|
||||
.setRequired(false)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { options, guild, user } = interaction;
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
guild
|
||||
);
|
||||
|
||||
const optionAccount = options?.getUser("account");
|
||||
|
||||
if (!guild) throw new Error("Server unavailable");
|
||||
if (!user) throw new Error("User unavailable");
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: (optionAccount || user).id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: (optionAccount || user).id,
|
||||
},
|
||||
where: {
|
||||
id: (optionAccount || user).id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
const reputationType = (reputation: number) => {
|
||||
if (reputation < 0) return `negative reputation of ${reputation}`;
|
||||
if (reputation > 0) return `positive reputation of ${reputation}`;
|
||||
return "neutral reputation";
|
||||
};
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle(
|
||||
optionAccount
|
||||
? `:loudspeaker:︱Showing ${optionAccount.username}'s reputation`
|
||||
: ":loudspeaker:︱Showing your reputation"
|
||||
)
|
||||
.setDescription(
|
||||
optionAccount
|
||||
? `${optionAccount} have a ${reputationType(
|
||||
createGuildMember.user.reputationsEarned
|
||||
)}`
|
||||
: `You have a ${reputationType(
|
||||
createGuildMember.user.reputationsEarned
|
||||
)}`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,122 +0,0 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
import noSelfReputation from "./components/noSelfReputation";
|
||||
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("repute")
|
||||
.setDescription("Repute an account")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("account")
|
||||
.setDescription("The account you repute")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("type")
|
||||
.setDescription("Type of reputation")
|
||||
.setRequired(true)
|
||||
.addChoices(
|
||||
{ name: "Positive", value: "positive" },
|
||||
{
|
||||
name: "Negative",
|
||||
value: "negative",
|
||||
}
|
||||
)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { options, user, guild, commandId } = interaction;
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
guild
|
||||
);
|
||||
|
||||
const optionAccount = options?.getUser("account");
|
||||
const optionType = options?.getString("type");
|
||||
|
||||
if (!guild) throw new Error("Server unavailable");
|
||||
if (!optionAccount) throw new Error("User unavailable");
|
||||
|
||||
// Pre-checks
|
||||
noSelfReputation(optionAccount, user);
|
||||
|
||||
// Check if user is on cooldown otherwise create one
|
||||
await cooldown(
|
||||
guild,
|
||||
user,
|
||||
commandId,
|
||||
parseInt(process.env.REPUTATION_TIMEOUT)
|
||||
);
|
||||
|
||||
switch (optionType) {
|
||||
case "positive": {
|
||||
const createUser = await prisma.user.upsert({
|
||||
where: {
|
||||
id: optionAccount.id,
|
||||
},
|
||||
update: {
|
||||
reputationsEarned: {
|
||||
increment: 1,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
id: optionAccount.id,
|
||||
reputationsEarned: 1,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createUser);
|
||||
break;
|
||||
}
|
||||
case "negative": {
|
||||
const createUser = await prisma.user.upsert({
|
||||
where: {
|
||||
id: optionAccount.id,
|
||||
},
|
||||
update: {
|
||||
reputationsEarned: {
|
||||
decrement: 1,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
id: optionAccount.id,
|
||||
reputationsEarned: -1,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createUser);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error("Invalid reputation type");
|
||||
}
|
||||
}
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle(`:loudspeaker:︱Reputing ${optionAccount.username}`)
|
||||
.setDescription(
|
||||
`You have given a ${optionType} repute to ${optionAccount}!`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
},
|
||||
};
|
101
src/commands/reputation/subcommands/check/index.ts
Normal file
101
src/commands/reputation/subcommands/check/index.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("check")
|
||||
.setDescription("Check reputation")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("account")
|
||||
.setDescription("The account you checking")
|
||||
.setRequired(false)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { options, guild, user } = interaction;
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(guild);
|
||||
|
||||
const optionAccount = options?.getUser("account");
|
||||
|
||||
if (!guild) throw new Error("Server unavailable");
|
||||
if (!user) throw new Error("User unavailable");
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: (optionAccount || user).id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: (optionAccount || user).id,
|
||||
},
|
||||
where: {
|
||||
id: (optionAccount || user).id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
const reputationType = (reputation: number) => {
|
||||
if (reputation < 0) return `negative reputation of ${reputation}`;
|
||||
if (reputation > 0) return `positive reputation of ${reputation}`;
|
||||
return "neutral reputation";
|
||||
};
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle(
|
||||
optionAccount
|
||||
? `:loudspeaker:︱Showing ${optionAccount.username}'s reputation`
|
||||
: ":loudspeaker:︱Showing your reputation"
|
||||
)
|
||||
.setDescription(
|
||||
optionAccount
|
||||
? `${optionAccount} have a ${reputationType(
|
||||
createGuildMember.user.reputationsEarned
|
||||
)}`
|
||||
: `You have a ${reputationType(
|
||||
createGuildMember.user.reputationsEarned
|
||||
)}`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
};
|
119
src/commands/reputation/subcommands/repute/index.ts
Normal file
119
src/commands/reputation/subcommands/repute/index.ts
Normal file
|
@ -0,0 +1,119 @@
|
|||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
import noSelfReputation from "./components/noSelfReputation";
|
||||
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import cooldown from "../../../../middlewares/cooldown";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("repute")
|
||||
.setDescription("Repute an account")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("account")
|
||||
.setDescription("The account you repute")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("type")
|
||||
.setDescription("Type of reputation")
|
||||
.setRequired(true)
|
||||
.addChoices(
|
||||
{ name: "Positive", value: "positive" },
|
||||
{
|
||||
name: "Negative",
|
||||
value: "negative",
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { options, user, guild, commandId } = interaction;
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(guild);
|
||||
|
||||
const optionAccount = options?.getUser("account");
|
||||
const optionType = options?.getString("type");
|
||||
|
||||
if (!guild) throw new Error("Server unavailable");
|
||||
if (!optionAccount) throw new Error("User unavailable");
|
||||
|
||||
// Pre-checks
|
||||
noSelfReputation(optionAccount, user);
|
||||
|
||||
// Check if user is on cooldown otherwise create one
|
||||
await cooldown(
|
||||
guild,
|
||||
user,
|
||||
commandId,
|
||||
parseInt(process.env.REPUTATION_TIMEOUT)
|
||||
);
|
||||
|
||||
switch (optionType) {
|
||||
case "positive": {
|
||||
const createUser = await prisma.user.upsert({
|
||||
where: {
|
||||
id: optionAccount.id,
|
||||
},
|
||||
update: {
|
||||
reputationsEarned: {
|
||||
increment: 1,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
id: optionAccount.id,
|
||||
reputationsEarned: 1,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createUser);
|
||||
break;
|
||||
}
|
||||
case "negative": {
|
||||
const createUser = await prisma.user.upsert({
|
||||
where: {
|
||||
id: optionAccount.id,
|
||||
},
|
||||
update: {
|
||||
reputationsEarned: {
|
||||
decrement: 1,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
id: optionAccount.id,
|
||||
reputationsEarned: -1,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createUser);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error("Invalid reputation type");
|
||||
}
|
||||
}
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle(`:loudspeaker:︱Reputing ${optionAccount.username}`)
|
||||
.setDescription(
|
||||
`You have given a ${optionType} repute to ${optionAccount}!`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
};
|
52
src/commands/shop/groups/roles/index.ts
Normal file
52
src/commands/shop/groups/roles/index.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
// Handlers
|
||||
|
||||
// Modules
|
||||
import {
|
||||
builder as BuyBuilder,
|
||||
execute as BuyExecute,
|
||||
} from "./subcommands/buy";
|
||||
import {
|
||||
builder as CancelBuilder,
|
||||
execute as CancelExecute,
|
||||
} from "./subcommands/cancel";
|
||||
|
||||
import prisma from "../../../../handlers/database";
|
||||
|
||||
export const builder = (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return (
|
||||
group
|
||||
.setName("roles")
|
||||
.setDescription("Shop for custom roles.")
|
||||
|
||||
// Modules
|
||||
.addSubcommand(BuyBuilder)
|
||||
.addSubcommand(CancelBuilder)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
if (!interaction.guild) return;
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const getGuild = await prisma.guild.findUnique({
|
||||
where: { id: guild.id },
|
||||
});
|
||||
if (!getGuild) throw new Error("Guild not found");
|
||||
|
||||
if (!getGuild.shopRolesEnabled)
|
||||
throw new Error("This server has disabled shop roles.");
|
||||
|
||||
if (options?.getSubcommand() === "buy") {
|
||||
await BuyExecute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "cancel") {
|
||||
await CancelExecute(interaction);
|
||||
}
|
||||
};
|
177
src/commands/shop/groups/roles/subcommands/buy/index.ts
Normal file
177
src/commands/shop/groups/roles/subcommands/buy/index.ts
Normal file
|
@ -0,0 +1,177 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
ColorResolvable,
|
||||
EmbedBuilder,
|
||||
GuildMemberRoleManager,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import getEmbedData from "../../../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
// Configurations
|
||||
// import fetchUser from "../../../../../../helpers/userData";
|
||||
// Models
|
||||
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
// Function
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("buy")
|
||||
.setDescription("Buy a custom role.")
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("name")
|
||||
.setDescription("Name of the role you wish to buy.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("color")
|
||||
.setDescription("Color of the role you wish to buy.")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedData(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild, user, member } = interaction;
|
||||
const optionName = options?.getString("name");
|
||||
const optionColor = options?.getString("color");
|
||||
// If amount is null
|
||||
if (optionName === null)
|
||||
throw new Error("We could not read your requested name");
|
||||
await guild?.roles
|
||||
.create({
|
||||
name: optionName,
|
||||
color: optionColor as ColorResolvable,
|
||||
reason: `${user?.id} bought from shop`,
|
||||
})
|
||||
.then(async (role) => {
|
||||
const userId = "SNOWFLKAE";
|
||||
const guildId = "SNOWFLAKE";
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId,
|
||||
guildId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: userId,
|
||||
},
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guildId,
|
||||
},
|
||||
where: {
|
||||
id: guildId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
// Get guild object
|
||||
const pricePerHour = createGuildMember.guild.shopRolesPricePerHour;
|
||||
|
||||
const updateGuildMember = await prisma.guildMember.update({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId,
|
||||
guildId,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
creditsEarned: { decrement: pricePerHour },
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(updateGuildMember);
|
||||
|
||||
const createShopRole = await prisma.guildShopRoles.upsert({
|
||||
where: {
|
||||
guildId_userId_roleId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
roleId: role.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roleId: role.id,
|
||||
lastPayed: new Date(),
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createShopRole);
|
||||
|
||||
await (member?.roles as GuildMemberRoleManager)?.add(role?.id);
|
||||
logger?.silly(`Role ${role?.name} was bought by ${user?.tag}`);
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] Buy")
|
||||
.setDescription(
|
||||
`You bought **${optionName}** for **${pluralize(
|
||||
pricePerHour,
|
||||
"credit"
|
||||
)}**.`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error("Failed creating role.");
|
||||
});
|
||||
};
|
126
src/commands/shop/groups/roles/subcommands/cancel/index.ts
Normal file
126
src/commands/shop/groups/roles/subcommands/cancel/index.ts
Normal file
|
@ -0,0 +1,126 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
GuildMemberRoleManager,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
// Configurations
|
||||
// Models
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
// Configurations
|
||||
// Models
|
||||
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import getEmbedData from "../../../../../../helpers/getEmbedData";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
// Function
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cancel")
|
||||
.setDescription("Cancel a purchase.")
|
||||
.addRoleOption((option) =>
|
||||
option
|
||||
.setName("role")
|
||||
.setDescription("Role you wish to cancel.")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedData(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild, user, member } = interaction;
|
||||
const optionRole = options.getRole("role");
|
||||
if (optionRole === null)
|
||||
throw new Error("We could not read your requested role.");
|
||||
if (!guild) throw new Error("No guild specified");
|
||||
if (!user) throw new Error("No user specified");
|
||||
|
||||
const roleExist = await prisma.guildShopRoles.findUnique({
|
||||
where: {
|
||||
guildId_userId_roleId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
roleId: optionRole.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (roleExist === null) return;
|
||||
await (member?.roles as GuildMemberRoleManager)?.remove(optionRole?.id);
|
||||
await guild?.roles
|
||||
.delete(optionRole?.id, `${user?.id} canceled from shop`)
|
||||
.then(async () => {
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
if (!createGuildMember) throw new Error("Guild member not created");
|
||||
|
||||
const deleteShopRole = await prisma.guildShopRoles.delete({
|
||||
where: {
|
||||
guildId_userId_roleId: {
|
||||
guildId: guild?.id,
|
||||
userId: user?.id,
|
||||
roleId: optionRole?.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(deleteShopRole);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] Cancel")
|
||||
.setDescription(`You have canceled ${optionRole.name}.`)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.addFields({
|
||||
name: "Your balance",
|
||||
value: `${pluralize(createGuildMember.creditsEarned, "credit")}`,
|
||||
})
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
});
|
||||
};
|
|
@ -2,8 +2,14 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleCpgg from "./modules/cpgg";
|
||||
import moduleRoles from "./modules/roles";
|
||||
import {
|
||||
builder as RolesBuilder,
|
||||
execute as RolesExecute,
|
||||
} from "./groups/roles";
|
||||
import {
|
||||
builder as CpggBuilder,
|
||||
execute as CpggExecute,
|
||||
} from "./subcommands/cpgg";
|
||||
|
||||
// Function
|
||||
export const builder = new SlashCommandBuilder()
|
||||
|
@ -12,8 +18,8 @@ export const builder = new SlashCommandBuilder()
|
|||
.setDMPermission(false)
|
||||
|
||||
// Modules
|
||||
.addSubcommand(moduleCpgg.builder)
|
||||
.addSubcommandGroup(moduleRoles.builder);
|
||||
.addSubcommand(CpggBuilder)
|
||||
.addSubcommandGroup(RolesBuilder);
|
||||
|
||||
// Execute the command
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
|
@ -21,7 +27,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
|
||||
switch (options.getSubcommand()) {
|
||||
case "cpgg": {
|
||||
await moduleCpgg.execute(interaction);
|
||||
await CpggExecute(interaction);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -31,7 +37,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
|||
|
||||
switch (options.getSubcommandGroup()) {
|
||||
case "roles": {
|
||||
await moduleRoles.execute(interaction);
|
||||
await RolesExecute(interaction);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
import axios from "axios";
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
Message,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import encryption from "../../../../helpers/encryption";
|
||||
import getEmbedData from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cpgg")
|
||||
.setDescription("Buy cpgg power.")
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription("How much credits you want to withdraw.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { errorColor, successColor, footerText, footerIcon } =
|
||||
await getEmbedData(interaction.guild);
|
||||
const { options, guild, user, client } = interaction;
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
if (optionAmount === null) {
|
||||
logger?.silly(`Amount is null.`);
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:dollar:] Gift")
|
||||
.setDescription("We could not read your requested amount.")
|
||||
.setTimestamp()
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
}
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
const dmUser = client?.users?.cache?.get(user?.id);
|
||||
|
||||
if ((optionAmount || createGuildMember.creditsEarned) < 100)
|
||||
throw new Error("You can't withdraw to CPGG below 100 credits.");
|
||||
|
||||
if ((optionAmount || createGuildMember.creditsEarned) > 1000000)
|
||||
throw new Error("Amount or user credits is above 1.000.000.");
|
||||
|
||||
if (createGuildMember.creditsEarned < optionAmount)
|
||||
throw new Error("You can't withdraw more than you have on your account.");
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggUrlIv ||
|
||||
!createGuildMember.guild.apiCpggUrlContent
|
||||
)
|
||||
throw new Error("No API url available");
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggTokenIv ||
|
||||
!createGuildMember.guild.apiCpggTokenContent
|
||||
)
|
||||
throw new Error("No API token available");
|
||||
|
||||
const code = uuidv4();
|
||||
const url = encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggUrlIv,
|
||||
content: createGuildMember.guild.apiCpggUrlContent,
|
||||
});
|
||||
const api = axios?.create({
|
||||
baseURL: `${url}/api/`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggTokenIv,
|
||||
content: createGuildMember.guild.apiCpggTokenContent,
|
||||
})}`,
|
||||
},
|
||||
});
|
||||
const shopUrl = `${url}/store`;
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel("Redeem it here")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("🏦")
|
||||
.setURL(`${shopUrl}?voucher=${code}`)
|
||||
);
|
||||
await api
|
||||
?.post("vouchers", {
|
||||
uses: 1,
|
||||
code,
|
||||
credits: optionAmount || createGuildMember.creditsEarned,
|
||||
memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`,
|
||||
})
|
||||
?.then(async () => {
|
||||
logger?.silly(`Successfully created voucher.`);
|
||||
createGuildMember.creditsEarned -=
|
||||
optionAmount || createGuildMember.creditsEarned;
|
||||
|
||||
const updateGuildMember = await prisma.guildMember.update({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
creditsEarned: {
|
||||
decrement: optionAmount || createGuildMember.creditsEarned,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(updateGuildMember);
|
||||
|
||||
if (!interaction.guild) throw new Error("Guild is undefined");
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] CPGG")
|
||||
.setDescription(
|
||||
`This voucher comes from **${interaction.guild.name}**.`
|
||||
)
|
||||
.setTimestamp()
|
||||
.addFields({
|
||||
name: "💶 Credits",
|
||||
value: `${optionAmount || createGuildMember.creditsEarned}`,
|
||||
inline: true,
|
||||
})
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
await dmUser
|
||||
?.send({
|
||||
embeds: [dmEmbed],
|
||||
components: [buttons],
|
||||
})
|
||||
.then(async (msg: Message) => {
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] CPGG")
|
||||
.setDescription(`I have sent you the code in [DM](${msg.url})!`)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
});
|
||||
});
|
||||
return true;
|
||||
},
|
||||
};
|
|
@ -1,47 +0,0 @@
|
|||
// Dependencies
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from "discord.js";
|
||||
|
||||
// Handlers
|
||||
|
||||
// Modules
|
||||
import moduleBuy from "./modules/buy";
|
||||
import moduleCancel from "./modules/cancel";
|
||||
|
||||
import prisma from "../../../../handlers/database";
|
||||
|
||||
export default {
|
||||
builder: (group: SlashCommandSubcommandGroupBuilder) => {
|
||||
return (
|
||||
group
|
||||
.setName("roles")
|
||||
.setDescription("Shop for custom roles.")
|
||||
|
||||
// Modules
|
||||
.addSubcommand(moduleBuy.builder)
|
||||
.addSubcommand(moduleCancel.builder)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
if (!interaction.guild) return;
|
||||
const { options, guild } = interaction;
|
||||
|
||||
const getGuild = await prisma.guild.findUnique({
|
||||
where: { id: guild.id },
|
||||
});
|
||||
if (!getGuild) throw new Error("Guild not found");
|
||||
|
||||
if (!getGuild.shopRolesEnabled)
|
||||
throw new Error("This server has disabled shop roles.");
|
||||
|
||||
if (options?.getSubcommand() === "buy") {
|
||||
await moduleBuy.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "cancel") {
|
||||
await moduleCancel.execute(interaction);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -1,178 +0,0 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
ColorResolvable,
|
||||
EmbedBuilder,
|
||||
GuildMemberRoleManager,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import getEmbedData from "../../../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
// Configurations
|
||||
// import fetchUser from "../../../../../../helpers/userData";
|
||||
// Models
|
||||
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("buy")
|
||||
.setDescription("Buy a custom role.")
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("name")
|
||||
.setDescription("Name of the role you wish to buy.")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("color")
|
||||
.setDescription("Color of the role you wish to buy.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedData(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild, user, member } = interaction;
|
||||
const optionName = options?.getString("name");
|
||||
const optionColor = options?.getString("color");
|
||||
// If amount is null
|
||||
if (optionName === null)
|
||||
throw new Error("We could not read your requested name");
|
||||
await guild?.roles
|
||||
.create({
|
||||
name: optionName,
|
||||
color: optionColor as ColorResolvable,
|
||||
reason: `${user?.id} bought from shop`,
|
||||
})
|
||||
.then(async (role) => {
|
||||
const userId = "SNOWFLKAE";
|
||||
const guildId = "SNOWFLAKE";
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId,
|
||||
guildId,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: userId,
|
||||
},
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guildId,
|
||||
},
|
||||
where: {
|
||||
id: guildId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
// Get guild object
|
||||
const pricePerHour = createGuildMember.guild.shopRolesPricePerHour;
|
||||
|
||||
const updateGuildMember = await prisma.guildMember.update({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId,
|
||||
guildId,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
creditsEarned: { decrement: pricePerHour },
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(updateGuildMember);
|
||||
|
||||
const createShopRole = await prisma.guildShopRoles.upsert({
|
||||
where: {
|
||||
guildId_userId_roleId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
roleId: role.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roleId: role.id,
|
||||
lastPayed: new Date(),
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createShopRole);
|
||||
|
||||
await (member?.roles as GuildMemberRoleManager)?.add(role?.id);
|
||||
logger?.silly(`Role ${role?.name} was bought by ${user?.tag}`);
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] Buy")
|
||||
.setDescription(
|
||||
`You bought **${optionName}** for **${pluralize(
|
||||
pricePerHour,
|
||||
"credit"
|
||||
)}**.`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error("Failed creating role.");
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,127 +0,0 @@
|
|||
// Dependencies
|
||||
// Helpers
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
GuildMemberRoleManager,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
// Configurations
|
||||
// Models
|
||||
import deferReply from "../../../../../../handlers/deferReply";
|
||||
import logger from "../../../../../../middlewares/logger";
|
||||
// Configurations
|
||||
// Models
|
||||
|
||||
import prisma from "../../../../../../handlers/database";
|
||||
import getEmbedData from "../../../../../../helpers/getEmbedData";
|
||||
import pluralize from "../../../../../../helpers/pluralize";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cancel")
|
||||
.setDescription("Cancel a purchase.")
|
||||
.addRoleOption((option) =>
|
||||
option
|
||||
.setName("role")
|
||||
.setDescription("Role you wish to cancel.")
|
||||
.setRequired(true)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedData(
|
||||
interaction.guild
|
||||
);
|
||||
const { options, guild, user, member } = interaction;
|
||||
const optionRole = options.getRole("role");
|
||||
if (optionRole === null)
|
||||
throw new Error("We could not read your requested role.");
|
||||
if (!guild) throw new Error("No guild specified");
|
||||
if (!user) throw new Error("No user specified");
|
||||
|
||||
const roleExist = await prisma.guildShopRoles.findUnique({
|
||||
where: {
|
||||
guildId_userId_roleId: {
|
||||
guildId: guild.id,
|
||||
userId: user.id,
|
||||
roleId: optionRole.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (roleExist === null) return;
|
||||
await (member?.roles as GuildMemberRoleManager)?.remove(optionRole?.id);
|
||||
await guild?.roles
|
||||
.delete(optionRole?.id, `${user?.id} canceled from shop`)
|
||||
.then(async () => {
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
if (!createGuildMember) throw new Error("Guild member not created");
|
||||
|
||||
const deleteShopRole = await prisma.guildShopRoles.delete({
|
||||
where: {
|
||||
guildId_userId_roleId: {
|
||||
guildId: guild?.id,
|
||||
userId: user?.id,
|
||||
roleId: optionRole?.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(deleteShopRole);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] Cancel")
|
||||
.setDescription(`You have canceled ${optionRole.name}.`)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.addFields({
|
||||
name: "Your balance",
|
||||
value: `${pluralize(createGuildMember.creditsEarned, "credit")}`,
|
||||
})
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
194
src/commands/shop/subcommands/cpgg/index.ts
Normal file
194
src/commands/shop/subcommands/cpgg/index.ts
Normal file
|
@ -0,0 +1,194 @@
|
|||
import axios from "axios";
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
Message,
|
||||
SlashCommandSubcommandBuilder,
|
||||
} from "discord.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import prisma from "../../../../handlers/database";
|
||||
import deferReply from "../../../../handlers/deferReply";
|
||||
import encryption from "../../../../helpers/encryption";
|
||||
import getEmbedData from "../../../../helpers/getEmbedData";
|
||||
import logger from "../../../../middlewares/logger";
|
||||
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("cpgg")
|
||||
.setDescription("Buy cpgg power.")
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("amount")
|
||||
.setDescription("How much credits you want to withdraw.")
|
||||
.setRequired(true)
|
||||
);
|
||||
};
|
||||
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
await deferReply(interaction, true);
|
||||
|
||||
const { errorColor, successColor, footerText, footerIcon } =
|
||||
await getEmbedData(interaction.guild);
|
||||
const { options, guild, user, client } = interaction;
|
||||
const optionAmount = options?.getInteger("amount");
|
||||
if (optionAmount === null) {
|
||||
logger?.silly(`Amount is null.`);
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:dollar:] Gift")
|
||||
.setDescription("We could not read your requested amount.")
|
||||
.setTimestamp()
|
||||
.setColor(errorColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
return interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
}
|
||||
if (!guild) throw new Error("Guild not found");
|
||||
|
||||
const createGuildMember = await prisma.guildMember.upsert({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
user: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: user.id,
|
||||
},
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
guild: {
|
||||
connectOrCreate: {
|
||||
create: {
|
||||
id: guild.id,
|
||||
},
|
||||
where: {
|
||||
id: guild.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
guild: true,
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(createGuildMember);
|
||||
|
||||
const dmUser = client?.users?.cache?.get(user?.id);
|
||||
|
||||
if ((optionAmount || createGuildMember.creditsEarned) < 100)
|
||||
throw new Error("You can't withdraw to CPGG below 100 credits.");
|
||||
|
||||
if ((optionAmount || createGuildMember.creditsEarned) > 1000000)
|
||||
throw new Error("Amount or user credits is above 1.000.000.");
|
||||
|
||||
if (createGuildMember.creditsEarned < optionAmount)
|
||||
throw new Error("You can't withdraw more than you have on your account.");
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggUrlIv ||
|
||||
!createGuildMember.guild.apiCpggUrlContent
|
||||
)
|
||||
throw new Error("No API url available");
|
||||
|
||||
if (
|
||||
!createGuildMember.guild.apiCpggTokenIv ||
|
||||
!createGuildMember.guild.apiCpggTokenContent
|
||||
)
|
||||
throw new Error("No API token available");
|
||||
|
||||
const code = uuidv4();
|
||||
const url = encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggUrlIv,
|
||||
content: createGuildMember.guild.apiCpggUrlContent,
|
||||
});
|
||||
const api = axios?.create({
|
||||
baseURL: `${url}/api/`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${encryption.decrypt({
|
||||
iv: createGuildMember.guild.apiCpggTokenIv,
|
||||
content: createGuildMember.guild.apiCpggTokenContent,
|
||||
})}`,
|
||||
},
|
||||
});
|
||||
const shopUrl = `${url}/store`;
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel("Redeem it here")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("🏦")
|
||||
.setURL(`${shopUrl}?voucher=${code}`)
|
||||
);
|
||||
await api
|
||||
?.post("vouchers", {
|
||||
uses: 1,
|
||||
code,
|
||||
credits: optionAmount || createGuildMember.creditsEarned,
|
||||
memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`,
|
||||
})
|
||||
?.then(async () => {
|
||||
logger?.silly(`Successfully created voucher.`);
|
||||
createGuildMember.creditsEarned -=
|
||||
optionAmount || createGuildMember.creditsEarned;
|
||||
|
||||
const updateGuildMember = await prisma.guildMember.update({
|
||||
where: {
|
||||
userId_guildId: {
|
||||
userId: user.id,
|
||||
guildId: guild.id,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
creditsEarned: {
|
||||
decrement: optionAmount || createGuildMember.creditsEarned,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.silly(updateGuildMember);
|
||||
|
||||
if (!interaction.guild) throw new Error("Guild is undefined");
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] CPGG")
|
||||
.setDescription(
|
||||
`This voucher comes from **${interaction.guild.name}**.`
|
||||
)
|
||||
.setTimestamp()
|
||||
.addFields({
|
||||
name: "💶 Credits",
|
||||
value: `${optionAmount || createGuildMember.creditsEarned}`,
|
||||
inline: true,
|
||||
})
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
await dmUser
|
||||
?.send({
|
||||
embeds: [dmEmbed],
|
||||
components: [buttons],
|
||||
})
|
||||
.then(async (msg: Message) => {
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setTitle("[:shopping_cart:] CPGG")
|
||||
.setDescription(`I have sent you the code in [DM](${msg.url})!`)
|
||||
.setTimestamp()
|
||||
.setColor(successColor)
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
await interaction?.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
});
|
||||
});
|
||||
});
|
||||
return true;
|
||||
};
|
|
@ -1,25 +1,31 @@
|
|||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import moduleAbout from "./modules/about";
|
||||
import moduleAvatar from "./modules/avatar";
|
||||
import {
|
||||
builder as AboutBuilder,
|
||||
execute as AboutExecute,
|
||||
} from "./modules/about";
|
||||
import {
|
||||
builder as AvatarBuilder,
|
||||
execute as AvatarExecute,
|
||||
} from "./modules/avatar";
|
||||
|
||||
export const builder = new SlashCommandBuilder()
|
||||
.setName("utils")
|
||||
.setDescription("Common utility.")
|
||||
|
||||
// Modules
|
||||
.addSubcommand(moduleAbout.builder)
|
||||
.addSubcommand(moduleAvatar.builder);
|
||||
.addSubcommand(AboutBuilder)
|
||||
.addSubcommand(AvatarBuilder);
|
||||
|
||||
// Execute the command
|
||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "about":
|
||||
await moduleAbout.execute(interaction);
|
||||
await AboutExecute(interaction);
|
||||
break;
|
||||
case "avatar":
|
||||
await moduleAvatar.execute(interaction);
|
||||
await AvatarExecute(interaction);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
|
|
|
@ -14,107 +14,103 @@ import deferReply from "../../../../handlers/deferReply";
|
|||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("about")
|
||||
.setDescription("Check information about this instance");
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
if (!interaction.guild) throw new Error("You need to be in a guild");
|
||||
|
||||
const { client } = interaction;
|
||||
|
||||
// await cooldown(
|
||||
// interaction.guild,
|
||||
// interaction.user,
|
||||
// interaction.commandId,
|
||||
// 3600
|
||||
// );
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
// // Initialize a storage for the user ids
|
||||
// const userIds = new Set();
|
||||
// // Iterate over all guilds (always cached)
|
||||
// for await (const guild of client.guilds.cache.values()) {
|
||||
// // Fetch all guild members and iterate over them
|
||||
// for await (const member of (await guild.members.fetch()).values()) {
|
||||
// // Fetch the user, if user already cached, returns value from cache
|
||||
// // Will probably always return from cache
|
||||
// const user = await client.users.fetch(member.id);
|
||||
// // Check if user id is not already in set and user is not a bot
|
||||
// if (!userIds.has(user.id) && !user.bot) {
|
||||
// // Add unique user id to our set
|
||||
// userIds.add(user.id);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel("Support")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("💬")
|
||||
.setURL("https://discord.zyner.org"),
|
||||
new ButtonBuilder()
|
||||
.setLabel("Documentation")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("📚")
|
||||
.setURL("https://xyter.zyner.org")
|
||||
);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setColor(successColor)
|
||||
.setTitle(":toolbox:︱About this instance")
|
||||
.setDescription(
|
||||
`This bot instance is hosted by [${process.env.BOT_HOSTER_NAME}](${process.env.BOT_HOSTER_URL}) who might have modified the [source code](https://github.com/ZynerOrg/xyter).`
|
||||
)
|
||||
.setFields(
|
||||
{
|
||||
name: "Latency",
|
||||
value: `${Math.round(client.ws.ping)} ms`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Servers (cached)",
|
||||
value: `${client.guilds.cache.size}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Users (cached)",
|
||||
value: `${client.guilds.cache.reduce(
|
||||
(a, g) => a + g.memberCount,
|
||||
0
|
||||
)}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Version",
|
||||
value: `[${process.env.npm_package_version}](https://github.com/ZynerOrg/xyter/releases/tag/${process.env.npm_package_version})`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Since last restart",
|
||||
value: `${formatDuration(
|
||||
intervalToDuration({
|
||||
start: subMilliseconds(new Date(), client.uptime),
|
||||
end: new Date(),
|
||||
})
|
||||
)}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
components: [buttons],
|
||||
});
|
||||
},
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("about")
|
||||
.setDescription("Check information about this instance");
|
||||
};
|
||||
|
||||
export const execute = async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
if (!interaction.guild) throw new Error("You need to be in a guild");
|
||||
|
||||
const { client } = interaction;
|
||||
|
||||
// await cooldown(
|
||||
// interaction.guild,
|
||||
// interaction.user,
|
||||
// interaction.commandId,
|
||||
// 3600
|
||||
// );
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
// // Initialize a storage for the user ids
|
||||
// const userIds = new Set();
|
||||
// // Iterate over all guilds (always cached)
|
||||
// for await (const guild of client.guilds.cache.values()) {
|
||||
// // Fetch all guild members and iterate over them
|
||||
// for await (const member of (await guild.members.fetch()).values()) {
|
||||
// // Fetch the user, if user already cached, returns value from cache
|
||||
// // Will probably always return from cache
|
||||
// const user = await client.users.fetch(member.id);
|
||||
// // Check if user id is not already in set and user is not a bot
|
||||
// if (!userIds.has(user.id) && !user.bot) {
|
||||
// // Add unique user id to our set
|
||||
// userIds.add(user.id);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setLabel("Support")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("💬")
|
||||
.setURL("https://discord.zyner.org"),
|
||||
new ButtonBuilder()
|
||||
.setLabel("Documentation")
|
||||
.setStyle(ButtonStyle.Link)
|
||||
.setEmoji("📚")
|
||||
.setURL("https://xyter.zyner.org")
|
||||
);
|
||||
|
||||
const interactionEmbed = new EmbedBuilder()
|
||||
.setColor(successColor)
|
||||
.setTitle(":toolbox:︱About this instance")
|
||||
.setDescription(
|
||||
`This bot instance is hosted by [${process.env.BOT_HOSTER_NAME}](${process.env.BOT_HOSTER_URL}) who might have modified the [source code](https://github.com/ZynerOrg/xyter).`
|
||||
)
|
||||
.setFields(
|
||||
{
|
||||
name: "Latency",
|
||||
value: `${Math.round(client.ws.ping)} ms`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Servers (cached)",
|
||||
value: `${client.guilds.cache.size}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Users (cached)",
|
||||
value: `${client.guilds.cache.reduce((a, g) => a + g.memberCount, 0)}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Version",
|
||||
value: `[${process.env.npm_package_version}](https://github.com/ZynerOrg/xyter/releases/tag/${process.env.npm_package_version})`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "Since last restart",
|
||||
value: `${formatDuration(
|
||||
intervalToDuration({
|
||||
start: subMilliseconds(new Date(), client.uptime),
|
||||
end: new Date(),
|
||||
})
|
||||
)}`,
|
||||
inline: true,
|
||||
}
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [interactionEmbed],
|
||||
components: [buttons],
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,45 +6,44 @@ import {
|
|||
import deferReply from "../../../../handlers/deferReply";
|
||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||
|
||||
export default {
|
||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("avatar")
|
||||
.setDescription("Check someones avatar!)")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user whose avatar you want to check")
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("avatar")
|
||||
.setDescription("Check someones avatar!)")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user whose avatar you want to check")
|
||||
);
|
||||
const userOption = interaction.options.getUser("user");
|
||||
|
||||
const targetUser = userOption || interaction.user;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(":toolbox:︱Avatar")
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
const avatarUrl = targetUser.displayAvatarURL();
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(
|
||||
userOption
|
||||
? `You can also [download it here](${avatarUrl})!`
|
||||
: `Your avatar is available to [download here](${avatarUrl}).`
|
||||
)
|
||||
.setThumbnail(avatarUrl)
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const execute = async (interaction: CommandInteraction) => {
|
||||
await deferReply(interaction, false);
|
||||
|
||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||
interaction.guild
|
||||
);
|
||||
const userOption = interaction.options.getUser("user");
|
||||
|
||||
const targetUser = userOption || interaction.user;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(":toolbox:︱Avatar")
|
||||
.setTimestamp(new Date())
|
||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||
|
||||
const avatarUrl = targetUser.displayAvatarURL();
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [
|
||||
embed
|
||||
.setDescription(
|
||||
userOption
|
||||
? `You can also [download it here](${avatarUrl})!`
|
||||
: `Your avatar is available to [download here](${avatarUrl}).`
|
||||
)
|
||||
.setThumbnail(avatarUrl)
|
||||
.setColor(successColor),
|
||||
],
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,4 +11,13 @@ export const execute = async (message: Message) => {
|
|||
await modules.credits.execute(message);
|
||||
await modules.points.execute(message);
|
||||
await modules.counters.execute(message);
|
||||
|
||||
const { client } = message;
|
||||
if (!message.member) return;
|
||||
if (message.author.bot) return;
|
||||
|
||||
client.emit("guildMemberAdd", message.member);
|
||||
client.emit("guildMemberRemove", message.member);
|
||||
client.emit("messageDelete", message);
|
||||
client.emit("messageUpdate", message, message);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue