Downgrade to v13

[vi] cảm giác đau khổ
This commit is contained in:
March 7th
2022-03-24 17:55:32 +07:00
parent 9596b1a210
commit 7dfdef46a5
218 changed files with 8584 additions and 9108 deletions

View File

@@ -1,8 +1,8 @@
'use strict';
const process = require('node:process');
const { setInterval } = require('node:timers');
const { Collection } = require('@discordjs/collection');
const { OAuth2Scopes, Routes } = require('discord-api-types/v9');
const BaseClient = require('./BaseClient');
const ActionsManager = require('./actions/ActionsManager');
const ClientVoiceManager = require('./voice/ClientVoiceManager');
@@ -12,9 +12,6 @@ const BaseGuildEmojiManager = require('../managers/BaseGuildEmojiManager');
const ChannelManager = require('../managers/ChannelManager');
const GuildManager = require('../managers/GuildManager');
const UserManager = require('../managers/UserManager');
const FriendsManager = require('../managers/FriendsManager');
const BlockedManager = require('../managers/BlockedManager');
const ClientUserSettingManager = require('../managers/ClientUserSettingManager');
const ShardClientUtil = require('../sharding/ShardClientUtil');
const ClientPresence = require('../structures/ClientPresence');
const GuildPreview = require('../structures/GuildPreview');
@@ -25,13 +22,16 @@ const StickerPack = require('../structures/StickerPack');
const VoiceRegion = require('../structures/VoiceRegion');
const Webhook = require('../structures/Webhook');
const Widget = require('../structures/Widget');
const { Events, InviteScopes, Status } = require('../util/Constants');
const DataResolver = require('../util/DataResolver');
const Events = require('../util/Events');
const IntentsBitField = require('../util/IntentsBitField');
const Intents = require('../util/Intents');
const Options = require('../util/Options');
const PermissionsBitField = require('../util/PermissionsBitField');
const Status = require('../util/Status');
const Permissions = require('../util/Permissions');
const Sweepers = require('../util/Sweepers');
// Patch
const FriendsManager = require('../managers/FriendsManager');
const BlockedManager = require('../managers/BlockedManager');
const ClientUserSettingManager = require('../managers/ClientUserSettingManager');
/**
* The main hub for interacting with the Discord API, and the starting point for any bot.
@@ -79,6 +79,20 @@ class Client extends BaseClient {
this._validateOptions();
/**
* Functions called when a cache is garbage collected or the Client is destroyed
* @type {Set<Function>}
* @private
*/
this._cleanups = new Set();
/**
* The finalizers used to cleanup items.
* @type {FinalizationRegistry}
* @private
*/
this._finalizers = new FinalizationRegistry(this._finalize.bind(this));
/**
* The WebSocket manager of the client
* @type {WebSocketManager}
@@ -111,6 +125,10 @@ class Client extends BaseClient {
* @type {UserManager}
*/
this.users = new UserManager(this);
/** Patch
*
*/
this.friends = new FriendsManager(this);
this.blocked = new BlockedManager(this);
this.setting = new ClientUserSettingManager(this);
@@ -156,12 +174,6 @@ class Client extends BaseClient {
this.token = null;
}
/**
* used for interacitons
* @type {?String}
*/
this.session_id = null;
/**
* User that the client is logged in as
* @type {?ClientUser}
@@ -173,13 +185,24 @@ class Client extends BaseClient {
* @type {?ClientApplication}
*/
this.application = null;
this.bot = null;
/**
* Timestamp of the time the client was last `READY` at
* @type {?number}
* Time at which the client was last regarded as being in the `READY` state
* (each time the client disconnects and successfully reconnects, this will be overwritten)
* @type {?Date}
*/
this.readyTimestamp = null;
this.readyAt = null;
if (this.options.messageSweepInterval > 0) {
process.emitWarning(
'The message sweeping client options are deprecated, use the global sweepers instead.',
'DeprecationWarning',
);
this.sweepMessageInterval = setInterval(
this.sweepMessages.bind(this),
this.options.messageSweepInterval * 1_000,
).unref();
}
}
/**
@@ -196,13 +219,12 @@ class Client extends BaseClient {
}
/**
* Time at which the client was last regarded as being in the `READY` state
* (each time the client disconnects and successfully reconnects, this will be overwritten)
* @type {?Date}
* Timestamp of the time the client was last `READY` at
* @type {?number}
* @readonly
*/
get readyAt() {
return this.readyTimestamp && new Date(this.readyTimestamp);
get readyTimestamp() {
return this.readyAt?.getTime() ?? null;
}
/**
@@ -211,23 +233,21 @@ class Client extends BaseClient {
* @readonly
*/
get uptime() {
return this.readyTimestamp && Date.now() - this.readyTimestamp;
return this.readyAt ? Date.now() - this.readyAt : null;
}
/**
* Logs the client in, establishing a WebSocket connection to Discord.
* @param {string} [token=this.token] Token of the account to log in with
* @param {Boolean} [bot=false] Wether the token used is a bot account or not
* @returns {Promise<string>} Token of the account used
* @example
* client.login('my token');
*/
async login(token = this.token, bot = false) {
async login(token = this.token) {
if (!token || typeof token !== 'string') throw new Error('TOKEN_INVALID');
this.token = token = token.replace(/^(Bot|Bearer)\s*/i, '');
this.bot = bot;
this.emit(
Events.Debug,
Events.DEBUG,
`Provided token: ${token
.split('.')
.map((val, i) => (i > 1 ? val.replace(/./g, '*') : val))
@@ -238,7 +258,7 @@ class Client extends BaseClient {
this.options.ws.presence = this.presence._parse(this.options.presence);
}
this.emit(Events.Debug, 'Preparing to connect to the gateway...');
this.emit(Events.DEBUG, 'Preparing to connect to the gateway...');
try {
await this.ws.connect();
@@ -255,7 +275,7 @@ class Client extends BaseClient {
* @returns {boolean}
*/
isReady() {
return this.ws.status === Status.Ready;
return this.ws.status === Status.READY;
}
/**
@@ -265,10 +285,14 @@ class Client extends BaseClient {
destroy() {
super.destroy();
for (const fn of this._cleanups) fn();
this._cleanups.clear();
if (this.sweepMessageInterval) clearInterval(this.sweepMessageInterval);
this.sweepers.destroy();
this.ws.destroy();
this.token = null;
//this.rest.setToken(null);
}
/**
@@ -290,14 +314,9 @@ class Client extends BaseClient {
*/
async fetchInvite(invite, options) {
const code = DataResolver.resolveInviteCode(invite);
const query = new URLSearchParams({
with_counts: true,
with_expiration: true,
const data = await this.api.invites(code).get({
query: { with_counts: true, with_expiration: true, guild_scheduled_event_id: options?.guildScheduledEventId },
});
if (options?.guildScheduledEventId) {
query.set('guild_scheduled_event_id', options.guildScheduledEventId);
}
const data = await this.api.invites(code).get({ query });
return new Invite(this, data);
}
@@ -327,7 +346,7 @@ class Client extends BaseClient {
* .catch(console.error);
*/
async fetchWebhook(id, token) {
const data = await this.api.webhook(id, token).get();
const data = await this.api.webhooks(id, token).get();
return new Webhook(this, { token, ...data });
}
@@ -372,6 +391,50 @@ class Client extends BaseClient {
const data = await this.api('sticker-packs').get();
return new Collection(data.sticker_packs.map(p => [p.id, new StickerPack(this, p)]));
}
/**
* A last ditch cleanup function for garbage collection.
* @param {Function} options.cleanup The function called to GC
* @param {string} [options.message] The message to send after a successful GC
* @param {string} [options.name] The name of the item being GCed
* @private
*/
_finalize({ cleanup, message, name }) {
try {
cleanup();
this._cleanups.delete(cleanup);
if (message) {
this.emit(Events.DEBUG, message);
}
} catch {
this.emit(Events.DEBUG, `Garbage collection failed on ${name ?? 'an unknown item'}.`);
}
}
/**
* Sweeps all text-based channels' messages and removes the ones older than the max message lifetime.
* If the message has been edited, the time of the edit is used rather than the time of the original message.
* @param {number} [lifetime=this.options.messageCacheLifetime] Messages that are older than this (in seconds)
* will be removed from the caches. The default is based on {@link ClientOptions#messageCacheLifetime}
* @returns {number} Amount of messages that were removed from the caches,
* or -1 if the message cache lifetime is unlimited
* @example
* // Remove all messages older than 1800 seconds from the messages cache
* const amount = client.sweepMessages(1800);
* console.log(`Successfully removed ${amount} messages from the cache.`);
*/
sweepMessages(lifetime = this.options.messageCacheLifetime) {
if (typeof lifetime !== 'number' || isNaN(lifetime)) {
throw new TypeError('INVALID_TYPE', 'lifetime', 'number');
}
if (lifetime <= 0) {
this.emit(Events.DEBUG, "Didn't sweep messages - lifetime is unlimited");
return -1;
}
const messages = this.sweepers.sweepMessages(Sweepers.outdatedMessageSweepFilter(lifetime)());
this.emit(Events.DEBUG, `Swept ${messages} messages older than ${lifetime} seconds`);
return messages;
}
/**
* Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds.
@@ -400,7 +463,7 @@ class Client extends BaseClient {
/**
* Options for {@link Client#generateInvite}.
* @typedef {Object} InviteGenerationOptions
* @property {OAuth2Scopes[]} scopes Scopes that should be requested
* @property {InviteScope[]} scopes Scopes that should be requested
* @property {PermissionResolvable} [permissions] Permissions to request
* @property {GuildResolvable} [guild] Guild to preselect
* @property {boolean} [disableGuildSelect] Whether to disable the guild selection
@@ -412,17 +475,17 @@ class Client extends BaseClient {
* @returns {string}
* @example
* const link = client.generateInvite({
* scopes: [OAuth2Scopes.ApplicationsCommands],
* scopes: ['applications.commands'],
* });
* console.log(`Generated application invite link: ${link}`);
* @example
* const link = client.generateInvite({
* permissions: [
* PermissionFlagsBits.SendMessages,
* PermissionFlagsBits.ManageGuild,
* PermissionFlagsBits.MentionEveryone,
* Permissions.FLAGS.SEND_MESSAGES,
* Permissions.FLAGS.MANAGE_GUILD,
* Permissions.FLAGS.MENTION_EVERYONE,
* ],
* scopes: [OAuth2Scopes.Bot],
* scopes: ['bot'],
* });
* console.log(`Generated bot invite link: ${link}`);
*/
@@ -441,18 +504,17 @@ class Client extends BaseClient {
if (!Array.isArray(scopes)) {
throw new TypeError('INVALID_TYPE', 'scopes', 'Array of Invite Scopes', true);
}
if (!scopes.some(scope => [OAuth2Scopes.Bot, OAuth2Scopes.ApplicationsCommands].includes(scope))) {
if (!scopes.some(scope => ['bot', 'applications.commands'].includes(scope))) {
throw new TypeError('INVITE_MISSING_SCOPES');
}
const validScopes = Object.values(OAuth2Scopes);
const invalidScope = scopes.find(scope => !validScopes.includes(scope));
const invalidScope = scopes.find(scope => !InviteScopes.includes(scope));
if (invalidScope) {
throw new TypeError('INVALID_ELEMENT', 'Array', 'scopes', invalidScope);
}
query.set('scope', scopes.join(' '));
if (options.permissions) {
const permissions = PermissionsBitField.resolve(options.permissions);
const permissions = Permissions.resolve(options.permissions);
if (permissions) query.set('permissions', permissions);
}
@@ -466,7 +528,7 @@ class Client extends BaseClient {
query.set('guild_id', guildId);
}
return `${this.options.rest.api}${Routes.oauth2Authorization()}?${query}`;
return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`;
}
toJSON() {
@@ -495,7 +557,7 @@ class Client extends BaseClient {
if (typeof options.intents === 'undefined') {
throw new TypeError('CLIENT_MISSING_INTENTS');
} else {
options.intents = IntentsBitField.resolve(options.intents);
options.intents = Intents.resolve(options.intents);
}
if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) {
throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1');
@@ -507,42 +569,56 @@ class Client extends BaseClient {
if (typeof options.makeCache !== 'function') {
throw new TypeError('CLIENT_INVALID_OPTION', 'makeCache', 'a function');
}
if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'The messageCacheLifetime', 'a number');
}
if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'messageSweepInterval', 'a number');
}
if (typeof options.sweepers !== 'object' || options.sweepers === null) {
throw new TypeError('CLIENT_INVALID_OPTION', 'sweepers', 'an object');
}
if (typeof options.invalidRequestWarningInterval !== 'number' || isNaN(options.invalidRequestWarningInterval)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'invalidRequestWarningInterval', 'a number');
}
if (!Array.isArray(options.partials)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'partials', 'an Array');
}
if (typeof options.waitGuildTimeout !== 'number' || isNaN(options.waitGuildTimeout)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'waitGuildTimeout', 'a number');
}
if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'restWsBridgeTimeout', 'a number');
}
if (typeof options.restRequestTimeout !== 'number' || isNaN(options.restRequestTimeout)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'restRequestTimeout', 'a number');
}
if (typeof options.restGlobalRateLimit !== 'number' || isNaN(options.restGlobalRateLimit)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'restGlobalRateLimit', 'a number');
}
if (typeof options.restSweepInterval !== 'number' || isNaN(options.restSweepInterval)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'restSweepInterval', 'a number');
}
if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'retryLimit', 'a number');
}
if (typeof options.failIfNotExists !== 'boolean') {
throw new TypeError('CLIENT_INVALID_OPTION', 'failIfNotExists', 'a boolean');
}
if (!Array.isArray(options.userAgentSuffix)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'userAgentSuffix', 'an array of strings');
}
if (
typeof options.rejectOnRateLimit !== 'undefined' &&
!(typeof options.rejectOnRateLimit === 'function' || Array.isArray(options.rejectOnRateLimit))
) {
throw new TypeError('CLIENT_INVALID_OPTION', 'rejectOnRateLimit', 'an array or a function');
}
}
}
module.exports = Client;
/**
* A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
* except the epoch is 2015-01-01T00:00:00.000Z.
*
* If we have a snowflake '266241948824764416' we can represent it as binary:
* ```
* 64 22 17 12 0
* 000000111011000111100001101001000101000000 00001 00000 000000000000
* number of milliseconds since Discord epoch worker pid increment
* ```
* @typedef {string} Snowflake
*/
/**
* Emitted for general debugging information.
* @event Client#debug
* @param {string} info The debug information
*/
/**
* Emitted for general warnings.
* @event Client#warn
@@ -553,13 +629,3 @@ module.exports = Client;
* @external Collection
* @see {@link https://discord.js.org/#/docs/collection/main/class/Collection}
*/
/**
* @external ImageURLOptions
* @see {@link https://discord.js.org/#/docs/rest/main/typedef/ImageURLOptions}
*/
/**
* @external BaseImageURLOptions
* @see {@link https://discord.js.org/#/docs/rest/main/typedef/BaseImageURLOptions}
*/