Files
discord.js/src/structures/GuildChannel.js
2016-08-18 13:22:36 +01:00

226 lines
6.2 KiB
JavaScript

const Channel = require('./Channel');
const PermissionOverwrites = require('./PermissionOverwrites');
const EvaluatedPermissions = require('./EvaluatedPermissions');
const Constants = require('../util/Constants');
function arraysEqual(a, b) {
if (a === b) return true;
if (a.length !== b.length) return false;
for (const itemInd in a) {
const item = a[itemInd];
const ind = b.indexOf(item);
if (ind) {
b.splice(ind, 1);
}
}
return b.length === 0;
}
/**
* Represents a Guild Channel (i.e. Text Channels and Voice Channels)
* @extends {Channel}
*/
class GuildChannel extends Channel {
constructor(guild, data) {
super(guild.client, data, guild);
}
setup(data) {
super.setup(data);
/**
* The type of the Guild Channel
* @type {Number}
*/
this.type = data.type;
/**
* The topic of the Guild Channel, if there is one.
* @type {?String}
*/
this.topic = data.topic;
/**
* The position of the channel in the list.
* @type {Number}
*/
this.position = data.position;
/**
* The name of the Guild Channel
* @type {String}
*/
this.name = data.name;
/**
* The ID of the last message in the channel, if one was sent.
* @type {?String}
*/
this.lastMessageID = data.last_message_id;
this.ow = data.permission_overwrites;
/**
* A list of permission overwrites in this channel for roles and users.
* @type {Array<PermissionOverwrites>}
*/
this.permissionOverwrites = [];
if (data.permission_overwrites) {
for (const overwrite of data.permission_overwrites) {
this.permissionOverwrites.push(new PermissionOverwrites(this, overwrite));
}
}
}
/**
* Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel.
* In most cases, a simple `channel.id === channel2.id` will do, and is much faster too.
* @param {GuildChannel} channel the channel to compare this channel to
* @returns {Boolean}
*/
equals(other) {
let base = (
this.type === other.type &&
this.topic === other.topic &&
this.position === other.position &&
this.name === other.name &&
this.id === other.id
);
if (base) {
if (other.permission_overwrites) {
const thisIDSet = this.permissionOverwrites.map(overwrite => overwrite.id);
const otherIDSet = other.permission_overwrites.map(overwrite => overwrite.id);
if (arraysEqual(thisIDSet, otherIDSet)) {
base = true;
} else {
base = false;
}
} else {
base = false;
}
}
return base;
}
/**
* 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
* @returns {?EvaluatedPermissions}
*/
permissionsFor(member) {
member = this.client.resolver.resolveGuildMember(this.guild, member);
if (member) {
if (this.guild.owner.id === member.id) {
return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS);
}
const roles = member.roles;
let permissions = 0;
const overwrites = this.overwritesFor(member, true);
for (const role of roles) {
permissions |= role.permissions;
}
for (const overwrite of overwrites.role.concat(overwrites.member)) {
permissions &= ~overwrite.denyData;
permissions |= overwrite.allowData;
}
const admin = Boolean(permissions & (Constants.PermissionFlags.ADMINISTRATOR));
if (admin) {
permissions = Constants.ALL_PERMISSIONS;
}
return new EvaluatedPermissions(member, permissions);
}
return null;
}
overwritesFor(member, verified) {
// for speed
if (!verified) member = this.client.resolver.resolveGuildMember(this.guild, member);
if (member) {
const memberRoles = member._roles;
const roleOverwrites = [];
const memberOverwrites = [];
for (const overwrite of this.permissionOverwrites) {
if (overwrite.id === member.id) {
memberOverwrites.push(overwrite);
} else if (memberRoles.indexOf(overwrite.id) > -1) {
roleOverwrites.push(overwrite);
}
}
return {
role: roleOverwrites,
member: memberOverwrites,
};
}
return [];
}
edit(data) {
return this.client.rest.methods.updateChannel(this, data);
}
/**
* Set a new name for the Guild Channel
* @param {String} name the new name for the guild channel
* @returns {Promise<GuildChannel>}
* @example
* // set a new channel name
* channel.setName('not general')
* .then(newChannel => console.log(`Channel's new name is ${newChannel.name}`))
* .catch(console.log);
*/
setName(name) {
return this.client.rest.methods.updateChannel(this, { name });
}
/**
* Set a new position for the Guild Channel
* @param {Number} position the new position for the guild channel
* @returns {Promise<GuildChannel>}
* @example
* // set a new channel position
* channel.setPosition(2)
* .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`))
* .catch(console.log);
*/
setPosition(position) {
return this.rest.client.rest.methods.updateChannel(this, { position });
}
/**
* Set a new topic for the Guild Channel
* @param {String} topic the new topic for the guild channel
* @returns {Promise<GuildChannel>}
* @example
* // set a new channel topic
* channel.setTopic('needs more rate limiting')
* .then(newChannel => console.log(`Channel's new topic is ${newChannel.topic}`))
* .catch(console.log);
*/
setTopic(topic) {
return this.rest.client.rest.methods.updateChannel(this, { topic });
}
/**
* When concatenated with a String, this automatically concatenates the Channel's name instead of the Channel object.
* @returns {String}
* @example
* // Outputs: Hello from general
* console.log(`Hello from ${channel}`);
* @example
* // Outputs: Hello from general
* console.log('Hello from ' + ${channel});
*/
toString() {
return this.name;
}
}
module.exports = GuildChannel;