Discord-InterChat/InterChat

View on GitHub
src/services/formatters/CompactMsgFormatter.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { Connection } from '@prisma/client';
import { WebhookMessageCreateOptions, EmbedBuilder, Message } from 'discord.js';
import { DefaultFormaterOpts, MessageFormatterStrategy } from '../MessageFormattingService.js';
import { censor } from '#main/utils/ProfanityUtils.js';
import Constants from '#main/utils/Constants.js';


export class CompactMessageFormatter implements MessageFormatterStrategy {
  format(
    message: Message<true>,
    connection: Connection,
    opts: DefaultFormaterOpts,
  ): WebhookMessageCreateOptions {
    const contents = {
      normal: message.content,
      referred: opts.referredContent,
      censored: opts.censoredContent,
    };

    const { referredAuthor } = opts.referredMsgData;

    // check if the person being replied to explicitly allowed mentionOnReply setting for themself
    const replyContent = this.getReplyContent(contents.referred, connection.profFilter);

    // discord displays either an embed or an attachment url in a compact message (embeds take priority, so image will not display)
    // which is why if there is an image, we don't send the reply embed. Reply button remains though
    const replyEmbed =
      replyContent && !opts.attachmentURL
        ? [
          new EmbedBuilder()
            .setDescription(replyContent)
            .setAuthor({
              name: referredAuthor?.username.slice(0, 30) ?? 'Unknown User',
              iconURL: referredAuthor?.displayAvatarURL(),
            })
            .setColor(Constants.Colors.invisible),
        ]
        : undefined;

    const { author, servername, jumpButton } = opts;

    // compact mode doesn't need new attachment url for tenor and direct image links
    // we can just slap them right in the content without any problems
    // [] has an empty char in between its not magic kthxbye
    const attachmentURL = message.attachments.size > 0 ? `\n[⁥](${opts.attachmentURL})` : '';
    const messageContent = `${connection.profFilter ? contents.censored : contents.normal} ${attachmentURL}`;

    return {
      username: `@${author.username} • ${servername}`,
      avatarURL: author.avatarURL,
      embeds: replyEmbed,
      components: jumpButton,
      content: messageContent,
      threadId: connection.parentId ? connection.channelId : undefined,
      allowedMentions: { parse: [] },
    };
  }

  private getReplyContent(content: string | undefined, profFilter: boolean) {
    if (!content) return null;
    return profFilter ? censor(content) : content;
  }
}