mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
feat(Managers): add customizable caching for managers (#6013)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const RESTManager = require('../rest/RESTManager');
|
||||
const { DefaultOptions } = require('../util/Constants');
|
||||
const Options = require('../util/Options');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
@@ -38,7 +38,7 @@ class BaseClient extends EventEmitter {
|
||||
* The options the client was instantiated with
|
||||
* @type {ClientOptions}
|
||||
*/
|
||||
this.options = Util.mergeDefault(DefaultOptions, options);
|
||||
this.options = Util.mergeDefault(Options.createDefault(), options);
|
||||
|
||||
/**
|
||||
* The REST manager of the client
|
||||
|
||||
@@ -17,9 +17,10 @@ const VoiceRegion = require('../structures/VoiceRegion');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const Widget = require('../structures/Widget');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Events, DefaultOptions, InviteScopes } = require('../util/Constants');
|
||||
const { Events, InviteScopes } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Intents = require('../util/Intents');
|
||||
const Options = require('../util/Options');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Structures = require('../util/Structures');
|
||||
|
||||
@@ -35,14 +36,15 @@ class Client extends BaseClient {
|
||||
super(Object.assign({ _tokenType: 'Bot' }, options));
|
||||
|
||||
const data = require('worker_threads').workerData ?? process.env;
|
||||
const defaults = Options.createDefault();
|
||||
|
||||
if (this.options.shards === DefaultOptions.shards) {
|
||||
if (this.options.shards === defaults.shards) {
|
||||
if ('SHARDS' in data) {
|
||||
this.options.shards = JSON.parse(data.SHARDS);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.shardCount === DefaultOptions.shardCount) {
|
||||
if (this.options.shardCount === defaults.shardCount) {
|
||||
if ('SHARD_COUNT' in data) {
|
||||
this.options.shardCount = Number(data.SHARD_COUNT);
|
||||
} else if (Array.isArray(this.options.shards)) {
|
||||
@@ -468,8 +470,8 @@ class Client extends BaseClient {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers");
|
||||
}
|
||||
if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS');
|
||||
if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'messageCacheMaxSize', 'a number');
|
||||
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');
|
||||
|
||||
@@ -127,6 +127,8 @@ const Messages = {
|
||||
INTERACTION_NOT_REPLIED: 'This interaction has not been deferred or replied to.',
|
||||
INTERACTION_EPHEMERAL_REPLIED: 'Ephemeral responses cannot be fetched or deleted.',
|
||||
INTERACTION_FETCH_EPHEMERAL: 'Ephemeral responses cannot be fetched.',
|
||||
|
||||
NOT_IMPLEMENTED: (what, name) => `Method ${what} not implemented on ${name}.`,
|
||||
};
|
||||
|
||||
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
||||
|
||||
@@ -23,6 +23,7 @@ module.exports = {
|
||||
RateLimitError: require('./rest/RateLimitError'),
|
||||
MessageFlags: require('./util/MessageFlags'),
|
||||
Intents: require('./util/Intents'),
|
||||
Options: require('./util/Options'),
|
||||
Permissions: require('./util/Permissions'),
|
||||
SnowflakeUtil: require('./util/SnowflakeUtil'),
|
||||
Structures: require('./util/Structures'),
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const ApplicationCommand = require('../structures/ApplicationCommand');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for application commands and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ApplicationCommandManager extends BaseManager {
|
||||
class ApplicationCommandManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, iterable, ApplicationCommand);
|
||||
super(client, ApplicationCommand, iterable);
|
||||
|
||||
/**
|
||||
* The manager for permissions of arbitrary commands on arbitrary guilds
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
const { ApplicationCommandPermissionTypes, APIErrors } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for permissions of Application Commands.
|
||||
* @extends {BaseManager}
|
||||
*/
|
||||
class ApplicationCommandPermissionsManager {
|
||||
class ApplicationCommandPermissionsManager extends BaseManager {
|
||||
constructor(manager) {
|
||||
super(manager.client);
|
||||
|
||||
/**
|
||||
* The manager or command that this manager belongs to
|
||||
* @type {ApplicationCommandManager|ApplicationCommand}
|
||||
@@ -32,14 +36,6 @@ class ApplicationCommandPermissionsManager {
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.commandID = manager.id ?? null;
|
||||
|
||||
/**
|
||||
* The client that instantiated this Manager
|
||||
* @name ApplicationCommandPermissionsManager#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: manager.client });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||
const { parseEmoji } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Holds methods to resolve GuildEmojis and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class BaseGuildEmojiManager extends BaseManager {
|
||||
class BaseGuildEmojiManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, iterable, GuildEmoji);
|
||||
super(client, GuildEmoji, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
let Structures;
|
||||
|
||||
/**
|
||||
* Manages the API methods of a data model and holds its cache.
|
||||
* Manages the API methods of a data model.
|
||||
* @abstract
|
||||
*/
|
||||
class BaseManager {
|
||||
constructor(client, iterable, holds, cacheType = Collection, ...cacheOptions) {
|
||||
if (!Structures) Structures = require('../util/Structures');
|
||||
/**
|
||||
* The data structure belonging to this manager
|
||||
* @name BaseManager#holds
|
||||
* @type {Function}
|
||||
* @private
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) ?? holds });
|
||||
|
||||
constructor(client) {
|
||||
/**
|
||||
* The client that instantiated this Manager
|
||||
* @name BaseManager#client
|
||||
@@ -26,55 +13,6 @@ class BaseManager {
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The type of Collection of the Manager
|
||||
* @type {Collection}
|
||||
*/
|
||||
this.cacheType = cacheType;
|
||||
|
||||
/**
|
||||
* Holds the cache for the data model
|
||||
* @type {Collection}
|
||||
*/
|
||||
this.cache = new cacheType(...cacheOptions);
|
||||
if (iterable) for (const i of iterable) this.add(i);
|
||||
}
|
||||
|
||||
add(data, cache = true, { id, extras = [] } = {}) {
|
||||
const existing = this.cache.get(id ?? data.id);
|
||||
if (cache) existing?._patch(data);
|
||||
if (existing) return existing;
|
||||
|
||||
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
|
||||
if (cache) this.cache.set(id ?? entry.id, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a data entry to a data Object.
|
||||
* @param {string|Object} idOrInstance The id or instance of something in this Manager
|
||||
* @returns {?Object} An instance from this Manager
|
||||
*/
|
||||
resolve(idOrInstance) {
|
||||
if (idOrInstance instanceof this.holds) return idOrInstance;
|
||||
if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a data entry to an instance ID.
|
||||
* @param {string|Object} idOrInstance The id or instance of something in this Manager
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveID(idOrInstance) {
|
||||
if (idOrInstance instanceof this.holds) return idOrInstance.id;
|
||||
if (typeof idOrInstance === 'string') return idOrInstance;
|
||||
return null;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
src/managers/CachedManager.js
Normal file
43
src/managers/CachedManager.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const DataManager = require('./DataManager');
|
||||
|
||||
/**
|
||||
* Manages the API methods of a data model with a mutable cache of instances.
|
||||
* @extends {DataManager}
|
||||
* @abstract
|
||||
*/
|
||||
class CachedManager extends DataManager {
|
||||
constructor(client, holds, iterable) {
|
||||
super(client, holds);
|
||||
|
||||
Object.defineProperty(this, '_cache', { value: this.client.options.makeCache(this.constructor, this.holds) });
|
||||
|
||||
if (iterable) {
|
||||
for (const item of iterable) {
|
||||
this.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of items for this manager.
|
||||
* @type {Collection}
|
||||
* @abstract
|
||||
*/
|
||||
get cache() {
|
||||
return this._cache;
|
||||
}
|
||||
|
||||
add(data, cache = true, { id, extras = [] } = {}) {
|
||||
const existing = this.cache.get(id ?? data.id);
|
||||
if (cache) existing?._patch(data);
|
||||
if (existing) return existing;
|
||||
|
||||
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
|
||||
if (cache) this.cache.set(id ?? entry.id, entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CachedManager;
|
||||
@@ -1,16 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const Channel = require('../structures/Channel');
|
||||
const { Events, ThreadChannelTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* A manager of channels belonging to a client
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ChannelManager extends BaseManager {
|
||||
class ChannelManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, iterable, Channel);
|
||||
super(client, Channel, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
65
src/managers/DataManager.js
Normal file
65
src/managers/DataManager.js
Normal file
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { Error } = require('../errors');
|
||||
|
||||
let Structures;
|
||||
|
||||
/**
|
||||
* Manages the API methods of a data model along with a collection of instances.
|
||||
* @extends {BaseManager}
|
||||
* @abstract
|
||||
*/
|
||||
class DataManager extends BaseManager {
|
||||
constructor(client, holds) {
|
||||
super(client);
|
||||
|
||||
if (!Structures) Structures = require('../util/Structures');
|
||||
|
||||
/**
|
||||
* The data structure belonging to this manager.
|
||||
* @name DataManager#holds
|
||||
* @type {Function}
|
||||
* @private
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) ?? holds });
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of items for this manager.
|
||||
* @type {Collection}
|
||||
* @abstract
|
||||
*/
|
||||
get cache() {
|
||||
throw new Error('NOT_IMPLEMENTED', 'get cache', this.constructor.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a data entry to a data Object.
|
||||
* @param {string|Object} idOrInstance The id or instance of something in this Manager
|
||||
* @returns {?Object} An instance from this Manager
|
||||
*/
|
||||
resolve(idOrInstance) {
|
||||
if (idOrInstance instanceof this.holds) return idOrInstance;
|
||||
if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a data entry to an instance ID.
|
||||
* @param {string|Object} idOrInstance The id or instance of something in this Manager
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveID(idOrInstance) {
|
||||
if (idOrInstance instanceof this.holds) return idOrInstance.id;
|
||||
if (typeof idOrInstance === 'string') return idOrInstance;
|
||||
return null;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DataManager;
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError, Error } = require('../errors');
|
||||
const GuildBan = require('../structures/GuildBan');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
@@ -8,11 +8,11 @@ const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildBans and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildBanManager extends BaseManager {
|
||||
class GuildBanManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable, GuildBan);
|
||||
super(guild.client, GuildBan, iterable);
|
||||
|
||||
/**
|
||||
* The guild this Manager belongs to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||
const ThreadChannel = require('../structures/ThreadChannel');
|
||||
@@ -9,11 +9,11 @@ const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildChannels and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildChannelManager extends BaseManager {
|
||||
class GuildChannelManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable, GuildChannel);
|
||||
super(guild.client, GuildChannel, iterable);
|
||||
|
||||
/**
|
||||
* The guild this Manager belongs to
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const DataManager = require('./DataManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const Role = require('../structures/Role');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles belonging to emojis and stores their cache.
|
||||
* @extends {DataManager}
|
||||
*/
|
||||
class GuildEmojiRoleManager {
|
||||
class GuildEmojiRoleManager extends DataManager {
|
||||
constructor(emoji) {
|
||||
super(emoji.client, Role);
|
||||
|
||||
/**
|
||||
* The emoji belonging to this manager
|
||||
* @type {GuildEmoji}
|
||||
@@ -18,12 +23,6 @@ class GuildEmojiRoleManager {
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = emoji.guild;
|
||||
/**
|
||||
* The client belonging to this manager
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: emoji.client });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const Guild = require('../structures/Guild');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
@@ -23,11 +23,11 @@ const { resolveColor } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for Guilds and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildManager extends BaseManager {
|
||||
class GuildManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, iterable, Guild);
|
||||
super(client, Guild, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
@@ -11,11 +11,12 @@ const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildMemberManager extends BaseManager {
|
||||
class GuildMemberManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable, GuildMember);
|
||||
super(guild.client, GuildMember, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const DataManager = require('./DataManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const Role = require('../structures/Role');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles of a GuildMember and stores their cache.
|
||||
* @extends {DataManager}
|
||||
*/
|
||||
class GuildMemberRoleManager {
|
||||
class GuildMemberRoleManager extends DataManager {
|
||||
constructor(member) {
|
||||
super(member.client, Role);
|
||||
|
||||
/**
|
||||
* The GuildMember this manager belongs to
|
||||
* @type {GuildMember}
|
||||
*/
|
||||
this.member = member;
|
||||
|
||||
/**
|
||||
* The Guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = member.guild;
|
||||
Object.defineProperty(this, 'client', { value: member.client });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,10 +175,6 @@ class GuildMemberRoleManager {
|
||||
clone.member._roles = [...this.cache.keyArray()];
|
||||
return clone;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildMemberRoleManager;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const Message = require('../structures/Message');
|
||||
const MessagePayload = require('../structures/MessagePayload');
|
||||
const Collection = require('../util/Collection');
|
||||
const LimitedCollection = require('../util/LimitedCollection');
|
||||
|
||||
/**
|
||||
* Manages API methods for Messages and holds their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class MessageManager extends BaseManager {
|
||||
class MessageManager extends CachedManager {
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, iterable, Message, LimitedCollection, channel.client.options.messageCacheMaxSize);
|
||||
super(channel.client, Message, iterable);
|
||||
|
||||
/**
|
||||
* The channel that the messages belong to
|
||||
* @type {TextBasedChannel}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||
const Role = require('../structures/Role');
|
||||
@@ -9,11 +9,11 @@ const { OverwriteTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for guild channel permission overwrites and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class PermissionOverwriteManager extends BaseManager {
|
||||
class PermissionOverwriteManager extends CachedManager {
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, iterable, PermissionOverwrites);
|
||||
super(channel.client, PermissionOverwrites, iterable);
|
||||
|
||||
/**
|
||||
* The channel of the permission overwrite this manager belongs to
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { Presence } = require('../structures/Presence');
|
||||
|
||||
/**
|
||||
* Manages API methods for Presences and holds their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class PresenceManager extends BaseManager {
|
||||
class PresenceManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, iterable, Presence);
|
||||
super(client, Presence, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const MessageReaction = require('../structures/MessageReaction');
|
||||
|
||||
/**
|
||||
* Manages API methods for reactions and holds their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ReactionManager extends BaseManager {
|
||||
class ReactionManager extends CachedManager {
|
||||
constructor(message, iterable) {
|
||||
super(message.client, iterable, MessageReaction);
|
||||
super(message.client, MessageReaction, iterable);
|
||||
|
||||
/**
|
||||
* The message that this manager belongs to
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { Error } = require('../errors');
|
||||
const User = require('../structures/User');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for users who reacted to a reaction and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ReactionUserManager extends BaseManager {
|
||||
constructor(client, iterable, reaction) {
|
||||
super(client, iterable, { name: 'User' });
|
||||
class ReactionUserManager extends CachedManager {
|
||||
constructor(reaction, iterable) {
|
||||
super(reaction.client, User, iterable);
|
||||
|
||||
/**
|
||||
* The reaction that this manager belongs to
|
||||
* @type {MessageReaction}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const Role = require('../structures/Role');
|
||||
const Collection = require('../util/Collection');
|
||||
@@ -9,11 +9,12 @@ const { resolveColor, setPosition } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class RoleManager extends BaseManager {
|
||||
class RoleManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable, Role);
|
||||
super(guild.client, Role, iterable);
|
||||
|
||||
/**
|
||||
* The guild belonging to this manager
|
||||
* @type {Guild}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError, Error } = require('../errors');
|
||||
const StageInstance = require('../structures/StageInstance');
|
||||
const { PrivacyLevels } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for {@link StageInstance} objects and holds their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class StageInstanceManager extends BaseManager {
|
||||
class StageInstanceManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable, StageInstance);
|
||||
super(guild.client, StageInstance, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const ThreadChannel = require('../structures/ThreadChannel');
|
||||
const Collection = require('../util/Collection');
|
||||
@@ -8,11 +8,11 @@ const { ChannelTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ThreadManager extends BaseManager {
|
||||
class ThreadManager extends CachedManager {
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, iterable, ThreadChannel);
|
||||
super(channel.client, ThreadChannel, iterable);
|
||||
|
||||
/**
|
||||
* The channel this Manager belongs to
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const ThreadMember = require('../structures/ThreadMember');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for ThreadMembers and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ThreadMemberManager extends BaseManager {
|
||||
class ThreadMemberManager extends CachedManager {
|
||||
constructor(thread, iterable) {
|
||||
super(thread.client, iterable, ThreadMember);
|
||||
super(thread.client, ThreadMember, iterable);
|
||||
|
||||
/**
|
||||
* The thread this manager belongs to
|
||||
* @type {ThreadChannel}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const Message = require('../structures/Message');
|
||||
const ThreadMember = require('../structures/ThreadMember');
|
||||
@@ -8,11 +8,11 @@ const User = require('../structures/User');
|
||||
|
||||
/**
|
||||
* Manages API methods for users and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class UserManager extends BaseManager {
|
||||
class UserManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, iterable, User);
|
||||
super(client, User, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const VoiceState = require('../structures/VoiceState');
|
||||
|
||||
/**
|
||||
* Manages API methods for VoiceStates and stores their cache.
|
||||
* @extends {BaseManager}
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class VoiceStateManager extends BaseManager {
|
||||
class VoiceStateManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable, { name: 'VoiceState' });
|
||||
super(guild.client, VoiceState, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
|
||||
@@ -22,6 +22,7 @@ class MessageReaction {
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The message that this reaction refers to
|
||||
* @type {Message}
|
||||
@@ -38,7 +39,7 @@ class MessageReaction {
|
||||
* A manager of the users that have given this reaction
|
||||
* @type {ReactionUserManager}
|
||||
*/
|
||||
this.users = new ReactionUserManager(client, undefined, this);
|
||||
this.users = new ReactionUserManager(this);
|
||||
|
||||
this._emoji = new ReactionEmoji(this, data.emoji);
|
||||
|
||||
|
||||
@@ -3,117 +3,6 @@
|
||||
const Package = (exports.Package = require('../../package.json'));
|
||||
const { Error, RangeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Rate limit data
|
||||
* @typedef {Object} RateLimitData
|
||||
* @property {number} timeout Time until this rate limit ends, in ms
|
||||
* @property {number} limit The maximum amount of requests of this endpoint
|
||||
* @property {string} method The http method of this request
|
||||
* @property {string} path The path of the request relative to the HTTP endpoint
|
||||
* @property {string} route The route of the request relative to the HTTP endpoint
|
||||
* @property {boolean} global Whether this is a global rate limit
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether this rate limit should throw an Error
|
||||
* @typedef {Function} RateLimitQueueFilter
|
||||
* @param {RateLimitData} rateLimitData The data of this rate limit
|
||||
* @returns {boolean|Promise<boolean>}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for a client.
|
||||
* @typedef {Object} ClientOptions
|
||||
* @property {number|number[]|string} [shards] ID of the shard to run, or an array of shard IDs. If not specified,
|
||||
* the client will spawn {@link ClientOptions#shardCount} shards. If set to `auto`, it will fetch the
|
||||
* recommended amount of shards from Discord and spawn that amount
|
||||
* @property {number} [shardCount=1] The total amount of shards used by all processes of this bot
|
||||
* (e.g. recommended shard count, shard count of the ShardingManager)
|
||||
* @property {number} [messageCacheMaxSize=200] Maximum number of messages to cache per channel
|
||||
* (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb
|
||||
* indefinitely)
|
||||
* @property {number} [messageCacheLifetime=0] How long a message should stay in the cache until it is considered
|
||||
* sweepable (in seconds, 0 for forever)
|
||||
* @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than
|
||||
* the message cache lifetime (in seconds, 0 for never)
|
||||
* @property {MessageMentionOptions} [allowedMentions] Default value for {@link MessageOptions#allowedMentions}
|
||||
* @property {number} [invalidRequestWarningInterval=0] The number of invalid REST requests (those that return
|
||||
* 401, 403, or 429) in a 10 minute window between emitted warnings (0 for no warnings). That is, if set to 500,
|
||||
* warnings will be emitted at invalid request number 500, 1000, 1500, and so on.
|
||||
* @property {PartialType[]} [partials] Structures allowed to be partial. This means events can be emitted even when
|
||||
* they're missing all the data for a particular structure. See the "Partial Structures" topic on the
|
||||
* [guide](https://discordjs.guide/popular-topics/partials.html) for some
|
||||
* important usage information, as partials require you to put checks in place when handling data.
|
||||
* @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their
|
||||
* corresponding websocket events
|
||||
* @property {number} [restTimeOffset=500] Extra time in milliseconds to wait before continuing to make REST
|
||||
* requests (higher values will reduce rate-limiting errors on bad connections)
|
||||
* @property {number} [restRequestTimeout=15000] Time to wait before cancelling a REST request, in milliseconds
|
||||
* @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds
|
||||
* (or 0 for never)
|
||||
* @property {number} [restGlobalRateLimit=0] How many requests to allow sending per second (0 for unlimited, 50 for
|
||||
* the standard global limit used by Discord)
|
||||
* @property {string[]|RateLimitQueueFilter} [rejectOnRateLimit] Decides how rate limits and pre-emptive throttles
|
||||
* should be handled. If this option is an array containing the prefix of the request route (e.g. /channels to match any
|
||||
* route starting with /channels, such as /channels/222197033908436994/messages) or a function returning true, a
|
||||
* {@link RateLimitError} will be thrown. Otherwise the request will be queued for later
|
||||
* @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries)
|
||||
* @property {PresenceData} [presence={}] Presence data to use upon login
|
||||
* @property {IntentsResolvable} intents Intents to enable for this connection
|
||||
* @property {WebsocketOptions} [ws] Options for the WebSocket
|
||||
* @property {HTTPOptions} [http] HTTP options
|
||||
*/
|
||||
exports.DefaultOptions = {
|
||||
shardCount: 1,
|
||||
messageCacheMaxSize: 200,
|
||||
messageCacheLifetime: 0,
|
||||
messageSweepInterval: 0,
|
||||
invalidRequestWarningInterval: 0,
|
||||
partials: [],
|
||||
restWsBridgeTimeout: 5000,
|
||||
restRequestTimeout: 15000,
|
||||
restGlobalRateLimit: 0,
|
||||
retryLimit: 1,
|
||||
restTimeOffset: 500,
|
||||
restSweepInterval: 60,
|
||||
presence: {},
|
||||
|
||||
/**
|
||||
* WebSocket options (these are left as snake_case to match the API)
|
||||
* @typedef {Object} WebsocketOptions
|
||||
* @property {number} [large_threshold=50] Number of members in a guild after which offline users will no longer be
|
||||
* sent in the initial guild member list, must be between 50 and 250
|
||||
*/
|
||||
ws: {
|
||||
large_threshold: 50,
|
||||
compress: false,
|
||||
properties: {
|
||||
$os: process.platform,
|
||||
$browser: 'discord.js',
|
||||
$device: 'discord.js',
|
||||
},
|
||||
version: 9,
|
||||
},
|
||||
|
||||
/**
|
||||
* HTTP options
|
||||
* @typedef {Object} HTTPOptions
|
||||
* @property {number} [version=9] API version to use
|
||||
* @property {string} [api='https://discord.com/api'] Base url of the API
|
||||
* @property {string} [cdn='https://cdn.discordapp.com'] Base url of the CDN
|
||||
* @property {string} [invite='https://discord.gg'] Base url of invites
|
||||
* @property {string} [template='https://discord.new'] Base url of templates
|
||||
* @property {Object} [headers] Additional headers to send for all API requests
|
||||
*/
|
||||
http: {
|
||||
version: 9,
|
||||
api: 'https://discord.com/api',
|
||||
cdn: 'https://cdn.discordapp.com',
|
||||
invite: 'https://discord.gg',
|
||||
template: 'https://discord.new',
|
||||
},
|
||||
};
|
||||
|
||||
exports.UserAgent = `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`;
|
||||
|
||||
exports.WSCodes = {
|
||||
|
||||
160
src/util/Options.js
Normal file
160
src/util/Options.js
Normal file
@@ -0,0 +1,160 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Rate limit data
|
||||
* @typedef {Object} RateLimitData
|
||||
* @property {number} timeout Time until this rate limit ends, in ms
|
||||
* @property {number} limit The maximum amount of requests of this endpoint
|
||||
* @property {string} method The http method of this request
|
||||
* @property {string} path The path of the request relative to the HTTP endpoint
|
||||
* @property {string} route The route of the request relative to the HTTP endpoint
|
||||
* @property {boolean} global Whether this is a global rate limit
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether this rate limit should throw an Error
|
||||
* @typedef {Function} RateLimitQueueFilter
|
||||
* @param {RateLimitData} rateLimitData The data of this rate limit
|
||||
* @returns {boolean|Promise<boolean>}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Function} CacheFactory
|
||||
* @param {Function} manager The manager class the cache is being requested from.
|
||||
* @param {Function} holds The class that the cache will hold.
|
||||
* @returns {Collection} Cache instance that follows collection interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for a client.
|
||||
* @typedef {Object} ClientOptions
|
||||
* @property {number|number[]|string} [shards] ID of the shard to run, or an array of shard IDs. If not specified,
|
||||
* the client will spawn {@link ClientOptions#shardCount} shards. If set to `auto`, it will fetch the
|
||||
* recommended amount of shards from Discord and spawn that amount
|
||||
* @property {number} [shardCount=1] The total amount of shards used by all processes of this bot
|
||||
* (e.g. recommended shard count, shard count of the ShardingManager)
|
||||
* @property {CacheFactory} [makeCache] Function to create a cache.
|
||||
* (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb
|
||||
* indefinitely)
|
||||
* @property {number} [messageCacheLifetime=0] How long a message should stay in the cache until it is considered
|
||||
* sweepable (in seconds, 0 for forever)
|
||||
* @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than
|
||||
* the message cache lifetime (in seconds, 0 for never)
|
||||
* @property {MessageMentionOptions} [allowedMentions] Default value for {@link MessageOptions#allowedMentions}
|
||||
* @property {number} [invalidRequestWarningInterval=0] The number of invalid REST requests (those that return
|
||||
* 401, 403, or 429) in a 10 minute window between emitted warnings (0 for no warnings). That is, if set to 500,
|
||||
* warnings will be emitted at invalid request number 500, 1000, 1500, and so on.
|
||||
* @property {PartialType[]} [partials] Structures allowed to be partial. This means events can be emitted even when
|
||||
* they're missing all the data for a particular structure. See the "Partial Structures" topic on the
|
||||
* [guide](https://discordjs.guide/popular-topics/partials.html) for some
|
||||
* important usage information, as partials require you to put checks in place when handling data.
|
||||
* @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their
|
||||
* corresponding websocket events
|
||||
* @property {number} [restTimeOffset=500] Extra time in milliseconds to wait before continuing to make REST
|
||||
* requests (higher values will reduce rate-limiting errors on bad connections)
|
||||
* @property {number} [restRequestTimeout=15000] Time to wait before cancelling a REST request, in milliseconds
|
||||
* @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds
|
||||
* (or 0 for never)
|
||||
* @property {number} [restGlobalRateLimit=0] How many requests to allow sending per second (0 for unlimited, 50 for
|
||||
* the standard global limit used by Discord)
|
||||
* @property {string[]|RateLimitQueueFilter} [rejectOnRateLimit] Decides how rate limits and pre-emptive throttles
|
||||
* should be handled. If this option is an array containing the prefix of the request route (e.g. /channels to match any
|
||||
* route starting with /channels, such as /channels/222197033908436994/messages) or a function returning true, a
|
||||
* {@link RateLimitError} will be thrown. Otherwise the request will be queued for later
|
||||
* @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries)
|
||||
* @property {PresenceData} [presence={}] Presence data to use upon login
|
||||
* @property {IntentsResolvable} intents Intents to enable for this connection
|
||||
* @property {WebsocketOptions} [ws] Options for the WebSocket
|
||||
* @property {HTTPOptions} [http] HTTP options
|
||||
*/
|
||||
|
||||
/**
|
||||
* WebSocket options (these are left as snake_case to match the API)
|
||||
* @typedef {Object} WebsocketOptions
|
||||
* @property {number} [large_threshold=50] Number of members in a guild after which offline users will no longer be
|
||||
* sent in the initial guild member list, must be between 50 and 250
|
||||
*/
|
||||
|
||||
/**
|
||||
* HTTP options
|
||||
* @typedef {Object} HTTPOptions
|
||||
* @property {number} [version=9] API version to use
|
||||
* @property {string} [api='https://discord.com/api'] Base url of the API
|
||||
* @property {string} [cdn='https://cdn.discordapp.com'] Base url of the CDN
|
||||
* @property {string} [invite='https://discord.gg'] Base url of invites
|
||||
* @property {string} [template='https://discord.new'] Base url of templates
|
||||
* @property {Object} [headers] Additional headers to send for all API requests
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains various utilities for client options.
|
||||
*/
|
||||
class Options extends null {
|
||||
/**
|
||||
* The default client options.
|
||||
* @returns {ClientOptions}
|
||||
*/
|
||||
static createDefault() {
|
||||
return {
|
||||
shardCount: 1,
|
||||
makeCache: this.cacheWithLimits({ MessageManager: 200 }),
|
||||
messageCacheLifetime: 0,
|
||||
messageSweepInterval: 0,
|
||||
invalidRequestWarningInterval: 0,
|
||||
partials: [],
|
||||
restWsBridgeTimeout: 5000,
|
||||
restRequestTimeout: 15000,
|
||||
restGlobalRateLimit: 0,
|
||||
retryLimit: 1,
|
||||
restTimeOffset: 500,
|
||||
restSweepInterval: 60,
|
||||
presence: {},
|
||||
ws: {
|
||||
large_threshold: 50,
|
||||
compress: false,
|
||||
properties: {
|
||||
$os: process.platform,
|
||||
$browser: 'discord.js',
|
||||
$device: 'discord.js',
|
||||
},
|
||||
version: 9,
|
||||
},
|
||||
http: {
|
||||
version: 9,
|
||||
api: 'https://discord.com/api',
|
||||
cdn: 'https://cdn.discordapp.com',
|
||||
invite: 'https://discord.gg',
|
||||
template: 'https://discord.new',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cache factory using predefined limits.
|
||||
* @param {Record<string, number>} [limits={}] Limits for structures.
|
||||
* @returns {CacheFactory}
|
||||
*/
|
||||
static cacheWithLimits(limits = {}) {
|
||||
const Collection = require('./Collection');
|
||||
const LimitedCollection = require('./LimitedCollection');
|
||||
|
||||
return manager => {
|
||||
const limit = limits[manager.name];
|
||||
if (limit === null || limit === undefined || limit === Infinity) {
|
||||
return new Collection();
|
||||
}
|
||||
return new LimitedCollection(limit);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cache factory that always caches everything.
|
||||
* @returns {CacheFactory}
|
||||
*/
|
||||
static cacheEverything() {
|
||||
const Collection = require('./Collection');
|
||||
return () => new Collection();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Options;
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
const { parse } = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
|
||||
const { Colors, Endpoints } = require('./Constants');
|
||||
const Options = require('./Options');
|
||||
const { Error: DiscordError, RangeError, TypeError } = require('../errors');
|
||||
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
||||
const isObject = d => typeof d === 'object' && d !== null;
|
||||
@@ -261,7 +262,8 @@ class Util extends null {
|
||||
*/
|
||||
static fetchRecommendedShards(token, guildsPerShard = 1000) {
|
||||
if (!token) throw new DiscordError('TOKEN_MISSING');
|
||||
return fetch(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`, {
|
||||
const defaults = Options.createDefault();
|
||||
return fetch(`${defaults.http.api}/v${defaults.http.version}${Endpoints.botGateway}`, {
|
||||
method: 'GET',
|
||||
headers: { Authorization: `Bot ${token.replace(/^Bot\s*/i, '')}` },
|
||||
})
|
||||
|
||||
57
test/tester2000.js
Normal file
57
test/tester2000.js
Normal file
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
const { token, prefix, owner } = require('./auth.js');
|
||||
const { Client, Options, Intents, Formatters } = require('../src');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
const log = (...args) => console.log(process.uptime().toFixed(3), ...args);
|
||||
|
||||
const client = new Client({
|
||||
intents: Intents.ALL,
|
||||
makeCache: Options.cacheWithLimits({
|
||||
MessageManager: 10,
|
||||
PresenceManager: 10,
|
||||
}),
|
||||
});
|
||||
|
||||
client.on('debug', log);
|
||||
client.on('ready', () => {
|
||||
log('READY', client.user.tag, client.user.id);
|
||||
});
|
||||
client.on('rateLimit', log);
|
||||
client.on('error', console.error);
|
||||
|
||||
const commands = {
|
||||
eval: message => {
|
||||
if (message.author.id !== owner) return;
|
||||
let res;
|
||||
try {
|
||||
res = eval(message.content);
|
||||
if (typeof res !== 'string') res = require('util').inspect(res);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err.stack);
|
||||
res = err.message;
|
||||
}
|
||||
message.channel.send(Formatters.codeBlock(res));
|
||||
},
|
||||
ping: message => message.channel.send('pong'),
|
||||
};
|
||||
|
||||
client.on('message', message => {
|
||||
if (!message.content.startsWith(prefix) || message.author.bot) return;
|
||||
|
||||
message.content = message.content.replace(prefix, '').trim().split(' ');
|
||||
const command = message.content.shift();
|
||||
message.content = message.content.join(' ');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('COMMAND', command, message.content);
|
||||
|
||||
if (command in commands) commands[command](message);
|
||||
});
|
||||
|
||||
client.login(token);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
process.on('unhandledRejection', console.error);
|
||||
83
typings/index.d.ts
vendored
83
typings/index.d.ts
vendored
@@ -526,6 +526,12 @@ declare module 'discord.js' {
|
||||
public setUsername(username: string): Promise<this>;
|
||||
}
|
||||
|
||||
export class Options {
|
||||
public static createDefaultOptions(): ClientOptions;
|
||||
public static cacheWithLimits(limits?: Record<string, number>): CacheFactory;
|
||||
public static cacheEverything(): CacheFactory;
|
||||
}
|
||||
|
||||
export class ClientVoiceManager {
|
||||
constructor(client: Client);
|
||||
public readonly client: Client;
|
||||
@@ -608,7 +614,6 @@ declare module 'discord.js' {
|
||||
devDependencies: { [key: string]: string };
|
||||
[key: string]: any;
|
||||
};
|
||||
DefaultOptions: ClientOptions;
|
||||
UserAgent: string | null;
|
||||
Endpoints: {
|
||||
botGateway: string;
|
||||
@@ -2340,13 +2345,15 @@ declare module 'discord.js' {
|
||||
|
||||
//#region Managers
|
||||
|
||||
export abstract class BaseManager<K, Holds, R> {
|
||||
constructor(client: Client, iterable: Iterable<any>, holds: Constructable<Holds>, cacheType: Collection<K, Holds>);
|
||||
public holds: Constructable<Holds>;
|
||||
public cache: Collection<K, Holds>;
|
||||
public cacheType: Collection<K, Holds>;
|
||||
export abstract class BaseManager {
|
||||
constructor(client: Client);
|
||||
public readonly client: Client;
|
||||
public add(data: any, cache?: boolean, { id, extras }?: { id: K; extras: any[] }): Holds;
|
||||
}
|
||||
|
||||
export abstract class DataManager<K, Holds, R> extends BaseManager {
|
||||
constructor(client: Client, holds: Constructable<Holds>);
|
||||
public readonly holds: Constructable<Holds>;
|
||||
public readonly cache: Collection<K, Holds>;
|
||||
public resolve(resolvable: Holds): Holds;
|
||||
public resolve(resolvable: R): Holds | null;
|
||||
public resolveID(resolvable: Holds): K;
|
||||
@@ -2354,11 +2361,16 @@ declare module 'discord.js' {
|
||||
public valueOf(): Collection<K, Holds>;
|
||||
}
|
||||
|
||||
export abstract class CachedManager<K, Holds, R> extends DataManager<K, Holds, R> {
|
||||
constructor(client: Client, holds: Constructable<Holds>);
|
||||
public add(data: any, cache?: boolean, { id, extras }?: { id: K; extras: any[] }): Holds;
|
||||
}
|
||||
|
||||
export class ApplicationCommandManager<
|
||||
ApplicationCommandType = ApplicationCommand<{ guild: GuildResolvable }>,
|
||||
PermissionsOptionsExtras = { guild: GuildResolvable },
|
||||
PermissionsGuildType = null,
|
||||
> extends BaseManager<Snowflake, ApplicationCommandType, ApplicationCommandResolvable> {
|
||||
> extends CachedManager<Snowflake, ApplicationCommandType, ApplicationCommandResolvable> {
|
||||
constructor(client: Client, iterable?: Iterable<any>);
|
||||
public permissions: ApplicationCommandPermissionsManager<
|
||||
{ command?: ApplicationCommandResolvable } & PermissionsOptionsExtras,
|
||||
@@ -2400,7 +2412,12 @@ declare module 'discord.js' {
|
||||
private static transformCommand(command: ApplicationCommandData): unknown;
|
||||
}
|
||||
|
||||
export class ApplicationCommandPermissionsManager<BaseOptions, FetchSingleOptions, GuildType, CommandIDType> {
|
||||
export class ApplicationCommandPermissionsManager<
|
||||
BaseOptions,
|
||||
FetchSingleOptions,
|
||||
GuildType,
|
||||
CommandIDType,
|
||||
> extends BaseManager {
|
||||
constructor(manager: ApplicationCommandManager | GuildApplicationCommandManager | ApplicationCommand);
|
||||
public client: Client;
|
||||
public commandID: CommandIDType;
|
||||
@@ -2436,12 +2453,12 @@ declare module 'discord.js' {
|
||||
private static transformPermissions(permissions: ApplicationCommandPermissionData, received?: boolean): unknown;
|
||||
}
|
||||
|
||||
export class BaseGuildEmojiManager extends BaseManager<Snowflake, GuildEmoji, EmojiResolvable> {
|
||||
export class BaseGuildEmojiManager extends CachedManager<Snowflake, GuildEmoji, EmojiResolvable> {
|
||||
constructor(client: Client, iterable?: Iterable<any>);
|
||||
public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null;
|
||||
}
|
||||
|
||||
export class ChannelManager extends BaseManager<Snowflake, Channel, ChannelResolvable> {
|
||||
export class ChannelManager extends CachedManager<Snowflake, Channel, ChannelResolvable> {
|
||||
constructor(client: Client, iterable: Iterable<any>);
|
||||
public fetch(id: Snowflake, options?: BaseFetchOptions): Promise<Channel | null>;
|
||||
}
|
||||
@@ -2457,7 +2474,7 @@ declare module 'discord.js' {
|
||||
public set(commands: ApplicationCommandData[]): Promise<Collection<Snowflake, ApplicationCommand>>;
|
||||
}
|
||||
|
||||
export class GuildChannelManager extends BaseManager<
|
||||
export class GuildChannelManager extends CachedManager<
|
||||
Snowflake,
|
||||
GuildChannel | ThreadChannel,
|
||||
GuildChannelResolvable
|
||||
@@ -2499,11 +2516,10 @@ declare module 'discord.js' {
|
||||
public fetch(id?: Snowflake, options?: BaseFetchOptions): Promise<Collection<Snowflake, GuildEmoji>>;
|
||||
}
|
||||
|
||||
export class GuildEmojiRoleManager {
|
||||
export class GuildEmojiRoleManager extends DataManager<Snowflake, Role, RoleResolvable> {
|
||||
constructor(emoji: GuildEmoji);
|
||||
public emoji: GuildEmoji;
|
||||
public guild: Guild;
|
||||
public cache: Collection<Snowflake, Role>;
|
||||
public add(
|
||||
roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection<Snowflake, Role>,
|
||||
): Promise<GuildEmoji>;
|
||||
@@ -2511,17 +2527,16 @@ declare module 'discord.js' {
|
||||
public remove(
|
||||
roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection<Snowflake, Role>,
|
||||
): Promise<GuildEmoji>;
|
||||
public valueOf(): Collection<Snowflake, Role>;
|
||||
}
|
||||
|
||||
export class GuildManager extends BaseManager<Snowflake, Guild, GuildResolvable> {
|
||||
export class GuildManager extends CachedManager<Snowflake, Guild, GuildResolvable> {
|
||||
constructor(client: Client, iterable?: Iterable<any>);
|
||||
public create(name: string, options?: GuildCreateOptions): Promise<Guild>;
|
||||
public fetch(options: Snowflake | FetchGuildOptions): Promise<Guild>;
|
||||
public fetch(options?: FetchGuildsOptions): Promise<Collection<Snowflake, OAuth2Guild>>;
|
||||
}
|
||||
|
||||
export class GuildMemberManager extends BaseManager<Snowflake, GuildMember, GuildMemberResolvable> {
|
||||
export class GuildMemberManager extends CachedManager<Snowflake, GuildMember, GuildMemberResolvable> {
|
||||
constructor(guild: Guild, iterable?: Iterable<any>);
|
||||
public guild: Guild;
|
||||
public ban(user: UserResolvable, options?: BanOptions): Promise<GuildMember | User | Snowflake>;
|
||||
@@ -2537,7 +2552,7 @@ declare module 'discord.js' {
|
||||
public unban(user: UserResolvable, reason?: string): Promise<User>;
|
||||
}
|
||||
|
||||
export class GuildBanManager extends BaseManager<Snowflake, GuildBan, GuildBanResolvable> {
|
||||
export class GuildBanManager extends CachedManager<Snowflake, GuildBan, GuildBanResolvable> {
|
||||
constructor(guild: Guild, iterable?: Iterable<any>);
|
||||
public guild: Guild;
|
||||
public create(user: UserResolvable, options?: BanOptions): Promise<GuildMember | User | Snowflake>;
|
||||
@@ -2546,9 +2561,8 @@ declare module 'discord.js' {
|
||||
public remove(user: UserResolvable, reason?: string): Promise<User>;
|
||||
}
|
||||
|
||||
export class GuildMemberRoleManager {
|
||||
export class GuildMemberRoleManager extends DataManager<Snowflake, Role, RoleResolvable> {
|
||||
constructor(member: GuildMember);
|
||||
public readonly cache: Collection<Snowflake, Role>;
|
||||
public readonly hoist: Role | null;
|
||||
public readonly color: Role | null;
|
||||
public readonly highest: Role;
|
||||
@@ -2566,10 +2580,9 @@ declare module 'discord.js' {
|
||||
roleOrRoles: RoleResolvable | readonly RoleResolvable[] | Collection<Snowflake, Role>,
|
||||
reason?: string,
|
||||
): Promise<GuildMember>;
|
||||
public valueOf(): Collection<Snowflake, Role>;
|
||||
}
|
||||
|
||||
export class MessageManager extends BaseManager<Snowflake, Message, MessageResolvable> {
|
||||
export class MessageManager extends CachedManager<Snowflake, Message, MessageResolvable> {
|
||||
constructor(channel: TextChannel | DMChannel | ThreadChannel, iterable?: Iterable<any>);
|
||||
public channel: TextBasedChannelFields;
|
||||
public cache: Collection<Snowflake, Message>;
|
||||
@@ -2587,7 +2600,7 @@ declare module 'discord.js' {
|
||||
public unpin(message: MessageResolvable): Promise<void>;
|
||||
}
|
||||
|
||||
export class PermissionOverwriteManager extends BaseManager<
|
||||
export class PermissionOverwriteManager extends CachedManager<
|
||||
Snowflake,
|
||||
PermissionOverwrites,
|
||||
PermissionOverwriteResolvable
|
||||
@@ -2616,24 +2629,24 @@ declare module 'discord.js' {
|
||||
public delete(userOrRole: RoleResolvable | UserResolvable, reason?: string): Promise<GuildChannel>;
|
||||
}
|
||||
|
||||
export class PresenceManager extends BaseManager<Snowflake, Presence, PresenceResolvable> {
|
||||
export class PresenceManager extends CachedManager<Snowflake, Presence, PresenceResolvable> {
|
||||
constructor(client: Client, iterable?: Iterable<any>);
|
||||
}
|
||||
|
||||
export class ReactionManager extends BaseManager<Snowflake | string, MessageReaction, MessageReactionResolvable> {
|
||||
export class ReactionManager extends CachedManager<Snowflake | string, MessageReaction, MessageReactionResolvable> {
|
||||
constructor(message: Message, iterable?: Iterable<any>);
|
||||
public message: Message;
|
||||
public removeAll(): Promise<Message>;
|
||||
}
|
||||
|
||||
export class ReactionUserManager extends BaseManager<Snowflake, User, UserResolvable> {
|
||||
constructor(client: Client, iterable: Iterable<any> | undefined, reaction: MessageReaction);
|
||||
export class ReactionUserManager extends CachedManager<Snowflake, User, UserResolvable> {
|
||||
constructor(reaction: MessageReaction, iterable?: Iterable<any>);
|
||||
public reaction: MessageReaction;
|
||||
public fetch(options?: FetchReactionUsersOptions): Promise<Collection<Snowflake, User>>;
|
||||
public remove(user?: UserResolvable): Promise<MessageReaction>;
|
||||
}
|
||||
|
||||
export class RoleManager extends BaseManager<Snowflake, Role, RoleResolvable> {
|
||||
export class RoleManager extends CachedManager<Snowflake, Role, RoleResolvable> {
|
||||
constructor(guild: Guild, iterable?: Iterable<any>);
|
||||
public readonly everyone: Role;
|
||||
public readonly highest: Role;
|
||||
@@ -2646,7 +2659,7 @@ declare module 'discord.js' {
|
||||
public edit(role: RoleResolvable, options: RoleData, reason?: string): Promise<Role>;
|
||||
}
|
||||
|
||||
export class StageInstanceManager extends BaseManager<Snowflake, StageInstance, StageInstanceResolvable> {
|
||||
export class StageInstanceManager extends CachedManager<Snowflake, StageInstance, StageInstanceResolvable> {
|
||||
constructor(guild: Guild, iterable?: Iterable<any>);
|
||||
public guild: Guild;
|
||||
public create(channel: StageChannel | Snowflake, options: StageInstanceCreateOptions): Promise<StageInstance>;
|
||||
@@ -2655,7 +2668,7 @@ declare module 'discord.js' {
|
||||
public delete(channel: StageChannel | Snowflake): Promise<void>;
|
||||
}
|
||||
|
||||
export class ThreadManager<AllowedThreadType> extends BaseManager<Snowflake, ThreadChannel, ThreadChannelResolvable> {
|
||||
export class ThreadManager<AllowedThreadType> extends CachedManager<Snowflake, ThreadChannel, ThreadChannelResolvable> {
|
||||
constructor(channel: TextChannel | NewsChannel, iterable?: Iterable<any>);
|
||||
public channel: TextChannel | NewsChannel;
|
||||
public create(options: ThreadCreateOptions<AllowedThreadType>): Promise<ThreadChannel>;
|
||||
@@ -2666,7 +2679,7 @@ declare module 'discord.js' {
|
||||
}
|
||||
|
||||
export interface ThreadMemberManager
|
||||
extends Omit<BaseManager<Snowflake, ThreadMember, ThreadMemberResolvable>, 'add'> {}
|
||||
extends Omit<CachedManager<Snowflake, ThreadMember, ThreadMemberResolvable>, 'add'> {}
|
||||
export class ThreadMemberManager {
|
||||
constructor(thread: ThreadChannel, iterable?: Iterable<any>);
|
||||
public thread: ThreadChannel;
|
||||
@@ -2676,12 +2689,12 @@ declare module 'discord.js' {
|
||||
public remove(id: Snowflake | '@me', reason?: string): Promise<Snowflake>;
|
||||
}
|
||||
|
||||
export class UserManager extends BaseManager<Snowflake, User, UserResolvable> {
|
||||
export class UserManager extends CachedManager<Snowflake, User, UserResolvable> {
|
||||
constructor(client: Client, iterable?: Iterable<any>);
|
||||
public fetch(id: Snowflake, options?: BaseFetchOptions): Promise<User>;
|
||||
}
|
||||
|
||||
export class VoiceStateManager extends BaseManager<Snowflake, VoiceState, typeof VoiceState> {
|
||||
export class VoiceStateManager extends CachedManager<Snowflake, VoiceState, typeof VoiceState> {
|
||||
constructor(guild: Guild, iterable?: Iterable<any>);
|
||||
public guild: Guild;
|
||||
}
|
||||
@@ -3008,6 +3021,8 @@ declare module 'discord.js' {
|
||||
|
||||
type BufferResolvable = Buffer | string;
|
||||
|
||||
type CacheFactory = <T>(manager: { name: string }, holds: { name: string }) => Collection<Snowflake, T>;
|
||||
|
||||
interface ChannelCreationOverwrites {
|
||||
allow?: PermissionResolvable;
|
||||
deny?: PermissionResolvable;
|
||||
@@ -3133,7 +3148,7 @@ declare module 'discord.js' {
|
||||
interface ClientOptions {
|
||||
shards?: number | number[] | 'auto';
|
||||
shardCount?: number;
|
||||
messageCacheMaxSize?: number;
|
||||
makeCache?: CacheFactory;
|
||||
messageCacheLifetime?: number;
|
||||
messageSweepInterval?: number;
|
||||
allowedMentions?: MessageMentionOptions;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import {
|
||||
Client,
|
||||
Options,
|
||||
Collection,
|
||||
Intents,
|
||||
Message,
|
||||
@@ -17,6 +18,9 @@ import {
|
||||
|
||||
const client: Client = new Client({
|
||||
intents: Intents.NON_PRIVILEGED,
|
||||
makeCache: Options.cacheWithLimits({
|
||||
MessageManager: 200,
|
||||
}),
|
||||
});
|
||||
|
||||
const testGuildID = '222078108977594368'; // DJS
|
||||
|
||||
Reference in New Issue
Block a user