Discord-InterChat/InterChat

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

Summary

Maintainability
B
6 hrs
Test Coverage
import Constants, { emojis } from '#utils/Constants.js';
import db from '#utils/Db.js';
import { t } from '#utils/Locale.js';
import Logger from '#utils/Logger.js';
import { captureException } from '@sentry/node';
import { CacheType, ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import ms from 'ms';
import HubCommand from './index.js';

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

  async execute(interaction: ChatInputCommandInteraction<CacheType>) {
    const subcommand = interaction.options.getSubcommand();

    const { userManager } = interaction.client;
    const locale = await userManager.getUserLocale(interaction.user.id);

    switch (subcommand) {
      case 'create': {
        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 hubInDb = await db.hub.findFirst({
          where: {
            name: hubName,
            private: true,
            OR: [
              { ownerId: interaction.user.id },
              { moderators: { some: { userId: interaction.user.id, position: 'manager' } } },
            ],
          },
        });

        if (!hubInDb) {
          await this.replyEmbed(interaction, t('hub.notFound_mod', locale, { 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 db.hubInvite.create({
          data: {
            hub: { connect: { name: hubName } },
            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,
        });
        break;
      }

      case 'revoke': {
        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, position: '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) {
          Logger.error(e);
          captureException(e);
          await this.replyEmbed(
            interaction,
            t('errors.unknown', locale, {
              emoji: emojis.no,
              support_invite: Constants.Links.SupportInvite,
            }),
            {
              ephemeral: true,
            },
          ).catch(() => null);
          return;
        }
        break;
      }

      case 'list': {
        const hubName = interaction.options.getString('hub', true);
        const hubInDb = await db.hub.findFirst({
          where: {
            name: hubName,
            OR: [
              { ownerId: interaction.user.id },
              { moderators: { some: { userId: interaction.user.id, position: 'manager' } } },
            ],
          },
        });

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

        const invitesInDb = await db.hubInvite.findMany({ where: { hubId: hubInDb.id } });
        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 EmbedBuilder()
          .setTitle(t('hub.invite.list.title', locale))
          .setDescription(inviteArr.join('\n'))
          .setColor('Yellow')
          .setTimestamp();

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

      default:
        break;
    }
  }
}