mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor(client)!: remove BaseClient (#11274)
BREAKING CHANGE: `BaseClient` has been removed and its functionality has been merged into `Client`.
This commit is contained in:
@@ -1,131 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { REST, RESTEvents } = require('@discordjs/rest');
|
||||
const { AsyncEventEmitter } = require('@vladfrangu/async_event_emitter');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
|
||||
const { Events } = require('../util/Events.js');
|
||||
const { Options } = require('../util/Options.js');
|
||||
const { flatten } = require('../util/Util.js');
|
||||
|
||||
/**
|
||||
* The base class for all clients.
|
||||
*
|
||||
* @extends {AsyncEventEmitter}
|
||||
*/
|
||||
class BaseClient extends AsyncEventEmitter {
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
if (typeof options !== 'object' || options === null) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
}
|
||||
|
||||
const defaultOptions = Options.createDefault();
|
||||
/**
|
||||
* The options the client was instantiated with
|
||||
*
|
||||
* @type {ClientOptions}
|
||||
*/
|
||||
this.options = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
presence: {
|
||||
...defaultOptions.presence,
|
||||
...options.presence,
|
||||
},
|
||||
sweepers: {
|
||||
...defaultOptions.sweepers,
|
||||
...options.sweepers,
|
||||
},
|
||||
ws: {
|
||||
...defaultOptions.ws,
|
||||
...options.ws,
|
||||
},
|
||||
rest: {
|
||||
...defaultOptions.rest,
|
||||
...options.rest,
|
||||
userAgentAppendix: options.rest?.userAgentAppendix
|
||||
? `${Options.userAgentAppendix} ${options.rest.userAgentAppendix}`
|
||||
: Options.userAgentAppendix,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* The REST manager of the client
|
||||
*
|
||||
* @type {REST}
|
||||
*/
|
||||
this.rest = new REST(this.options.rest);
|
||||
|
||||
this.rest.on(RESTEvents.Debug, message => this.emit(Events.Debug, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys all assets used by the base client.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
destroy() {
|
||||
this.rest.clearHashSweeper();
|
||||
this.rest.clearHandlerSweeper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for deleting a webhook.
|
||||
*
|
||||
* @typedef {Object} WebhookDeleteOptions
|
||||
* @property {string} [token] Token of the webhook
|
||||
* @property {string} [reason] The reason for deleting the webhook
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deletes a webhook.
|
||||
*
|
||||
* @param {Snowflake} id The webhook's id
|
||||
* @param {WebhookDeleteOptions} [options] Options for deleting the webhook
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async deleteWebhook(id, { token, reason } = {}) {
|
||||
await this.rest.delete(Routes.webhook(id, token), { auth: !token, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments max listeners by one, if they are not zero.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
incrementMaxListeners() {
|
||||
const maxListeners = this.getMaxListeners();
|
||||
if (maxListeners !== 0) {
|
||||
this.setMaxListeners(maxListeners + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements max listeners by one, if they are not zero.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
decrementMaxListeners() {
|
||||
const maxListeners = this.getMaxListeners();
|
||||
if (maxListeners !== 0) {
|
||||
this.setMaxListeners(maxListeners - 1);
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(...props) {
|
||||
return flatten(this, ...props);
|
||||
}
|
||||
|
||||
async [Symbol.asyncDispose]() {
|
||||
await this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.BaseClient = BaseClient;
|
||||
|
||||
/**
|
||||
* @external REST
|
||||
* @see {@link https://discord.js.org/docs/packages/rest/stable/REST:Class}
|
||||
*/
|
||||
@@ -3,8 +3,9 @@
|
||||
const process = require('node:process');
|
||||
const { clearTimeout, setImmediate, setTimeout } = require('node:timers');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { REST, RESTEvents, makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { WebSocketManager, WebSocketShardEvents, WebSocketShardStatus } = require('@discordjs/ws');
|
||||
const { AsyncEventEmitter } = require('@vladfrangu/async_event_emitter');
|
||||
const { GatewayDispatchEvents, GatewayIntentBits, OAuth2Scopes, Routes } = require('discord-api-types/v10');
|
||||
const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
|
||||
const { ChannelManager } = require('../managers/ChannelManager.js');
|
||||
@@ -28,7 +29,7 @@ const { Options } = require('../util/Options.js');
|
||||
const { PermissionsBitField } = require('../util/PermissionsBitField.js');
|
||||
const { Status } = require('../util/Status.js');
|
||||
const { Sweepers } = require('../util/Sweepers.js');
|
||||
const { BaseClient } = require('./BaseClient.js');
|
||||
const { flatten } = require('../util/Util.js');
|
||||
const { ActionsManager } = require('./actions/ActionsManager.js');
|
||||
const { ClientVoiceManager } = require('./voice/ClientVoiceManager.js');
|
||||
const { PacketHandlers } = require('./websocket/handlers/index.js');
|
||||
@@ -47,24 +48,66 @@ const BeforeReadyWhitelist = [
|
||||
/**
|
||||
* The main hub for interacting with the Discord API, and the starting point for any bot.
|
||||
*
|
||||
* @extends {BaseClient}
|
||||
* @extends {AsyncEventEmitter}
|
||||
*/
|
||||
class Client extends BaseClient {
|
||||
class Client extends AsyncEventEmitter {
|
||||
/**
|
||||
* @param {ClientOptions} options Options for the client
|
||||
*/
|
||||
constructor(options) {
|
||||
super(options);
|
||||
super();
|
||||
|
||||
if (typeof options !== 'object' || options === null) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
}
|
||||
|
||||
const defaultOptions = Options.createDefault();
|
||||
/**
|
||||
* The options the client was instantiated with
|
||||
*
|
||||
* @type {ClientOptions}
|
||||
*/
|
||||
this.options = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
presence: {
|
||||
...defaultOptions.presence,
|
||||
...options.presence,
|
||||
},
|
||||
sweepers: {
|
||||
...defaultOptions.sweepers,
|
||||
...options.sweepers,
|
||||
},
|
||||
ws: {
|
||||
...defaultOptions.ws,
|
||||
...options.ws,
|
||||
},
|
||||
rest: {
|
||||
...defaultOptions.rest,
|
||||
...options.rest,
|
||||
userAgentAppendix: options.rest?.userAgentAppendix
|
||||
? `${Options.userAgentAppendix} ${options.rest.userAgentAppendix}`
|
||||
: Options.userAgentAppendix,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* The REST manager of the client
|
||||
*
|
||||
* @type {REST}
|
||||
*/
|
||||
this.rest = new REST(this.options.rest);
|
||||
|
||||
this.rest.on(RESTEvents.Debug, message => this.emit(Events.Debug, message));
|
||||
|
||||
const data = require('node:worker_threads').workerData ?? process.env;
|
||||
const defaults = Options.createDefault();
|
||||
|
||||
if (this.options.ws.shardIds === defaults.ws.shardIds && 'SHARDS' in data) {
|
||||
if (this.options.ws.shardIds === defaultOptions.ws.shardIds && 'SHARDS' in data) {
|
||||
const shards = JSON.parse(data.SHARDS);
|
||||
this.options.ws.shardIds = Array.isArray(shards) ? shards : [shards];
|
||||
}
|
||||
|
||||
if (this.options.ws.shardCount === defaults.ws.shardCount && 'SHARD_COUNT' in data) {
|
||||
if (this.options.ws.shardCount === defaultOptions.ws.shardCount && 'SHARD_COUNT' in data) {
|
||||
this.options.ws.shardCount = Number(data.SHARD_COUNT);
|
||||
}
|
||||
|
||||
@@ -442,12 +485,56 @@ class Client extends BaseClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out, terminates the connection to Discord, and destroys the client.
|
||||
* Options used for deleting a webhook.
|
||||
*
|
||||
* @typedef {Object} WebhookDeleteOptions
|
||||
* @property {string} [token] Token of the webhook
|
||||
* @property {string} [reason] The reason for deleting the webhook
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deletes a webhook.
|
||||
*
|
||||
* @param {Snowflake} id The webhook's id
|
||||
* @param {WebhookDeleteOptions} [options] Options for deleting the webhook
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async deleteWebhook(id, { token, reason } = {}) {
|
||||
await this.rest.delete(Routes.webhook(id, token), { auth: !token, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments max listeners by one, if they are not zero.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
incrementMaxListeners() {
|
||||
const maxListeners = this.getMaxListeners();
|
||||
if (maxListeners !== 0) {
|
||||
this.setMaxListeners(maxListeners + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements max listeners by one, if they are not zero.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
decrementMaxListeners() {
|
||||
const maxListeners = this.getMaxListeners();
|
||||
if (maxListeners !== 0) {
|
||||
this.setMaxListeners(maxListeners - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys all assets used by the client.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async destroy() {
|
||||
super.destroy();
|
||||
this.rest.clearHashSweeper();
|
||||
this.rest.clearHandlerSweeper();
|
||||
|
||||
this.sweepers.destroy();
|
||||
await this.ws.destroy();
|
||||
@@ -701,10 +788,7 @@ class Client extends BaseClient {
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return super.toJSON({
|
||||
actions: false,
|
||||
presence: false,
|
||||
});
|
||||
return flatten(this, { actions: false, presence: false });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -797,6 +881,10 @@ class Client extends BaseClient {
|
||||
throw new DiscordjsTypeError(ErrorCodes.ClientInvalidOption, 'jsonTransformer', 'a function');
|
||||
}
|
||||
}
|
||||
|
||||
async [Symbol.asyncDispose]() {
|
||||
await this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
exports.Client = Client;
|
||||
@@ -846,6 +934,11 @@ exports.Client = Client;
|
||||
* @see {@link https://discord.js.org/docs/packages/collection/stable/Collection:Class}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external REST
|
||||
* @see {@link https://discord.js.org/docs/packages/rest/stable/REST:Class}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external ImageURLOptions
|
||||
* @see {@link https://discord.js.org/docs/packages/rest/stable/ImageURLOptions:Interface}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
const { __exportStar } = require('tslib');
|
||||
|
||||
// "Root" classes (starting points)
|
||||
exports.BaseClient = require('./client/BaseClient.js').BaseClient;
|
||||
exports.Client = require('./client/Client.js').Client;
|
||||
exports.Shard = require('./sharding/Shard.js').Shard;
|
||||
exports.ShardClientUtil = require('./sharding/ShardClientUtil.js').ShardClientUtil;
|
||||
|
||||
21
packages/discord.js/typings/index.d.ts
vendored
21
packages/discord.js/typings/index.d.ts
vendored
@@ -492,18 +492,6 @@ export abstract class Base {
|
||||
public valueOf(): string;
|
||||
}
|
||||
|
||||
export class BaseClient<Events extends {}> extends AsyncEventEmitter<Events> implements AsyncDisposable {
|
||||
public constructor(options?: ClientOptions);
|
||||
private decrementMaxListeners(): void;
|
||||
private incrementMaxListeners(): void;
|
||||
|
||||
public options: ClientOptions;
|
||||
public rest: REST;
|
||||
public destroy(): void;
|
||||
public toJSON(...props: Record<string, boolean | string>[]): unknown;
|
||||
public [Symbol.asyncDispose](): Promise<void>;
|
||||
}
|
||||
|
||||
export type GuildCacheMessage<Cached extends CacheType> = CacheTypeReducer<
|
||||
Cached,
|
||||
Message<true>,
|
||||
@@ -913,7 +901,10 @@ export type If<Value extends boolean, TrueResult, FalseResult = null> = Value ex
|
||||
? FalseResult
|
||||
: FalseResult | TrueResult;
|
||||
|
||||
export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEventTypes> {
|
||||
export class Client<Ready extends boolean = boolean>
|
||||
extends AsyncEventEmitter<ClientEventTypes>
|
||||
implements AsyncDisposable
|
||||
{
|
||||
public constructor(options: ClientOptions);
|
||||
private readonly actions: unknown;
|
||||
private readonly expectedGuilds: Set<Snowflake>;
|
||||
@@ -928,6 +919,8 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
|
||||
private _triggerClientReady(): void;
|
||||
private _validateOptions(options: ClientOptions): void;
|
||||
private get _censoredToken(): string | null;
|
||||
private decrementMaxListeners(): void;
|
||||
private incrementMaxListeners(): void;
|
||||
// This a technique used to brand the ready state. Or else we'll get `never` errors on typeguard checks.
|
||||
private readonly _ready: Ready;
|
||||
|
||||
@@ -939,6 +932,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
|
||||
public get ping(): number | null;
|
||||
public get readyAt(): If<Ready, Date>;
|
||||
public readyTimestamp: If<Ready, number>;
|
||||
public rest: REST;
|
||||
public sweepers: Sweepers;
|
||||
public shard: ShardClientUtil | null;
|
||||
public status: Status;
|
||||
@@ -969,6 +963,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient<ClientEv
|
||||
public login(token?: string): Promise<string>;
|
||||
public isReady(): this is Client<true>;
|
||||
public toJSON(): unknown;
|
||||
public [Symbol.asyncDispose](): Promise<void>;
|
||||
}
|
||||
|
||||
export interface StickerPackFetchOptions {
|
||||
|
||||
Reference in New Issue
Block a user