import { ClientEvents, ClientOptions, Client as DiscordClient } from 'discord.js'; import { getDiscordVersion, getInfo } from '../other/utils'; import { RefClusterManager } from './clusterManager'; import { ClusterClient } from './clusterClient'; /** Modified ClientEvents such that the ready event has the ShardingClient instead of the normal Client. */ export type ClientEventsModifiable = Omit & { ready: [client: ShardingClient]; clientReady: [client: ShardingClient]; }; export type ShardingClientOptions = ClientOptions; /** Modified DiscordClient with bunch of new methods. */ export class ShardingClient< Ready extends boolean = boolean, InternalManager extends RefClusterManager = RefClusterManager, > extends DiscordClient { /** Cluster associated with this client. */ cluster: ClusterClient; /** Creates an instance of ShardingClient. */ constructor (options: ShardingClientOptions) { super({ ...options, shards: getInfo().ShardList, shardCount: getInfo().TotalShards, }); this.cluster = new ClusterClient(this); this.shardsReady(); } private async shardsReady() { let readyEvent: 'ready' | 'clientReady' = 'ready'; try { const { major, minor } = await getDiscordVersion('discord.js'); readyEvent = major > 14 || (major === 14 && minor >= 22) ? 'clientReady' : 'ready'; } catch { readyEvent = 'ready'; } this.once(readyEvent, () => this.cluster.triggerReady()); } } export type RefShardingClient = ShardingClient; export declare interface ShardingClient { /** Emit an event. */ emit: ((event: K, ...args: ClientEventsModifiable[K]) => boolean) & ((event: Exclude, ...args: unknown[]) => boolean); /** Remove an event listener. */ off: ((event: K, listener: (...args: ClientEventsModifiable[K]) => void) => this) & ((event: Exclude, listener: (...args: unknown[]) => void) => this); /** Listen for an event. */ on: ((event: K, listener: (...args: ClientEventsModifiable[K]) => void) => this) & ((event: Exclude, listener: (...args: unknown[]) => void) => this); /** Listen for an event once. */ once: ((event: K, listener: (...args: ClientEventsModifiable[K]) => void) => this) & ((event: Exclude, listener: (...args: unknown[]) => void) => this); /** Remove all listeners for an event. */ removeAllListeners: ((event?: K) => this) & ((event?: Exclude) => this); }