🚚 one file per credit transaction type

This commit is contained in:
Axel Olausson Holtenäs 2022-10-23 23:07:54 +02:00
parent cf3f3449e8
commit 976e8e7fdc
No known key found for this signature in database
GPG key ID: BEDBB4D61E6C8462
13 changed files with 335 additions and 409 deletions

View file

@ -5,7 +5,7 @@ import {
import deferReply from "../../../../handlers/deferReply";
import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds";
import { transfer as CreditsTransfer } from "../../../../helpers/credits";
import creditsTransfer from "../../../../helpers/credits/transfer";
// 1. Export a builder function.
export const builder = (command: SlashCommandSubcommandBuilder) => {
@ -55,7 +55,7 @@ export const execute = async (interaction: ChatInputCommandInteraction) => {
const EmbedSuccess = await BaseEmbedSuccess(guild, "[:dollar:] Gift");
// 5. Start an transaction of the credits.
await CreditsTransfer(guild, user, target, credits);
await creditsTransfer(guild, user, target, credits);
// 6. Tell the target that they have been gifted credits.
await target.send({

View file

@ -6,7 +6,7 @@ import { command as CooldownCommand } from "../../../../handlers/cooldown";
import prisma from "../../../../handlers/database";
import deferReply from "../../../../handlers/deferReply";
import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds";
import { give as CreditsGive } from "../../../../helpers/credits";
import creditsGive from "../../../../helpers/credits/give";
import logger from "../../../../middlewares/logger";
// 1. Export a builder function.
@ -52,7 +52,7 @@ export const execute = async (interaction: CommandInteraction) => {
max: createGuild.creditsWorkRate,
});
const upsertGuildMember = await CreditsGive(guild, user, creditsEarned);
const upsertGuildMember = await creditsGive(guild, user, creditsEarned);
// 8. Send embed.
await interaction.editReply({

View file

@ -4,7 +4,7 @@ import { ChatInputCommandInteraction, PermissionsBitField } from "discord.js";
import deferReply from "../../../../../../handlers/deferReply";
import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds";
import checkPermission from "../../../../../../helpers/checkPermission";
import { give as CreditsGive } from "../../../../../../helpers/credits";
import creditsGive from "../../../../../../helpers/credits/give";
import pluralize from "../../../../../../helpers/pluralize";
export default {
@ -51,7 +51,7 @@ export default {
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Give");
// 6. Give the credits.
await CreditsGive(guild, discordReceiver, creditsAmount);
await creditsGive(guild, discordReceiver, creditsAmount);
// 7. Send embed.
return await interaction.editReply({

View file

@ -1,21 +1,14 @@
// Dependencies
// Helpers
// Models
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import {
ChatInputCommandInteraction,
EmbedBuilder,
PermissionsBitField,
SlashCommandSubcommandBuilder,
} from "discord.js";
// Configurations
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
// Handlers
import prisma from "../../../../../../handlers/database";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
import logger from "../../../../../../middlewares/logger";
// Function
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
@ -35,107 +28,35 @@ export default {
);
},
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);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
// 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");
// If amount is null
if (creditAmount === null) {
logger?.silly(`Amount is null`);
// 5. Set the credits.
await creditsSet(guild, discordUser, creditAmount);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`You must provide an amount.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// 6. Create base embeds.
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Set");
if (discordUser === null) {
logger?.silly(`User is null`);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`You must provide a user.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (guild === null) {
logger?.silly(`Guild is null`);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`You must provide a guild.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
const createGuildMember = await prisma.guildMember.upsert({
where: {
userId_guildId: {
userId: discordUser.id,
guildId: guild.id,
},
},
update: { creditsEarned: creditAmount },
create: {
creditsEarned: creditAmount,
user: {
connectOrCreate: {
create: {
id: discordUser.id,
},
where: {
id: discordUser.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
},
});
logger.silly(createGuildMember);
return interaction?.editReply({
// 7. Send embed.
return await interaction.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`Set **${discordUser}**'s credits to **${creditAmount}**.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
embedSuccess.setDescription(
`Set **${discordUser}**'s credits to **${creditAmount}**.`
),
],
});
},

View file

@ -1,22 +1,15 @@
// Dependencies
// Models
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import {
ChatInputCommandInteraction,
EmbedBuilder,
PermissionsBitField,
SlashCommandSubcommandBuilder,
} from "discord.js";
// Configurations
import getEmbedConfig from "../../../../../../helpers/getEmbedData";
// Helpers../../../../../../../helpers/userData
import pluralize from "../../../../../../helpers/pluralize";
// Handlers
import prisma from "../../../../../../handlers/database";
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
import logger from "../../../../../../middlewares/logger";
// Function
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
@ -36,127 +29,36 @@ export default {
);
},
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);
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure
// 3. Destructure interaction object.
const { guild, options } = interaction;
if (!guild) throw new Error("Invalid guild.");
if (!options) throw new Error("Invalid options.");
// User option
const discordReceiver = options?.getUser("user");
// 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.");
// Amount option
const optionAmount = options?.getInteger("amount");
// 5. Create base embeds.
const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Take");
// If amount is null
if (optionAmount === null) {
logger?.silly(`Amount is null`);
// 6. Take the credits.
await creditsTake(guild, discordReceiver, optionAmount);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`You must provide an amount.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If amount is zero or below
if (optionAmount <= 0) {
logger?.silly(`Amount is zero or below`);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`You must provide an amount greater than zero.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (discordReceiver === null) {
logger?.silly(`Discord receiver is null`);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`You must provide a user.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (guild === null) {
logger?.silly(`Guild is null`);
return interaction?.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`You must be in a guild.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
const createGuildMember = await prisma.guildMember.upsert({
where: {
userId_guildId: {
userId: discordReceiver.id,
guildId: guild.id,
},
},
update: { creditsEarned: { decrement: optionAmount } },
create: {
creditsEarned: -optionAmount,
user: {
connectOrCreate: {
create: {
id: discordReceiver.id,
},
where: {
id: discordReceiver.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
},
});
logger.silly(createGuildMember);
await interaction?.editReply({
// 7. Send embed.
return await interaction.editReply({
embeds: [
new EmbedBuilder()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
embedSuccess.setDescription(
`Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.`
),
],
});
return;
},
};

View file

@ -6,7 +6,7 @@ import {
EmbedBuilder,
PermissionsBitField,
} from "discord.js";
import { transfer as CreditsTransfer } from "../../../../../../helpers/credits";
import creditsTransfer from "../../../../../../helpers/credits/transfer";
// Configurations
import deferReply from "../../../../../../handlers/deferReply";
import checkPermission from "../../../../../../helpers/checkPermission";
@ -65,7 +65,7 @@ export default {
if (!optionToUser)
throw new Error("You must provide a user to transfer to.");
await CreditsTransfer(guild, optionFromUser, optionToUser, optionAmount);
await creditsTransfer(guild, optionFromUser, optionToUser, optionAmount);
return interaction?.editReply({
embeds: [

View file

@ -1,7 +1,7 @@
import { ChannelType, Message } from "discord.js";
import { message as CooldownMessage } from "../../../../handlers/cooldown";
import prisma from "../../../../handlers/database";
import { give as CreditsGive } from "../../../../helpers/credits";
import creditsGive from "../../../../helpers/credits/give";
import logger from "../../../../middlewares/logger";
export default {
@ -59,6 +59,6 @@ export default {
);
if (isOnCooldown) return;
await CreditsGive(guild, author, createGuildMember.guild.creditsRate);
await creditsGive(guild, author, createGuildMember.guild.creditsRate);
},
};

View file

@ -0,0 +1,54 @@
import { Guild, User } from "discord.js";
import prisma from "../../handlers/database";
import transactionRules from "./transactionRules";
export default async (guild: Guild, user: User, amount: number) => {
return await prisma.$transaction(async (tx) => {
// 1. Check if the transaction is valid.
await transactionRules(guild, user, amount);
// 2. Make the transaction.
const recipient = await tx.guildMember.upsert({
update: {
creditsEarned: {
increment: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: user.id,
},
where: {
id: user.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: amount,
},
where: {
userId_guildId: {
userId: user.id,
guildId: guild.id,
},
},
});
// 3. Verify that the recipient actually is created.
if (!recipient) throw new Error("No recipient available");
// 4. Return the recipient.
return recipient;
});
};

View file

@ -1,173 +0,0 @@
import { Guild, User } from "discord.js";
import prisma from "../../handlers/database";
// Start an transaction between two users in a guild.
export const transfer = async (
guild: Guild,
from: User,
to: User,
amount: number
) => {
return await prisma.$transaction(async (tx) => {
// 1. Decrement amount from the sender.
const sender = await tx.guildMember.upsert({
update: {
creditsEarned: {
decrement: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: from.id,
},
where: {
id: from.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: -amount,
},
where: {
userId_guildId: {
userId: from.id,
guildId: guild.id,
},
},
});
// 2. Verify that the sender actually is created.
if (!sender) throw new Error("No sender available");
// 3. Verify that the sender's balance exists.
if (!sender.creditsEarned) throw new Error("No credits available");
// 4. Verify that the sender's balance didn't go below zero.
if (sender.creditsEarned < 0) {
throw new Error(`${from} doesn't have enough to send ${amount}`);
}
// 5. Verify that the sender is not trying to send less that one credits.
if (amount <= 0) {
throw new Error("You can't transfer below one credit.");
}
// 6. Verify that the sender is not trying to send more than 100.000.000 credits.
if (amount > 100000000) {
throw new Error("You can't transfer more than 100.000.000 credits.");
}
// 7. Verify that recipient are not an bot.
if (to.bot) throw new Error("You can't transfer to an bot.");
// 8. Verify that sender and recipient are not the same user.
if (from.id === to.id) throw new Error("You can't transfer to yourself.");
// 9. Increment the recipient's balance by amount.
const recipient = await tx.guildMember.upsert({
update: {
creditsEarned: {
increment: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: to.id,
},
where: {
id: to.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: amount,
},
where: {
userId_guildId: {
userId: to.id,
guildId: guild.id,
},
},
});
return recipient;
});
};
// Give to guildMember
export const give = async (guild: Guild, user: User, amount: number) => {
// 1. Verify that the amount is not above 100.000.000 credits.
if (amount > 100000000) {
throw new Error("You can't give more than 1.000.000 credits.");
}
// 2. Verify that the amount is not below 1 credits.
if (amount <= 0) {
throw new Error("You can't give below one credit.");
}
// 3. Verify that the user is not an bot.
if (user.bot) {
throw new Error("You can't give to an bot.");
}
// 4. Increment the user's balance by amount.
return await prisma.guildMember.upsert({
update: {
creditsEarned: {
increment: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: user.id,
},
where: {
id: user.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: amount,
},
where: {
userId_guildId: {
userId: user.id,
guildId: guild.id,
},
},
});
};

View file

@ -0,0 +1,52 @@
import { Guild, User } from "discord.js";
import prisma from "../../handlers/database";
import transactionRules from "./transactionRules";
export default async (guild: Guild, user: User, amount: number) => {
return await prisma.$transaction(async (tx) => {
// 1. Check if the transaction is valid.
await transactionRules(guild, user, amount);
// 2. Make the transaction.
const recipient = await tx.guildMember.upsert({
update: {
creditsEarned: amount,
},
create: {
user: {
connectOrCreate: {
create: {
id: user.id,
},
where: {
id: user.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: amount,
},
where: {
userId_guildId: {
userId: user.id,
guildId: guild.id,
},
},
});
// 3. Verify that the recipient actually is created.
if (!recipient) throw new Error("No recipient available");
// 4. Return the recipient.
return recipient;
});
};

View file

@ -0,0 +1,55 @@
import { Guild, User } from "discord.js";
import prisma from "../../handlers/database";
import transactionRules from "./transactionRules";
export default async (guild: Guild, user: User, amount: number) => {
return await prisma.$transaction(async (tx) => {
// 1. Check if the transaction is valid.
await transactionRules(guild, user, amount);
// 2. Make the transaction.
const recipient = await tx.guildMember.upsert({
update: {
creditsEarned: {
decrement: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: user.id,
},
where: {
id: user.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: -amount,
},
where: {
userId_guildId: {
userId: user.id,
guildId: guild.id,
},
},
});
// 3. Verify that the recipient credits are not below zero.
if (recipient.creditsEarned < -100)
throw new Error("User do not have enough credits");
// 4. Return the recipient.
return recipient;
});
};

View file

@ -0,0 +1,18 @@
import { Guild, User } from "discord.js";
export default async (guild: Guild, user: User, amount: number) => {
// 1. Verify that the amount is not above 100.000.000 credits.
if (amount > 100000000) {
throw new Error("You can't give more than 1.000.000 credits.");
}
// 2. Verify that the amount is not below 1 credits.
if (amount <= 0) {
throw new Error("You can't give below one credit.");
}
// 3. Verify that the user is not an bot.
if (user.bot) {
throw new Error("You can't give to an bot.");
}
};

View file

@ -0,0 +1,97 @@
import { Guild, User } from "discord.js";
import prisma from "../../handlers/database";
import transactionRules from "./transactionRules";
export default async (guild: Guild, from: User, to: User, amount: number) => {
return await prisma.$transaction(async (tx) => {
// 1. Decrement amount from the sender.
const sender = await tx.guildMember.upsert({
update: {
creditsEarned: {
decrement: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: from.id,
},
where: {
id: from.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: -amount,
},
where: {
userId_guildId: {
userId: from.id,
guildId: guild.id,
},
},
});
// 4. Verify that the sender's balance didn't go below zero.
if (sender.creditsEarned < 0) {
throw new Error(`${from} doesn't have enough to send ${amount}`);
}
// 5. Check if the transactions is valid.
await transactionRules(guild, from, amount);
await transactionRules(guild, to, amount);
// 6. Verify that sender and recipient are not the same user.
if (from.id === to.id) throw new Error("You can't transfer to yourself.");
// 7. Increment the recipient's balance by amount.
const recipient = await tx.guildMember.upsert({
update: {
creditsEarned: {
increment: amount,
},
},
create: {
user: {
connectOrCreate: {
create: {
id: to.id,
},
where: {
id: to.id,
},
},
},
guild: {
connectOrCreate: {
create: {
id: guild.id,
},
where: {
id: guild.id,
},
},
},
creditsEarned: amount,
},
where: {
userId_guildId: {
userId: to.id,
guildId: guild.id,
},
},
});
return recipient;
});
};