structures/Role.js

"use strict";

const Base = require("./Base");
const Endpoints = require("../rest/Endpoints");
const Permission = require("./Permission");

/**
 * Represents a role
 * @prop {Number} color The hex color of the role in base 10
 * @prop {Number} createdAt Timestamp of the role's creation
 * @prop {Number} flags The flags of the role (see constants)
 * @prop {Guild} guild The guild that owns the role
 * @prop {Boolean} hoist Whether users with the role are hoisted in the user list or not
 * @prop {String?} icon The hash of the role's icon, or null if no icon
 * @prop {String?} iconURL The URL of the role's icon
 * @prop {String} id The ID of the role
 * @prop {Object} json Generates a JSON representation of the role permissions
 * @prop {Boolean} managed Whether a guild integration manages the role or not
 * @prop {String} mention A string that mentions the role
 * @prop {Boolean} mentionable Whether the role is mentionable or not
 * @prop {String} name The name of the role
 * @prop {Permission} permissions The permissions representation of the role
 * @prop {Number} position The position of the role
 * @prop {Object?} tags The tags of the role
 * @prop {String?} tags.bot_id The ID of the bot associated with the role
 * @prop {String?} tags.integration_id The ID of the integration associated with the role
 * @prop {Boolean?} tags.premium_subscriber Whether the role is the guild's premium subscriber role
 * @prop {String?} tags.subscription_listing_id The id of the role's subscription sku and listing
 * @prop {Boolean?} tags.available_for_purchase Whether the role is available for purchase
 * @prop {Boolean?} tags.guild_connections Whether the role is a guild's linked role
 * @prop {String?} unicodeEmoji Unicode emoji for the role
 */
class Role extends Base {
  constructor(data, guild) {
    super(data.id);
    this.guild = guild; // REVIEW Should really consider changing this to client
    this.update(data);
  }

  update(data) {
    if (data.name !== undefined) {
      this.name = data.name;
    }
    if (data.mentionable !== undefined) {
      this.mentionable = data.mentionable;
    }
    if (data.managed !== undefined) {
      this.managed = data.managed;
    }
    if (data.hoist !== undefined) {
      this.hoist = data.hoist;
    }
    if (data.color !== undefined) {
      this.color = data.color;
    }
    if (data.position !== undefined) {
      this.position = data.position;
    }
    if (data.permissions !== undefined) {
      this.permissions = new Permission(data.permissions);
    }
    if (data.tags !== undefined) {
      this.tags = data.tags;
      if (this.tags.available_for_purchase === null) {
        this.tags.available_for_purchase = true;
      } else if (this.tags.guild_connections === null) {
        this.tags.guild_connections = true;
      } else if (this.tags.premium_subscriber === null) {
        this.tags.premium_subscriber = true;
      }
    }
    if (data.icon !== undefined) {
      this.icon = data.icon;
    }
    if (data.unicode_emoji !== undefined) {
      this.unicodeEmoji = data.unicode_emoji;
    }
    if (data.flags !== undefined) {
      this.flags = data.flags;
    }
  }

  get iconURL() {
    return this.icon ? this.guild.shard.client._formatImage(Endpoints.ROLE_ICON(this.id, this.icon)) : null;
  }

  get json() {
    return this.permissions.json;
  }

  get mention() {
    return `<@&${this.id}>`;
  }

  /**
   * Delete the role
   * @arg {String} [reason] The reason to be displayed in audit logs
   * @returns {Promise}
   */
  delete(reason) {
    return this.guild.shard.client.deleteRole.call(this.guild.shard.client, this.guild.id, this.id, reason);
  }

  /**
   * Edit the guild role
   * @arg {Object} options The properties to edit
   * @arg {Number} [options.color] The hex color of the role, in number form (ex: 0x3da5b3 or 4040115)
   * @arg {Boolean} [options.hoist] Whether to hoist the role in the user list or not
   * @arg {String} [options.icon] The role icon as a base64 data URI
   * @arg {Boolean} [options.mentionable] Whether the role is mentionable or not
   * @arg {String} [options.name] The name of the role
   * @arg {BigInt | Number} [options.permissions] The role permissions number
   * @arg {String?} [options.unicodeEmoji] The role's unicode emoji
   * @arg {String} [reason] The reason to be displayed in audit logs
   * @returns {Promise<Role>}
   */
  edit(options, reason) {
    return this.guild.shard.client.editRole.call(this.guild.shard.client, this.guild.id, this.id, options, reason);
  }

  /**
   * Edit the role's position. Note that role position numbers are highest on top and lowest at the bottom.
   * @arg {Number} position The new position of the role
   * @returns {Promise}
   */
  editPosition(position) {
    return this.guild.shard.client.editRolePosition.call(this.guild.shard.client, this.guild.id, this.id, position);
  }

  toJSON(props = []) {
    return super.toJSON([
      "color",
      "hoist",
      "icon",
      "managed",
      "mentionable",
      "name",
      "permissions",
      "position",
      "tags",
      "unicodeEmoji",
      ...props,
    ]);
  }
}

module.exports = Role;