Discord-InterChat/InterChat

View on GitHub
src/commands/slash/Main/hub/moderator.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { emojis } from '#utils/Constants.js';
import db from '#utils/Db.js';
import { type supportedLocaleCodes, t } from '#utils/Locale.js';
import type { HubModeratorPosition, Hub } from '@prisma/client';
import { ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import HubCommand from './index.js';

export default class Moderator extends HubCommand {
  async execute(interaction: ChatInputCommandInteraction): Promise<void> {
    const hubName = interaction.options.getString('hub', true);
    const hub = await db.hub.findFirst({
      where: {
        name: hubName,
        OR: [
          { ownerId: interaction.user.id },
          { moderators: { some: { userId: interaction.user.id, position: 'manager' } } },
        ],
      },
    });

    const locale = await interaction.client.userManager.getUserLocale(interaction.user.id);
    if (!hub) {
      await this.replyEmbed(interaction, t('hub.notFound_mod', locale, { emoji: emojis.no }), {
        ephemeral: true,
      });
      return;
    }

    switch (interaction.options.getSubcommand()) {
      case 'add':
        await this.handleAddSubcommand(interaction, hub, locale);
        break;
      case 'remove':
        await this.handleRemoveSubcommand(interaction, hub, locale);
        break;
      case 'edit':
        await this.handleEditSubcommand(interaction, hub, locale);
        break;
      case 'list':
        await this.handleListSubcommand(interaction, hub, locale);
        break;

      default:
        break;
    }
  }
  private async handleRemoveSubcommand(
    interaction: ChatInputCommandInteraction,
    hub: Hub,
    locale: supportedLocaleCodes,
  ) {
    const user = interaction.options.getUser('user', true);
    if (!hub.moderators.find((mod) => mod.userId === user.id)) {
      await this.replyEmbed(
        interaction,
        t('hub.moderator.remove.notModerator', locale, { user: user.toString(), emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }

    const mod = hub.moderators.find((m) => m.userId === user.id);

    const isRestrictedAction = mod?.position === 'manager' || user.id === interaction.user.id;
    const isExecutorOwner = hub.ownerId === interaction.user.id;

    /* executor needs to be owner to:
     - change position of other managers
     - change their own position
     */
    if (!isExecutorOwner && isRestrictedAction) {
      await this.replyEmbed(
        interaction,
        t('hub.moderator.remove.notOwner', locale, { emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }

    await db.hub.update({
      where: { id: hub.id },
      data: {
        moderators: { deleteMany: { where: { userId: user.id } } },
      },
    });

    await this.replyEmbed(
      interaction,
      t('hub.moderator.remove.success', locale, { user: user.toString(), emoji: emojis.yes }),
    );
  }

  private async handleEditSubcommand(
    interaction: ChatInputCommandInteraction,
    hub: Hub,
    locale: supportedLocaleCodes,
  ) {
    const user = interaction.options.getUser('user', true);
    const position = interaction.options.getString('position', true) as HubModeratorPosition;
    const isUserMod = hub.moderators.find((mod) => mod.userId === user.id);
    const isExecutorManager = hub.moderators.find(
      (mod) =>
        (mod.userId === interaction.user.id && mod.position === 'manager') ||
        hub.ownerId === interaction.user.id,
    );

    if (!isExecutorManager) {
      await this.replyEmbed(
        interaction,
        t('hub.moderator.update.notAllowed', locale, { emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }
    else if (!isUserMod) {
      await this.replyEmbed(
        interaction,
        t('hub.moderator.update.notModerator', locale, { user: user.toString(), emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }
    else if (isUserMod.position === 'manager' && hub.ownerId !== interaction.user.id) {
      await this.replyEmbed(
        interaction,
        t('hub.moderator.update.notOwner', locale, { emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }

    await db.hub.update({
      where: { id: hub.id },
      data: {
        moderators: { updateMany: { where: { userId: user.id }, data: { position } } },
      },
    });

    await this.replyEmbed(
      interaction,
      t('hub.moderator.update.success', locale, {
        user: user.toString(),
        position,
        emoji: emojis.yes,
      }),
    );
  }

  private async handleListSubcommand(
    interaction: ChatInputCommandInteraction,
    hub: Hub,
    locale: supportedLocaleCodes,
  ) {
    await interaction.reply({
      embeds: [
        new EmbedBuilder()
          .setTitle('Hub Moderators')
          .setDescription(
            hub.moderators.length > 0
              ? hub.moderators
                .map(
                  (mod, index) =>
                    `${index + 1}. <@${mod.userId}> - ${
                      mod.position === 'network_mod' ? 'Network Moderator' : 'Hub Manager'
                    }`,
                )
                .join('\n')
              : t('hub.moderator.noModerators', locale, { emoji: emojis.no }),
          )
          .setColor('Aqua')
          .setTimestamp(),
      ],
      ephemeral: true,
    });
  }

  private async handleAddSubcommand(
    interaction: ChatInputCommandInteraction,
    hub: Hub,
    locale: supportedLocaleCodes,
  ) {
    const user = interaction.options.getUser('user', true);

    if (hub.moderators.find((mod) => mod.userId === user.id)) {
      await this.replyEmbed(
        interaction,
        t('hub.moderator.add.alreadyModerator', locale, {
          user: user.toString(),
          emoji: emojis.no,
        }),
        { ephemeral: true },
      );
      return;
    }

    const position = (interaction.options.getString('position') ??
      'network_mod') as HubModeratorPosition;
    await db.hub.update({
      where: { id: hub.id },
      data: { moderators: { push: { userId: user.id, position } } },
    });

    await this.replyEmbed(
      interaction,
      t('hub.moderator.add.success', locale, {
        user: user.toString(),
        position,
        emoji: emojis.yes,
      }),
    );
  }
}