mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 02:23:31 +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 EventEmitter = require('events');
|
||||||
const RESTManager = require('../rest/RESTManager');
|
const RESTManager = require('../rest/RESTManager');
|
||||||
const ClientDataResolver = require('./ClientDataResolver');
|
|
||||||
const Util = require('../util/Util');
|
const Util = require('../util/Util');
|
||||||
const Constants = require('../util/Constants');
|
const Constants = require('../util/Constants');
|
||||||
|
|
||||||
@@ -25,13 +24,6 @@ class BaseClient extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
this.rest = new RESTManager(this, options._tokenType);
|
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
|
* Timeouts set by {@link WebhookClient#setTimeout} that are still active
|
||||||
* @type {Set<Timeout>}
|
* @type {Set<Timeout>}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const ChannelStore = require('../stores/ChannelStore');
|
|||||||
const GuildStore = require('../stores/GuildStore');
|
const GuildStore = require('../stores/GuildStore');
|
||||||
const ClientPresenceStore = require('../stores/ClientPresenceStore');
|
const ClientPresenceStore = require('../stores/ClientPresenceStore');
|
||||||
const Constants = require('../util/Constants');
|
const Constants = require('../util/Constants');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const { Error, TypeError, RangeError } = require('../errors');
|
const { Error, TypeError, RangeError } = require('../errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -292,7 +293,7 @@ class Client extends BaseClient {
|
|||||||
* @returns {Promise<Invite>}
|
* @returns {Promise<Invite>}
|
||||||
*/
|
*/
|
||||||
fetchInvite(invite) {
|
fetchInvite(invite) {
|
||||||
const code = this.resolver.resolveInviteCode(invite);
|
const code = DataResolver.resolveInviteCode(invite);
|
||||||
return this.api.invites(code).get({ query: { with_counts: true } })
|
return this.api.invites(code).get({ query: { with_counts: true } })
|
||||||
.then(data => new Invite(this, data));
|
.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}
|
* @returns {ReadableStream}
|
||||||
*/
|
*/
|
||||||
createOpusStream(user) {
|
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 (!user) throw new Error('VOICE_USER_MISSING');
|
||||||
if (this.opusStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
if (this.opusStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
||||||
const stream = new Readable();
|
const stream = new Readable();
|
||||||
@@ -138,7 +138,7 @@ class VoiceReceiver extends EventEmitter {
|
|||||||
* @returns {ReadableStream}
|
* @returns {ReadableStream}
|
||||||
*/
|
*/
|
||||||
createPCMStream(user) {
|
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 (!user) throw new Error('VOICE_USER_MISSING');
|
||||||
if (this.pcmStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
if (this.pcmStreams.get(user.id)) throw new Error('VOICE_STREAM_EXISTS');
|
||||||
const stream = new Readable();
|
const stream = new Readable();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ module.exports = {
|
|||||||
// Utilities
|
// Utilities
|
||||||
Collection: require('./util/Collection'),
|
Collection: require('./util/Collection'),
|
||||||
Constants: require('./util/Constants'),
|
Constants: require('./util/Constants'),
|
||||||
|
DataResolver: require('./util/DataResolver'),
|
||||||
DiscordAPIError: require('./rest/DiscordAPIError'),
|
DiscordAPIError: require('./rest/DiscordAPIError'),
|
||||||
EvaluatedPermissions: require('./util/Permissions'),
|
EvaluatedPermissions: require('./util/Permissions'),
|
||||||
Permissions: require('./util/Permissions'),
|
Permissions: require('./util/Permissions'),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class ChannelStore extends DataStore {
|
|||||||
options = iterableOrOptions;
|
options = iterableOrOptions;
|
||||||
iterableOrOptions = undefined;
|
iterableOrOptions = undefined;
|
||||||
}
|
}
|
||||||
super(client, iterableOrOptions);
|
super(client, iterableOrOptions, Channel);
|
||||||
|
|
||||||
if (options.lru) {
|
if (options.lru) {
|
||||||
const lru = this[kLru] = [];
|
const lru = this[kLru] = [];
|
||||||
@@ -72,6 +72,29 @@ class ChannelStore extends DataStore {
|
|||||||
if (channel.guild) channel.guild.channels.remove(id);
|
if (channel.guild) channel.guild.channels.remove(id);
|
||||||
super.remove(id);
|
super.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @method resolve
|
||||||
|
* @memberof ChannelStore
|
||||||
|
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||||
|
* @returns {?Channel}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a ChannelResolvable to a channel ID string.
|
||||||
|
* @method resolveID
|
||||||
|
* @memberof ChannelStore
|
||||||
|
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ChannelStore;
|
module.exports = ChannelStore;
|
||||||
|
|||||||
@@ -5,15 +5,45 @@ const Collection = require('../util/Collection');
|
|||||||
* @extends {Collection}
|
* @extends {Collection}
|
||||||
*/
|
*/
|
||||||
class DataStore extends Collection {
|
class DataStore extends Collection {
|
||||||
constructor(client, iterable) {
|
constructor(client, iterable, holds) {
|
||||||
super();
|
super();
|
||||||
Object.defineProperty(this, 'client', { value: client });
|
Object.defineProperty(this, 'client', { value: client });
|
||||||
|
Object.defineProperty(this, 'holds', { value: holds });
|
||||||
if (iterable) for (const item of iterable) this.create(item);
|
if (iterable) for (const item of iterable) this.create(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stubs
|
create(data, cache = true, { id, extras = [] } = {}) {
|
||||||
create() { return undefined; }
|
const existing = this.get(id || data.id);
|
||||||
|
if (existing) return existing;
|
||||||
|
|
||||||
|
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
|
||||||
|
if (cache) this.set(id || entry.id, entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
remove(key) { return this.delete(key); }
|
remove(key) { return this.delete(key); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a data entry to a data Object.
|
||||||
|
* @param {string|Object} idOrInstance The id or instance of something in this datastore
|
||||||
|
* @returns {?Object} An instance from this datastore
|
||||||
|
*/
|
||||||
|
resolve(idOrInstance) {
|
||||||
|
if (idOrInstance instanceof this.holds) return idOrInstance;
|
||||||
|
if (typeof idOrInstance === 'string') return this.get(idOrInstance) || null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a data entry to a instance ID.
|
||||||
|
* @param {string|Instance} idOrInstance The id or instance of something in this datastore
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveID(idOrInstance) {
|
||||||
|
if (idOrInstance instanceof this.holds) return idOrInstance.id;
|
||||||
|
if (typeof channel === 'string') return idOrInstance;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DataStore;
|
module.exports = DataStore;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const Emoji = require('../structures/Emoji');
|
const Emoji = require('../structures/Emoji');
|
||||||
|
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores emojis.
|
* Stores emojis.
|
||||||
* @private
|
* @private
|
||||||
@@ -7,20 +9,62 @@ const Emoji = require('../structures/Emoji');
|
|||||||
*/
|
*/
|
||||||
class EmojiStore extends DataStore {
|
class EmojiStore extends DataStore {
|
||||||
constructor(guild, iterable) {
|
constructor(guild, iterable) {
|
||||||
super(guild.client, iterable);
|
super(guild.client, iterable, Emoji);
|
||||||
this.guild = guild;
|
this.guild = guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
create(data) {
|
create(data, cache) {
|
||||||
const guild = this.guild;
|
super.create(data, cache, { extras: [this.guild] });
|
||||||
|
}
|
||||||
|
|
||||||
const existing = guild.emojis.get(data.id);
|
/**
|
||||||
if (existing) return existing;
|
* Data that can be resolved into an Emoji object. This can be:
|
||||||
|
* * A custom emoji ID
|
||||||
|
* * An Emoji object
|
||||||
|
* * A ReactionEmoji object
|
||||||
|
* @typedef {Snowflake|Emoji|ReactionEmoji} EmojiResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
const emoji = new Emoji(guild, data);
|
/**
|
||||||
guild.emojis.set(emoji.id, emoji);
|
* Resolves a EmojiResolvable to a Emoji object.
|
||||||
|
* @param {EmojiResolvable} emoji The Emoji resolvable to identify
|
||||||
|
* @returns {?Emoji}
|
||||||
|
*/
|
||||||
|
resolve(emoji) {
|
||||||
|
if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id);
|
||||||
|
return super.resolve(emoji);
|
||||||
|
}
|
||||||
|
|
||||||
return emoji;
|
/**
|
||||||
|
* Resolves a EmojiResolvable to a Emoji ID string.
|
||||||
|
* @param {EmojiResolvable} emoji The Emoji resolvable to identify
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveID(emoji) {
|
||||||
|
if (emoji instanceof ReactionEmoji) return emoji.id;
|
||||||
|
return super.resolveID(emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that can be resolved to give an emoji identifier. This can be:
|
||||||
|
* * The unicode representation of an emoji
|
||||||
|
* * An EmojiResolveable
|
||||||
|
* @typedef {string|EmojiResolvable} EmojiIdentifierResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves an EmojiResolvable to an emoji identifier.
|
||||||
|
* @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveIdentifier(emoji) {
|
||||||
|
const emojiResolveable = this.resolve(emoji);
|
||||||
|
if (emojiResolveable) return emojiResolveable.identifier;
|
||||||
|
if (typeof emoji === 'string') {
|
||||||
|
if (!emoji.includes('%')) return encodeURIComponent(emoji);
|
||||||
|
else return emoji;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const Channel = require('../structures/Channel');
|
const Channel = require('../structures/Channel');
|
||||||
|
const GuildChannel = require('../structures/GuildChannel');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores guild channels.
|
* Stores guild channels.
|
||||||
@@ -8,7 +9,7 @@ const Channel = require('../structures/Channel');
|
|||||||
*/
|
*/
|
||||||
class GuildChannelStore extends DataStore {
|
class GuildChannelStore extends DataStore {
|
||||||
constructor(guild, iterable) {
|
constructor(guild, iterable) {
|
||||||
super(guild.client, iterable);
|
super(guild.client, iterable, GuildChannel);
|
||||||
this.guild = guild;
|
this.guild = guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,6 +19,29 @@ class GuildChannelStore extends DataStore {
|
|||||||
|
|
||||||
return Channel.create(this.client, data, this.guild);
|
return Channel.create(this.client, data, this.guild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that can be resolved to give a Channel object. This can be:
|
||||||
|
* * A GuildChannel object
|
||||||
|
* * A Snowflake
|
||||||
|
* @typedef {Channel|Snowflake} GuildChannelResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a GuildChannelResolvable to a Channel object.
|
||||||
|
* @method resolve
|
||||||
|
* @memberof GuildChannelStore
|
||||||
|
* @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve
|
||||||
|
* @returns {?Channel}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a GuildChannelResolvable to a channel ID string.
|
||||||
|
* @method resolveID
|
||||||
|
* @memberof GuildChannelStore
|
||||||
|
* @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = GuildChannelStore;
|
module.exports = GuildChannelStore;
|
||||||
|
|||||||
@@ -10,18 +10,44 @@ const { Error } = require('../errors');
|
|||||||
*/
|
*/
|
||||||
class GuildMemberStore extends DataStore {
|
class GuildMemberStore extends DataStore {
|
||||||
constructor(guild, iterable) {
|
constructor(guild, iterable) {
|
||||||
super(guild.client, iterable);
|
super(guild.client, iterable, GuildMember);
|
||||||
this.guild = guild;
|
this.guild = guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
create(data, cache = true) {
|
create(data, cache) {
|
||||||
const existing = this.get(data.user.id);
|
return super.create(data, cache, { extras: [this.guild] });
|
||||||
if (existing) return existing;
|
}
|
||||||
|
|
||||||
const member = new GuildMember(this.guild, data);
|
/**
|
||||||
if (cache) this.set(member.id, member);
|
* Data that resolves to give a GuildMember object. This can be:
|
||||||
|
* * A GuildMember object
|
||||||
|
* * A User resolvable
|
||||||
|
* @typedef {GuildMember|UserResolveable} GuildMemberResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
return member;
|
/**
|
||||||
|
* Resolves a GuildMemberResolvable to a GuildMember object.
|
||||||
|
* @param {GuildMemberResolvable} member The user that is part of the guild
|
||||||
|
* @returns {?GuildMember}
|
||||||
|
*/
|
||||||
|
resolve(member) {
|
||||||
|
const memberResolveable = super.resolve(member);
|
||||||
|
if (memberResolveable) return memberResolveable;
|
||||||
|
const userResolveable = this.client.users.resolveID(member);
|
||||||
|
if (userResolveable) return super.resolve(userResolveable);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a GuildMemberResolvable to an member ID string.
|
||||||
|
* @param {GuildMemberResolvable} member The user that is part of the guild
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveID(member) {
|
||||||
|
const memberResolveable = super.resolveID(member);
|
||||||
|
if (memberResolveable) return memberResolveable;
|
||||||
|
const userResolveable = this.client.users.resolveID(member);
|
||||||
|
return this.has(userResolveable) ? userResolveable : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,10 +90,10 @@ class GuildMemberStore extends DataStore {
|
|||||||
*/
|
*/
|
||||||
fetch(options) {
|
fetch(options) {
|
||||||
if (!options) return this._fetchMany();
|
if (!options) return this._fetchMany();
|
||||||
const user = this.client.resolver.resolveUserID(options);
|
const user = this.resolveID(options);
|
||||||
if (user) return this._fetchSingle({ user, cache: true });
|
if (user) return this._fetchSingle({ user, cache: true });
|
||||||
if (options.user) {
|
if (options.user) {
|
||||||
options.user = this.client.resolver.resolveUserID(options.user);
|
options.user = this.resolveID(options.user);
|
||||||
if (options.user) return this._fetchSingle(options);
|
if (options.user) return this._fetchSingle(options);
|
||||||
}
|
}
|
||||||
return this._fetchMany(options);
|
return this._fetchMany(options);
|
||||||
|
|||||||
@@ -1,20 +1,38 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const Guild = require('../structures/Guild');
|
const Guild = require('../structures/Guild');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores guilds.
|
* Stores guilds.
|
||||||
* @private
|
* @private
|
||||||
* @extends {DataStore}
|
* @extends {DataStore}
|
||||||
*/
|
*/
|
||||||
class GuildStore extends DataStore {
|
class GuildStore extends DataStore {
|
||||||
create(data, cache = true) {
|
constructor(client, iterable) {
|
||||||
const existing = this.get(data.id);
|
super(client, iterable, Guild);
|
||||||
if (existing) return existing;
|
|
||||||
|
|
||||||
const guild = new Guild(this.client, data);
|
|
||||||
if (cache) this.set(guild.id, guild);
|
|
||||||
|
|
||||||
return guild;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @method resolve
|
||||||
|
* @memberof GuildStore
|
||||||
|
* @param {GuildResolvable} guild The guild resolvable to identify
|
||||||
|
* @returns {?Guild}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a GuildResolvable to a Guild ID string.
|
||||||
|
* @method resolveID
|
||||||
|
* @memberof GuildStore
|
||||||
|
* @param {GuildResolvable} guild The guild resolvable to identify
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = GuildStore;
|
module.exports = GuildStore;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const Collection = require('../util/Collection');
|
const Collection = require('../util/Collection');
|
||||||
|
const Message = require('../structures/Message');
|
||||||
const { Error } = require('../errors');
|
const { Error } = require('../errors');
|
||||||
let Message;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores messages for text-based channels.
|
* Stores messages for text-based channels.
|
||||||
@@ -9,19 +9,12 @@ let Message;
|
|||||||
*/
|
*/
|
||||||
class MessageStore extends DataStore {
|
class MessageStore extends DataStore {
|
||||||
constructor(channel, iterable) {
|
constructor(channel, iterable) {
|
||||||
super(channel.client, iterable);
|
super(channel.client, iterable, Message);
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
Message = require('../structures/Message');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create(data, cache = true) {
|
create(data, cache) {
|
||||||
const existing = this.get(data.id);
|
return super.create(data, cache, { extras: [this.channel] });
|
||||||
if (existing) return existing;
|
|
||||||
|
|
||||||
const message = new Message(this.client.channels.get(data.channel_id), data, this.client);
|
|
||||||
|
|
||||||
if (cache) this.set(message.id, message);
|
|
||||||
return message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key, value) {
|
set(key, value) {
|
||||||
@@ -95,6 +88,30 @@ class MessageStore extends DataStore {
|
|||||||
return messages;
|
return messages;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that can be resolved to a Message object. This can be:
|
||||||
|
* * A Message
|
||||||
|
* * A Snowflake
|
||||||
|
* @typedef {Message|Snowflake} MessageResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a MessageResolvable to a Message object.
|
||||||
|
* @method resolve
|
||||||
|
* @memberof MessageStore
|
||||||
|
* @param {MessageResolvable} message The message resolvable to resolve
|
||||||
|
* @returns {?Message}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a MessageResolvable to a Message ID string.
|
||||||
|
* @method MessageStore
|
||||||
|
* @memberof PresenceStore
|
||||||
|
* @param {MessageResolvable} message The message resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = MessageStore;
|
module.exports = MessageStore;
|
||||||
|
|||||||
@@ -2,13 +2,46 @@ const DataStore = require('./DataStore');
|
|||||||
const { Presence } = require('../structures/Presence');
|
const { Presence } = require('../structures/Presence');
|
||||||
|
|
||||||
class PresenceStore extends DataStore {
|
class PresenceStore extends DataStore {
|
||||||
create(data) {
|
constructor(client, iterable) {
|
||||||
if (this.has(data.user.id)) {
|
super(client, iterable, Presence);
|
||||||
this.get(data.user.id).patch(data);
|
}
|
||||||
} else {
|
|
||||||
this.set(data.user.id, new Presence(this.client, data));
|
create(data, cache) {
|
||||||
}
|
const existing = this.get(data.user.id);
|
||||||
return this.get(data.user.id);
|
return existing ? existing.patch(data) : super.create(data, cache, { id: data.user.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that can be resolved to a Presence object. This can be:
|
||||||
|
* * A Presence
|
||||||
|
* * A UserResolveable
|
||||||
|
* * A Snowflake
|
||||||
|
* @typedef {Presence|UserResolveable|Snowflake} PresenceResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a PresenceResolvable to a Presence object.
|
||||||
|
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||||
|
* @returns {?Presence}
|
||||||
|
*/
|
||||||
|
resolve(presence) {
|
||||||
|
const presenceResolveable = super.resolve(presence);
|
||||||
|
if (presenceResolveable) return presenceResolveable;
|
||||||
|
const UserResolveable = this.client.users.resolveID(presence);
|
||||||
|
return super.resolve(UserResolveable) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a PresenceResolvable to a Presence ID string.
|
||||||
|
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveID(presence) {
|
||||||
|
const presenceResolveable = super.resolveID(presence);
|
||||||
|
if (presenceResolveable) return presenceResolveable;
|
||||||
|
const userResolveable = this.client.users.resolveID(presence);
|
||||||
|
return this.has(userResolveable) ? userResolveable : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const MessageReaction = require('../structures/MessageReaction');
|
const MessageReaction = require('../structures/MessageReaction');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores reactions.
|
* Stores reactions.
|
||||||
* @private
|
* @private
|
||||||
@@ -7,21 +8,37 @@ const MessageReaction = require('../structures/MessageReaction');
|
|||||||
*/
|
*/
|
||||||
class ReactionStore extends DataStore {
|
class ReactionStore extends DataStore {
|
||||||
constructor(message, iterable) {
|
constructor(message, iterable) {
|
||||||
super(message.client, iterable);
|
super(message.client, iterable, MessageReaction);
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
create(data) {
|
create(data, cache) {
|
||||||
const emojiID = data.emoji.id || decodeURIComponent(data.emoji.name);
|
data.emoji.id = data.emoji.id || decodeURIComponent(data.emoji.name);
|
||||||
|
return super.create(data, cache, { id: data.emoji.id, extras: [this.message] });
|
||||||
const existing = this.get(emojiID);
|
|
||||||
if (existing) return existing;
|
|
||||||
|
|
||||||
const reaction = new MessageReaction(this.message, data.emoji, data.count, data.me);
|
|
||||||
this.set(emojiID, reaction);
|
|
||||||
|
|
||||||
return reaction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that can be resolved to a MessageReaction object. This can be:
|
||||||
|
* * A MessageReaction
|
||||||
|
* * A Snowflake
|
||||||
|
* @typedef {MessageReaction|Snowflake} MessageReactionResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a MessageReactionResolvable to a MessageReaction object.
|
||||||
|
* @method resolve
|
||||||
|
* @memberof ReactionStore
|
||||||
|
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||||
|
* @returns {?MessageReaction}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a MessageReactionResolvable to a MessageReaction ID string.
|
||||||
|
* @method resolveID
|
||||||
|
* @memberof ReactionStore
|
||||||
|
* @param {MessageReactionResolvable} role The role resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ReactionStore;
|
module.exports = ReactionStore;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const Role = require('../structures/Role');
|
const Role = require('../structures/Role');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores roles.
|
* Stores roles.
|
||||||
* @private
|
* @private
|
||||||
@@ -7,19 +8,36 @@ const Role = require('../structures/Role');
|
|||||||
*/
|
*/
|
||||||
class RoleStore extends DataStore {
|
class RoleStore extends DataStore {
|
||||||
constructor(guild, iterable) {
|
constructor(guild, iterable) {
|
||||||
super(guild.client, iterable);
|
super(guild.client, iterable, Role);
|
||||||
this.guild = guild;
|
this.guild = guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
create(data) {
|
create(data, cache) {
|
||||||
const existing = this.get(data.id);
|
return super.create(data, cache, { extras: [this.guild] });
|
||||||
if (existing) return existing;
|
|
||||||
|
|
||||||
const role = new Role(this.guild, data);
|
|
||||||
this.set(role.id, role);
|
|
||||||
|
|
||||||
return role;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @method resolve
|
||||||
|
* @memberof RoleStore
|
||||||
|
* @param {RoleResolvable} role The role resolvable to resolve
|
||||||
|
* @returns {?Role}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a RoleResolvable to a role ID string.
|
||||||
|
* @method resolveID
|
||||||
|
* @memberof RoleStore
|
||||||
|
* @param {RoleResolvable} role The role resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = RoleStore;
|
module.exports = RoleStore;
|
||||||
|
|||||||
@@ -1,18 +1,46 @@
|
|||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
const User = require('../structures/User');
|
const User = require('../structures/User');
|
||||||
|
const GuildMember = require('../structures/GuildMember');
|
||||||
|
const Message = require('../structures/Message');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data store to store User models.
|
* A data store to store User models.
|
||||||
* @extends {DataStore}
|
* @extends {DataStore}
|
||||||
*/
|
*/
|
||||||
class UserStore extends DataStore {
|
class UserStore extends DataStore {
|
||||||
create(data, cache = true) {
|
constructor(client, iterable) {
|
||||||
const existing = this.get(data.id);
|
super(client, iterable, User);
|
||||||
if (existing) return existing;
|
}
|
||||||
|
|
||||||
const user = new User(this.client, data);
|
/**
|
||||||
if (cache) this.set(user.id, user);
|
* Data that resolves to give a User object. This can be:
|
||||||
return user;
|
* * 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}
|
||||||
|
*/
|
||||||
|
resolve(user) {
|
||||||
|
if (user instanceof GuildMember) return user.user;
|
||||||
|
if (user instanceof Message) return user.author;
|
||||||
|
return super.resolve(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a UserResolvable to a user ID string.
|
||||||
|
* @param {UserResolvable} user The UserResolvable to identify
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveID(user) {
|
||||||
|
if (user instanceof GuildMember) return user.user.id;
|
||||||
|
if (user instanceof Message) return user.author.id;
|
||||||
|
return super.resolveID(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const Snowflake = require('../util/Snowflake');
|
const Snowflake = require('../util/Snowflake');
|
||||||
const Constants = require('../util/Constants');
|
const Constants = require('../util/Constants');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const Base = require('./Base');
|
const Base = require('./Base');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,7 +166,7 @@ class ClientApplication extends Base {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
createAsset(name, data, type) {
|
createAsset(name, data, type) {
|
||||||
return this.client.resolveBase64(data).then(b64 =>
|
return DataResolver.resolveBase64(data).then(b64 =>
|
||||||
this.client.api.applications(this.id).assets.post({ data: {
|
this.client.api.applications(this.id).assets.post({ data: {
|
||||||
name,
|
name,
|
||||||
data: b64,
|
data: b64,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const ClientUserSettings = require('./ClientUserSettings');
|
|||||||
const ClientUserGuildSettings = require('./ClientUserGuildSettings');
|
const ClientUserGuildSettings = require('./ClientUserGuildSettings');
|
||||||
const Constants = require('../util/Constants');
|
const Constants = require('../util/Constants');
|
||||||
const Util = require('../util/Util');
|
const Util = require('../util/Util');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const Guild = require('./Guild');
|
const Guild = require('./Guild');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,7 +178,7 @@ class ClientUser extends User {
|
|||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
async setAvatar(avatar) {
|
async setAvatar(avatar) {
|
||||||
return this.edit({ avatar: await this.client.resolver.resolveImage(avatar) });
|
return this.edit({ avatar: await DataResolver.resolveImage(avatar, this.client.browser) });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,7 +294,7 @@ class ClientUser extends User {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.client.resolver.resolveImage(icon)
|
return DataResolver.resolveImage(icon, this.client.browser)
|
||||||
.then(data => this.createGuild(name, { region, icon: data || null }));
|
.then(data => this.createGuild(name, { region, icon: data || null }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +321,7 @@ class ClientUser extends User {
|
|||||||
if (r.nick) o[r.user ? r.user.id : r.id] = r.nick;
|
if (r.nick) o[r.user ? r.user.id : r.id] = r.nick;
|
||||||
return o;
|
return o;
|
||||||
}, {}),
|
}, {}),
|
||||||
} : { recipients: recipients.map(u => this.client.resolver.resolveUserID(u.user || u.id)) };
|
} : { recipients: recipients.map(u => this.client.users.resolveID(u.user || u.id)) };
|
||||||
return this.client.api.users('@me').channels.post({ data })
|
return this.client.api.users('@me').channels.post({ data })
|
||||||
.then(res => this.client.channels.create(res));
|
.then(res => this.client.channels.create(res));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ const { TypeError } = require('../errors');
|
|||||||
* @extends {Base}
|
* @extends {Base}
|
||||||
*/
|
*/
|
||||||
class Emoji extends Base {
|
class Emoji extends Base {
|
||||||
constructor(guild, data) {
|
constructor(client, data, guild) {
|
||||||
super(guild.client);
|
super(client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The guild this emoji is part of
|
* The guild this emoji is part of
|
||||||
@@ -152,7 +152,7 @@ class Emoji extends Base {
|
|||||||
addRestrictedRoles(roles) {
|
addRestrictedRoles(roles) {
|
||||||
const newRoles = new Collection(this.roles);
|
const newRoles = new Collection(this.roles);
|
||||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||||
'Array or Collection of Roles or Snowflakes', true));
|
'Array or Collection of Roles or Snowflakes', true));
|
||||||
@@ -179,7 +179,7 @@ class Emoji extends Base {
|
|||||||
removeRestrictedRoles(roles) {
|
removeRestrictedRoles(roles) {
|
||||||
const newRoles = new Collection(this.roles);
|
const newRoles = new Collection(this.roles);
|
||||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||||
'Array or Collection of Roles or Snowflakes', true));
|
'Array or Collection of Roles or Snowflakes', true));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const Channel = require('./Channel');
|
const Channel = require('./Channel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
const Collection = require('../util/Collection');
|
const Collection = require('../util/Collection');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const MessageStore = require('../stores/MessageStore');
|
const MessageStore = require('../stores/MessageStore');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -160,7 +161,7 @@ class GroupDMChannel extends Channel {
|
|||||||
* @returns {Promise<GroupDMChannel>}
|
* @returns {Promise<GroupDMChannel>}
|
||||||
*/
|
*/
|
||||||
async setIcon(icon) {
|
async setIcon(icon) {
|
||||||
return this.edit({ icon: await this.client.resolver.resolveImage(icon) });
|
return this.edit({ icon: await DataResolver.resolveImage(icon, this.client.browser) });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,7 +183,7 @@ class GroupDMChannel extends Channel {
|
|||||||
* @returns {Promise<GroupDMChannel>}
|
* @returns {Promise<GroupDMChannel>}
|
||||||
*/
|
*/
|
||||||
addUser({ user, accessToken, nick }) {
|
addUser({ user, accessToken, nick }) {
|
||||||
const id = this.client.resolver.resolveUserID(user);
|
const id = this.client.users.resolveID(user);
|
||||||
const data = this.client.user.bot ?
|
const data = this.client.user.bot ?
|
||||||
{ nick, access_token: accessToken } :
|
{ nick, access_token: accessToken } :
|
||||||
{ recipient: id };
|
{ recipient: id };
|
||||||
@@ -196,7 +197,7 @@ class GroupDMChannel extends Channel {
|
|||||||
* @returns {Promise<GroupDMChannel>}
|
* @returns {Promise<GroupDMChannel>}
|
||||||
*/
|
*/
|
||||||
removeUser(user) {
|
removeUser(user) {
|
||||||
const id = this.client.resolver.resolveUserID(user);
|
const id = this.client.users.resolveID(user);
|
||||||
return this.client.api.channels[this.id].recipients[id].delete()
|
return this.client.api.channels[this.id].recipients[id].delete()
|
||||||
.then(() => this);
|
.then(() => this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const VoiceRegion = require('./VoiceRegion');
|
|||||||
const Constants = require('../util/Constants');
|
const Constants = require('../util/Constants');
|
||||||
const Collection = require('../util/Collection');
|
const Collection = require('../util/Collection');
|
||||||
const Util = require('../util/Util');
|
const Util = require('../util/Util');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const Snowflake = require('../util/Snowflake');
|
const Snowflake = require('../util/Snowflake');
|
||||||
const Permissions = require('../util/Permissions');
|
const Permissions = require('../util/Permissions');
|
||||||
const Shared = require('./shared');
|
const Shared = require('./shared');
|
||||||
@@ -431,7 +432,7 @@ class Guild extends Base {
|
|||||||
* const member = guild.member(message.author);
|
* const member = guild.member(message.author);
|
||||||
*/
|
*/
|
||||||
member(user) {
|
member(user) {
|
||||||
return this.client.resolver.resolveGuildMember(this, user);
|
return this.members.resolve(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -511,7 +512,7 @@ class Guild extends Base {
|
|||||||
before: options.before,
|
before: options.before,
|
||||||
after: options.after,
|
after: options.after,
|
||||||
limit: options.limit,
|
limit: options.limit,
|
||||||
user_id: this.client.resolver.resolveUserID(options.user),
|
user_id: this.client.users.resolveID(options.user),
|
||||||
action_type: options.type,
|
action_type: options.type,
|
||||||
} })
|
} })
|
||||||
.then(data => GuildAuditLogs.build(this, data));
|
.then(data => GuildAuditLogs.build(this, data));
|
||||||
@@ -536,7 +537,7 @@ class Guild extends Base {
|
|||||||
if (options.roles) {
|
if (options.roles) {
|
||||||
const roles = [];
|
const roles = [];
|
||||||
for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) {
|
for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) {
|
||||||
role = this.client.resolver.resolveRole(this, role);
|
role = this.roles.resolve(role);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return Promise.reject(new TypeError('INVALID_TYPE', 'options.roles',
|
return Promise.reject(new TypeError('INVALID_TYPE', 'options.roles',
|
||||||
'Array or Collection of Roles or Snowflakes', true));
|
'Array or Collection of Roles or Snowflakes', true));
|
||||||
@@ -601,14 +602,14 @@ class Guild extends Base {
|
|||||||
if (data.region) _data.region = data.region;
|
if (data.region) _data.region = data.region;
|
||||||
if (typeof data.verificationLevel !== 'undefined') _data.verification_level = Number(data.verificationLevel);
|
if (typeof data.verificationLevel !== 'undefined') _data.verification_level = Number(data.verificationLevel);
|
||||||
if (typeof data.afkChannel !== 'undefined') {
|
if (typeof data.afkChannel !== 'undefined') {
|
||||||
_data.afk_channel_id = this.client.resolver.resolveChannelID(data.afkChannel);
|
_data.afk_channel_id = this.client.channels.resolveID(data.afkChannel);
|
||||||
}
|
}
|
||||||
if (typeof data.systemChannel !== 'undefined') {
|
if (typeof data.systemChannel !== 'undefined') {
|
||||||
_data.system_channel_id = this.client.resolver.resolveChannelID(data.systemChannel);
|
_data.system_channel_id = this.client.channels.resolveID(data.systemChannel);
|
||||||
}
|
}
|
||||||
if (data.afkTimeout) _data.afk_timeout = Number(data.afkTimeout);
|
if (data.afkTimeout) _data.afk_timeout = Number(data.afkTimeout);
|
||||||
if (typeof data.icon !== 'undefined') _data.icon = data.icon;
|
if (typeof data.icon !== 'undefined') _data.icon = data.icon;
|
||||||
if (data.owner) _data.owner_id = this.client.resolver.resolveUser(data.owner).id;
|
if (data.owner) _data.owner_id = this.client.users.resolve(data.owner).id;
|
||||||
if (data.splash) _data.splash = data.splash;
|
if (data.splash) _data.splash = data.splash;
|
||||||
if (typeof data.explicitContentFilter !== 'undefined') {
|
if (typeof data.explicitContentFilter !== 'undefined') {
|
||||||
_data.explicit_content_filter = Number(data.explicitContentFilter);
|
_data.explicit_content_filter = Number(data.explicitContentFilter);
|
||||||
@@ -724,7 +725,7 @@ class Guild extends Base {
|
|||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
async setIcon(icon, reason) {
|
async setIcon(icon, reason) {
|
||||||
return this.edit({ icon: await this.client.resolver.resolveImage(icon), reason });
|
return this.edit({ icon: await DataResolver.resolveImage(icon, this.client.browser), reason });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -754,7 +755,7 @@ class Guild extends Base {
|
|||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
async setSplash(splash, reason) {
|
async setSplash(splash, reason) {
|
||||||
return this.edit({ splash: await this.client.resolver.resolveImage(splash), reason });
|
return this.edit({ splash: await DataResolver.resolveImage(splash, this.client.browser), reason });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -815,14 +816,14 @@ class Guild extends Base {
|
|||||||
*/
|
*/
|
||||||
ban(user, options = { days: 0 }) {
|
ban(user, options = { days: 0 }) {
|
||||||
if (options.days) options['delete-message-days'] = options.days;
|
if (options.days) options['delete-message-days'] = options.days;
|
||||||
const id = this.client.resolver.resolveUserID(user);
|
const id = this.client.users.resolveID(user);
|
||||||
if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID', true));
|
if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID', true));
|
||||||
return this.client.api.guilds(this.id).bans[id].put({ query: options })
|
return this.client.api.guilds(this.id).bans[id].put({ query: options })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (user instanceof GuildMember) return user;
|
if (user instanceof GuildMember) return user;
|
||||||
const _user = this.client.resolver.resolveUser(id);
|
const _user = this.client.users.resolve(id);
|
||||||
if (_user) {
|
if (_user) {
|
||||||
const member = this.client.resolver.resolveGuildMember(this, _user);
|
const member = this.members.resolve(_user);
|
||||||
return member || _user;
|
return member || _user;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
@@ -841,7 +842,7 @@ class Guild extends Base {
|
|||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
unban(user, reason) {
|
unban(user, reason) {
|
||||||
const id = this.client.resolver.resolveUserID(user);
|
const id = this.client.users.resolverID(user);
|
||||||
if (!id) throw new Error('BAN_RESOLVE_ID');
|
if (!id) throw new Error('BAN_RESOLVE_ID');
|
||||||
return this.client.api.guilds(this.id).bans[id].delete({ reason })
|
return this.client.api.guilds(this.id).bans[id].delete({ reason })
|
||||||
.then(() => user);
|
.then(() => user);
|
||||||
@@ -910,12 +911,12 @@ class Guild extends Base {
|
|||||||
if (allow instanceof Array) allow = Permissions.resolve(allow);
|
if (allow instanceof Array) allow = Permissions.resolve(allow);
|
||||||
if (deny instanceof Array) deny = Permissions.resolve(deny);
|
if (deny instanceof Array) deny = Permissions.resolve(deny);
|
||||||
|
|
||||||
const role = this.client.resolver.resolveRole(this, overwrite.id);
|
const role = this.roles.resolve(overwrite.id);
|
||||||
if (role) {
|
if (role) {
|
||||||
overwrite.id = role.id;
|
overwrite.id = role.id;
|
||||||
overwrite.type = 'role';
|
overwrite.type = 'role';
|
||||||
} else {
|
} else {
|
||||||
overwrite.id = this.client.resolver.resolveUserID(overwrite.id);
|
overwrite.id = this.client.users.resolveID(overwrite.id);
|
||||||
overwrite.type = 'member';
|
overwrite.type = 'member';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,7 +989,7 @@ class Guild extends Base {
|
|||||||
*/
|
*/
|
||||||
setChannelPositions(channelPositions) {
|
setChannelPositions(channelPositions) {
|
||||||
const updatedChannels = channelPositions.map(r => ({
|
const updatedChannels = channelPositions.map(r => ({
|
||||||
id: this.client.resolver.resolveChannelID(r.channel),
|
id: this.client.channels.resolveID(r.channel),
|
||||||
position: r.position,
|
position: r.position,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -1063,7 +1064,7 @@ class Guild extends Base {
|
|||||||
if (roles) {
|
if (roles) {
|
||||||
data.roles = [];
|
data.roles = [];
|
||||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||||
role = this.client.resolver.resolveRole(this, role);
|
role = this.roles.resolve(role);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return Promise.reject(new TypeError('INVALID_TYPE', 'options.roles',
|
return Promise.reject(new TypeError('INVALID_TYPE', 'options.roles',
|
||||||
'Array or Collection of Roles or Snowflakes', true));
|
'Array or Collection of Roles or Snowflakes', true));
|
||||||
@@ -1076,7 +1077,7 @@ class Guild extends Base {
|
|||||||
.then(emoji => this.client.actions.GuildEmojiCreate.handle(this, emoji).emoji);
|
.then(emoji => this.client.actions.GuildEmojiCreate.handle(this, emoji).emoji);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.client.resolver.resolveImage(attachment)
|
return DataResolver.resolveImage(attachment, this.client.browser)
|
||||||
.then(image => this.createEmoji(image, name, { roles, reason }));
|
.then(image => this.createEmoji(image, name, { roles, reason }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class GuildChannel extends Channel {
|
|||||||
* @returns {?Permissions}
|
* @returns {?Permissions}
|
||||||
*/
|
*/
|
||||||
permissionsFor(member) {
|
permissionsFor(member) {
|
||||||
member = this.client.resolver.resolveGuildMember(this.guild, member);
|
member = this.guild.members.resolve(member);
|
||||||
if (!member) return null;
|
if (!member) return null;
|
||||||
if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL);
|
if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL);
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ class GuildChannel extends Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
overwritesFor(member, verified = false, roles = null) {
|
overwritesFor(member, verified = false, roles = null) {
|
||||||
if (!verified) member = this.client.resolver.resolveGuildMember(this.guild, member);
|
if (!verified) member = this.guild.members.resolve(member);
|
||||||
if (!member) return [];
|
if (!member) return [];
|
||||||
|
|
||||||
roles = roles || member.roles;
|
roles = roles || member.roles;
|
||||||
@@ -158,13 +158,13 @@ class GuildChannel extends Channel {
|
|||||||
deny: 0,
|
deny: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (userOrRole instanceof Role) {
|
const role = this.guild.roles.get(userOrRole);
|
||||||
payload.type = 'role';
|
|
||||||
} else if (this.guild.roles.has(userOrRole)) {
|
if (role || userOrRole instanceof Role) {
|
||||||
userOrRole = this.guild.roles.get(userOrRole);
|
userOrRole = role || userOrRole;
|
||||||
payload.type = 'role';
|
payload.type = 'role';
|
||||||
} else {
|
} else {
|
||||||
userOrRole = this.client.resolver.resolveUser(userOrRole);
|
userOrRole = this.client.users.resolve(userOrRole);
|
||||||
payload.type = 'member';
|
payload.type = 'member';
|
||||||
if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role', true));
|
if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role', true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ const { Error, TypeError } = require('../errors');
|
|||||||
* @extends {Base}
|
* @extends {Base}
|
||||||
*/
|
*/
|
||||||
class GuildMember extends Base {
|
class GuildMember extends Base {
|
||||||
constructor(guild, data) {
|
constructor(client, data, guild) {
|
||||||
super(guild.client);
|
super(client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The guild that this member is part of
|
* The guild that this member is part of
|
||||||
@@ -291,7 +291,7 @@ class GuildMember extends Base {
|
|||||||
* @returns {?Permissions}
|
* @returns {?Permissions}
|
||||||
*/
|
*/
|
||||||
permissionsIn(channel) {
|
permissionsIn(channel) {
|
||||||
channel = this.client.resolver.resolveChannel(channel);
|
channel = this.client.channels.resolve(channel);
|
||||||
if (!channel || !channel.guild) throw new Error('GUILD_CHANNEL_RESOLVE');
|
if (!channel || !channel.guild) throw new Error('GUILD_CHANNEL_RESOLVE');
|
||||||
return channel.permissionsFor(this);
|
return channel.permissionsFor(this);
|
||||||
}
|
}
|
||||||
@@ -342,7 +342,7 @@ class GuildMember extends Base {
|
|||||||
*/
|
*/
|
||||||
edit(data, reason) {
|
edit(data, reason) {
|
||||||
if (data.channel) {
|
if (data.channel) {
|
||||||
data.channel_id = this.client.resolver.resolveChannel(data.channel).id;
|
data.channel_id = this.client.channels.resolve(data.channel).id;
|
||||||
data.channel = null;
|
data.channel = null;
|
||||||
}
|
}
|
||||||
if (data.roles) data.roles = data.roles.map(role => role instanceof Role ? role.id : role);
|
if (data.roles) data.roles = data.roles.map(role => role instanceof Role ? role.id : role);
|
||||||
@@ -412,7 +412,7 @@ class GuildMember extends Base {
|
|||||||
* @returns {Promise<GuildMember>}
|
* @returns {Promise<GuildMember>}
|
||||||
*/
|
*/
|
||||||
addRole(role, reason) {
|
addRole(role, reason) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'));
|
if (!role) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'));
|
||||||
if (this._roles.includes(role.id)) return Promise.resolve(this);
|
if (this._roles.includes(role.id)) return Promise.resolve(this);
|
||||||
return this.client.api.guilds(this.guild.id).members(this.user.id).roles(role.id)
|
return this.client.api.guilds(this.guild.id).members(this.user.id).roles(role.id)
|
||||||
@@ -433,7 +433,7 @@ class GuildMember extends Base {
|
|||||||
addRoles(roles, reason) {
|
addRoles(roles, reason) {
|
||||||
let allRoles = this._roles.slice();
|
let allRoles = this._roles.slice();
|
||||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||||
'Array or Collection of Roles or Snowflakes', true));
|
'Array or Collection of Roles or Snowflakes', true));
|
||||||
@@ -450,7 +450,7 @@ class GuildMember extends Base {
|
|||||||
* @returns {Promise<GuildMember>}
|
* @returns {Promise<GuildMember>}
|
||||||
*/
|
*/
|
||||||
removeRole(role, reason) {
|
removeRole(role, reason) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'));
|
if (!role) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'));
|
||||||
if (!this._roles.includes(role.id)) return Promise.resolve(this);
|
if (!this._roles.includes(role.id)) return Promise.resolve(this);
|
||||||
return this.client.api.guilds(this.guild.id).members(this.user.id).roles(role.id)
|
return this.client.api.guilds(this.guild.id).members(this.user.id).roles(role.id)
|
||||||
@@ -472,7 +472,7 @@ class GuildMember extends Base {
|
|||||||
removeRoles(roles, reason) {
|
removeRoles(roles, reason) {
|
||||||
const allRoles = this._roles.slice();
|
const allRoles = this._roles.slice();
|
||||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||||
'Array or Collection of Roles or Snowflakes', true));
|
'Array or Collection of Roles or Snowflakes', true));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ let GuildMember;
|
|||||||
* @extends {Base}
|
* @extends {Base}
|
||||||
*/
|
*/
|
||||||
class Message extends Base {
|
class Message extends Base {
|
||||||
constructor(channel, data, client) {
|
constructor(client, data, channel) {
|
||||||
super(client);
|
super(client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -393,7 +393,7 @@ class Message extends Base {
|
|||||||
|
|
||||||
// Add the reply prefix
|
// Add the reply prefix
|
||||||
if (reply && this.channel.type !== 'dm') {
|
if (reply && this.channel.type !== 'dm') {
|
||||||
const id = this.client.resolver.resolveUserID(reply);
|
const id = this.client.users.resolveID(reply);
|
||||||
const mention = `<@${reply instanceof GuildMember && reply.nickname ? '!' : ''}${id}>`;
|
const mention = `<@${reply instanceof GuildMember && reply.nickname ? '!' : ''}${id}>`;
|
||||||
content = `${mention}${content ? `, ${content}` : ''}`;
|
content = `${mention}${content ? `, ${content}` : ''}`;
|
||||||
}
|
}
|
||||||
@@ -427,11 +427,11 @@ class Message extends Base {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a reaction to the message.
|
* Add a reaction to the message.
|
||||||
* @param {string|Emoji|ReactionEmoji} emoji The emoji to react with
|
* @param {EmojiIdentifierResolveable} emoji The emoji to react with
|
||||||
* @returns {Promise<MessageReaction>}
|
* @returns {Promise<MessageReaction>}
|
||||||
*/
|
*/
|
||||||
react(emoji) {
|
react(emoji) {
|
||||||
emoji = this.client.resolver.resolveEmojiIdentifier(emoji);
|
emoji = this.client.emojis.resolveIdentifier(emoji);
|
||||||
if (!emoji) throw new TypeError('EMOJI_TYPE');
|
if (!emoji) throw new TypeError('EMOJI_TYPE');
|
||||||
|
|
||||||
return this.client.api.channels(this.channel.id).messages(this.id).reactions(emoji, '@me')
|
return this.client.api.channels(this.channel.id).messages(this.id).reactions(emoji, '@me')
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const { Error } = require('../errors');
|
|||||||
* Represents a reaction to a message.
|
* Represents a reaction to a message.
|
||||||
*/
|
*/
|
||||||
class MessageReaction {
|
class MessageReaction {
|
||||||
constructor(message, emoji, count, me) {
|
constructor(client, data, message) {
|
||||||
/**
|
/**
|
||||||
* The message that this reaction refers to
|
* The message that this reaction refers to
|
||||||
* @type {Message}
|
* @type {Message}
|
||||||
@@ -18,13 +18,13 @@ class MessageReaction {
|
|||||||
* Whether the client has given this reaction
|
* Whether the client has given this reaction
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
this.me = me;
|
this.me = data.me;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of people that have given the same reaction
|
* The number of people that have given the same reaction
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.count = count || 0;
|
this.count = data.count || 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The users that have given this reaction, mapped by their ID
|
* The users that have given this reaction, mapped by their ID
|
||||||
@@ -32,7 +32,7 @@ class MessageReaction {
|
|||||||
*/
|
*/
|
||||||
this.users = new Collection();
|
this.users = new Collection();
|
||||||
|
|
||||||
this._emoji = new ReactionEmoji(this, emoji.name, emoji.id);
|
this._emoji = new ReactionEmoji(this, data.emoji.name, data.emoji.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,7 +62,7 @@ class MessageReaction {
|
|||||||
* @returns {Promise<MessageReaction>}
|
* @returns {Promise<MessageReaction>}
|
||||||
*/
|
*/
|
||||||
remove(user = this.message.client.user) {
|
remove(user = this.message.client.user) {
|
||||||
const userID = this.message.client.resolver.resolveUserID(user);
|
const userID = this.message.client.users.resolveID(user);
|
||||||
if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER'));
|
if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER'));
|
||||||
return this.message.client.api.channels[this.message.channel.id].messages[this.message.id]
|
return this.message.client.api.channels[this.message.channel.id].messages[this.message.id]
|
||||||
.reactions[this.emoji.identifier][userID === this.message.client.user.id ? '@me' : userID]
|
.reactions[this.emoji.identifier][userID === this.message.client.user.id ? '@me' : userID]
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class Presence {
|
|||||||
* @type {?Activity}
|
* @type {?Activity}
|
||||||
*/
|
*/
|
||||||
this.activity = activity ? new Activity(this, activity) : null;
|
this.activity = activity ? new Activity(this, activity) : null;
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_clone() {
|
_clone() {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ const { TypeError } = require('../errors');
|
|||||||
* @extends {Base}
|
* @extends {Base}
|
||||||
*/
|
*/
|
||||||
class Role extends Base {
|
class Role extends Base {
|
||||||
constructor(guild, data) {
|
constructor(client, data, guild) {
|
||||||
super(guild.client);
|
super(client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The guild that the role belongs to
|
* The guild that the role belongs to
|
||||||
@@ -171,7 +171,7 @@ class Role extends Base {
|
|||||||
* positive number if the this one is higher (other's is lower), 0 if equal
|
* positive number if the this one is higher (other's is lower), 0 if equal
|
||||||
*/
|
*/
|
||||||
comparePositionTo(role) {
|
comparePositionTo(role) {
|
||||||
role = this.client.resolver.resolveRole(this.guild, role);
|
role = this.guild.roles.resolve(role);
|
||||||
if (!role) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'));
|
if (!role) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake'));
|
||||||
return this.constructor.comparePositions(this, role);
|
return this.constructor.comparePositions(this, role);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ const GuildChannel = require('./GuildChannel');
|
|||||||
const Webhook = require('./Webhook');
|
const Webhook = require('./Webhook');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
const Collection = require('../util/Collection');
|
const Collection = require('../util/Collection');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const MessageStore = require('../stores/MessageStore');
|
const MessageStore = require('../stores/MessageStore');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +64,7 @@ class TextChannel extends GuildChannel {
|
|||||||
*/
|
*/
|
||||||
async createWebhook(name, { avatar, reason } = {}) {
|
async createWebhook(name, { avatar, reason } = {}) {
|
||||||
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
||||||
avatar = await this.client.resolver.resolveImage(avatar);
|
avatar = await DataResolver.resolveImage(avatar, this.client.browser);
|
||||||
}
|
}
|
||||||
return this.client.api.channels[this.id].webhooks.post({ data: {
|
return this.client.api.channels[this.id].webhooks.post({ data: {
|
||||||
name, avatar,
|
name, avatar,
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ class User extends Base {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
typingIn(channel) {
|
typingIn(channel) {
|
||||||
channel = this.client.resolver.resolveChannel(channel);
|
channel = this.client.channels.resolve(channel);
|
||||||
return channel._typing.has(this.id);
|
return channel._typing.has(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ class User extends Base {
|
|||||||
* @returns {?Date}
|
* @returns {?Date}
|
||||||
*/
|
*/
|
||||||
typingSinceIn(channel) {
|
typingSinceIn(channel) {
|
||||||
channel = this.client.resolver.resolveChannel(channel);
|
channel = this.client.channels.resolve(channel);
|
||||||
return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null;
|
return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ class User extends Base {
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
typingDurationIn(channel) {
|
typingDurationIn(channel) {
|
||||||
channel = this.client.resolver.resolveChannel(channel);
|
channel = this.client.channels.resolve(channel);
|
||||||
return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1;
|
return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const Util = require('../util/Util');
|
const Util = require('../util/Util');
|
||||||
|
const DataResolver = require('../util/DataResolver');
|
||||||
const Embed = require('./MessageEmbed');
|
const Embed = require('./MessageEmbed');
|
||||||
const MessageAttachment = require('./MessageAttachment');
|
const MessageAttachment = require('./MessageAttachment');
|
||||||
const MessageEmbed = require('./MessageEmbed');
|
const MessageEmbed = require('./MessageEmbed');
|
||||||
@@ -168,7 +169,7 @@ class Webhook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(options.files.map(file =>
|
return Promise.all(options.files.map(file =>
|
||||||
this.client.resolver.resolveFile(file.attachment).then(resource => {
|
DataResolver.resolveFile(file.attachment, this.client.browser).then(resource => {
|
||||||
file.file = resource;
|
file.file = resource;
|
||||||
return file;
|
return file;
|
||||||
})
|
})
|
||||||
@@ -248,7 +249,7 @@ class Webhook {
|
|||||||
*/
|
*/
|
||||||
edit({ name = this.name, avatar }, reason) {
|
edit({ name = this.name, avatar }, reason) {
|
||||||
if (avatar && (typeof avatar === 'string' && !avatar.startsWith('data:'))) {
|
if (avatar && (typeof avatar === 'string' && !avatar.startsWith('data:'))) {
|
||||||
return this.client.resolver.resolveImage(avatar).then(image =>
|
return DataResolver.resolveImage(avatar, this.client.browser).then(image =>
|
||||||
this.edit({ name, avatar: image }, reason)
|
this.edit({ name, avatar: image }, reason)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const MessageCollector = require('../MessageCollector');
|
const MessageCollector = require('../MessageCollector');
|
||||||
const Shared = require('../shared');
|
const Shared = require('../shared');
|
||||||
const MessageStore = require('../../stores/MessageStore');
|
|
||||||
const Snowflake = require('../../util/Snowflake');
|
const Snowflake = require('../../util/Snowflake');
|
||||||
const Collection = require('../../util/Collection');
|
const Collection = require('../../util/Collection');
|
||||||
|
const DataResolver = require('../../util/DataResolver');
|
||||||
const MessageAttachment = require('../../structures/MessageAttachment');
|
const MessageAttachment = require('../../structures/MessageAttachment');
|
||||||
const MessageEmbed = require('../../structures/MessageEmbed');
|
const MessageEmbed = require('../../structures/MessageEmbed');
|
||||||
const { RangeError, TypeError } = require('../../errors');
|
const { RangeError, TypeError } = require('../../errors');
|
||||||
@@ -124,7 +124,7 @@ class TextBasedChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(options.files.map(file =>
|
return Promise.all(options.files.map(file =>
|
||||||
this.client.resolver.resolveFile(file.attachment).then(resource => {
|
DataResolver.resolveFile(file.attachment, this.client.browser).then(resource => {
|
||||||
file.file = resource;
|
file.file = resource;
|
||||||
return file;
|
return file;
|
||||||
})
|
})
|
||||||
@@ -341,3 +341,6 @@ class TextBasedChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TextBasedChannel;
|
module.exports = TextBasedChannel;
|
||||||
|
|
||||||
|
// Fixes Circular
|
||||||
|
const MessageStore = require('../../stores/MessageStore');
|
||||||
|
|||||||
@@ -52,9 +52,9 @@ module.exports = function search(target, options) {
|
|||||||
options.minID = long.fromNumber(t).shiftLeft(22).toString();
|
options.minID = long.fromNumber(t).shiftLeft(22).toString();
|
||||||
options.maxID = long.fromNumber(t + 864e5).shiftLeft(22).toString();
|
options.maxID = long.fromNumber(t + 864e5).shiftLeft(22).toString();
|
||||||
}
|
}
|
||||||
if (options.channel) options.channel = target.client.resolver.resolveChannelID(options.channel);
|
if (options.channel) options.channel = target.client.channels.resolveID(options.channel);
|
||||||
if (options.author) options.author = target.client.resolver.resolveUserID(options.author);
|
if (options.author) options.author = target.client.users.resolveID(options.author);
|
||||||
if (options.mentions) options.mentions = target.client.resolver.resolveUserID(options.options.mentions);
|
if (options.mentions) options.mentions = target.client.users.resolveID(options.options.mentions);
|
||||||
if (options.sortOrder) {
|
if (options.sortOrder) {
|
||||||
options.sortOrder = { ascending: 'asc', descending: 'desc' }[options.sortOrder] || options.sortOrder;
|
options.sortOrder = { ascending: 'asc', descending: 'desc' }[options.sortOrder] || options.sortOrder;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ module.exports = function sendMessage(channel, options) { // eslint-disable-line
|
|||||||
|
|
||||||
// Add the reply prefix
|
// Add the reply prefix
|
||||||
if (reply && !(channel instanceof User || channel instanceof GuildMember) && channel.type !== 'dm') {
|
if (reply && !(channel instanceof User || channel instanceof GuildMember) && channel.type !== 'dm') {
|
||||||
const id = channel.client.resolver.resolveUserID(reply);
|
const id = channel.client.users.resolveID(reply);
|
||||||
const mention = `<@${reply instanceof GuildMember && reply.nickname ? '!' : ''}${id}>`;
|
const mention = `<@${reply instanceof GuildMember && reply.nickname ? '!' : ''}${id}>`;
|
||||||
if (split) split.prepend = `${mention}, ${split.prepend || ''}`;
|
if (split) split.prepend = `${mention}, ${split.prepend || ''}`;
|
||||||
content = `${mention}${typeof content !== 'undefined' ? `, ${content}` : ''}`;
|
content = `${mention}${typeof content !== 'undefined' ? `, ${content}` : ''}`;
|
||||||
|
|||||||
124
src/util/DataResolver.js
Normal file
124
src/util/DataResolver.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const snekfetch = require('snekfetch');
|
||||||
|
const Util = require('../util/Util');
|
||||||
|
const { Error, TypeError } = require('../errors');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
class DataResolver {
|
||||||
|
constructor() {
|
||||||
|
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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}
|
||||||
|
*/
|
||||||
|
static 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
|
||||||
|
* @param {boolean} browser Whether this should resolve for a browser
|
||||||
|
* @returns {Promise<?string>}
|
||||||
|
*/
|
||||||
|
static async resolveImage(image, browser) {
|
||||||
|
if (!image) return null;
|
||||||
|
if (typeof image === 'string' && image.startsWith('data:')) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
const file = await this.resolveFile(image, browser);
|
||||||
|
return this.constructor.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}
|
||||||
|
*/
|
||||||
|
static 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
|
||||||
|
* @param {boolean} browser Whether this should resolve for a browser
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
static resolveFile(resource, browser) {
|
||||||
|
if (resource instanceof Buffer) return Promise.resolve(resource);
|
||||||
|
if (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'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DataResolver;
|
||||||
Reference in New Issue
Block a user