import { SlashCommandBuilder, Interaction, CommandInteraction, ChatInputCommandInteraction, MessageFlags, GuildMemberRoleManager, InteractionReplyOptions, GuildMember, EmbedBuilder, AutocompleteInteraction } from "discord.js"; import {AutocompleteCommand, ChatInteractionCommand, Command} from "./Command"; import {GroupModel} from "../../Models/GroupModel"; import {GroupRepository} from "../../Repositories/GroupRepository"; import {DatabaseConnection} from "../../Database/DatabaseConnection"; import {Container} from "../../Container/Container"; import {GroupSelection} from "../CommandPartials/GroupSelection"; import {UserError} from "../UserError"; import {ArrayUtils} from "../../Utilities/ArrayUtils"; import {GroupConfigurationRenderer} from "../../Groups/GroupConfigurationRenderer"; import {GroupConfigurationHandler} from "../../Groups/GroupConfigurationHandler"; import {GroupConfigurationTransformers} from "../../Groups/GroupConfigurationTransformers"; import {GroupConfigurationRepository} from "../../Repositories/GroupConfigurationRepository"; export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand { private static GOODBYE_MESSAGES: string[] = [ 'Sad to see you go.', 'May your next adventure be fruitful.', 'I hope, I served you well.', 'I wish you, good luck on your next adventures.', ] definition(): SlashCommandBuilder { // @ts-ignore return new SlashCommandBuilder() .setName('groups') .setDescription(`Manages groups`) .addSubcommand(create => create.setName("create") .setDescription("Creates a new group, with executing user being the leader") .addStringOption((option) => option.setName("name") .setDescription("Defines the name for the group.") .setRequired(true) ) .addRoleOption((builder) => builder.setName("role") .setDescription("Defines the role, where all the members are located in.") .setRequired(true) ) ) .addSubcommand(listCommand => listCommand .setName("list") .setDescription("Displays the groups you are apart of.") ) .addSubcommand(command => command .setName('config') .setDescription("Starts the config manager for the group.") .addIntegerOption(GroupSelection.createOptionSetup()) ) .addSubcommand(command => command .setName("remove") .setDescription("Deletes a group you are the leader for.") .addIntegerOption(GroupSelection.createOptionSetup()) ); } async execute(interaction: ChatInputCommandInteraction): Promise { switch (interaction.options.getSubcommand()) { case "create": this.create(interaction); break; case "list": this.list(interaction); break; case "remove": await this.remove(interaction); break; case "config": await this.runConfigurator(interaction); break; default: throw new Error("Unsupported command"); } return Promise.resolve(); } private create(interaction: ChatInputCommandInteraction): void { const name = interaction.options.getString("name") ?? ''; const role = interaction.options.getRole("role"); const group: GroupModel = { id: -1, name: name, leader: { server: interaction.guildId ?? '', memberid: interaction.member?.user.id ?? '' }, role: { server: interaction.guildId ?? '', roleid: role?.id ?? '' } } Container.get(GroupRepository.name).create(group); interaction.reply({content: `:white_check_mark: Created group \`${name}\``, flags: MessageFlags.Ephemeral }) } private list(interaction: ChatInputCommandInteraction) { const repo = Container.get(GroupRepository.name); const groups = repo.findGroupsByMember(interaction.member); const embed = new EmbedBuilder() .setTitle("Your groups on this server:") .setFields( groups.map(group => { return { name: group.name, value: ` Role: <@&${group.role.roleid}> ` } }) ) const reply: InteractionReplyOptions = { embeds: [ embed ], allowedMentions: { roles: [] }, flags: MessageFlags.Ephemeral } interaction.reply(reply); } private async remove(interaction: ChatInputCommandInteraction) { const group = GroupSelection.getGroup(interaction); const repo = Container.get(GroupRepository.name); if (group.leader.memberid != interaction.member?.user.id) { throw new UserError("Can't remove group. You are not the leader."); } repo.deleteGroup(group); const embed = new EmbedBuilder() .setTitle("Group deleted.") .setDescription( `:x: Deleted \`${group.name}\`. ${ArrayUtils.chooseRandom(GroupCommand.GOODBYE_MESSAGES)}` ) await interaction.reply({ embeds: [ embed ], flags: MessageFlags.Ephemeral, }) } async handleAutocomplete(interaction: AutocompleteInteraction): Promise { const option = interaction.options.getFocused(true); if (option.name == "group") { await GroupSelection.handleAutocomplete(interaction, true); return; } } private async runConfigurator(interaction: ChatInputCommandInteraction) { const group = GroupSelection.getGroup(interaction); const configurationRenderer = new GroupConfigurationRenderer( new GroupConfigurationHandler( Container.get(GroupConfigurationRepository.name), group ), new GroupConfigurationTransformers(), ) await configurationRenderer.setup(interaction); } }