buddy

node MVC discord bot
Log | Files | Refs | README

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;