@@ -4,8 +4,9 @@ const { process } = require('node:process');
44const { setTimeout, clearTimeout } = require ( 'node:timers' ) ;
55const { Collection } = require ( '@discordjs/collection' ) ;
66const { makeURLSearchParams } = require ( '@discordjs/rest' ) ;
7+ const { GatewayRateLimitError } = require ( '@discordjs/util' ) ;
78const { DiscordSnowflake } = require ( '@sapphire/snowflake' ) ;
8- const { Routes, GatewayOpcodes } = require ( 'discord-api-types/v10' ) ;
9+ const { Routes, GatewayOpcodes, GatewayDispatchEvents } = require ( 'discord-api-types/v10' ) ;
910const CachedManager = require ( './CachedManager' ) ;
1011const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = require ( '../errors' ) ;
1112const BaseGuildVoiceChannel = require ( '../structures/BaseGuildVoiceChannel' ) ;
@@ -239,19 +240,25 @@ class GuildMemberManager extends CachedManager {
239240
240241 return new Promise ( ( resolve , reject ) => {
241242 if ( ! query && ! users ) query = '' ;
242- this . guild . shard . send ( {
243- op : GatewayOpcodes . RequestGuildMembers ,
244- d : {
245- guild_id : this . guild . id ,
246- presences,
247- user_ids : users ,
248- query,
249- nonce,
250- limit,
251- } ,
252- } ) ;
253243 const fetchedMembers = new Collection ( ) ;
254244 let i = 0 ;
245+
246+ const cleanup = ( ) => {
247+ /* eslint-disable no-use-before-define */
248+ clearTimeout ( timeout ) ;
249+
250+ this . client . removeListener ( Events . Raw , rateLimitHandler ) ;
251+ this . client . decrementMaxListeners ( ) ;
252+ this . client . removeListener ( Events . GuildMembersChunk , handler ) ;
253+ this . client . decrementMaxListeners ( ) ;
254+ /* eslint-enable no-use-before-define */
255+ } ;
256+
257+ const timeout = setTimeout ( ( ) => {
258+ cleanup ( ) ;
259+ reject ( new DiscordjsError ( ErrorCodes . GuildMembersTimeout ) ) ;
260+ } , time ) . unref ( ) ;
261+
255262 const handler = ( members , _ , chunk ) => {
256263 if ( chunk . nonce !== nonce ) return ;
257264 timeout . refresh ( ) ;
@@ -260,19 +267,37 @@ class GuildMemberManager extends CachedManager {
260267 fetchedMembers . set ( member . id , member ) ;
261268 }
262269 if ( members . size < 1_000 || ( limit && fetchedMembers . size >= limit ) || i === chunk . count ) {
263- clearTimeout ( timeout ) ;
264- this . client . removeListener ( Events . GuildMembersChunk , handler ) ;
265- this . client . decrementMaxListeners ( ) ;
270+ cleanup ( ) ;
266271 resolve ( users && ! Array . isArray ( users ) && fetchedMembers . size ? fetchedMembers . first ( ) : fetchedMembers ) ;
267272 }
268273 } ;
269- const timeout = setTimeout ( ( ) => {
270- this . client . removeListener ( Events . GuildMembersChunk , handler ) ;
271- this . client . decrementMaxListeners ( ) ;
272- reject ( new DiscordjsError ( ErrorCodes . GuildMembersTimeout ) ) ;
273- } , time ) . unref ( ) ;
274+
275+ const requestData = {
276+ guild_id : this . guild . id ,
277+ presences,
278+ user_ids : users ,
279+ query,
280+ nonce,
281+ limit,
282+ } ;
283+
284+ const rateLimitHandler = payload => {
285+ if ( payload . t === GatewayDispatchEvents . RateLimited && payload . d . meta . nonce === nonce ) {
286+ cleanup ( ) ;
287+ reject ( new GatewayRateLimitError ( payload . d , requestData ) ) ;
288+ }
289+ } ;
290+
291+ this . client . incrementMaxListeners ( ) ;
292+ this . client . on ( Events . Raw , rateLimitHandler ) ;
293+
274294 this . client . incrementMaxListeners ( ) ;
275295 this . client . on ( Events . GuildMembersChunk , handler ) ;
296+
297+ this . guild . shard . send ( {
298+ op : GatewayOpcodes . RequestGuildMembers ,
299+ d : requestData ,
300+ } ) ;
276301 } ) ;
277302 }
278303
0 commit comments