From c3d7235918bc85448fa7b06be5480e1afa68a2b6 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:57:49 +0000 Subject: [PATCH] feat(handlers): add getMembers() (#412) * Update guild.ts * add types * forgot to import * review things * Update mod.ts * Apply suggestions from code review Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> * remove redundant code * Update guild.ts * Paginate * remove extra () * dont log if limit is < 1000 * thats unnecessary too * Update guild.ts * add sugg Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> --- src/api/handlers/guild.ts | 62 +++++++++++++++++++++++++++++++++++++++ src/api/handlers/mod.ts | 2 ++ src/types/guild.ts | 7 +++++ 3 files changed, 71 insertions(+) diff --git a/src/api/handlers/guild.ts b/src/api/handlers/guild.ts index 9757dd2d6..a5f3fbf90 100644 --- a/src/api/handlers/guild.ts +++ b/src/api/handlers/guild.ts @@ -20,6 +20,7 @@ import { Errors, FetchMembersOptions, GetAuditLogsOptions, + GetMemberOptions, GuildEditOptions, GuildTemplate, ImageFormats, @@ -580,6 +581,67 @@ export function fetchMembers(guild: Guild, options?: FetchMembersOptions) { }) as Promise>; } +/** + * ⚠️ BEGINNER DEVS!! YOU SHOULD ALMOST NEVER NEED THIS AND YOU CAN GET FROM cache.members.get() + * + * ADVANCED: + * Highly recommended to **NOT** use this function to get members instead use fetchMembers(). + * REST(this function): 50/s global(across all shards) rate limit with ALL requests this included + * GW(fetchMembers): 120/m(PER shard) rate limit. Meaning if you have 8 shards your limit is 960/m. +*/ +export async function getMembers( + guildID: string, + options?: GetMemberOptions, +) { + if (!(identifyPayload.intents && Intents.GUILD_MEMBERS)) { + throw new Error(Errors.MISSING_INTENT_GUILD_MEMBERS); + } + + const guild = await cacheHandlers.get("guilds", guildID); + if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); + + const members = new Collection(); + + let membersLeft = options?.limit ?? guild.memberCount; + let loops = 1; + while ( + (options?.limit ?? guild.memberCount) > members.size && membersLeft > 0 + ) { + if (options?.limit && options.limit > 1000) { + console.log( + `Paginating get members from REST. #${loops} / ${ + Math.ceil((options?.limit ?? 1) / 1000) + }`, + ); + } + + const result = await RequestManager.get( + `${endpoints.GUILD_MEMBERS(guildID)}?limit=${ + membersLeft > 1000 ? 1000 : membersLeft + }${options?.after ? `&after=${options.after}` : ""}`, + ) as MemberCreatePayload[]; + + const memberStructures = await Promise.all( + result.map((member) => structures.createMember(member, guildID)), + ) as Member[]; + + if (!memberStructures.length) break; + + memberStructures.forEach((member) => members.set(member.id, member)); + + options = { + limit: options?.limit, + after: memberStructures[memberStructures.length - 1].id, + }; + + membersLeft -= 1000; + + loops++; + } + + return members; +} + /** Returns the audit logs for the guild. Requires VIEW AUDIT LOGS permission */ export async function getAuditLogs( guildID: string, diff --git a/src/api/handlers/mod.ts b/src/api/handlers/mod.ts index 93083ba57..ddd9070a0 100644 --- a/src/api/handlers/mod.ts +++ b/src/api/handlers/mod.ts @@ -57,6 +57,7 @@ import { getIntegrations, getInvites, getMember, + getMembers, getMembersByQuery, getPruneCount, getRoles, @@ -183,6 +184,7 @@ export let handlers = { getIntegrations, getInvites, getMember, + getMembers, getTemplate, getMembersByQuery, getPruneCount, diff --git a/src/types/guild.ts b/src/types/guild.ts index 9b43877b7..a9b2faaad 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -608,6 +608,13 @@ export interface FetchMembersOptions { limit?: number; } +export interface GetMemberOptions { + /** max number of members to return (1-1000), defaults to 1 */ + limit?: number; + /** the highest user id in the previous page */ + after?: string; +} + export interface CreateServerOptions { /** name of the guild (2-100 characters) */ name: string;