GuildMemberRoleManager.js (5385B)
1 'use strict'; 2 3 const { TypeError } = require('../errors'); 4 const Collection = require('../util/Collection'); 5 6 /** 7 * Manages API methods for roles of a GuildMember and stores their cache. 8 */ 9 class GuildMemberRoleManager { 10 constructor(member) { 11 /** 12 * The GuildMember this manager belongs to 13 * @type {GuildMember} 14 */ 15 this.member = member; 16 /** 17 * The Guild this manager belongs to 18 * @type {Guild} 19 */ 20 this.guild = member.guild; 21 Object.defineProperty(this, 'client', { value: member.client }); 22 } 23 24 /** 25 * The filtered collection of roles of the member 26 * @type {Collection<Snowflake, Role>} 27 * @private 28 * @readonly 29 */ 30 get _roles() { 31 const everyone = this.guild.roles.everyone; 32 return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone); 33 } 34 35 /** 36 * The roles of this member 37 * @type {Collection<Snowflake, Role>} 38 * @readonly 39 */ 40 get cache() { 41 return this._roles; 42 } 43 44 /** 45 * The role of the member used to hoist them in a separate category in the users list 46 * @type {?Role} 47 * @readonly 48 */ 49 get hoist() { 50 const hoistedRoles = this._roles.filter(role => role.hoist); 51 if (!hoistedRoles.size) return null; 52 return hoistedRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev)); 53 } 54 55 /** 56 * The role of the member used to set their color 57 * @type {?Role} 58 * @readonly 59 */ 60 get color() { 61 const coloredRoles = this._roles.filter(role => role.color); 62 if (!coloredRoles.size) return null; 63 return coloredRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev)); 64 } 65 66 /** 67 * The role of the member with the highest position 68 * @type {Role} 69 * @readonly 70 */ 71 get highest() { 72 return this._roles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this._roles.first()); 73 } 74 75 /** 76 * Adds a role (or multiple roles) to the member. 77 * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add 78 * @param {string} [reason] Reason for adding the role(s) 79 * @returns {Promise<GuildMember>} 80 */ 81 async add(roleOrRoles, reason) { 82 if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { 83 roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); 84 if (roleOrRoles.includes(null)) { 85 throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); 86 } 87 88 const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))]; 89 return this.set(newRoles, reason); 90 } else { 91 roleOrRoles = this.guild.roles.resolve(roleOrRoles); 92 if (roleOrRoles === null) { 93 throw new TypeError( 94 'INVALID_TYPE', 95 'roles', 96 'Role, Snowflake or Array or Collection of Roles or Snowflakes', 97 true, 98 ); 99 } 100 101 await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].put({ reason }); 102 103 const clone = this.member._clone(); 104 clone._roles = [...this._roles.keys(), roleOrRoles.id]; 105 return clone; 106 } 107 } 108 109 /** 110 * Removes a role (or multiple roles) from the member. 111 * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove 112 * @param {string} [reason] Reason for removing the role(s) 113 * @returns {Promise<GuildMember>} 114 */ 115 async remove(roleOrRoles, reason) { 116 if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) { 117 roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r)); 118 if (roleOrRoles.includes(null)) { 119 throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); 120 } 121 122 const newRoles = this._roles.filter(role => !roleOrRoles.includes(role)); 123 return this.set(newRoles, reason); 124 } else { 125 roleOrRoles = this.guild.roles.resolve(roleOrRoles); 126 if (roleOrRoles === null) { 127 throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true); 128 } 129 130 await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].delete({ reason }); 131 132 const clone = this.member._clone(); 133 const newRoles = this._roles.filter(role => role.id !== roleOrRoles.id); 134 clone._roles = [...newRoles.keys()]; 135 return clone; 136 } 137 } 138 139 /** 140 * Sets the roles applied to the member. 141 * @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to apply 142 * @param {string} [reason] Reason for applying the roles 143 * @returns {Promise<GuildMember>} 144 * @example 145 * // Set the member's roles to a single role 146 * guildMember.roles.set(['391156570408615936']) 147 * .then(console.log) 148 * .catch(console.error); 149 * @example 150 * // Remove all the roles from a member 151 * guildMember.roles.set([]) 152 * .then(member => console.log(`Member roles is now of ${member.roles.cache.size} size`)) 153 * .catch(console.error); 154 */ 155 set(roles, reason) { 156 return this.member.edit({ roles }, reason); 157 } 158 159 clone() { 160 const clone = new this.constructor(this.member); 161 clone.member._roles = [...this._roles.keyArray()]; 162 return clone; 163 } 164 } 165 166 module.exports = GuildMemberRoleManager;