import discord, { MessageReaction, PartialMessageReaction, User, PartialUser, } from 'discord.js'; import {HydratedDocument} from 'mongoose'; import {logger} from '../logger'; import {config} from '../config'; import {Guild, guildModel} from '../models/Guild'; import {AutoroleMsg, autoroleMsgModel} from '../models/AutoroleMsg'; function isMessageReaction(reaction: MessageReaction | PartialMessageReaction): reaction is MessageReaction{ return reaction.partial === false; } function isUser(user: User | PartialUser): user is User{ return user.partial === false; } async function handleRole( reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser, action: string ): Promise{ try{ if(config.clientId === user.id) return; if(reaction.partial) reaction = await reaction.fetch(); if(user.partial) user = await user.fetch(); if(!isMessageReaction(reaction)) throw Error('type mismatch: reaction.partial'); if(!isUser(user)) throw Error('type mismatch: user.partial'); if(!reaction.emoji) throw Error('reaction.emoji not exist'); const dbAutoroleMsg: HydratedDocument | null = await autoroleMsgModel.findOneAndUpdate( {messageId: reaction.message.id}, {$set: {emoji: reaction.emoji.toString()}}, {new: true} ); if(!dbAutoroleMsg || dbAutoroleMsg.emoji !== reaction.emoji.toString()) return; if(!reaction.me) await reaction.react(); const dbGuild: HydratedDocument | null = await guildModel.findById(dbAutoroleMsg.guild._id); if(!dbGuild) throw Error('dbGuild not exist'); const guild: discord.Guild | null = await reaction.client.guilds.resolve(dbGuild.id); if(!guild) throw Error('guild not exist'); const role: discord.Role | null = await guild.roles.resolve(dbAutoroleMsg.roleId); if(!role) throw Error('role not exist'); switch(action){ case 'add': await guild.members.addRole({ user: user.id, role: role.id }); break; case 'remove': await guild.members.removeRole({ user: user.id, role: role.id }); break; } logger.log(`${user} has been ${action === 'add'?'given':'removed'} ${role} role.`); if('autoroleLogChannelId' in dbGuild && dbGuild.autoroleLogChannelId){ const autoroleChannel: discord.Channel | null = await guild.channels.resolve(dbGuild.autoroleLogChannelId); if(autoroleChannel === null || !autoroleChannel.isTextBased()) throw Error('autoroleChannel not exist or autoroleChannel isn\'t text based'); await autoroleChannel.send({content: `${user} has been ${action === 'add'?'given':'removed'} ${role} role.` }); } }catch(err: unknown){ let message; if(err instanceof Error) message = err.message; else message = String(message); logger.error(`While executing "handle-autorole", ${message}`); } } export async function handleRoleAdd( reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser ): Promise{ await handleRole(reaction, user, 'add'); } export async function handleRoleRemove( reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser ): Promise{ await handleRole(reaction, user, 'remove'); }