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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
import moduleAudits from "./modules/audits";
|
import {
|
||||||
import moduleCpgg from "./modules/cpgg";
|
builder as AuditsBuilder,
|
||||||
import moduleCredits from "./modules/credits";
|
execute as AuditsExecute,
|
||||||
import moduleEmbeds from "./modules/embeds";
|
} from "./subcommands/audits";
|
||||||
import modulePoints from "./modules/points";
|
import {
|
||||||
import moduleShop from "./modules/shop";
|
builder as CpggBuilder,
|
||||||
import moduleWelcome from "./modules/welcome";
|
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()
|
export const builder = new SlashCommandBuilder()
|
||||||
.setName("config")
|
.setName("config")
|
||||||
.setDescription("Manage guild configurations.")
|
.setDescription("Manage guild configurations.")
|
||||||
.setDMPermission(false)
|
.setDMPermission(false)
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
.addSubcommand(moduleAudits.builder)
|
.addSubcommand(AuditsBuilder)
|
||||||
.addSubcommand(moduleCpgg.builder)
|
.addSubcommand(CpggBuilder)
|
||||||
.addSubcommand(moduleCredits.builder)
|
.addSubcommand(CreditsBuilder)
|
||||||
.addSubcommand(moduleEmbeds.builder)
|
.addSubcommand(EmbedsBuilder)
|
||||||
.addSubcommand(modulePoints.builder)
|
.addSubcommand(PointsBuilder)
|
||||||
.addSubcommand(moduleShop.builder)
|
.addSubcommand(ShopBuilder)
|
||||||
.addSubcommand(moduleWelcome.builder);
|
.addSubcommand(WelcomeBuilder);
|
||||||
|
|
||||||
// Execute function
|
// Execute function
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
switch (interaction.options.getSubcommand()) {
|
switch (interaction.options.getSubcommand()) {
|
||||||
case "audits":
|
case "audits":
|
||||||
await moduleAudits.execute(interaction);
|
await AuditsExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "cpgg":
|
case "cpgg":
|
||||||
await moduleCpgg.execute(interaction);
|
await CpggExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "credits":
|
case "credits":
|
||||||
await moduleCredits.execute(interaction);
|
await CreditsExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "embeds":
|
case "embeds":
|
||||||
await moduleEmbeds.execute(interaction);
|
await EmbedsExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "points":
|
case "points":
|
||||||
await modulePoints.execute(interaction);
|
await PointsExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "shop":
|
case "shop":
|
||||||
await moduleShop.execute(interaction);
|
await ShopExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "welcome":
|
case "welcome":
|
||||||
await moduleWelcome.execute(interaction);
|
await WelcomeExecute(interaction);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("No module found for that specific command.");
|
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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
import { builder as ViewBuilder, execute as ViewExecute } from "./modules/view";
|
import {
|
||||||
|
builder as ViewBuilder,
|
||||||
|
execute as ViewExecute,
|
||||||
|
} from "./subcommands/view";
|
||||||
|
|
||||||
//
|
//
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
|
@ -9,7 +12,7 @@ export const builder = new SlashCommandBuilder()
|
||||||
.setDescription("View guild counters")
|
.setDescription("View guild counters")
|
||||||
.setDMPermission(false)
|
.setDMPermission(false)
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
.addSubcommand(ViewBuilder);
|
.addSubcommand(ViewBuilder);
|
||||||
|
|
||||||
// Execute function
|
// Execute function
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
import {
|
import {
|
||||||
builder as BalanceBuilder,
|
builder as BalanceBuilder,
|
||||||
execute as BalanceExecute,
|
execute as BalanceExecute,
|
||||||
} from "./modules/balance";
|
} from "./subcommands/balance";
|
||||||
import { builder as GiftBuilder, execute as GiftExecute } from "./modules/gift";
|
import {
|
||||||
import { builder as TopBuilder, execute as TopExecute } from "./modules/top";
|
builder as GiftBuilder,
|
||||||
import { builder as WorkBuilder, execute as WorkExecute } from "./modules/work";
|
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.
|
// 1. Export a builder function.
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
import moduleLookup from "./modules/lookup";
|
import {
|
||||||
|
builder as LookupBuilder,
|
||||||
|
execute as LookupExecute,
|
||||||
|
} from "./subcommands/lookup";
|
||||||
|
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
.setName("dns")
|
.setName("dns")
|
||||||
.setDescription("DNS commands.")
|
.setDescription("DNS commands.")
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
.addSubcommand(moduleLookup.builder);
|
.addSubcommand(LookupBuilder);
|
||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
switch (interaction.options.getSubcommand()) {
|
switch (interaction.options.getSubcommand()) {
|
||||||
case "lookup":
|
case "lookup":
|
||||||
await moduleLookup.execute(interaction);
|
await LookupExecute(interaction);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
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 { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
import logger from "../../middlewares/logger";
|
import logger from "../../middlewares/logger";
|
||||||
|
|
||||||
// Modules
|
// Subcommands
|
||||||
import moduleMeme from "./modules/meme";
|
import {
|
||||||
|
builder as MemeBuilder,
|
||||||
|
execute as MemeExecute,
|
||||||
|
} from "./subcommands/meme";
|
||||||
|
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
.setName("fun")
|
.setName("fun")
|
||||||
.setDescription("Fun commands.")
|
.setDescription("Fun commands.")
|
||||||
|
|
||||||
.addSubcommand(moduleMeme.builder);
|
.addSubcommand(MemeBuilder);
|
||||||
|
|
||||||
// Execute function
|
// Execute function
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
const { options } = interaction;
|
const { options } = interaction;
|
||||||
|
|
||||||
if (options.getSubcommand() === "meme") {
|
if (options.getSubcommand() === "meme") {
|
||||||
await moduleMeme.execute(interaction);
|
await MemeExecute(interaction);
|
||||||
} else {
|
} else {
|
||||||
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
|
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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
import moduleCounters from "./modules/counters";
|
import {
|
||||||
import moduleCredits from "./modules/credits";
|
builder as CountersBuilder,
|
||||||
|
execute as CountersExecute,
|
||||||
|
} from "./groups/counters";
|
||||||
|
import {
|
||||||
|
builder as CreditsBuilder,
|
||||||
|
execute as CreditsExecute,
|
||||||
|
} from "./groups/credits";
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
|
@ -12,8 +18,8 @@ export const builder = new SlashCommandBuilder()
|
||||||
.setDMPermission(false)
|
.setDMPermission(false)
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
.addSubcommandGroup(moduleCounters.builder)
|
.addSubcommandGroup(CountersBuilder)
|
||||||
.addSubcommandGroup(moduleCredits.builder);
|
.addSubcommandGroup(CreditsBuilder);
|
||||||
|
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
// Destructure
|
// Destructure
|
||||||
|
@ -21,11 +27,11 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
|
|
||||||
switch (options.getSubcommandGroup()) {
|
switch (options.getSubcommandGroup()) {
|
||||||
case "credits": {
|
case "credits": {
|
||||||
await moduleCredits.execute(interaction);
|
await CreditsExecute(interaction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "counters": {
|
case "counters": {
|
||||||
await moduleCounters.execute(interaction);
|
await CountersExecute(interaction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
import modulePrune from "./modules/prune";
|
import {
|
||||||
|
builder as PruneBuilder,
|
||||||
|
execute as PruneExecute,
|
||||||
|
} from "./subcommands/prune";
|
||||||
|
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
.setName("moderation")
|
.setName("moderation")
|
||||||
.setDescription("Moderation.")
|
.setDescription("Moderation.")
|
||||||
.setDMPermission(false)
|
.setDMPermission(false)
|
||||||
|
|
||||||
.addSubcommand(modulePrune.builder);
|
.addSubcommand(PruneBuilder);
|
||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
switch (interaction.options.getSubcommand()) {
|
switch (interaction.options.getSubcommand()) {
|
||||||
case "prune": {
|
case "prune": {
|
||||||
await modulePrune.execute(interaction);
|
await PruneExecute(interaction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
import moduleCheck from "./modules/check";
|
import {
|
||||||
import moduleRepute from "./modules/repute";
|
builder as CheckBuilder,
|
||||||
|
execute as CheckExecute,
|
||||||
|
} from "./subcommands/check";
|
||||||
|
import {
|
||||||
|
builder as ReputeBuilder,
|
||||||
|
execute as ReputeExecute,
|
||||||
|
} from "./subcommands/repute";
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
|
@ -12,17 +18,17 @@ export const builder = new SlashCommandBuilder()
|
||||||
.setDMPermission(false)
|
.setDMPermission(false)
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
.addSubcommand(moduleRepute.builder)
|
.addSubcommand(ReputeBuilder)
|
||||||
.addSubcommand(moduleCheck.builder);
|
.addSubcommand(CheckBuilder);
|
||||||
|
|
||||||
// Execute function
|
// Execute function
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
if (interaction.options.getSubcommand() === "repute") {
|
if (interaction.options.getSubcommand() === "repute") {
|
||||||
await moduleRepute.execute(interaction);
|
await ReputeExecute(interaction);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (interaction.options.getSubcommand() === "check") {
|
if (interaction.options.getSubcommand() === "check") {
|
||||||
await moduleCheck.execute(interaction);
|
await CheckExecute(interaction);
|
||||||
return;
|
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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
import moduleCpgg from "./modules/cpgg";
|
import {
|
||||||
import moduleRoles from "./modules/roles";
|
builder as RolesBuilder,
|
||||||
|
execute as RolesExecute,
|
||||||
|
} from "./groups/roles";
|
||||||
|
import {
|
||||||
|
builder as CpggBuilder,
|
||||||
|
execute as CpggExecute,
|
||||||
|
} from "./subcommands/cpgg";
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
|
@ -12,8 +18,8 @@ export const builder = new SlashCommandBuilder()
|
||||||
.setDMPermission(false)
|
.setDMPermission(false)
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
.addSubcommand(moduleCpgg.builder)
|
.addSubcommand(CpggBuilder)
|
||||||
.addSubcommandGroup(moduleRoles.builder);
|
.addSubcommandGroup(RolesBuilder);
|
||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
|
@ -21,7 +27,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
|
|
||||||
switch (options.getSubcommand()) {
|
switch (options.getSubcommand()) {
|
||||||
case "cpgg": {
|
case "cpgg": {
|
||||||
await moduleCpgg.execute(interaction);
|
await CpggExecute(interaction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -31,7 +37,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
|
|
||||||
switch (options.getSubcommandGroup()) {
|
switch (options.getSubcommandGroup()) {
|
||||||
case "roles": {
|
case "roles": {
|
||||||
await moduleRoles.execute(interaction);
|
await RolesExecute(interaction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
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";
|
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
import moduleAbout from "./modules/about";
|
import {
|
||||||
import moduleAvatar from "./modules/avatar";
|
builder as AboutBuilder,
|
||||||
|
execute as AboutExecute,
|
||||||
|
} from "./modules/about";
|
||||||
|
import {
|
||||||
|
builder as AvatarBuilder,
|
||||||
|
execute as AvatarExecute,
|
||||||
|
} from "./modules/avatar";
|
||||||
|
|
||||||
export const builder = new SlashCommandBuilder()
|
export const builder = new SlashCommandBuilder()
|
||||||
.setName("utils")
|
.setName("utils")
|
||||||
.setDescription("Common utility.")
|
.setDescription("Common utility.")
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
.addSubcommand(moduleAbout.builder)
|
.addSubcommand(AboutBuilder)
|
||||||
.addSubcommand(moduleAvatar.builder);
|
.addSubcommand(AvatarBuilder);
|
||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
export const execute = async (interaction: ChatInputCommandInteraction) => {
|
||||||
switch (interaction.options.getSubcommand()) {
|
switch (interaction.options.getSubcommand()) {
|
||||||
case "about":
|
case "about":
|
||||||
await moduleAbout.execute(interaction);
|
await AboutExecute(interaction);
|
||||||
break;
|
break;
|
||||||
case "avatar":
|
case "avatar":
|
||||||
await moduleAvatar.execute(interaction);
|
await AvatarExecute(interaction);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
@ -14,107 +14,103 @@ import deferReply from "../../../../handlers/deferReply";
|
||||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
export default {
|
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
return command
|
||||||
return command
|
.setName("about")
|
||||||
.setName("about")
|
.setDescription("Check information about this instance");
|
||||||
.setDescription("Check information about this instance");
|
};
|
||||||
},
|
|
||||||
execute: async (interaction: CommandInteraction) => {
|
export const execute = async (interaction: CommandInteraction) => {
|
||||||
await deferReply(interaction, false);
|
await deferReply(interaction, false);
|
||||||
|
|
||||||
if (!interaction.guild) throw new Error("You need to be in a guild");
|
if (!interaction.guild) throw new Error("You need to be in a guild");
|
||||||
|
|
||||||
const { client } = interaction;
|
const { client } = interaction;
|
||||||
|
|
||||||
// await cooldown(
|
// await cooldown(
|
||||||
// interaction.guild,
|
// interaction.guild,
|
||||||
// interaction.user,
|
// interaction.user,
|
||||||
// interaction.commandId,
|
// interaction.commandId,
|
||||||
// 3600
|
// 3600
|
||||||
// );
|
// );
|
||||||
|
|
||||||
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||||
interaction.guild
|
interaction.guild
|
||||||
);
|
);
|
||||||
|
|
||||||
// // Initialize a storage for the user ids
|
// // Initialize a storage for the user ids
|
||||||
// const userIds = new Set();
|
// const userIds = new Set();
|
||||||
// // Iterate over all guilds (always cached)
|
// // Iterate over all guilds (always cached)
|
||||||
// for await (const guild of client.guilds.cache.values()) {
|
// for await (const guild of client.guilds.cache.values()) {
|
||||||
// // Fetch all guild members and iterate over them
|
// // Fetch all guild members and iterate over them
|
||||||
// for await (const member of (await guild.members.fetch()).values()) {
|
// for await (const member of (await guild.members.fetch()).values()) {
|
||||||
// // Fetch the user, if user already cached, returns value from cache
|
// // Fetch the user, if user already cached, returns value from cache
|
||||||
// // Will probably always return from cache
|
// // Will probably always return from cache
|
||||||
// const user = await client.users.fetch(member.id);
|
// const user = await client.users.fetch(member.id);
|
||||||
// // Check if user id is not already in set and user is not a bot
|
// // Check if user id is not already in set and user is not a bot
|
||||||
// if (!userIds.has(user.id) && !user.bot) {
|
// if (!userIds.has(user.id) && !user.bot) {
|
||||||
// // Add unique user id to our set
|
// // Add unique user id to our set
|
||||||
// userIds.add(user.id);
|
// userIds.add(user.id);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setLabel("Support")
|
.setLabel("Support")
|
||||||
.setStyle(ButtonStyle.Link)
|
.setStyle(ButtonStyle.Link)
|
||||||
.setEmoji("💬")
|
.setEmoji("💬")
|
||||||
.setURL("https://discord.zyner.org"),
|
.setURL("https://discord.zyner.org"),
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setLabel("Documentation")
|
.setLabel("Documentation")
|
||||||
.setStyle(ButtonStyle.Link)
|
.setStyle(ButtonStyle.Link)
|
||||||
.setEmoji("📚")
|
.setEmoji("📚")
|
||||||
.setURL("https://xyter.zyner.org")
|
.setURL("https://xyter.zyner.org")
|
||||||
);
|
);
|
||||||
|
|
||||||
const interactionEmbed = new EmbedBuilder()
|
const interactionEmbed = new EmbedBuilder()
|
||||||
.setColor(successColor)
|
.setColor(successColor)
|
||||||
.setTitle(":toolbox:︱About this instance")
|
.setTitle(":toolbox:︱About this instance")
|
||||||
.setDescription(
|
.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).`
|
`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(
|
.setFields(
|
||||||
{
|
{
|
||||||
name: "Latency",
|
name: "Latency",
|
||||||
value: `${Math.round(client.ws.ping)} ms`,
|
value: `${Math.round(client.ws.ping)} ms`,
|
||||||
inline: true,
|
inline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Servers (cached)",
|
name: "Servers (cached)",
|
||||||
value: `${client.guilds.cache.size}`,
|
value: `${client.guilds.cache.size}`,
|
||||||
inline: true,
|
inline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Users (cached)",
|
name: "Users (cached)",
|
||||||
value: `${client.guilds.cache.reduce(
|
value: `${client.guilds.cache.reduce((a, g) => a + g.memberCount, 0)}`,
|
||||||
(a, g) => a + g.memberCount,
|
inline: true,
|
||||||
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: "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({
|
||||||
name: "Since last restart",
|
start: subMilliseconds(new Date(), client.uptime),
|
||||||
value: `${formatDuration(
|
end: new Date(),
|
||||||
intervalToDuration({
|
})
|
||||||
start: subMilliseconds(new Date(), client.uptime),
|
)}`,
|
||||||
end: new Date(),
|
inline: true,
|
||||||
})
|
}
|
||||||
)}`,
|
)
|
||||||
inline: true,
|
.setTimestamp()
|
||||||
}
|
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||||
)
|
|
||||||
.setTimestamp()
|
await interaction.editReply({
|
||||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
embeds: [interactionEmbed],
|
||||||
|
components: [buttons],
|
||||||
await interaction.editReply({
|
});
|
||||||
embeds: [interactionEmbed],
|
|
||||||
components: [buttons],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,45 +6,44 @@ import {
|
||||||
import deferReply from "../../../../handlers/deferReply";
|
import deferReply from "../../../../handlers/deferReply";
|
||||||
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
import getEmbedConfig from "../../../../helpers/getEmbedData";
|
||||||
|
|
||||||
export default {
|
export const builder = (command: SlashCommandSubcommandBuilder) => {
|
||||||
builder: (command: SlashCommandSubcommandBuilder) => {
|
return command
|
||||||
return command
|
.setName("avatar")
|
||||||
.setName("avatar")
|
.setDescription("Check someones avatar!)")
|
||||||
.setDescription("Check someones avatar!)")
|
.addUserOption((option) =>
|
||||||
.addUserOption((option) =>
|
option
|
||||||
option
|
.setName("user")
|
||||||
.setName("user")
|
.setDescription("The user whose avatar you want to check")
|
||||||
.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
|
|
||||||
);
|
);
|
||||||
const userOption = interaction.options.getUser("user");
|
};
|
||||||
|
|
||||||
const targetUser = userOption || interaction.user;
|
export const execute = async (interaction: CommandInteraction) => {
|
||||||
|
await deferReply(interaction, false);
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle(":toolbox:︱Avatar")
|
const { successColor, footerText, footerIcon } = await getEmbedConfig(
|
||||||
.setTimestamp(new Date())
|
interaction.guild
|
||||||
.setFooter({ text: footerText, iconURL: footerIcon });
|
);
|
||||||
|
const userOption = interaction.options.getUser("user");
|
||||||
const avatarUrl = targetUser.displayAvatarURL();
|
|
||||||
|
const targetUser = userOption || interaction.user;
|
||||||
return interaction.editReply({
|
|
||||||
embeds: [
|
const embed = new EmbedBuilder()
|
||||||
embed
|
.setTitle(":toolbox:︱Avatar")
|
||||||
.setDescription(
|
.setTimestamp(new Date())
|
||||||
userOption
|
.setFooter({ text: footerText, iconURL: footerIcon });
|
||||||
? `You can also [download it here](${avatarUrl})!`
|
|
||||||
: `Your avatar is available to [download here](${avatarUrl}).`
|
const avatarUrl = targetUser.displayAvatarURL();
|
||||||
)
|
|
||||||
.setThumbnail(avatarUrl)
|
return interaction.editReply({
|
||||||
.setColor(successColor),
|
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.credits.execute(message);
|
||||||
await modules.points.execute(message);
|
await modules.points.execute(message);
|
||||||
await modules.counters.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