Discord-InterChat/InterChat

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

Summary

Maintainability
B
5 hrs
Test Coverage
import { handleError } from '#main/utils/Utils.js';
import Constants, { emojis } from '#utils/Constants.js';
import db from '#utils/Db.js';
import { supportedLocaleCodes, t } from '#utils/Locale.js';
import { CacheType, ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import ms from 'ms';
import HubCommand from './index.js';
import { HubService } from '#main/services/HubService.js';
import { InfoEmbed } from '#main/utils/EmbedUtils.js';

export default class Invite extends HubCommand {
  readonly cooldown = 3000; // 3 seconds

  async execute(interaction: ChatInputCommandInteraction<CacheType>) {
    const { userManager } = interaction.client;
    const locale = await userManager.getUserLocale(interaction.user.id);

    const handlers = {
      create: () => this.handleCreateSubcommand(interaction, locale),
      revoke: () => this.handleRevokeSubcommand(interaction, locale),
      list: () => this.handleListSubcommand(interaction, locale),
    };

    const subcommand = interaction.options.getSubcommand() as keyof typeof handlers;
    await handlers[subcommand]?.();
  }

  private async handleCreateSubcommand(
    interaction: ChatInputCommandInteraction,
    locale: supportedLocaleCodes,
  ) {
    const hubName = interaction.options.getString('hub', true);
    const expiryStr = interaction.options.getString('expiry');
    const duration = expiryStr ? ms(expiryStr) : undefined;
    const expires = new Date(Date.now() + (duration || 60 * 60 * 4000));

    const hubService = new HubService();
    const hub = await (await hubService.findHubsByName(hubName)).at(0);

    if (!hub) {
      await this.replyEmbed(interaction, 'hub.notFound_mod', {
        t: { emoji: emojis.no },
        ephemeral: true,
      });
      return;
    }
    else if (!hub?.data.private) {
      await this.replyEmbed(interaction, 'hub.notPrivate', {
        t: { emoji: emojis.no },
        ephemeral: true,
      });
      return;
    }

    if (!await hub.isManager(interaction.user.id)) {
      await this.replyEmbed(interaction, 'hub.notManager', {
        t: { emoji: emojis.no },
        ephemeral: true,
      });
      return;
    }

    if (!Date.parse(expires.toString())) {
      await interaction.reply({
        content: `${emojis.no} Invalid Expiry Duration provided!`,
        ephemeral: true,
      });
      return;
    }

    const createdInvite = await hub.createInvite(expires);

    const embed = new EmbedBuilder()
      .setDescription(
        t('hub.invite.create.success', locale, {
          inviteCode: createdInvite.code,
          docs_link: Constants.Links.Docs,
          expiry: `<t:${Math.round(createdInvite.expires.getTime() / 1000)}:R>`,
        }),
      )
      .setColor('Green')
      .setTimestamp();

    await interaction.reply({
      embeds: [embed],
      ephemeral: true,
    });
  }

  private async handleRevokeSubcommand(
    interaction: ChatInputCommandInteraction,
    locale: supportedLocaleCodes,
  ) {
    const code = interaction.options.getString('code', true);

    const inviteInDb = await db.hubInvite.findFirst({
      where: {
        code,
        hub: {
          OR: [
            { ownerId: interaction.user.id },
            { moderators: { some: { userId: interaction.user.id, role: 'MANAGER' } } },
          ],
        },
      },
    });

    if (!inviteInDb) {
      await interaction.reply({
        content: t('hub.invite.revoke.invalidCode', locale, { emoji: emojis.no }),
        ephemeral: true,
      });
      return;
    }

    try {
      await db.hubInvite.delete({ where: { code } });
      await this.replyEmbed(
        interaction,
        t('hub.invite.revoke.success', locale, { emoji: emojis.yes, inviteCode: code }),
        { ephemeral: true },
      );
    }
    catch (e) {
      handleError(e, interaction);
      return;
    }
  }

  private async handleListSubcommand(
    interaction: ChatInputCommandInteraction,
    locale: supportedLocaleCodes,
  ) {
    const hubName = interaction.options.getString('hub', true);

    const hub = (await this.hubService.findHubsByName(hubName)).at(0);

    if (!await hub?.isManager(interaction.user.id)) {
      await this.replyEmbed(
        interaction,
        t('hub.notManager', locale, { emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }

    if (!hub?.data.private) {
      await this.replyEmbed(
        interaction,
        t('hub.invite.list.notPrivate', locale, { emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }

    const invitesInDb = await hub.fetchInvites();
    if (invitesInDb.length === 0) {
      await this.replyEmbed(
        interaction,
        t('hub.invite.list.noInvites', locale, { emoji: emojis.no }),
        { ephemeral: true },
      );
      return;
    }

    const inviteArr = invitesInDb.map(
      (inv, index) =>
        `${index + 1}. \`${inv.code}\` - <t:${Math.round(inv.expires.getTime() / 1000)}:R>`,
    );

    const inviteEmbed = new InfoEmbed()
      .setTitle(t('hub.invite.list.title', locale))
      .setDescription(inviteArr.join('\n'));

    await interaction.reply({
      embeds: [inviteEmbed],
      ephemeral: true,
    });
  }
}