diff --git a/src/commands/slash/Main/hub/logging.ts b/src/commands/slash/Main/hub/logging.ts new file mode 100644 index 000000000..be0247a46 --- /dev/null +++ b/src/commands/slash/Main/hub/logging.ts @@ -0,0 +1,117 @@ +import { ChatInputCommandInteraction } from 'discord.js'; +import HubCommand from './index.js'; +import db from '#main/utils/Db.js'; +import HubLogManager, { LogConfigTypes, RoleIdLogConfigs } from '#main/managers/HubLogManager.js'; +import { Hub } from '@prisma/client'; + +export default class LoggingCommand extends HubCommand { + async execute(interaction: ChatInputCommandInteraction) { + const subcommand = interaction.options.getSubcommand(); + + const hub = await this.runHubChecks(interaction); + if (!hub) return; + + switch (subcommand) { + case 'view': + await this.handleView(interaction, hub); + break; + case 'set_channel': + await this.handleSet(interaction, hub.id, 'channel'); + break; + case 'set_role': + await this.handleSet(interaction, hub.id, 'role'); + break; + default: + break; + } + } + + private async handleView(interaction: ChatInputCommandInteraction, hub: Hub) { + const hubLogManager = await HubLogManager.create(hub.id); + const embed = hubLogManager.createEmbed(hub.iconUrl); + await interaction.reply({ embeds: [embed] }); + } + + private async handleSet( + interaction: ChatInputCommandInteraction, + hubId: string, + setType: 'channel' | 'role', + ) { + const id = + setType === 'channel' + ? interaction.options.getChannel('channel')?.id + : interaction.options.getRole('role')?.id; + + const logType = interaction.options.getString('log_type', true) as LogConfigTypes; + const hubLogManager = await HubLogManager.create(hubId); + + if (!id) { + if (setType === 'channel') await hubLogManager.resetLog(logType); + else await hubLogManager.removeRoleId(logType as RoleIdLogConfigs); + + await this.replyEmbed( + interaction, + `Successfully reset logging ${setType} for type \`${logType}\`.`, + { + ephemeral: true, + }, + ); + return; + } + + if (setType === 'channel') { + await hubLogManager.setLogChannel(logType, id); + await this.replyEmbed( + interaction, + `Successfully set \`${logType}\` logging channel to <#${id}>.`, + { ephemeral: true }, + ); + } + else if (setType === 'role' && hubLogManager.config.appeals?.channelId) { + await hubLogManager.setRoleId(logType as RoleIdLogConfigs, id); + await this.replyEmbed( + interaction, + `Successfully set \`${logType}\` mention role to <@&${id}>.`, + { ephemeral: true }, + ); + } + else { + await this.replyEmbed( + interaction, + 'You must set the logging channel before setting the role ID.', + { ephemeral: true }, + ); + return; + } + } + + private async runHubChecks(interaction: ChatInputCommandInteraction) { + const hubName = interaction.options.getString('hub') as string | undefined; + const hubs = await db.hub.findMany({ + where: { + OR: [ + { ownerId: interaction.user.id }, + { moderators: { some: { userId: interaction.user.id, position: 'manager' } } }, + ], + }, + }); + + let hub; + if (hubName) { + hub = hubs.find((h) => h.name.toLowerCase() === hubName.toLowerCase()); + } + else if (hubs.length === 1) { + hub = hubs[0]; + } + else if (hubs.length > 1 || !hub) { + await this.replyEmbed( + interaction, + 'You must provide a hub in the `hub` option of the command.', + { ephemeral: true }, + ); + return null; + } + + return hub; + } +} diff --git a/src/commands/slash/Main/hub/settings.ts b/src/commands/slash/Main/hub/settings.ts new file mode 100644 index 000000000..991ff6d96 --- /dev/null +++ b/src/commands/slash/Main/hub/settings.ts @@ -0,0 +1,108 @@ +import HubCommand from '#main/commands/slash/Main/hub/index.js'; +import { emojis } from '#main/config/Constants.js'; +import { RegisterInteractionHandler } from '#main/decorators/Interaction.js'; +import { type HubSettingsString } from '#main/modules/BitFields.js'; +import HubSettingsManager from '#main/modules/HubSettingsManager.js'; +import { CustomID } from '#main/utils/CustomID.js'; +import db from '#main/utils/Db.js'; +import { t } from '#main/utils/Locale.js'; +import type { Hub } from '@prisma/client'; +import { + ActionRowBuilder, + ButtonBuilder, + ButtonInteraction, + ButtonStyle, + type ChatInputCommandInteraction, +} from 'discord.js'; + +export default class Settings extends HubCommand { + async execute(interaction: ChatInputCommandInteraction) { + const subcommand = interaction.options.getSubcommand(); + + const hub = await this.runHubCheck(interaction); + if (!hub) return; + + if (subcommand === 'list') { + await this.handleList(interaction, hub); + } + else if (subcommand === 'toggle') { + await this.handleToggle(interaction, hub); + } + } + + private async handleList(interaction: ChatInputCommandInteraction, hub: Hub) { + const settingsManager = new HubSettingsManager(hub.id, hub.settings); + + await interaction.reply({ embeds: [settingsManager.settingsEmbed] }); + } + + private async handleToggle(interaction: ChatInputCommandInteraction, hub: Hub) { + const settingStr = interaction.options.getString('setting', true) as HubSettingsString; + const settingsManager = new HubSettingsManager(hub.id, hub.settings); + + const value = await settingsManager.updateSetting(settingStr); + const viewSettingsButton = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId( + new CustomID() + .setIdentifier('hubSettings', 'list') + .addArgs(hub.id, interaction.user.id) + .toString(), + ) + .setLabel('View Settings') + .setEmoji(emojis.settings) + .setStyle(ButtonStyle.Secondary), + ); + + await this.replyEmbed( + interaction, + `Setting \`${settingStr}\` is now **${value ? `${emojis.enabled} enabled` : `${emojis.disabled} disabled`}**.`, + { ephemeral: true, components: [viewSettingsButton] }, + ); + } + + @RegisterInteractionHandler('hubSettings') + async handleButtons(interaction: ButtonInteraction) { + const customId = CustomID.parseCustomId(interaction.customId); + if (customId.suffix !== 'list') return; + + const [hubId, userId] = customId.args; + + if (interaction.user.id !== userId) { + await this.replyEmbed( + interaction, + t({ + phrase: 'errors.notYourAction', + locale: await interaction.client.userManager.getUserLocale(interaction.user.id), + }), + { ephemeral: true }, + ); + } + + const settingsManager = await HubSettingsManager.create(hubId); + await interaction.reply({ embeds: [settingsManager.settingsEmbed], ephemeral: true }); + } + private async runHubCheck(interaction: ChatInputCommandInteraction) { + const hubName = interaction.options.getString('hub') as string | undefined; + const hub = await db.hub.findFirst({ + where: { + name: hubName, + OR: [ + { ownerId: interaction.user.id }, + { moderators: { some: { userId: interaction.user.id, position: 'manager' } } }, + ], + }, + }); + + if (!hub) { + await this.replyEmbed( + interaction, + 'Hub not found. Provide a valid hub in the `hub` option of the command.', + { ephemeral: true }, + ); + return null; + } + + return hub; + } +}