mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 08:33:30 +01:00
Merge branch 'master' into voice-rewrite
This commit is contained in:
@@ -1,97 +1,29 @@
|
||||
const Collection = require('../util/Collection');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Base = require('./Base');
|
||||
const { TypeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
* Represents an emoji, see {@link GuildEmoji} and {@link ReactionEmoji}.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Emoji extends Base {
|
||||
constructor(client, data, guild) {
|
||||
constructor(client, emoji) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The guild this emoji is part of
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The ID of the emoji
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of the emoji
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* Whether or not this emoji requires colons surrounding it
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.requiresColons = data.require_colons;
|
||||
|
||||
/**
|
||||
* Whether this emoji is managed by an external service
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
|
||||
/**
|
||||
* Whether this emoji is animated
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.animated = data.animated;
|
||||
this.animated = emoji.animated;
|
||||
|
||||
this._roles = data.roles;
|
||||
}
|
||||
/**
|
||||
* The name of this emoji
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = emoji.name;
|
||||
|
||||
/**
|
||||
* The timestamp the emoji was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the emoji was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of roles this emoji is active for (empty if all), mapped by role ID
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
const roles = new Collection();
|
||||
for (const role of this._roles) {
|
||||
if (this.guild.roles.has(role)) roles.set(role, this.guild.roles.get(role));
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to the emoji file
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png');
|
||||
/**
|
||||
* The ID of this emoji
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.id = emoji.id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,148 +32,34 @@ class Emoji extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) return `${this.name}:${this.id}`;
|
||||
if (this.id) return `${this.animated ? 'a:' : ''}${this.name}:${this.id}`;
|
||||
return encodeURIComponent(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for editing an emoji.
|
||||
* @typedef {Object} EmojiEditData
|
||||
* @property {string} [name] The name of the emoji
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] Roles to restrict emoji to
|
||||
* The URL to the emoji file if its a custom emoji
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the emoji.
|
||||
* @param {EmojiEditData} data The new data for the emoji
|
||||
* @param {string} [reason] Reason for editing this emoji
|
||||
* @returns {Promise<Emoji>}
|
||||
* @example
|
||||
* // Edit an emoji
|
||||
* emoji.edit({name: 'newemoji'})
|
||||
* .then(e => console.log(`Edited emoji ${e}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data, reason) {
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id)
|
||||
.patch({ data: {
|
||||
name: data.name,
|
||||
roles: data.roles ? data.roles.map(r => r.id ? r.id : r) : undefined,
|
||||
}, reason })
|
||||
.then(() => this);
|
||||
get url() {
|
||||
if (!this.id) return null;
|
||||
return this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the emoji.
|
||||
* @param {string} name The new name for the emoji
|
||||
* @param {string} [reason] Reason for changing the emoji's name
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a role to the list of roles that can use this emoji.
|
||||
* @param {Role} role The role to add
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
addRestrictedRole(role) {
|
||||
return this.addRestrictedRoles([role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple roles to the list of roles that can use this emoji.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles Roles to add
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
addRestrictedRoles(roles) {
|
||||
const newRoles = new Collection(this.roles);
|
||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||
role = this.guild.roles.resolve(role);
|
||||
if (!role) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
}
|
||||
newRoles.set(role.id, role);
|
||||
}
|
||||
return this.edit({ roles: newRoles });
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a role from the list of roles that can use this emoji.
|
||||
* @param {Role} role The role to remove
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
removeRestrictedRole(role) {
|
||||
return this.removeRestrictedRoles([role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple roles from the list of roles that can use this emoji.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles Roles to remove
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
removeRestrictedRoles(roles) {
|
||||
const newRoles = new Collection(this.roles);
|
||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||
role = this.guild.roles.resolve(role);
|
||||
if (!role) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
}
|
||||
if (newRoles.has(role.id)) newRoles.delete(role.id);
|
||||
}
|
||||
return this.edit({ roles: newRoles });
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the emoji's mention instead of the Emoji object.
|
||||
* When concatenated with a string, this automatically returns the text required to form a graphical emoji on Discord
|
||||
* instead of the Emoji object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Send an emoji:
|
||||
* // Send a custom emoji from a guild:
|
||||
* const emoji = guild.emojis.first();
|
||||
* msg.reply(`Hello! ${emoji}`);
|
||||
* @example
|
||||
* // Send the emoji used in a reaction to the channel the reaction is part of
|
||||
* reaction.message.channel.send(`The emoji used was: ${reaction.emoji}`);
|
||||
*/
|
||||
toString() {
|
||||
if (!this.id || !this.requiresColons) {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
return `<${this.animated ? 'a' : ''}:${this.name}:${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the emoji.
|
||||
* @param {string} [reason] Reason for deleting the emoji
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id).delete({ reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this emoji is the same as another one.
|
||||
* @param {Emoji|Object} other The emoji to compare it to
|
||||
* @returns {boolean} Whether the emoji is equal to the given emoji or not
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof Emoji) {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other.managed === this.managed &&
|
||||
other.requiresColons === this.requiresColons &&
|
||||
other._roles === this._roles
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other._roles === this._roles
|
||||
);
|
||||
}
|
||||
return this.id ? `<${this.animated ? 'a' : ''}:${this.name}:${this.id}>` : this.name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const Snowflake = require('../util/Snowflake');
|
||||
const Shared = require('./shared');
|
||||
const GuildMemberStore = require('../stores/GuildMemberStore');
|
||||
const RoleStore = require('../stores/RoleStore');
|
||||
const EmojiStore = require('../stores/EmojiStore');
|
||||
const GuildEmojiStore = require('../stores/GuildEmojiStore');
|
||||
const GuildChannelStore = require('../stores/GuildChannelStore');
|
||||
const PresenceStore = require('../stores/PresenceStore');
|
||||
const Base = require('./Base');
|
||||
@@ -218,9 +218,9 @@ class Guild extends Base {
|
||||
if (!this.emojis) {
|
||||
/**
|
||||
* A collection of emojis that are in this guild. The key is the emoji's ID, the value is the emoji.
|
||||
* @type {EmojiStore<Snowflake, Emoji>}
|
||||
* @type {GuildEmojiStore<Snowflake, GuildEmoji>}
|
||||
*/
|
||||
this.emojis = new EmojiStore(this);
|
||||
this.emojis = new GuildEmojiStore(this);
|
||||
if (data.emojis) for (const emoji of data.emojis) this.emojis.add(emoji);
|
||||
} else {
|
||||
this.client.actions.GuildEmojisUpdate.handle({
|
||||
|
||||
@@ -148,7 +148,7 @@ class GuildAuditLogs {
|
||||
* * An invite
|
||||
* * A webhook
|
||||
* * An object where the keys represent either the new value or the old value
|
||||
* @typedef {?Object|Guild|User|Role|Emoji|Invite|Webhook} AuditLogEntryTarget
|
||||
* @typedef {?Object|Guild|User|Role|GuildEmoji|Invite|Webhook} AuditLogEntryTarget
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,31 +92,16 @@ class GuildChannel extends Channel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a user in this channel, taking into account roles and permission
|
||||
* overwrites.
|
||||
* @param {GuildMemberResolvable} member The user that you want to obtain the overall permissions for
|
||||
* Gets the overall set of permissions for a member or role in this channel, taking into account channel overwrites.
|
||||
* @param {GuildMemberResolvable|RoleResolvable} memberOrRole The member or role to obtain the overall permissions for
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
permissionsFor(member) {
|
||||
member = this.guild.members.resolve(member);
|
||||
if (!member) return null;
|
||||
if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const roles = member.roles;
|
||||
const permissions = new Permissions(roles.map(role => role.permissions));
|
||||
|
||||
if (permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const overwrites = this.overwritesFor(member, true, roles);
|
||||
|
||||
return permissions
|
||||
.remove(overwrites.everyone ? overwrites.everyone.denied : 0)
|
||||
.add(overwrites.everyone ? overwrites.everyone.allowed : 0)
|
||||
.remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.denied) : 0)
|
||||
.add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allowed) : 0)
|
||||
.remove(overwrites.member ? overwrites.member.denied : 0)
|
||||
.add(overwrites.member ? overwrites.member.allowed : 0)
|
||||
.freeze();
|
||||
permissionsFor(memberOrRole) {
|
||||
const member = this.guild.members.resolve(memberOrRole);
|
||||
if (member) return this.memberPermissions(member);
|
||||
const role = this.guild.roles.resolve(memberOrRole);
|
||||
if (role) return this.rolePermissions(role);
|
||||
return null;
|
||||
}
|
||||
|
||||
overwritesFor(member, verified = false, roles = null) {
|
||||
@@ -145,6 +130,52 @@ class GuildChannel extends Channel {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a member in this channel, taking into account channel overwrites.
|
||||
* @param {GuildMember} member The member to obtain the overall permissions for
|
||||
* @returns {Permissions}
|
||||
* @private
|
||||
*/
|
||||
memberPermissions(member) {
|
||||
if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const roles = member.roles;
|
||||
const permissions = new Permissions(roles.map(role => role.permissions));
|
||||
|
||||
if (permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const overwrites = this.overwritesFor(member, true, roles);
|
||||
|
||||
return permissions
|
||||
.remove(overwrites.everyone ? overwrites.everyone.denied : 0)
|
||||
.add(overwrites.everyone ? overwrites.everyone.allowed : 0)
|
||||
.remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.denied) : 0)
|
||||
.add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allowed) : 0)
|
||||
.remove(overwrites.member ? overwrites.member.denied : 0)
|
||||
.add(overwrites.member ? overwrites.member.allowed : 0)
|
||||
.freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a role in this channel, taking into account channel overwrites.
|
||||
* @param {Role} role The role to obtain the overall permissions for
|
||||
* @returns {Permissions}
|
||||
* @private
|
||||
*/
|
||||
rolePermissions(role) {
|
||||
if (role.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const everyoneOverwrites = this.permissionOverwrites.get(this.guild.id);
|
||||
const roleOverwrites = this.permissionOverwrites.get(role.id);
|
||||
|
||||
return role.permissions
|
||||
.remove(everyoneOverwrites ? everyoneOverwrites.denied : 0)
|
||||
.add(everyoneOverwrites ? everyoneOverwrites.allowed : 0)
|
||||
.remove(roleOverwrites ? roleOverwrites.denied : 0)
|
||||
.add(roleOverwrites ? roleOverwrites.allowed : 0)
|
||||
.freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* An object mapping permission flags to `true` (enabled), `null` (default) or `false` (disabled).
|
||||
* ```js
|
||||
|
||||
197
src/structures/GuildEmoji.js
Normal file
197
src/structures/GuildEmoji.js
Normal file
@@ -0,0 +1,197 @@
|
||||
const Collection = require('../util/Collection');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Emoji = require('./Emoji');
|
||||
const { TypeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
* @extends {Emoji}
|
||||
*/
|
||||
class GuildEmoji extends Emoji {
|
||||
constructor(client, data, guild) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The guild this emoji is part of
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* Whether or not this emoji requires colons surrounding it
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.requiresColons = data.require_colons;
|
||||
|
||||
/**
|
||||
* Whether this emoji is managed by an external service
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
|
||||
this._roles = data.roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the emoji was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the emoji was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of roles this emoji is active for (empty if all), mapped by role ID
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
const roles = new Collection();
|
||||
for (const role of this._roles) {
|
||||
if (this.guild.roles.has(role)) roles.set(role, this.guild.roles.get(role));
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for editing an emoji.
|
||||
* @typedef {Object} GuildEmojiEditData
|
||||
* @property {string} [name] The name of the emoji
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] Roles to restrict emoji to
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the emoji.
|
||||
* @param {Guild} data The new data for the emoji
|
||||
* @param {string} [reason] Reason for editing this emoji
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
* @example
|
||||
* // Edit an emoji
|
||||
* emoji.edit({name: 'newemoji'})
|
||||
* .then(e => console.log(`Edited emoji ${e}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data, reason) {
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id)
|
||||
.patch({ data: {
|
||||
name: data.name,
|
||||
roles: data.roles ? data.roles.map(r => r.id ? r.id : r) : undefined,
|
||||
}, reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the emoji.
|
||||
* @param {string} name The new name for the emoji
|
||||
* @param {string} [reason] Reason for changing the emoji's name
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a role to the list of roles that can use this emoji.
|
||||
* @param {Role} role The role to add
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
addRestrictedRole(role) {
|
||||
return this.addRestrictedRoles([role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple roles to the list of roles that can use this emoji.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles Roles to add
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
addRestrictedRoles(roles) {
|
||||
const newRoles = new Collection(this.roles);
|
||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||
role = this.guild.roles.resolve(role);
|
||||
if (!role) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
}
|
||||
newRoles.set(role.id, role);
|
||||
}
|
||||
return this.edit({ roles: newRoles });
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a role from the list of roles that can use this emoji.
|
||||
* @param {Role} role The role to remove
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
removeRestrictedRole(role) {
|
||||
return this.removeRestrictedRoles([role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple roles from the list of roles that can use this emoji.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles Roles to remove
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
removeRestrictedRoles(roles) {
|
||||
const newRoles = new Collection(this.roles);
|
||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||
role = this.guild.roles.resolve(role);
|
||||
if (!role) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
}
|
||||
if (newRoles.has(role.id)) newRoles.delete(role.id);
|
||||
}
|
||||
return this.edit({ roles: newRoles });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the emoji.
|
||||
* @param {string} [reason] Reason for deleting the emoji
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id).delete({ reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this emoji is the same as another one.
|
||||
* @param {GuildEmoji|Object} other The emoji to compare it to
|
||||
* @returns {boolean} Whether the emoji is equal to the given emoji or not
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof GuildEmoji) {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other.managed === this.managed &&
|
||||
other.requiresColons === this.requiresColons &&
|
||||
other._roles === this._roles
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other._roles === this._roles
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmoji;
|
||||
@@ -295,9 +295,9 @@ class GuildMember extends Base {
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
permissionsIn(channel) {
|
||||
channel = this.client.channels.resolve(channel);
|
||||
if (!channel || !channel.guild) throw new Error('GUILD_CHANNEL_RESOLVE');
|
||||
return channel.permissionsFor(this);
|
||||
channel = this.guild.channels.resolve(channel);
|
||||
if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE');
|
||||
return channel.memberPermissions(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -193,7 +193,7 @@ class MessageEmbed {
|
||||
|
||||
/**
|
||||
* Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when
|
||||
* setting an embed image or author/footer icons. Only one file may be attached.
|
||||
* setting an embed image or author/footer icons. Multiple files can be attached.
|
||||
* @param {Array<FileOptions|string|MessageAttachment>} files Files to attach
|
||||
* @returns {MessageEmbed}
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const Emoji = require('./Emoji');
|
||||
const GuildEmoji = require('./GuildEmoji');
|
||||
const ReactionEmoji = require('./ReactionEmoji');
|
||||
const ReactionUserStore = require('../stores/ReactionUserStore');
|
||||
|
||||
@@ -31,18 +31,18 @@ class MessageReaction {
|
||||
*/
|
||||
this.users = new ReactionUserStore(client, undefined, this);
|
||||
|
||||
this._emoji = new ReactionEmoji(this, data.emoji.name, data.emoji.id);
|
||||
this._emoji = new ReactionEmoji(this, data.emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji of this reaction, either an Emoji object for known custom emojis, or a ReactionEmoji
|
||||
* The emoji of this reaction, either an GuildEmoji object for known custom emojis, or a ReactionEmoji
|
||||
* object which has fewer properties. Whatever the prototype of the emoji, it will still have
|
||||
* `name`, `id`, `identifier` and `toString()`
|
||||
* @type {Emoji|ReactionEmoji}
|
||||
* @type {GuildEmoji|ReactionEmoji}
|
||||
* @readonly
|
||||
*/
|
||||
get emoji() {
|
||||
if (this._emoji instanceof Emoji) return this._emoji;
|
||||
if (this._emoji instanceof GuildEmoji) return this._emoji;
|
||||
// Check to see if the emoji has become known to the client
|
||||
if (this._emoji.id) {
|
||||
const emojis = this.message.client.emojis;
|
||||
|
||||
@@ -1,49 +1,19 @@
|
||||
const Emoji = require('./Emoji');
|
||||
|
||||
/**
|
||||
* Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
|
||||
* will use this class opposed to the Emoji class when the client doesn't know enough
|
||||
* information about them.
|
||||
* @extends {Emoji}
|
||||
*/
|
||||
class ReactionEmoji {
|
||||
constructor(reaction, name, id) {
|
||||
class ReactionEmoji extends Emoji {
|
||||
constructor(reaction, emoji) {
|
||||
super(reaction.message.client, emoji);
|
||||
/**
|
||||
* The message reaction this emoji refers to
|
||||
* @type {MessageReaction}
|
||||
*/
|
||||
this.reaction = reaction;
|
||||
|
||||
/**
|
||||
* The name of this reaction emoji
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The ID of this reaction emoji
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of this emoji, used for message reactions
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) return `${this.name}:${this.id}`;
|
||||
return encodeURIComponent(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the text required to form a graphical emoji on Discord
|
||||
* instead of the ReactionEmoji object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Send the emoji used in a reaction to the channel the reaction is part of
|
||||
* reaction.message.channel.send(`The emoji used was: ${reaction.emoji}`);
|
||||
*/
|
||||
toString() {
|
||||
return this.id ? `<:${this.name}:${this.id}>` : this.name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,18 @@ class Role extends Base {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `channel.permissionsFor(role)`. Returns permissions for a role in a guild channel,
|
||||
* taking into account permission overwrites.
|
||||
* @param {ChannelResolvable} channel The guild channel to use as context
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
permissionsIn(channel) {
|
||||
channel = this.guild.channels.resolve(channel);
|
||||
if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE');
|
||||
return channel.rolePermissions(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new name for the role.
|
||||
* @param {string} name The new name of the role
|
||||
|
||||
Reference in New Issue
Block a user