import Role from '../models/Role' ; import Emoji from '../structures/Emoji' ; type ManagedRole = { guildID : string ; channelID : string ; messageID : string ; } ; export type ManagedRoleEmoji = { role : string ; raw : string ; singleUse : boolean ; } ; type ChannelMessages = Map < string , MessageRoles > ; type MessageRoles = Map < string , ManagedRoleEmojis > ; export type ManagedRoleEmojis = Map < string , ManagedRoleEmoji > ; /**
 * Takes care of the client local roles storage.
 */ export class RoleManager { /**
     * Singleton instance of RoleManager.
     */ private static instance : RoleManager | undefined ; /**
     * Stores information about the location of the role message based on the role ID.
     *
     * The key has the following format: `message.role`
     *
     * This special key has to be used as the role might be connected to more messages.
     */ protected managedRoles : Map < string , ManagedRole > ; /**
     * Stores all messages the reaction role is connected to.
     */ protected managedRoleMessages : Map < string , string [ ] > ; /**
     * Stores information about the reaction role based on the location.
     * It is a map of nested maps in order: guild -> channel -> message -> roles -> reaction role
     */ protected managedRolesMap : Map < string , ChannelMessages > ; protected constructor ( ) { this . managedRoles = new Map < string , ManagedRole > ( ) ; this . managedRoleMessages = new Map < string , string [ ] > ( ) ; this . managedRolesMap = new Map < string , ChannelMessages > ( ) ; } /**
     * Get the instance of RoleManager.
     */ static get ( ) { if ( this . instance === undefined ) { this . instance = new RoleManager ; } return this . instance ; } param roles fetchRoles ( roles ) { for ( const role of roles ) { const emoji = new Emoji ( role . emoji_raw ) ; this . addRole ( role . guild , role . channel , role . message , role . role , emoji , role . single_use ) ; } } param guild param channel param message param role param emoji param singleUse addRole ( guild , channel , message , role , emoji , singleUse = false ) { if ( ! this . managedRolesMap . has ( guild ) ) { this . managedRolesMap . set ( guild , new Map < string , MessageRoles > ( ) ) ; } if ( ! this . managedRolesMap . get ( guild ) . has ( channel ) ) { this . managedRolesMap . get ( guild ) . set ( channel , new Map < string , ManagedRoleEmojis > ( ) ) ; } if ( ! this . managedRolesMap . get ( guild ) . get ( channel ) . has ( message ) ) { this . managedRolesMap . get ( guild ) . get ( channel ) . set ( message , new Map < string , ManagedRoleEmoji > ( ) ) ; } const reactionRoleData = { role : role , raw : emoji . raw , singleUse } ; this . managedRolesMap . get ( guild ) . get ( channel ) . get ( message ) . set ( emoji . id , reactionRoleData ) ; this . managedRoles . set ( `${ message }.${ role }` , { guildID : guild , channelID : channel , messageID : message } ) ; const messages = this . getRoleMessages ( role ) ; messages . push ( message ) ; this . managedRoleMessages . set ( role , messages ) ; } param guild param channel param message param role param emojiID param singleUse updateRoleSingleUse ( guild , channel , message , role , emojiID , singleUse ) { const roleData = this . getRoleData ( guild , channel , message , role ) ; if ( ! roleData ) { return false ; } roleData . singleUse = ! roleData . singleUse ; this . managedRolesMap . get ( guild ) . get ( channel ) . get ( message ) . set ( emojiID , roleData ) ; return true ; } param guild param channel param message param emojiID returns removeRole ( guild , channel , message , emojiID ) { const role = this . getRole ( guild , channel , message , emojiID ) ; if ( ! role ) { return false ; } this . managedRolesMap . get ( guild ) . get ( channel ) . get ( message ) . delete ( emojiID ) ; this . managedRoles . delete ( `${ message }.${ role }` ) ; const messages = this . getRoleMessages ( role ) ; if ( messages . length === 1 ) { this . managedRoleMessages . delete ( role ) ; } else { this . managedRoleMessages . set ( role , messages . filter ( ( roleMessage ) => roleMessage !== message ) ) ; } return true ; } param guild removeGuild ( guild ) { if ( ! this . managedRolesMap . has ( guild ) ) { return false ; } const guildData = this . managedRolesMap . get ( guild ) ; guildData . forEach ( ( channel , channelID ) => this . removeChannel ( guild , channelID ) ) ; this . managedRolesMap . delete ( guild ) ; return true ; } param guild param channel removeChannel ( guild , channel ) { if ( ! this . isChannelManaged ( guild , channel ) ) { return false ; } this . managedRolesMap . get ( guild ) . get ( channel ) . forEach ( ( messages , message ) => this . removeMessage ( guild , channel , message ) ) ; this . managedRolesMap . get ( guild ) . delete ( channel ) ; return true ; } param guild param channel param message removeMessage ( guild , channel , message ) { const roles = this . getRoles ( guild , channel , message ) ; if ( ! roles ) { return false ; } roles . forEach ( ( role , emoji ) => this . removeRole ( guild , channel , message , emoji ) ) ; this . managedRolesMap . get ( guild ) . get ( channel ) . delete ( message ) ; return true ; } /**
     * Get Snowflakes of all guilds with reaction roles from the local storage.
     */ getManagedGuilds ( ) { return this . managedRolesMap . keys ( ) ; } /**
     * Get location information about all stored reaction roles in the local storage.
     */ getManagedRoles ( ) { return this . managedRoles . values ( ) ; } param guild param channel param message returns getRoles ( guild , channel , message ) { if ( ! this . isChannelManaged ( guild , channel ) ) { return null ; } if ( ! this . managedRolesMap . get ( guild ) . get ( channel ) . has ( message ) ) { return null ; } return this . managedRolesMap . get ( guild ) . get ( channel ) . get ( message ) ; } param guildID param channelID param messageID param emojiID returns getRole ( guildID , channelID , messageID , emojiID ) { const roles = this . getRoles ( guildID , channelID , messageID ) ; if ( ! roles || ! roles . has ( emojiID ) ) { return null ; } return roles . get ( emojiID ) . role ; } param guild param channel param message param role getRoleData ( guild , channel , message , role ) { const roles = this . getRoles ( guild , channel , message ) ; for ( const [ , value ] of roles ) { if ( value . role === role ) { return value ; } } return null ; } param guildID param channelID param messageID param roleID returns getEmojiFromRole ( guildID , channelID , messageID , roleID ) { const roles = this . getRoles ( guildID , channelID , messageID ) ; if ( ! roles ) { return null ; } for ( const [ key , value ] of roles ) { if ( value . role === roleID ) { return key ; } } return null ; } param roleID isManagedRole ( roleID ) { return this . managedRoleMessages . has ( roleID ) ; } param message param role isRoleSingleUse ( message , role ) { const location = this . getRoleLocation ( message , role ) ; if ( ! location ) { return undefined ; } const roleData = this . getRoleData ( location . guildID , location . channelID , message , role ) ; if ( ! roleData ) { return undefined ; } return roleData . singleUse ; } param messageID param roleID getRoleLocation ( messageID , roleID ) { if ( ! this . isManagedRole ( roleID ) ) { return null ; } return this . managedRoles . get ( `${ messageID }.${ roleID }` ) ; } param roleID getRoleMessages ( roleID ) { return this . managedRoleMessages . has ( roleID ) ? this . managedRoleMessages . get ( roleID ) : [ ] ; } param guildID param channelID isChannelManaged ( guildID , channelID ) { return this . managedRolesMap . has ( guildID ) && this . managedRolesMap . get ( guildID ) . has ( channelID ) ; } /**
     * Get the count of all reaction roles.
     */ count ( ) { return this . managedRoles . size ; } }