-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add coin and balance operations
- Loading branch information
1 parent
5699b60
commit 5c32123
Showing
6 changed files
with
546 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { SlashCommandBuilder, EmbedBuilder, GuildMember } from 'discord.js'; | ||
|
||
import { SlashCommand } from '@marquinhos/types'; | ||
import { getCoinBalance } from '@marquinhos/services/coinBalanceManager'; | ||
|
||
export const balance: SlashCommand = { | ||
command: new SlashCommandBuilder() | ||
.setName('saldo') | ||
.setDescription('Retorna o seu saldo de moedas'), | ||
execute: async (interaction) => { | ||
const balance = await getCoinBalance( | ||
interaction.user.id, | ||
interaction.guild?.id ?? '' | ||
); | ||
|
||
const balanceEmbed = new EmbedBuilder(); | ||
|
||
balanceEmbed | ||
.setColor('#0099ff') | ||
.setThumbnail(interaction.user.displayAvatarURL()) | ||
.setTimestamp() | ||
.setFooter({ | ||
text: 'Marquinhos Bot ™️', | ||
iconURL: interaction.client.user?.displayAvatarURL(), | ||
}); | ||
|
||
if (balance === null) { | ||
balanceEmbed | ||
.setTitle('Sem saldo') | ||
.setDescription( | ||
'Você ainda não possui saldo. Tente ganhar quinhões fazendo atividades no servidor para ganhar moedas.' | ||
); | ||
} else { | ||
balanceEmbed | ||
.setTitle( | ||
`Saldo de ${ | ||
(interaction.member as GuildMember).nickname ?? | ||
interaction.user.username | ||
}` | ||
) | ||
.addFields({ | ||
name: 'Saldo Atual', | ||
value: `:coin: ${formatBalance(balance)}`, | ||
inline: true, | ||
}); | ||
} | ||
|
||
interaction.reply({ embeds: [balanceEmbed] }); | ||
}, | ||
cooldown: 10, | ||
}; | ||
|
||
function formatBalance(amount: Number) { | ||
if (amount === 0) return '0 Quinhões'; | ||
if (amount === 1) return '1 Quinhão'; | ||
return `${amount} Quinhões`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
import { SlashCommandBuilder } from '@discordjs/builders'; | ||
import { | ||
addCoins, | ||
resetCoins, | ||
subtractCoins, | ||
updateCoinBalance, | ||
} from '@marquinhos/services/coinBalanceManager'; | ||
import { BalanceChangeStatus, BalanceOperationType } from '@marquinhos/types'; | ||
import { | ||
BaseInteraction, | ||
CommandInteraction, | ||
CommandInteractionOptionResolver, | ||
EmbedBuilder, | ||
PermissionsBitField, | ||
} from 'discord.js'; | ||
|
||
export const balanceOperation = { | ||
command: new SlashCommandBuilder() | ||
.setName('atualizar-saldo') | ||
.setDescription('Execute operações no saldo') | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('adicionar') | ||
.setDescription('Adiciona moedas ao saldo') | ||
.addIntegerOption((option) => | ||
option | ||
.setName('valor') | ||
.setDescription('A quantidade de moedas a adicionar') | ||
.setRequired(true) | ||
) | ||
.addUserOption((option) => | ||
option | ||
.setName('usuário') | ||
.setDescription('O usuário que receberá as moedas') | ||
.setRequired(true) | ||
) | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('subtrair') | ||
.setDescription('Subtrai moedas do saldo') | ||
.addIntegerOption((option) => | ||
option | ||
.setName('valor') | ||
.setDescription('A quantidade de moedas a subtrair') | ||
.setRequired(true) | ||
) | ||
.addUserOption((option) => | ||
option | ||
.setName('usuário') | ||
.setDescription('O usuário que terá as moedas subtraídas') | ||
.setRequired(true) | ||
) | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('definir') | ||
.setDescription('Define um novo saldo') | ||
.addIntegerOption((option) => | ||
option | ||
.setName('valor') | ||
.setDescription('O novo saldo') | ||
.setRequired(true) | ||
) | ||
.addUserOption((option) => | ||
option | ||
.setName('usuário') | ||
.setDescription('O usuário que terá o saldo definido') | ||
.setRequired(true) | ||
) | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName('remover') | ||
.setDescription('Apaga o saldo atual') | ||
.addUserOption((option) => | ||
option | ||
.setName('usuário') | ||
.setDescription('O usuário que terá o saldo apagado') | ||
.setRequired(true) | ||
) | ||
) | ||
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator), | ||
execute: async (interaction: CommandInteraction) => { | ||
const subcommand = ( | ||
interaction.options as CommandInteractionOptionResolver | ||
).getSubcommand(); | ||
|
||
const amount = interaction.options.get('valor')?.value as number; | ||
|
||
const baseEmbed = new EmbedBuilder() | ||
.setColor('#0099ff') | ||
.setTitle('Operação no saldo') | ||
.setTimestamp() | ||
.setFooter({ | ||
text: 'Marquinhos Bot ™️', | ||
iconURL: interaction.client.user?.displayAvatarURL(), | ||
}); | ||
|
||
let operationResult: BalanceChangeStatus & { | ||
operationType: BalanceOperationType | null; | ||
} = { | ||
operationSuccess: false, | ||
statementCreated: false, | ||
validAmount: false, | ||
operationType: null, | ||
}; | ||
const user = interaction.options.get('usuário')?.user; | ||
|
||
switch (subcommand) { | ||
case 'adicionar': { | ||
operationResult = { | ||
...(await addCoins( | ||
user?.id ?? '', | ||
interaction.guild?.id ?? '', | ||
amount, | ||
interaction.user.id | ||
)), | ||
operationType: 'add', | ||
}; | ||
|
||
break; | ||
} | ||
case 'subtrair': { | ||
operationResult = { | ||
...(await subtractCoins( | ||
user?.id ?? '', | ||
interaction.guild?.id ?? '', | ||
amount, | ||
interaction.user.id | ||
)), | ||
operationType: 'subtract', | ||
}; | ||
break; | ||
} | ||
case 'definir': { | ||
operationResult = { | ||
...(await updateCoinBalance( | ||
user?.id ?? '', | ||
interaction.guild?.id ?? '', | ||
amount, | ||
interaction.user.id | ||
)), | ||
operationType: 'set', | ||
}; | ||
break; | ||
} | ||
case 'remover': { | ||
operationResult = { | ||
...(await resetCoins( | ||
user?.id ?? '', | ||
interaction.guild?.id ?? '', | ||
interaction.user.id | ||
)), | ||
operationType: 'reset', | ||
}; | ||
break; | ||
} | ||
} | ||
const replyContent = operationReply( | ||
operationResult, | ||
amount, | ||
user?.username ?? '' | ||
); | ||
|
||
baseEmbed.setTitle(replyContent.title); | ||
baseEmbed.setDescription(replyContent.description); | ||
|
||
await interaction.reply({ | ||
embeds: [baseEmbed], | ||
ephemeral: true, | ||
}); | ||
}, | ||
}; | ||
|
||
function operationReply( | ||
operationResult: BalanceChangeStatus & { | ||
operationType: BalanceOperationType | null; | ||
}, | ||
amount: number, | ||
username: string | ||
): { title: string; description: string } { | ||
if (operationResult.operationSuccess) { | ||
switch (operationResult.operationType) { | ||
case 'add': | ||
return { | ||
title: 'Operação bem-sucedida', | ||
description: `Adicionado ${amount} quinhões ao saldo de ${username}.`, | ||
}; | ||
case 'subtract': | ||
return { | ||
title: 'Operação bem-sucedida', | ||
description: `Subtraido ${amount} quinhões do saldo de ${username}.`, | ||
}; | ||
case 'reset': | ||
return { | ||
title: 'Operação bem-sucedida', | ||
description: `O saldo de ${username} foi removido.`, | ||
}; | ||
case 'set': | ||
return { | ||
title: 'Operação bem-sucedida', | ||
description: `O saldo de ${username} foi definido para ${amount}.`, | ||
}; | ||
default: | ||
return { | ||
title: 'Erro na operação', | ||
description: 'Tipo de operação inválido.', | ||
}; | ||
} | ||
} else if (!operationResult.validAmount) { | ||
return { | ||
title: 'Erro na operação', | ||
description: 'O valor deve ser um número maior que 0.', | ||
}; | ||
} else { | ||
return { | ||
title: 'Erro na operação', | ||
description: 'Ocorreu um erro ao executar a operação.', | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Schema, model } from 'mongoose'; | ||
import { IBalance, IBalanceStatement } from '@marquinhos/types'; | ||
|
||
const BalanceSchema = new Schema<IBalance>({ | ||
userId: { required: true, type: String }, | ||
guildId: { required: true, type: String }, | ||
amount: { required: true, type: Number }, | ||
lastUpdate: { required: true, type: Date }, | ||
}); | ||
|
||
const BalanceStatementSchema = new Schema<IBalanceStatement>({ | ||
userId: { required: true, type: String }, | ||
guildId: { required: true, type: String }, | ||
amount: { required: true, type: Number }, | ||
executedBy: { required: true, type: String }, | ||
type: { | ||
required: true, | ||
type: String, | ||
enum: ['add', 'subtract', 'set', 'reset'], | ||
}, | ||
date: { required: true, type: Date }, | ||
}); | ||
|
||
const BalanceModel = model('balance', BalanceSchema); | ||
|
||
const BalanceStatementModel = model('balanceStatement', BalanceStatementSchema); | ||
|
||
export { BalanceModel, BalanceStatementModel }; |
Oops, something went wrong.