Skip to content

Commit

Permalink
refactor: organize code and use base embed from client
Browse files Browse the repository at this point in the history
  • Loading branch information
Guilhermeasper committed Mar 31, 2024
1 parent c8a3acb commit 53b65cd
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 89 deletions.
239 changes: 150 additions & 89 deletions src/bot/commands/slashCommands/allowUser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import {
SlashCommandBuilder,
EmbedBuilder,
GuildMemberRoleManager,
GuildMember,
PermissionFlagsBits,
CommandInteraction,
} from 'discord.js';

import { Nullable, SlashCommand } from '@marquinhos/types';
import { Nullable, RolesConfig, SlashCommand } from '@marquinhos/types';
import GuildModel from '@schemas/guild';

const roleTranslations = {
externalRoleId: 'Cargo externo',
baseRoleId: 'Cargo base',
vipRoleId: 'Cargo vip',
};

export const allowUser: SlashCommand = {
command: new SlashCommandBuilder()
.setName('permitir')
Expand All @@ -20,117 +28,170 @@ export const allowUser: SlashCommand = {
execute: async (interaction) => {
const userId = interaction.options.get('usuário')
?.value as Nullable<string>;
const roles = {
externalRoleId: null,
baseRoleId: null,
vipRoleId: null,
} as {
externalRoleId: Nullable<string>;
baseRoleId: Nullable<string>;
vipRoleId: Nullable<string>;
};
const roles = (await findRoles(
(interaction.member as GuildMember).guild.id
)) as RolesConfig;
const allowUserEmbed = interaction.client.baseEmbed();
const selectedMember = (await interaction.guild?.members.fetch(
userId ?? ''
)) as GuildMember;

try {
const guildRoles = await findRoles(
interaction.guild?.id ?? ('' as string)
);
await validateRoles(roles, interaction, allowUserEmbed);
await validatePermissions(
roles.vipRoleId as string,
interaction,
allowUserEmbed
);
await validateMemberExists(selectedMember, interaction, allowUserEmbed);
await validateMemberHasAccess(
selectedMember,
roles,
interaction,
allowUserEmbed
);

roles.externalRoleId = guildRoles.externalRoleId;
roles.baseRoleId = guildRoles.baseRoleId;
roles.vipRoleId = guildRoles.vipRoleId;

if (!roles.externalRoleId || !roles.baseRoleId || !roles.vipRoleId) {
throw new Error('Roles not configured');
}
} catch (error: unknown) {
await interaction.reply({
try {
await interaction.deferReply();
await interaction.followUp({
embeds: [
new EmbedBuilder()
.setDescription(
'Cargos não configurados. Peça a um admin para usar o comando `/config-roles` para configurar os cargos.'
)
.setColor('#ff0000'),
allowUserEmbed
.setThumbnail(selectedMember.user.displayAvatarURL())
.setDescription(`Liberando o usuário <@${userId}>...`),
],
});
throw new Error((error as Error).message);
}

if (
!(interaction.member?.roles as GuildMemberRoleManager).cache.has(
roles.vipRoleId
)
) {
await interaction.reply({
await selectedMember.roles.remove(roles.externalRoleId as string);
await selectedMember.roles.add(roles.baseRoleId as string);
await interaction.editReply({
embeds: [
new EmbedBuilder()
.setDescription('Você não tem permissão para usar esse comando.')
.setColor('#ff0000'),
allowUserEmbed
.setTitle('Usuário liberado')
.setDescription(
`O usuário <@${userId}> foi liberado para acessar o servidor.`
),
],
});
throw new Error('User not allowed');
}

const member = await interaction.guild?.members.fetch(userId ?? '');

if (!member) {
await interaction.reply({
} catch (error) {
await interaction.editReply({
embeds: [
new EmbedBuilder()
.setDescription('Usuário não encontrado.')
allowUserEmbed
.setTitle('Erro ao executar o comando')
.setDescription(
'Houve um erro ao liberar o usuário.\n\nTente novamente ou entre em contato com um admin.'
)
.setColor('#ff0000'),
],
});
throw new Error('User not found');
throw new Error((error as Error).message);
}
},
cooldown: 10,
};

const memberRoles = member.roles.cache;
async function findRoles(guildId: string): Promise<RolesConfig> {
const guild = await GuildModel.findOne({ guildID: guildId }).exec();
if (guild) {
const { externalRoleId, baseRoleId, vipRoleId } = guild.options;
return { externalRoleId, baseRoleId, vipRoleId };
}
return { externalRoleId: null, baseRoleId: null, vipRoleId: null };
}

try {
if (memberRoles.has(roles.externalRoleId)) {
await member.roles.remove(roles.externalRoleId);
} else if (memberRoles.has(roles.baseRoleId)) {
await interaction.reply({
embeds: [
new EmbedBuilder()
.setDescription('O usuário já tem acesso ao servidor.')
.setColor('#ff0000'),
],
});
throw new Error('User already allowed');
}
function userHasPermission(member: GuildMember, vipRoleId: string): boolean {
return (
member.roles.cache.has(vipRoleId) ||
member.permissions.has(PermissionFlagsBits.Administrator)
);
}

if (!memberRoles.has(roles.baseRoleId)) {
await member.roles.add(roles.baseRoleId);
}
} catch (error) {
await interaction.reply({
embeds: [
new EmbedBuilder()
.setDescription('Erro ao liberar o usuário.')
.setColor('#ff0000'),
],
});
throw new Error((error as Error).message);
async function validateRoles(
roles: RolesConfig,
interaction: CommandInteraction,
allowUserEmbed: EmbedBuilder
) {
let rolesNotConfiguredList = 'Os seguintes cargos não estão configurados: \n';

for (const role in roles) {
if (!roles[role as keyof RolesConfig]) {
rolesNotConfiguredList += `- ${
roleTranslations[role as keyof RolesConfig]
}\n`;
}
}

if (!roles.externalRoleId || !roles.baseRoleId || !roles.vipRoleId) {
await interaction.reply({
embeds: [
new EmbedBuilder()
allowUserEmbed
.setTitle('Erro executar o comando')
.setDescription(
`O usuário <@${userId}> foi liberado para acessar o servidor.`
`${rolesNotConfiguredList}
Peça a um admin para usar o comando \` /configurar-cargos\` para configurar os cargos.`
)
.setColor('#00ff00'),
.setColor('#ff0000'),
],
ephemeral: true,
});
},
cooldown: 10,
};
throw new Error('Roles not configured');
}
}

async function findRoles(guildId: string) {
const guild = await GuildModel.findOne({ guildID: guildId }).exec();
if (guild) {
const { externalRoleId, baseRoleId, vipRoleId } = guild.options;
return { externalRoleId, baseRoleId, vipRoleId };
async function validatePermissions(
vipRoleId: string,
interaction: CommandInteraction,
allowUserEmbed: EmbedBuilder
) {
if (!userHasPermission(interaction.member as GuildMember, vipRoleId)) {
await interaction.reply({
embeds: [
allowUserEmbed
.setTitle('Erro ao executar o comando')
.setDescription('Você não tem permissão para usar esse comando.')
.setColor('#ff0000'),
],
ephemeral: true,
});
throw new Error('User not allowed');
}
}

async function validateMemberExists(
selectedMember: GuildMember,
interaction: CommandInteraction,
allowUserEmbed: EmbedBuilder
) {
if (!selectedMember) {
await interaction.reply({
embeds: [
allowUserEmbed
.setTitle('Erro ao executar o comando')
.setDescription('Usuário não encontrado.')
.setColor('#ff0000'),
],
ephemeral: true,
});
throw new Error('User not found');
}
}

async function validateMemberHasAccess(
selectedMember: GuildMember,
roles: RolesConfig,
interaction: CommandInteraction,
allowUserEmbed: EmbedBuilder
) {
if (
!selectedMember.roles.cache.has(roles.externalRoleId as string) &&
selectedMember.roles.cache.has(roles.baseRoleId as string)
) {
await interaction.reply({
embeds: [
allowUserEmbed
.setTitle('Erro ao executar o comando')
.setDescription('Usuário já tem acesso ao servidor.')
.setColor('#ff0000'),
],
ephemeral: true,
});
throw new Error('User already allowed');
}
return { externalRoleId: null, baseRoleId: null, vipRoleId: null };
}
6 changes: 6 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ export type FlipCoinResult = {
elapsedTime: number;
};

export type RolesConfig = {
externalRoleId: Nullable<string>;
baseRoleId: Nullable<string>;
vipRoleId: Nullable<string>;
};

export interface IGuildUser extends mongoose.Document {
guildId: string;
userId: string;
Expand Down

0 comments on commit 53b65cd

Please sign in to comment.