mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 08:33:30 +01:00
Datastore cleanup (#1892)
* Start Store cleanup * wip store cleanup * fix iterables initiating datastores * handle the possibility of a datastore with no holds and no its own 'create' method * more cleanup (instances that need more than just client/data) * missed RoleStore extras * not sure how eslint didn't catch that tab... * avoid re-getting the channel we already have... * cleanup resolvers and refactor them into DataStores * ^ * and remove * fix some bugs * fix lint * fix documentation maybe? * formatting * fix presences * really fix presences this time * bad fix was bad... let;s see how bad this one is.. * forgot to save a file * make presence resolving take userresolveables too * fix tabs in jsdocs * fix bad fix from last night that caused issues, with better fix... * oops
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
const EventEmitter = require('events');
|
||||
const RESTManager = require('../rest/RESTManager');
|
||||
const ClientDataResolver = require('./ClientDataResolver');
|
||||
const Util = require('../util/Util');
|
||||
const Constants = require('../util/Constants');
|
||||
|
||||
@@ -25,13 +24,6 @@ class BaseClient extends EventEmitter {
|
||||
*/
|
||||
this.rest = new RESTManager(this, options._tokenType);
|
||||
|
||||
/**
|
||||
* The data resolver of the client
|
||||
* @type {ClientDataResolver}
|
||||
* @private
|
||||
*/
|
||||
this.resolver = new ClientDataResolver(this);
|
||||
|
||||
/**
|
||||
* Timeouts set by {@link WebhookClient#setTimeout} that are still active
|
||||
* @type {Set<Timeout>}
|
||||
|
||||
@@ -17,6 +17,7 @@ const ChannelStore = require('../stores/ChannelStore');
|
||||
const GuildStore = require('../stores/GuildStore');
|
||||
const ClientPresenceStore = require('../stores/ClientPresenceStore');
|
||||
const Constants = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
|
||||
/**
|
||||
@@ -292,7 +293,7 @@ class Client extends BaseClient {
|
||||
* @returns {Promise<Invite>}
|
||||
*/
|
||||
fetchInvite(invite) {
|
||||
const code = this.resolver.resolveInviteCode(invite);
|
||||
const code = DataResolver.resolveInviteCode(invite);
|
||||
return this.api.invites(code).get({ query: { with_counts: true } })
|
||||
.then(data => new Invite(this, data));
|
||||
}
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const snekfetch = require('snekfetch');
|
||||
|
||||
const Util = require('../util/Util');
|
||||
const User = require('../structures/User');
|
||||
const Message = require('../structures/Message');
|
||||
const Guild = require('../structures/Guild');
|
||||
const Channel = require('../structures/Channel');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const Role = require('../structures/Role');
|
||||
const Emoji = require('../structures/Emoji');
|
||||
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them, e.g.
|
||||
* extracting a User from a Message object.
|
||||
* @private
|
||||
*/
|
||||
class ClientDataResolver {
|
||||
/**
|
||||
* @param {Client} client The client the resolver is for
|
||||
*/
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a User object. This can be:
|
||||
* * A User object
|
||||
* * A Snowflake
|
||||
* * A Message object (resolves to the message author)
|
||||
* * A GuildMember object
|
||||
* @typedef {User|Snowflake|Message|GuildMember} UserResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a UserResolvable to a User object.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @returns {?User}
|
||||
*/
|
||||
resolveUser(user) {
|
||||
if (user instanceof User) return user;
|
||||
if (typeof user === 'string') return this.client.users.get(user) || null;
|
||||
if (user instanceof GuildMember) return user.user;
|
||||
if (user instanceof Message) return user.author;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a UserResolvable to a user ID string.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveUserID(user) {
|
||||
if (user instanceof User || user instanceof GuildMember) return user.id;
|
||||
if (typeof user === 'string') return user || null;
|
||||
if (user instanceof Message) return user.author.id;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a Guild object. This can be:
|
||||
* * A Guild object
|
||||
* * A Snowflake
|
||||
* @typedef {Guild|Snowflake} GuildResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a GuildResolvable to a Guild object.
|
||||
* @param {GuildResolvable} guild The GuildResolvable to identify
|
||||
* @returns {?Guild}
|
||||
*/
|
||||
resolveGuild(guild) {
|
||||
if (guild instanceof Guild) return guild;
|
||||
if (typeof guild === 'string') return this.client.guilds.get(guild) || null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a GuildMember object. This can be:
|
||||
* * A GuildMember object
|
||||
* * A User object
|
||||
* @typedef {GuildMember|User} GuildMemberResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a GuildMemberResolvable to a GuildMember object.
|
||||
* @param {GuildResolvable} guild The guild that the member is part of
|
||||
* @param {UserResolvable} user The user that is part of the guild
|
||||
* @returns {?GuildMember}
|
||||
*/
|
||||
resolveGuildMember(guild, user) {
|
||||
if (user instanceof GuildMember) return user;
|
||||
guild = this.resolveGuild(guild);
|
||||
user = this.resolveUser(user);
|
||||
if (!guild || !user) return null;
|
||||
return guild.members.get(user.id) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Role object. This can be:
|
||||
* * A Role
|
||||
* * A Snowflake
|
||||
* @typedef {Role|Snowflake} RoleResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a RoleResolvable to a Role object.
|
||||
* @param {GuildResolvable} guild The guild that this role is part of
|
||||
* @param {RoleResolvable} role The role resolvable to resolve
|
||||
* @returns {?Role}
|
||||
*/
|
||||
resolveRole(guild, role) {
|
||||
if (role instanceof Role) return role;
|
||||
guild = this.resolveGuild(guild);
|
||||
if (!guild) return null;
|
||||
if (typeof role === 'string') return guild.roles.get(role);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Channel object. This can be:
|
||||
* * A Channel object
|
||||
* * A Snowflake
|
||||
* @typedef {Channel|Snowflake} ChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a ChannelResolvable to a Channel object.
|
||||
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||
* @returns {?Channel}
|
||||
*/
|
||||
resolveChannel(channel) {
|
||||
if (channel instanceof Channel) return channel;
|
||||
if (typeof channel === 'string') return this.client.channels.get(channel) || null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a ChannelResolvable to a channel ID.
|
||||
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveChannelID(channel) {
|
||||
if (channel instanceof Channel) return channel.id;
|
||||
if (typeof channel === 'string') return channel;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give an invite code. This can be:
|
||||
* * An invite code
|
||||
* * An invite URL
|
||||
* @typedef {string} InviteResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves InviteResolvable to an invite code.
|
||||
* @param {InviteResolvable} data The invite resolvable to resolve
|
||||
* @returns {string}
|
||||
*/
|
||||
resolveInviteCode(data) {
|
||||
const inviteRegex = /discord(?:app\.com\/invite|\.gg)\/([\w-]{2,255})/i;
|
||||
const match = inviteRegex.exec(data);
|
||||
if (match && match[1]) return match[1];
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a Base64Resolvable, a string, or a BufferResolvable to a Base 64 image.
|
||||
* @param {BufferResolvable|Base64Resolvable} image The image to be resolved
|
||||
* @returns {Promise<?string>}
|
||||
*/
|
||||
async resolveImage(image) {
|
||||
if (!image) return null;
|
||||
if (typeof image === 'string' && image.startsWith('data:')) {
|
||||
return image;
|
||||
}
|
||||
const file = await this.resolveFile(image);
|
||||
return this.resolveBase64(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a Base64 string, typically for image uploading. This can be:
|
||||
* * A Buffer
|
||||
* * A base64 string
|
||||
* @typedef {Buffer|string} Base64Resolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a Base64Resolvable to a Base 64 image.
|
||||
* @param {Base64Resolvable} data The base 64 resolvable you want to resolve
|
||||
* @returns {?string}
|
||||
*/
|
||||
resolveBase64(data) {
|
||||
if (data instanceof Buffer) return `data:image/jpg;base64,${data.toString('base64')}`;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Buffer. This can be:
|
||||
* * A Buffer
|
||||
* * The path to a local file
|
||||
* * A URL
|
||||
* @typedef {string|Buffer} BufferResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external Stream
|
||||
* @see {@link https://nodejs.org/api/stream.html}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a BufferResolvable to a Buffer.
|
||||
* @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
|
||||
* @returns {Promise<Buffer>}
|
||||
*/
|
||||
resolveFile(resource) {
|
||||
if (resource instanceof Buffer) return Promise.resolve(resource);
|
||||
if (this.client.browser && resource instanceof ArrayBuffer) return Promise.resolve(Util.convertToBuffer(resource));
|
||||
|
||||
if (typeof resource === 'string') {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (/^https?:\/\//.test(resource)) {
|
||||
snekfetch.get(resource)
|
||||
.end((err, res) => {
|
||||
if (err) return reject(err);
|
||||
if (!(res.body instanceof Buffer)) return reject(new TypeError('REQ_BODY_TYPE'));
|
||||
return resolve(res.body);
|
||||
});
|
||||
} else {
|
||||
const file = path.resolve(resource);
|
||||
fs.stat(file, (err, stats) => {
|
||||
if (err) return reject(err);
|
||||
if (!stats || !stats.isFile()) return reject(new Error('FILE_NOT_FOUND', file));
|
||||
fs.readFile(file, (err2, data) => {
|
||||
if (err2) reject(err2); else resolve(data);
|
||||
});
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (resource.pipe && typeof resource.pipe === 'function') {
|
||||
return new Promise((resolve, reject) => {
|
||||
const buffers = [];
|
||||
resource.once('error', reject);
|
||||
resource.on('data', data => buffers.push(data));
|
||||
resource.once('end', () => resolve(Buffer.concat(buffers)));
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new TypeError('REQ_RESOURCE_TYPE'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give an emoji identifier. This can be:
|
||||
* * The unicode representation of an emoji
|
||||
* * A custom emoji ID
|
||||
* * An Emoji object
|
||||
* * A ReactionEmoji object
|
||||
* @typedef {string|Snowflake|Emoji|ReactionEmoji} EmojiIdentifierResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an EmojiResolvable to an emoji identifier.
|
||||
* @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve
|
||||
* @returns {?string}
|
||||
*/
|
||||
resolveEmojiIdentifier(emoji) {
|
||||
if (emoji instanceof Emoji || emoji instanceof ReactionEmoji) return emoji.identifier;
|
||||
if (typeof emoji === 'string') {
|
||||
if (this.client.emojis.has(emoji)) return this.client.emojis.get(emoji).identifier;
|
||||
else if (!emoji.includes('%')) return encodeURIComponent(emoji);
|
||||
else return emoji;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientDataResolver;
|
||||
@@ -123,7 +123,7 @@ class VoiceReceiver extends EventEmitter {
|
||||
* @returns {ReadableStream}
|
||||
*/
|
||||
createOpusStream(user) {
|
||||
user = this.voiceConnection.voiceManager.client.resolver.resolveUser(user);
|
||||
user = this.voiceConnection.voiceManager.client.users.resolve(user);
|
||||
if (!user) throw new Error('VOICE_USER_MISSING');
|
||||
if (this.opusStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
||||
const stream = new Readable();
|
||||
@@ -138,7 +138,7 @@ class VoiceReceiver extends EventEmitter {
|
||||
* @returns {ReadableStream}
|
||||
*/
|
||||
createPCMStream(user) {
|
||||
user = this.voiceConnection.voiceManager.client.resolver.resolveUser(user);
|
||||
user = this.voiceConnection.voiceManager.client.users.resolve(user);
|
||||
if (!user) throw new Error('VOICE_USER_MISSING');
|
||||
if (this.pcmStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
||||
const stream = new Readable();
|
||||
|
||||
Reference in New Issue
Block a user