Discord-InterChat/InterChat

View on GitHub
src/events/messageReactionAdd.ts

Summary

Maintainability
A
1 hr
Test Coverage
import BaseEventListener from '#main/core/BaseEventListener.js';
import { HubSettingsBitField } from '#main/modules/BitFields.js';
import { HubService } from '#main/services/HubService.js';
import db from '#main/utils/Db.js';
import {
  findOriginalMessage,
  getOriginalMessage,
  storeMessage,
} from '#main/utils/network/messageUtils.js';
import { addReaction, updateReactions } from '#utils/reaction/actions.js';
import { checkBlacklists } from '#utils/reaction/helpers.js';
import { MessageReaction, PartialMessageReaction, PartialUser, User } from 'discord.js';

export default class ReadctionAdd extends BaseEventListener<'messageReactionAdd'> {
  readonly name = 'messageReactionAdd';
  public async execute(
    reaction: MessageReaction | PartialMessageReaction,
    user: User | PartialUser,
  ) {
    if (user.bot || !reaction.message.inGuild()) return;

    const cooldown = reaction.client.reactionCooldowns.get(user.id);
    if (cooldown && cooldown > Date.now()) return;

    // add user to cooldown list
    user.client.reactionCooldowns.set(user.id, Date.now() + 3000);

    const originalMsg =
      (await getOriginalMessage(reaction.message.id)) ??
      (await findOriginalMessage(reaction.message.id));

    const hubService = new HubService(db);
    const hub = originalMsg ? await hubService.fetchHub(originalMsg?.hubId) : null;

    if (!originalMsg || !hub || !new HubSettingsBitField(hub.settings).has('Reactions')) {
      return;
    }

    const { userBlacklisted, serverBlacklisted } = await checkBlacklists(
      hub.id,
      reaction.message.guildId,
      user.id,
    );

    if (userBlacklisted || serverBlacklisted) return;

    const reactedEmoji = reaction.emoji.toString();
    const dbReactions = (originalMsg.reactions?.valueOf() ?? {}) as { [key: string]: string[] }; // eg. { '👍': 1, '👎': 2 }
    const emojiAlreadyReacted = dbReactions[reactedEmoji] ?? [user.id];

    // max 10 reactions
    if (Object.keys(dbReactions).length >= 10) return;

    // if there already are reactions by others and the user hasn't reacted yet
    if (!emojiAlreadyReacted?.includes(user.id)) addReaction(dbReactions, user.id, reactedEmoji);
    // update the data with a new arr containing userId
    else dbReactions[reactedEmoji] = emojiAlreadyReacted;

    await storeMessage(originalMsg.messageId, { ...originalMsg, reactions: dbReactions });

    reaction.users.remove(user.id).catch(() => null);
    await updateReactions(originalMsg, dbReactions);
  }
}