Skip to content

Commit

Permalink
Category channel (type 4) support
Browse files Browse the repository at this point in the history
  • Loading branch information
abalabahaha committed Sep 9, 2017
1 parent 710f071 commit a83deef
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 11 deletions.
10 changes: 7 additions & 3 deletions lib/Client.js
@@ -1,5 +1,6 @@
"use strict";

const CategoryChannel = require("./structures/CategoryChannel");
const GuildChannel = require("./structures/GuildChannel");
const Collection = require("./util/Collection");
const Constants = require("./Constants");
Expand Down Expand Up @@ -81,6 +82,7 @@ class Client extends EventEmitter {
* @arg {Number} [options.sequencerWait=200] How long to wait between sending potentially ratelimited requests. This number should be at least 3/4 your ping (in milliseconds)
* @arg {String} [options.defaultImageFormat="jpg"] The default format to provide user avatars, guild icons, and group icons in. Can be "jpg", "png", "gif", or "webp"
* @arg {Number} [options.defaultImageSize=128] The default size to return user avatars, guild icons, and group icons as. Can be 128, 256, 512, 1024, or 2048.
* @arg {Object} [options.ws] An object of WebSocket options to pass to the shard WebSocket constructors
*/
constructor(token, options) {
super();
Expand Down Expand Up @@ -363,6 +365,7 @@ class Client extends EventEmitter {
* @arg {Boolean} [options.nsfw] The nsfw status of the channel (guild channels only)
* @arg {Number} [options.bitrate] The bitrate of the channel (guild voice channels only)
* @arg {Number} [options.userLimit] The channel user limit (guild voice channels only)
* @arg {Number?} [options.parentID] The ID of the parent channel category for this channel (guild text/voice channels only)
* @arg {String} [reason] The reason to be displayed in audit logs
* @returns {Promise<GroupChannel | GuildChannel>}
*/
Expand All @@ -375,14 +378,15 @@ class Client extends EventEmitter {
nsfw: options.nsfw,
bitrate: options.bitrate,
user_limit: options.userLimit,
parent_id: options.parentID,
reason: reason
}).then((data) => {
if(!data.type || data.type === 2) { // undefined/0/2
if(!data.type || data.type === 2 || data.type === 4) { // undefined/0/2
var guild = this.channelGuildMap[channelID];
if(guild) {
guild = this.guilds.get(guild);
}
return new GuildChannel(data, guild);
return new (data.type === 4 ? CategoryChannel : GuildChannel)(data, guild);
} else {
return new GroupChannel(data, this);
}
Expand All @@ -406,7 +410,7 @@ class Client extends EventEmitter {
}
var min = Math.min(position, channel.position);
var max = Math.max(position, channel.position);
channels = channels.filter((chan) => chan.type === channel.type && min <= chan.position && chan.position <= max && chan.id !== channelID).sort((a, b) => a.position - b.position);
channels = channels.filter((chan) => chan.type === channel.type && chan.parentID === channel.parentID && min <= chan.position && chan.position <= max && chan.id !== channelID).sort((a, b) => a.position - b.position);
if(position > channel.position) {
channels.push(channel);
} else {
Expand Down
38 changes: 33 additions & 5 deletions lib/gateway/Shard.js
Expand Up @@ -2,6 +2,7 @@

const Bucket = require("../util/Bucket");
const Call = require("../structures/Call");
const CategoryChannel = require("../structures/CategoryChannel");
const Constants = require("../Constants");
const ExtendedUser = require("../structures/ExtendedUser");
const OPCodes = Constants.GatewayOPCodes;
Expand Down Expand Up @@ -824,14 +825,22 @@ class Shard extends EventEmitter {
this.client.privateChannelMap[packet.d.recipients[0].id] = packet.d.id;
this.client.emit("channelCreate", this.client.privateChannels.add(packet.d, this.client));
}
} else if(packet.d.type === 0 || packet.d.type === 2) {
} else if(packet.d.type === 0 || packet.d.type === 2 || packet.d.type === 4) {
var guild = this.client.guilds.get(packet.d.guild_id);
if(!guild) {
this.client.emit("warn", `Missing guild ${packet.d.guild_id} in CHANNEL_CREATE`);
break;
}
var channel = guild.channels.add(packet.d, guild);
var channel = guild.channels.add(packet.d.type === 4 ? new CategoryChannel(packet.d, guild) : packet.d, guild);
this.client.channelGuildMap[packet.d.id] = packet.d.guild_id;
if(packet.d.parent_id) {
var parentChannel = guild.channels.get(packet.d.parent_id);
if(!parentChannel) {
this.client.emit("warn", `Missing category channel ${packet.d.parent_id} in CHANNEL_CREATE`);
break;
}
parentChannel.channels.add(channel);
}
this.client.emit("channelCreate", channel);
} else if(packet.d.type === 3) {
if(this.id === 0) {
Expand All @@ -857,23 +866,42 @@ class Shard extends EventEmitter {
icon: channel.icon
};
}
if(channel.type === 0 || channel.type === 2) {
if(channel.type === 0 || channel.type === 2 || channel.type === 4) {
var oldChannel = {
name: channel.name,
topic: channel.topic,
position: channel.position,
bitrate: channel.bitrate,
permissionOverwrites: channel.permissionOverwrites
nsfw: channel.nsfw,
permissionOverwrites: channel.permissionOverwrites,
parentID: channel.parentID
};
}
channel.update(packet.d);

if(packet.d.parent_id) {
if(packet.d.parent_id !== channel.parentID) {
var oldParentChannel = guild.channels.get(channel.parentID);
if(!oldParentChannel) {
break;
}
oldParentChannel.channels.remove(channel);
}
var parentChannel = guild.channels.get(packet.d.parent_id);
if(!parentChannel) {
this.client.emit("warn", `Missing category channel ${packet.d.parent_id} in UPDATE`);
break;
}
parentChannel.channels.add(channel);
}
/**
* Fired when a channel is updated
* @event Client#channelUpdate
* @prop {Channel} channel The updated channel
* @prop {Object} oldChannel The old channel data
* @prop {String} oldChannel.name The name of the channel
* @prop {Number} oldChannel.position The position of the channel
* @prop {Boolean} oldChannel.nsfw Whether the channel is NSFW or not
* @prop {String?} oldChannel.topic The topic of the channel (text channels only)
* @prop {Number?} oldChannel.bitrate The bitrate of the channel (voice channels only)
* @prop {Collection} oldChannel.permissionOverwrites Collection of PermissionOverwrites in this channel
Expand All @@ -895,7 +923,7 @@ class Shard extends EventEmitter {
this.client.emit("channelDelete", channel);
}
}
} else if(packet.d.type === 0 || packet.d.type === 2) {
} else if(packet.d.type === 0 || packet.d.type === 2 || packet.d.type === 4) {
delete this.client.channelGuildMap[packet.d.id];
var guild = this.client.guilds.get(packet.d.guild_id);
if(!guild) {
Expand Down
2 changes: 1 addition & 1 deletion lib/rest/Endpoints.js
Expand Up @@ -69,6 +69,6 @@ module.exports.USER_SETTINGS = (userID)
module.exports.USERS = "/users";
module.exports.VOICE_REGIONS = "/voice/regions";
module.exports.WEBHOOK = (hookID) => `/webhooks/${hookID}`;
module.exports.WEBHOOK_TOKEN = (hookID, token) => `/webhooks/${hookID}/${token}`;
module.exports.WEBHOOK_SLACK = (hookID) => `/webhooks/${hookID}/slack`;
module.exports.WEBHOOK_TOKEN = (hookID, token) => `/webhooks/${hookID}/${token}`;
module.exports.WEBHOOK_TOKEN_SLACK = (hookID, token) => `/webhooks/${hookID}/${token}/slack`;
25 changes: 25 additions & 0 deletions lib/structures/CategoryChannel.js
@@ -0,0 +1,25 @@
"use strict";

const GuildChannel = require("./GuildChannel");
const Collection = require("../util/Collection");

/**
* Represents a guild category channel
* @extends GuildChannel
* @prop {Collection<GuildChannel>?} channels A collection of guild channels that are part of this category
*/
class CategoryChannel extends GuildChannel {
constructor(data, guild) {
super(data, guild);

this.channels = new Collection(GuildChannel);

guild.channels.forEach((channel) => {
if(channel.parentID === this.id) {
this.channels.add(channel);
}
});
}
}

module.exports = CategoryChannel;
3 changes: 2 additions & 1 deletion lib/structures/Guild.js
@@ -1,6 +1,7 @@
"use strict";

const Base = require("./Base");
const CategoryChannel = require("./CategoryChannel");
const CDN_URL = require("../rest/Endpoints").CDN_URL;
const Constants = require("../Constants");
const Collection = require("../util/Collection");
Expand Down Expand Up @@ -56,7 +57,7 @@ class Guild extends Base {

if(data.channels) {
for(var channel of data.channels) {
channel = this.channels.add(channel, this);
channel = this.channels.add(channel.type === 4 ? new CategoryChannel(channel, this) : channel, this);
client.channelGuildMap[channel.id] = this.id;
}

Expand Down
5 changes: 4 additions & 1 deletion lib/structures/GuildChannel.js
Expand Up @@ -15,6 +15,7 @@ const PermissionOverwrite = require("./PermissionOverwrite");
* @prop {Guild} guild The guild that owns the channel
* @prop {Collection<Message>} messages Collection of Messages in this channel
* @prop {String} lastMessageID The ID of the last message in this channel
* @prop {String?} parentID The ID of the category this channel belongs to
* @prop {Number} lastPinTimestamp The timestamp of the last pinned message
* @prop {Collection<PermissionOverwrite>} permissionOverwrites Collection of PermissionOverwrites in this channel
* @prop {Number} type The type of the channel, either 0 (text) or 2 (voice)
Expand All @@ -32,7 +33,7 @@ class GuildChannel extends Channel {
this.guild = guild;
if(this.type === 2) {
this.voiceMembers = new Collection(Member);
} else {
} else if(this.type === 0) {
if(messageLimit == null && guild) {
messageLimit = guild.shard.client.options.messageLimit;
}
Expand All @@ -49,6 +50,7 @@ class GuildChannel extends Channel {
this.position = data.position !== undefined ? data.position : this.position;
this.bitrate = data.bitrate !== undefined ? data.bitrate : this.bitrate;
this.userLimit = data.user_limit !== undefined ? data.user_limit : this.userLimit;
this.parentID = data.parent_id !== undefined ? data.parent_id : this.parentID;
this.nsfw = this.type !== 2 && ((this.name.length === 4 ? this.name === "nsfw" : this.name.startsWith("nsfw-")) || data.nsfw);
if(data.permission_overwrites) {
this.permissionOverwrites = new Collection(PermissionOverwrite);
Expand Down Expand Up @@ -100,6 +102,7 @@ class GuildChannel extends Channel {
* @arg {String} [options.topic] The topic of the channel (guild text channels only)
* @arg {Number} [options.bitrate] The bitrate of the channel (guild voice channels only)
* @arg {Number} [options.userLimit] The channel user limit (guild voice channels only)
* @arg {Number?} [options.parentID] The ID of the parent channel category for this channel (guild text/voice channels only)
* @arg {String} [reason] The reason to be displayed in audit logs
* @returns {Promise<GuildChannel>}
*/
Expand Down

0 comments on commit a83deef

Please sign in to comment.