Skip to content

Commit

Permalink
Merge pull request #2 from discordjs/master
Browse files Browse the repository at this point in the history
dd
  • Loading branch information
wonderlandpark authored Oct 16, 2020
2 parents 1e63f37 + d234165 commit 65c9ef2
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 87 deletions.
2 changes: 1 addition & 1 deletion src/client/actions/Action.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class GenericAction {
}

getUserFromMember(data) {
if (data.guild_id) {
if (data.guild_id && data.member && data.member.user) {
const guild = this.client.guilds.cache.get(data.guild_id);
if (guild) {
const member = this.getMember(data.member, guild);
Expand Down
2 changes: 2 additions & 0 deletions src/errors/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ const Messages = {
SHARDING_IN_PROCESS: 'Shards are still being spawned.',
SHARDING_ALREADY_SPAWNED: count => `Already spawned ${count} shards.`,
SHARDING_PROCESS_EXISTS: id => `Shard ${id} already has an active process.`,
SHARDING_WORKER_EXISTS: id => `Shard ${id} already has an active worker.`,
SHARDING_READY_TIMEOUT: id => `Shard ${id}'s Client took too long to become ready.`,
SHARDING_READY_DISCONNECTED: id => `Shard ${id}'s Client disconnected before becoming ready.`,
SHARDING_READY_DIED: id => `Shard ${id}'s process exited before its Client became ready.`,
SHARDING_NO_CHILD_EXISTS: id => `Shard ${id} has no active process or worker.`,

COLOR_RANGE: 'Color must be within the range 0 - 16777215 (0xFFFFFF).',
COLOR_CONVERT: 'Unable to convert color to a number.',
Expand Down
13 changes: 12 additions & 1 deletion src/managers/GuildManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const GuildMember = require('../structures/GuildMember');
const Invite = require('../structures/Invite');
const Role = require('../structures/Role');
const {
ChannelTypes,
Events,
VerificationLevels,
DefaultMessageNotifications,
Expand Down Expand Up @@ -129,6 +130,8 @@ class GuildManager extends BaseManager {
* <warn>This is only available to bots in fewer than 10 guilds.</warn>
* @param {string} name The name of the guild
* @param {Object} [options] Options for the creating
* @param {number} [options.afkChannelID] The ID of the AFK channel
* @param {number} [options.afkTimeout] The AFK timeout in seconds
* @param {PartialChannelData[]} [options.channels] The channels for this guild
* @param {DefaultMessageNotifications} [options.defaultMessageNotifications] The default message notifications
* for the guild
Expand All @@ -137,18 +140,22 @@ class GuildManager extends BaseManager {
* @param {string} [options.region] The region for the server, defaults to the closest one available
* @param {PartialRoleData[]} [options.roles] The roles for this guild,
* the first element of this array is used to change properties of the guild's everyone role.
* @param {number} [options.systemChannelID] The ID of the system channel
* @param {VerificationLevel} [options.verificationLevel] The verification level for the guild
* @returns {Promise<Guild>} The guild that was created
*/
async create(
name,
{
afkChannelID,
afkTimeout,
channels = [],
defaultMessageNotifications,
explicitContentFilter,
icon = null,
region,
roles = [],
systemChannelID,
verificationLevel,
} = {},
) {
Expand All @@ -163,6 +170,7 @@ class GuildManager extends BaseManager {
explicitContentFilter = ExplicitContentFilterLevels.indexOf(explicitContentFilter);
}
for (const channel of channels) {
if (channel.type) channel.type = ChannelTypes[channel.type.toUpperCase()];
channel.parent_id = channel.parentID;
delete channel.parentID;
if (!channel.permissionOverwrites) continue;
Expand All @@ -187,8 +195,11 @@ class GuildManager extends BaseManager {
verification_level: verificationLevel,
default_message_notifications: defaultMessageNotifications,
explicit_content_filter: explicitContentFilter,
channels,
roles,
channels,
afk_channel_id: afkChannelID,
afk_timeout: afkTimeout,
system_channel_id: systemChannelID,
},
})
.then(data => {
Expand Down
7 changes: 4 additions & 3 deletions src/managers/MessageManager.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const BaseManager = require('./BaseManager');
const { TypeError } = require('../errors');
const Message = require('../structures/Message');
const Collection = require('../util/Collection');
const LimitedCollection = require('../util/LimitedCollection');
Expand Down Expand Up @@ -120,9 +121,9 @@ class MessageManager extends BaseManager {
*/
async delete(message, reason) {
message = this.resolveID(message);
if (message) {
await this.client.api.channels(this.channel.id).messages(message).delete({ reason });
}
if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable');

await this.client.api.channels(this.channel.id).messages(message).delete({ reason });
}

async _fetchId(messageID, cache, force) {
Expand Down
14 changes: 7 additions & 7 deletions src/managers/ReactionUserManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ class ReactionUserManager extends BaseManager {

/**
* Removes a user from this reaction.
* @param {UserResolvable} [user=this.reaction.message.client.user] The user to remove the reaction of
* @param {UserResolvable} [user=this.client.user] The user to remove the reaction of
* @returns {Promise<MessageReaction>}
*/
remove(user = this.reaction.message.client.user) {
const message = this.reaction.message;
const userID = message.client.users.resolveID(user);
remove(user = this.client.user) {
const userID = this.client.users.resolveID(user);
if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER'));
return message.client.api.channels[message.channel.id].messages[message.id].reactions[
this.reaction.emoji.identifier
][userID === message.client.user.id ? '@me' : userID]
const message = this.reaction.message;
return this.client.api.channels[message.channel.id].messages[message.id].reactions[this.reaction.emoji.identifier][
userID === this.client.user.id ? '@me' : userID
]
.delete()
.then(() => this.reaction);
}
Expand Down
1 change: 1 addition & 0 deletions src/rest/APIRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class APIRequest {
this.method = method;
this.route = options.route;
this.options = options;
this.retries = 0;

let queryString = '';
if (options.query) {
Expand Down
95 changes: 95 additions & 0 deletions src/rest/AsyncQueue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* MIT License
*
* Copyright (c) 2020 kyranet, discord.js
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

'use strict';

// TODO(kyranet, vladfrangu): replace this with discord.js v13's core AsyncQueue.

/**
* An async queue that preserves the stack and prevents lock-ups.
* @private
*/
class AsyncQueue {
constructor() {
/**
* The promises array.
* @type {Array<{promise: Promise<void>, resolve: Function}>}
* @private
*/
this.promises = [];
}

/**
* The remaining amount of queued promises
* @type {number}
*/
get remaining() {
return this.promises.length;
}

/**
* Waits for last promise and queues a new one.
* @returns {Promise<void>}
* @example
* const queue = new AsyncQueue();
* async function request(url, options) {
* await queue.wait();
* try {
* const result = await fetch(url, options);
* // Do some operations with 'result'
* } finally {
* // Remove first entry from the queue and resolve for the next entry
* queue.shift();
* }
* }
*
* request(someUrl1, someOptions1); // Will call fetch() immediately
* request(someUrl2, someOptions2); // Will call fetch() after the first finished
* request(someUrl3, someOptions3); // Will call fetch() after the second finished
*/
wait() {
const next = this.promises.length ? this.promises[this.promises.length - 1].promise : Promise.resolve();
let resolve;
const promise = new Promise(res => {
resolve = res;
});

this.promises.push({
resolve,
promise,
});

return next;
}

/**
* Frees the queue's lock for the next item to process.
*/
shift() {
const deferred = this.promises.shift();
if (typeof deferred !== 'undefined') deferred.resolve();
}
}

module.exports = AsyncQueue;
15 changes: 1 addition & 14 deletions src/rest/RESTManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,6 @@ class RESTManager {
return Endpoints.CDN(this.client.options.http.cdn);
}

push(handler, apiRequest) {
return new Promise((resolve, reject) => {
handler
.push({
request: apiRequest,
resolve,
reject,
retries: 0,
})
.catch(reject);
});
}

request(method, url, options = {}) {
const apiRequest = new APIRequest(this, method, url, options);
let handler = this.handlers.get(apiRequest.route);
Expand All @@ -57,7 +44,7 @@ class RESTManager {
this.handlers.set(apiRequest.route, handler);
}

return this.push(handler, apiRequest);
return handler.push(apiRequest);
}

get endpoint() {
Expand Down
Loading

0 comments on commit 65c9ef2

Please sign in to comment.