diff --git a/index.d.ts b/index.d.ts index e462d62d3..f48b4b1c0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1205,7 +1205,7 @@ declare namespace Eris { iconURL?: string; explicitContentFilter: number; constructor(data: BaseData, client: Client); - fetchAllMembers(): void; + fetchAllMembers(timeout?: number): Promise; dynamicIconURL(format: string, size: number): string; createChannel(name: string): Promise; createChannel(name: string, type: 0, reason?: string, options?: CreateChannelOptions | string): Promise; diff --git a/lib/gateway/Shard.js b/lib/gateway/Shard.js index 67670dc63..9646ebce2 100644 --- a/lib/gateway/Shard.js +++ b/lib/gateway/Shard.js @@ -144,6 +144,16 @@ class Shard extends EventEmitter { this.connecting = false; this.ready = false; this.preReady = false; + if(this.requestMembersPromise !== undefined) { + for(const guildID in this.requestMembersPromise) { + if(!this.requestMembersPromise.hasOwnProperty(guildID)) { + continue; + } + clearTimeout(this.requestMembersPromise[guildID].timeout); + this.requestMembersPromise[guildID].res(this.requestMembersPromise[guildID].received); + } + } + this.requestMembersPromise = {}; this.getAllUsersCount = {}; this.getAllUsersQueue = []; this.getAllUsersLength = 1; @@ -1138,9 +1148,17 @@ class Shard extends EventEmitter { if(this.getAllUsersCount.hasOwnProperty(guild.id)) { if(this.getAllUsersCount[guild.id] <= 1) { delete this.getAllUsersCount[guild.id]; + if(this.requestMembersPromise.hasOwnProperty(guild.id)) { + clearTimeout(this.requestMembersPromise[guild.id].timeout); + this.requestMembersPromise[guild.id].res(this.requestMembersPromise[guild.id].received + packet.d.members.length); + delete this.requestMembersPromise[guild.id]; + } this.checkReady(); } else { --this.getAllUsersCount[guild.id]; + if(this.requestMembersPromise.hasOwnProperty(guild.id)) { + this.requestMembersPromise[guild.id].received += packet.d.members.length; + } } } @@ -1491,7 +1509,7 @@ class Shard extends EventEmitter { } } - getGuildMembers(guildID, chunkCount) { + getGuildMembers(guildID, chunkCount, timeout) { this.getAllUsersCount[guildID] = chunkCount; if(this.getAllUsersLength + 3 + guildID.length > 4048) { // 4096 - "{\"op\":8,\"d\":{\"guild_id\":[],\"query\":\"\",\"limit\":0}}".length + 1 for lazy comma offset this.requestGuildMembers(this.getAllUsersQueue); @@ -1499,6 +1517,15 @@ class Shard extends EventEmitter { this.getAllUsersLength = 1 + guildID.length + 3; } else if(this.ready) { this.requestGuildMembers([guildID]); + + return new Promise((res) => this.requestMembersPromise[guildID] = { + res: res, + received: 0, + timeout: setTimeout(() => { + res(this.requestMembersPromise[guildID].received); + delete this.requestMembersPromise[guildID]; + }, timeout || this.client.options.requestTimeout) + }); } else { this.getAllUsersQueue.push(guildID); this.getAllUsersLength += guildID.length + 3; diff --git a/lib/structures/Guild.js b/lib/structures/Guild.js index 631c0b697..f8f4dd050 100644 --- a/lib/structures/Guild.js +++ b/lib/structures/Guild.js @@ -195,9 +195,11 @@ class Guild extends Base { /** * Request all guild members from Discord + * @arg {Number} [timeout] The number of milliseconds to wait before resolving early. Defaults to the `requestTimeout` client option + * @returns {Promise} Resolves with the total number of fetched members. */ - fetchAllMembers() { - this.shard.getGuildMembers(this.id, Math.ceil(this.memberCount / 1000)); // TODO Promise with chunk timeout + fetchAllMembers(timeout) { + return this.shard.getGuildMembers(this.id, Math.ceil(this.memberCount / 1000), timeout); } get iconURL() {