diff --git a/.gitignore b/.gitignore index d1ca39f79..9167b884f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,38 +1,38 @@ -# Created by https://www.gitignore.io - -.tmp/ -.vscode/ - -### Node ### -# Logs -logs -*.log - -test/auth.json - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git -node_modules -test/auth.json -examples/auth.json +# Created by https://www.gitignore.io + +.tmp/ +.vscode/ + +### Node ### +# Logs +logs +*.log + +test/auth.json + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules +test/auth.json +examples/auth.json docs/_build \ No newline at end of file diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 41d5be9de..051cde9be 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -1,26 +1,27 @@ -'use strict'; - -const requireAction = name => require(`./${name}`); - -class ActionsManager { - constructor(client) { - this.client = client; - - this.register('MessageCreate'); - this.register('MessageDelete'); - this.register('MessageUpdate'); - this.register('ChannelCreate'); - this.register('ChannelDelete'); - this.register('ChannelUpdate'); - this.register('GuildDelete'); - this.register('GuildUpdate'); - this.register('UserUpdate'); - } - - register(name) { - let Action = requireAction(name); - this[name] = new Action(this.client); - } -} - -module.exports = ActionsManager; +'use strict'; + +const requireAction = name => require(`./${name}`); + +class ActionsManager { + constructor(client) { + this.client = client; + + this.register('MessageCreate'); + this.register('MessageDelete'); + this.register('MessageUpdate'); + this.register('ChannelCreate'); + this.register('ChannelDelete'); + this.register('ChannelUpdate'); + this.register('GuildDelete'); + this.register('GuildUpdate'); + this.register('GuildMemberRemove'); + this.register('UserUpdate'); + } + + register(name) { + let Action = requireAction(name); + this[name] = new Action(this.client); + } +} + +module.exports = ActionsManager; diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js index 4f021d0ed..36b6d0231 100644 --- a/src/client/actions/ChannelDelete.js +++ b/src/client/actions/ChannelDelete.js @@ -1,44 +1,44 @@ -'use strict'; - -const Action = require('./Action'); -const Constants = require('../../util/Constants'); -const Message = require('../../structures/Message'); - -class ChannelDeleteAction extends Action { - - constructor(client) { - super(client); - this.timeouts = []; - this.deleted = {}; - } - - handle(data) { - let client = this.client; - let channel = client.store.get('channels', data.id); - - if (channel) { - - client.store.KillChannel(channel); - this.deleted[channel.id] = channel; - this.scheduleForDeletion(channel.id); - - } else if (this.deleted[data.id]) { - - channel = this.deleted[data.id]; - - } - - return { - channel, - }; - } - - scheduleForDeletion(id) { - this.timeouts.push( - setTimeout(() => delete this.deleted[id], - this.client.options.rest_ws_bridge_timeout) - ); - } -}; - -module.exports = ChannelDeleteAction; +'use strict'; + +const Action = require('./Action'); +const Constants = require('../../util/Constants'); +const Message = require('../../structures/Message'); + +class ChannelDeleteAction extends Action { + + constructor(client) { + super(client); + this.timeouts = []; + this.deleted = {}; + } + + handle(data) { + let client = this.client; + let channel = client.store.get('channels', data.id); + + if (channel) { + + client.store.KillChannel(channel); + this.deleted[channel.id] = channel; + this.scheduleForDeletion(channel.id); + + } else if (this.deleted[data.id]) { + + channel = this.deleted[data.id]; + + } + + return { + channel, + }; + } + + scheduleForDeletion(id) { + this.timeouts.push( + setTimeout(() => delete this.deleted[id], + this.client.options.rest_ws_bridge_timeout) + ); + } +}; + +module.exports = ChannelDeleteAction; diff --git a/src/client/actions/GuildMemberRemove.js b/src/client/actions/GuildMemberRemove.js new file mode 100644 index 000000000..d9ddf62c7 --- /dev/null +++ b/src/client/actions/GuildMemberRemove.js @@ -0,0 +1,50 @@ +'use strict'; + +const Action = require('./Action'); +const Constants = require('../../util/Constants'); +const Message = require('../../structures/Message'); + +class GuildMemberRemoveAction extends Action { + + constructor(client) { + super(client); + this.timeouts = []; + this.deleted = {}; + } + + handle(data) { + let client = this.client; + let guild = client.store.get('guilds', data.guild_id); + if (guild) { + let member = guild.store.get('members', data.user.id); + if (member) { + guild._removeMember(member); + this.deleted[guild.id + data.user.id] = member; + this.scheduleForDeletion(guild.id, data.user.id); + } + + if (!member) { + member = this.deleted[guild.id + data.user.id]; + } + + return { + g: guild, + m: member, + }; + } + + return { + g: guild, + m: null, + }; + } + + scheduleForDeletion(guildID, userID) { + this.timeouts.push( + setTimeout(() => delete this.deleted[guildID + userID], + this.client.options.rest_ws_bridge_timeout) + ); + } +}; + +module.exports = GuildMemberRemoveAction; diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 54254689a..ea812ebd2 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -1,247 +1,260 @@ -'use strict'; - -const Constants = require('../../util/Constants'); -const Structure = name => require('../../structures/' + name); -const User = Structure('User'); -const GuildMember = Structure('GuildMember'); -const Message = Structure('Message'); - -class RESTMethods{ - constructor(restManager) { - this.rest = restManager; - } - - LoginEmailPassword(email, password) { - return new Promise((resolve, reject) => { - this.rest.client.store.email = email; - this.rest.client.store.password = password; - this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password }) - .then(data => { - this.rest.client.manager.connectToWebSocket(data.token, resolve, reject); - }) - .catch(reject); - - }); - } - - LoginToken(token) { - return new Promise((resolve, reject) => { - this.rest.client.manager.connectToWebSocket(token, resolve, reject); - }); - } - - GetGateway() { - return new Promise((resolve, reject) => { - this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true) - .then(res => resolve(res.url)) - .catch(reject); - }); - } - - SendMessage(channel, content, tts, nonce) { - return new Promise((resolve, reject) => { - - var _this = this; - - if (channel instanceof User || channel instanceof GuildMember) { - this.CreateDM(channel).then(chan => { - channel = chan; - req(); - }) - .catch(reject); - } else { - req(); - } - - function req() { - _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, { - content, tts, nonce, - }) - .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m)) - .catch(reject); - } - }); - } - - DeleteMessage(message) { - return new Promise((resolve, reject) => { - this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true) - .then(data => { - resolve(this.rest.client.actions.MessageDelete.handle({ - id: message.id, - channel_id: message.channel.id, - }).m); - }) - .catch(reject); - }); - } - - UpdateMessage(message, content) { - return new Promise((resolve, reject) => { - this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, { - content, - }) - .then(data => { - resolve(this.rest.client.actions.MessageUpdate.handle(data).updated); - }) - .catch(reject); - }); - } - - CreateChannel(guild, channelName, channelType) { - return new Promise((resolve, reject) => { - this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, { - name: channelName, - type: channelType, - }) - .then(data => { - resolve(this.rest.client.actions.ChannelCreate.handle(data).channel); - }) - .catch(reject); - }); - } - - GetExistingDM(recipient) { - let dmChannel = this.rest.client.store.getAsArray('channels') - .filter(channel => channel.recipient) - .filter(channel => channel.recipient.id === recipient.id); - - return dmChannel[0]; - } - - CreateDM(recipient) { - return new Promise((resolve, reject) => { - - let dmChannel = this.GetExistingDM(recipient); - - if (dmChannel) { - return resolve(dmChannel); - } - - this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, { - recipient_id: recipient.id, - }) - .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel)) - .catch(reject); - }); - } - - DeleteChannel(channel) { - return new Promise((resolve, reject) => { - if (channel instanceof User || channel instanceof GuildMember) { - channel = this.GetExistingDM(channel); - } - - this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true) - .then(data => { - data.id = channel.id; - resolve(this.rest.client.actions.ChannelDelete.handle(data).channel); - }) - .catch(reject); - }); - } - - UpdateChannel(channel, data) { - return new Promise((resolve, reject) => { - data.name = (data.name || channel.name).trim(); - data.topic = data.topic || channel.topic; - data.position = data.position || channel.position; - data.bitrate = data.bitrate || channel.bitrate; - - this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data) - .then(data => { - resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated); - }) - .catch(reject); - }); - } - - LeaveGuild(guild) { - return new Promise((resolve, reject) => { - this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true) - .then(() => { - resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild); - }) - .catch(reject); - }); - } - - // untested but probably will work - DeleteGuild(guild) { - return new Promise((resolve, reject) => { - this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true) - .then(() => { - resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild); - }) - .catch(reject); - }); - } - - UpdateCurrentUser(_data) { - return new Promise((resolve, reject) => { - let user = this.rest.client.store.user; - let data = {}; - - data.username = _data.username || user.username; - data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar; - if (!user.bot) { - data.password = this.rest.client.store.password; - data.email = _data.email || this.rest.client.store.email; - data.new_password = _data.newPassword; - } - - this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data) - .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated)) - .catch(reject); - }); - } - - UpdateGuild(guild, _data) { - return new Promise((resolve, reject) => { - /* - can contain: - name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash - */ - - let data = {}; - - if (_data.name) { - data.name = _data.name; - } - - if (_data.region) { - data.region = _data.region; - } - - if (_data.verificationLevel) { - data.verification_level = Number(_data.verificationLevel); - } - - if (_data.afkChannel) { - data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id; - } - - if (_data.afkTimeout) { - data.afk_timeout = Number(_data.afkTimeout); - } - - if (_data.icon) { - data.icon = this.rest.client.resolver.ResolveBase64(_data.icon); - } - - if (_data.owner) { - data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id; - } - - if (_data.splash) { - data.splash = this.rest.client.resolver.ResolveBase64(_data.splash); - } - - this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data) - .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated)) - .catch(reject); - }); - } -} - -module.exports = RESTMethods; +'use strict'; + +const Constants = require('../../util/Constants'); +const Structure = name => require('../../structures/' + name); +const User = Structure('User'); +const GuildMember = Structure('GuildMember'); +const Message = Structure('Message'); + +class RESTMethods{ + constructor(restManager) { + this.rest = restManager; + } + + LoginEmailPassword(email, password) { + return new Promise((resolve, reject) => { + this.rest.client.store.email = email; + this.rest.client.store.password = password; + this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password }) + .then(data => { + this.rest.client.manager.connectToWebSocket(data.token, resolve, reject); + }) + .catch(reject); + + }); + } + + LoginToken(token) { + return new Promise((resolve, reject) => { + this.rest.client.manager.connectToWebSocket(token, resolve, reject); + }); + } + + GetGateway() { + return new Promise((resolve, reject) => { + this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true) + .then(res => resolve(res.url)) + .catch(reject); + }); + } + + SendMessage(channel, content, tts, nonce) { + return new Promise((resolve, reject) => { + + var _this = this; + + if (channel instanceof User || channel instanceof GuildMember) { + this.CreateDM(channel).then(chan => { + channel = chan; + req(); + }) + .catch(reject); + } else { + req(); + } + + function req() { + _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, { + content, tts, nonce, + }) + .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m)) + .catch(reject); + } + }); + } + + DeleteMessage(message) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true) + .then(data => { + resolve(this.rest.client.actions.MessageDelete.handle({ + id: message.id, + channel_id: message.channel.id, + }).m); + }) + .catch(reject); + }); + } + + UpdateMessage(message, content) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, { + content, + }) + .then(data => { + resolve(this.rest.client.actions.MessageUpdate.handle(data).updated); + }) + .catch(reject); + }); + } + + CreateChannel(guild, channelName, channelType) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, { + name: channelName, + type: channelType, + }) + .then(data => { + resolve(this.rest.client.actions.ChannelCreate.handle(data).channel); + }) + .catch(reject); + }); + } + + GetExistingDM(recipient) { + let dmChannel = this.rest.client.store.getAsArray('channels') + .filter(channel => channel.recipient) + .filter(channel => channel.recipient.id === recipient.id); + + return dmChannel[0]; + } + + CreateDM(recipient) { + return new Promise((resolve, reject) => { + + let dmChannel = this.GetExistingDM(recipient); + + if (dmChannel) { + return resolve(dmChannel); + } + + this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, { + recipient_id: recipient.id, + }) + .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel)) + .catch(reject); + }); + } + + DeleteChannel(channel) { + return new Promise((resolve, reject) => { + if (channel instanceof User || channel instanceof GuildMember) { + channel = this.GetExistingDM(channel); + } + + this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true) + .then(data => { + data.id = channel.id; + resolve(this.rest.client.actions.ChannelDelete.handle(data).channel); + }) + .catch(reject); + }); + } + + UpdateChannel(channel, data) { + return new Promise((resolve, reject) => { + data.name = (data.name || channel.name).trim(); + data.topic = data.topic || channel.topic; + data.position = data.position || channel.position; + data.bitrate = data.bitrate || channel.bitrate; + + this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data) + .then(data => { + resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated); + }) + .catch(reject); + }); + } + + LeaveGuild(guild) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true) + .then(() => { + resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild); + }) + .catch(reject); + }); + } + + // untested but probably will work + DeleteGuild(guild) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true) + .then(() => { + resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild); + }) + .catch(reject); + }); + } + + UpdateCurrentUser(_data) { + return new Promise((resolve, reject) => { + let user = this.rest.client.store.user; + let data = {}; + + data.username = _data.username || user.username; + data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar; + if (!user.bot) { + data.password = this.rest.client.store.password; + data.email = _data.email || this.rest.client.store.email; + data.new_password = _data.newPassword; + } + + this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data) + .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated)) + .catch(reject); + }); + } + + UpdateGuild(guild, _data) { + return new Promise((resolve, reject) => { + /* + can contain: + name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash + */ + + let data = {}; + + if (_data.name) { + data.name = _data.name; + } + + if (_data.region) { + data.region = _data.region; + } + + if (_data.verificationLevel) { + data.verification_level = Number(_data.verificationLevel); + } + + if (_data.afkChannel) { + data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id; + } + + if (_data.afkTimeout) { + data.afk_timeout = Number(_data.afkTimeout); + } + + if (_data.icon) { + data.icon = this.rest.client.resolver.ResolveBase64(_data.icon); + } + + if (_data.owner) { + data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id; + } + + if (_data.splash) { + data.splash = this.rest.client.resolver.ResolveBase64(_data.splash); + } + + this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data) + .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated)) + .catch(reject); + }); + } + + KickGuildMember(guild, member) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('del', Constants.Endpoints.GUILD_MEMBER(guild.id, member.id), true) + .then(() => { + resolve(this.rest.client.actions.GuildMemberRemove.handle({ + guild_id : guild.id, + user : member.user, + }).m); + }) + .catch(reject); + }); + } +} + +module.exports = RESTMethods; diff --git a/src/client/websocket/packets/handlers/ChannelUpdate.js b/src/client/websocket/packets/handlers/ChannelUpdate.js index 699cfd432..41491a103 100644 --- a/src/client/websocket/packets/handlers/ChannelUpdate.js +++ b/src/client/websocket/packets/handlers/ChannelUpdate.js @@ -1,28 +1,28 @@ -'use strict'; - -const AbstractHandler = require('./AbstractHandler'); -const Structure = name => require(`../../../../structures/${name}`); - -const ClientUser = Structure('ClientUser'); -const Guild = Structure('Guild'); -const ServerChannel = Structure('ServerChannel'); - -const Constants = require('../../../../util/Constants'); -const CloneObject = require('../../../../util/CloneObject'); - -class ChannelUpdateHandler extends AbstractHandler { - - constructor(packetManager) { - super(packetManager); - } - - handle(packet) { - let data = packet.d; - let client = this.packetManager.client; - - client.actions.ChannelUpdate.handle(data); - } - -}; - -module.exports = ChannelUpdateHandler; +'use strict'; + +const AbstractHandler = require('./AbstractHandler'); +const Structure = name => require(`../../../../structures/${name}`); + +const ClientUser = Structure('ClientUser'); +const Guild = Structure('Guild'); +const ServerChannel = Structure('ServerChannel'); + +const Constants = require('../../../../util/Constants'); +const CloneObject = require('../../../../util/CloneObject'); + +class ChannelUpdateHandler extends AbstractHandler { + + constructor(packetManager) { + super(packetManager); + } + + handle(packet) { + let data = packet.d; + let client = this.packetManager.client; + + client.actions.ChannelUpdate.handle(data); + } + +}; + +module.exports = ChannelUpdateHandler; diff --git a/src/client/websocket/packets/handlers/GuildMemberRemove.js b/src/client/websocket/packets/handlers/GuildMemberRemove.js index a46556c38..185cb768c 100644 --- a/src/client/websocket/packets/handlers/GuildMemberRemove.js +++ b/src/client/websocket/packets/handlers/GuildMemberRemove.js @@ -20,13 +20,10 @@ class GuildMemberRemoveHandler extends AbstractHandler { let data = packet.d; let client = this.packetManager.client; - let guild = client.store.get('guilds', data.guild_id); + let response = client.actions.GuildMemberRemove.handle(data); - if (guild) { - let member = guild.store.get('members', data.user.id); - if (member) { - guild._removeMember(member); - } + if (response.m) { + client.emit(Constants.Events.GUILD_MEMBER_REMOVE, response.g, response.m); } } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 1d5e71a6d..a4607e03f 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -66,15 +66,16 @@ class Guild { _removeMember(guildMember) { this.store.remove('members', guildMember); - if (this.client.ws.status === Constants.Status.READY) { - this.client.emit(Constants.Events.GUILD_MEMBER_REMOVE, this, guildMember); - } } toString() { return this.name; } + kick(member) { + return this.member(member).kick(); + } + member(user) { return this.client.resolver.ResolveGuildMember(this, user); } diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index bacc3a314..d35cc163d 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -62,6 +62,10 @@ class GuildMember { deleteDM() { return this.client.rest.methods.DeleteChannel(this); } + + kick() { + return this.client.rest.methods.KickGuildMember(this.guild, this); + } } TextBasedChannel.applyToClass(GuildMember); diff --git a/src/util/Constants.js b/src/util/Constants.js index 33ceeca14..e03fdf105 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -58,6 +58,7 @@ const Endpoints = exports.Endpoints = { GUILD_BANS: (guildID) => `${Endpoints.GUILD(guildID)}/bans`, GUILD_INTEGRATIONS: (guildID) => `${Endpoints.GUILD(guildID)}/integrations`, GUILD_MEMBERS: (guildID) => `${Endpoints.GUILD(guildID)}/members`, + GUILD_MEMBER: (guildID, memberID) => `${Endpoints.GUILD_MEMBERS(guildID)}/${memberID}`, GUILD_CHANNELS: (guildID) => `${Endpoints.GUILD(guildID)}/channels`, // channels diff --git a/test/random.js b/test/random.js index aeb7147d2..dfe96f699 100644 --- a/test/random.js +++ b/test/random.js @@ -128,6 +128,13 @@ client.on('message', message => { message.author.deleteDM(); } + if (message.content.startsWith('kick')) { + message.guild.member(message.mentions[0]).kick().then(member => { + console.log(member); + message.channel.sendMessage('Kicked!' + member.user.username); + }).catch(console.log); + } + } });