Skip to content
This repository has been archived by the owner on Apr 27, 2024. It is now read-only.

refactor: change around GuildMemberStore a lot #276

Closed
wants to merge 9 commits into from
134 changes: 124 additions & 10 deletions src/lib/caching/stores/GuildMemberStore.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable no-dupe-class-members */
import { Cache } from '@klasa/cache';
import { ProxyCache } from '@klasa/cache';
import { DataStore } from './base/DataStore';
import { extender } from '../../util/Extender';
import { Routes, RequestOptions } from '@klasa/rest';
import { RequestGuildMembers, OpCodes, GuildMembersChunkDispatch } from '@klasa/ws';
import { EventIterator } from '@klasa/event-iterator';

import type { APIUserData, APIGuildMemberData } from '@klasa/dapi-types';
import type { Client } from '../../client/Client';
Expand Down Expand Up @@ -67,11 +69,11 @@ export class GuildMemberStore extends DataStore<GuildMember> {
/**
* Returns up to 1000 {@link GuildMember members}.
* @since 0.0.1
* @param userID The {@link User user} ID to fetch.
* @see https://discord.com/developers/docs/resources/guild#list-guild-members
* @param options The {@link GuildMemberStoreFetchOptions options} used to fetch.
* @see https://discord.com/developers/docs/topics/gateway#request-guild-members
*/
public fetch(options?: GuildMemberStoreFetchOptions): Promise<Cache<string, GuildMember>>;
public async fetch(idOrOptions?: string | GuildMemberStoreFetchOptions): Promise<GuildMember | Cache<string, GuildMember>> {
public fetch(options?: GuildMemberStoreFetchOptions): Promise<ProxyCache<string, GuildMember>>;
public async fetch(idOrOptions?: string | GuildMemberStoreFetchOptions): Promise<GuildMember | ProxyCache<string, GuildMember>> {
if (typeof idOrOptions === 'string') {
const previous = this.get(idOrOptions);
if (previous) return previous;
Expand All @@ -80,13 +82,75 @@ export class GuildMemberStore extends DataStore<GuildMember> {
return this._add(member);
}

const entries = await this.client.api.get(Routes.guildMembers(this.guild.id), { data: idOrOptions }) as APIGuildMemberData[];
if (typeof idOrOptions === 'undefined') idOrOptions = {};

const { query = '', userIDs, presences, limit = 0, nonce = Date.now().toString(16) } = idOrOptions;

/* eslint-disable id-length */
const options: RequestGuildMembers = {
op: OpCodes.REQUEST_GUILD_MEMBERS,
d: {
/* eslint-disable camelcase */
guild_id: this.guild.id,
user_ids: userIDs,
/* eslint-enable camelcase */
query,
presences,
limit,
nonce
}
};

this.guild.shard.send(options);

let i = 0;
// const cache = new Cache<string, GuildMember>();
const cache = new ProxyCache<string, GuildMember>(this);
for await (const [{ d }] of new EventIterator<[GuildMembersChunkDispatch]>(this.client.ws, 'GUILD_MEMBERS_CHUNK', {
filter: ([{ d: data }]): boolean => data.nonce === nonce && data.guild_id === this.guild.id
})) {
if (i === d.chunk_count) break;
i++;
for (const rawMember of d.members) {
const member = this._add(rawMember);
cache.set(member.id);
}
}
/* eslint-enable id-length */

const cache = new Cache<string, GuildMember>();
return cache;
}

/**
* TBD
* @param options
*/
public async search(data: GuildMemberStoreSearchOptions): Promise<ProxyCache<string, GuildMember>> {
const members = await this.client.api.get(Routes.guildMembersSearch(this.guild.id), { data }) as APIGuildMemberData[];
const cache = new ProxyCache<string, GuildMember>(this);
for (const rawMember of members) {
const member = this._add(rawMember);
cache.set(member.id);
}

return cache;
}

/**
* Returns up to 1000 {@link GuildMember members}.
* @since 0.0.3
* @param options The {@link GuildMemberStoreListOptions options} used to fetch.
* @see https://discord.com/developers/docs/resources/guild#list-guild-members
*/
public async list(options: GuildMemberStoreListOptions): Promise<ProxyCache<string, GuildMember>> {
const entries = await this.client.api.get(Routes.guildMembers(this.guild.id), { data: options }) as APIGuildMemberData[];

const cache = new ProxyCache<string, GuildMember>(this);
for (const entry of entries) {
const member = this._add(entry);
cache.set(member.id, member);
cache.set(member.id);
}

return cache;
}

Expand Down Expand Up @@ -170,11 +234,11 @@ export interface GuildMemberStoreAddData {
}

/**
* The options for {@link GuildMemberStore#fetch}.
* The options for {@link GuildMemberStore#list}.
* @since 0.0.1
* @see https://discord.com/developers/docs/resources/guild#list-guild-members-query-string-params
*/
export interface GuildMemberStoreFetchOptions {
export interface GuildMemberStoreListOptions {
/**
* Max number of members to return (1-1000).
* @since 0.0.1
Expand All @@ -188,4 +252,54 @@ export interface GuildMemberStoreFetchOptions {
after?: string;
}

/**
* The options for {@link GuildMemberStore#fetch} when fetching many.
* @since 0.0.3
* @see https://discord.com/developers/docs/topics/gateway#request-guild-members
*/
export interface GuildMemberStoreFetchOptions {
/**
* The query to fetch members with, will be used to search via nicknames.
* @since 0.0.3
*/
query?: string;
/**
* The number of members to fetch.
* @since 0.0.3
*/
limit?: number;
/**
* Whether to include presences with the request.
* @since 0.0.3
*/
presences?: boolean;
/**
* The user ID(s) to search for.
* @since 0.0.3
*/
userIDs?: string | string[];
/**
* The unique nonce to look for, this is mainly used internally.
* @since 0.0.3
* @internal
*/
nonce?: string;
}

/**
* The options for {@link GuildMemberStore#search}.
* @since 0.0.3
*/
export interface GuildMemberStoreSearchOptions {
/**
* The query to search for.
* @since 0.0.3
*/
query: string;
/**
* The limit for fetching members.
*/
limit?: number;
}

/* eslint-enable camelcase */