import { Guild, MessageReaction, Role, User } from "discord.js"; import { GuildMember } from "discord.js"; import { logger } from "../logger"; import { config } from "../configuration"; import { Maybe } from "../interfaces"; export default class RoleController { constructor() { } private getAnnounceRoleIdForGuild(guildId: string): string { const role = config.bot.announcement_role if (!role) throw new Error(`No announcementRole defined for guild ${guildId}`) return role } public async addRoleToUser(member: GuildMember, role: Role, guildId: string, requestId: string) { logger.info(`Adding Role ${role.id} to user ${member.id}|${member.user.username}`, { requestId, guildId }) return await member.roles.add(role) } private async removeRoleFromUser(member: GuildMember, role: Role, guildId: string, requestId: string) { logger.info(`Removing Role ${role.id} from user ${member.id}|${member.user.username}`, { requestId, guildId }) return await member.roles.remove(role) } public async addMediaRoleToUser(user: User, guild: Guild, requestId: string) { const roleToAdd = await this.getAnnouncementRoleForGuild(guild, requestId) if (!roleToAdd) throw new Error(`No announcementRole found to add to user`) const guildMember = await guild.members.fetch(user) return this.addRoleToUser(guildMember, roleToAdd, guild.id, requestId) } public async removeMediaRoleFromUser(user: User, guild: Guild, requestId: string) { const roleToRemove = await this.getAnnouncementRoleForGuild(guild, requestId) if (!roleToRemove) throw new Error(`No announcementRole found to remove from user`) const guildMember = await guild.members.fetch(user) return this.removeRoleFromUser(guildMember, roleToRemove, guild.id, requestId) } public async getAnnouncementRoleForGuild(guild: Guild, requestId: string): Promise> { const mediaRole = this.getAnnounceRoleIdForGuild(guild.id) return guild.roles.fetch() .then(fetchedRoles => fetchedRoles.find(role => role.id === mediaRole)) .catch(error => { logger.error(`Could not find announcement_role with id ${config.bot.announcement_role}. Error: ${error}`, { requestId, guildId: guild.id }) }) } public async assignAnnouncementRolesFromReaction(guild: Guild, reaction: MessageReaction, requestId: string) { const guildId = guild.id logger.info("Managing roles", { guildId, requestId }) const announcementRole = await this.getAnnouncementRoleForGuild(guild, requestId) if (!announcementRole) throw new Error(`No announcementRole found in guild ${guildId}`) const usersWhoWantRole: User[] = (await reaction.users.fetch()).filter(user => !user.bot).map(user => user) const allUsers = await guild.members.fetch() const usersWhoHaveRole: GuildMember[] = allUsers .filter(member => member.roles.cache .find(role => role.id === announcementRole.id) !== undefined) .map(member => member) const usersWhoNeedRoleRevoked: GuildMember[] = usersWhoHaveRole .filter(userWhoHas => !usersWhoWantRole.map(wanter => wanter.id).includes(userWhoHas.id)) const usersWhoDontHaveRole: GuildMember[] = allUsers .filter(member => member.roles.cache .find(role => role.id === announcementRole.id) === undefined) .map(member => member) const usersWhoNeedRole: GuildMember[] = usersWhoDontHaveRole .filter(userWhoNeeds => usersWhoWantRole.map(wanter => wanter.id).includes(userWhoNeeds.id)) logger.debug(`Theses users will get the role removed: ${JSON.stringify(usersWhoNeedRoleRevoked)}`, { guildId, requestId }) logger.debug(`Theses users will get the role added: ${JSON.stringify(usersWhoNeedRole)}`, { guildId, requestId }) usersWhoNeedRoleRevoked.forEach(user => this.removeRoleFromUser(user, announcementRole, guild.id, requestId)) usersWhoNeedRole.forEach(user => this.addRoleToUser(user, announcementRole, guild.id, requestId)) } }