102 lines
3.3 KiB
TypeScript
102 lines
3.3 KiB
TypeScript
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<void>{
|
|
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<AutoroleMsg> | 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<Guild> | 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<void>{
|
|
await handleRole(reaction, user, 'add');
|
|
}
|
|
|
|
export async function handleRoleRemove(
|
|
reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser
|
|
): Promise<void>{
|
|
await handleRole(reaction, user, 'remove');
|
|
}
|