mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-13 10:03:31 +01:00
refactor: Document relevant types as @internal (#9974)
* refactor: mark data resolver as internal * docs: mark relevant TypeScript symbols as `@internal` * docs: extra additions * style: prefer at end * docs: add more `@internal`s * test: update template code
This commit is contained in:
@@ -23,7 +23,7 @@ const StickerPack = require('../structures/StickerPack');
|
||||
const VoiceRegion = require('../structures/VoiceRegion');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const Widget = require('../structures/Widget');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveInviteCode, resolveGuildTemplateCode } = require('../util/DataResolver');
|
||||
const Events = require('../util/Events');
|
||||
const IntentsBitField = require('../util/IntentsBitField');
|
||||
const Options = require('../util/Options');
|
||||
@@ -273,7 +273,7 @@ class Client extends BaseClient {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchInvite(invite, options) {
|
||||
const code = DataResolver.resolveInviteCode(invite);
|
||||
const code = resolveInviteCode(invite);
|
||||
const query = makeURLSearchParams({
|
||||
with_counts: true,
|
||||
with_expiration: true,
|
||||
@@ -293,7 +293,7 @@ class Client extends BaseClient {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchGuildTemplate(template) {
|
||||
const code = DataResolver.resolveGuildTemplateCode(template);
|
||||
const code = resolveGuildTemplateCode(template);
|
||||
const data = await this.rest.get(Routes.template(code));
|
||||
return new GuildTemplate(this, data);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ exports.ChannelFlagsBitField = require('./util/ChannelFlagsBitField');
|
||||
exports.Collection = require('@discordjs/collection').Collection;
|
||||
exports.Constants = require('./util/Constants');
|
||||
exports.Colors = require('./util/Colors');
|
||||
exports.DataResolver = require('./util/DataResolver');
|
||||
__exportStar(require('./util/DataResolver.js'), exports);
|
||||
exports.Events = require('./util/Events');
|
||||
exports.Formatters = require('./util/Formatters');
|
||||
exports.GuildMemberFlagsBitField = require('./util/GuildMemberFlagsBitField').GuildMemberFlagsBitField;
|
||||
|
||||
@@ -13,7 +13,7 @@ const Webhook = require('../structures/Webhook');
|
||||
const ChannelFlagsBitField = require('../util/ChannelFlagsBitField');
|
||||
const { transformGuildForumTag, transformGuildDefaultReaction } = require('../util/Channels');
|
||||
const { ThreadChannelTypes } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const { setPosition } = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
@@ -219,7 +219,7 @@ class GuildChannelManager extends CachedManager {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
||||
avatar = await DataResolver.resolveImage(avatar);
|
||||
avatar = await resolveImage(avatar);
|
||||
}
|
||||
const data = await this.client.rest.post(Routes.channelWebhooks(id), {
|
||||
body: {
|
||||
|
||||
@@ -4,7 +4,7 @@ const { Collection } = require('@discordjs/collection');
|
||||
const { Routes, PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const BaseGuildEmojiManager = require('./BaseGuildEmojiManager');
|
||||
const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildEmojis and stores their cache.
|
||||
@@ -50,7 +50,7 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create({ attachment, name, roles, reason }) {
|
||||
attachment = await DataResolver.resolveImage(attachment);
|
||||
attachment = await resolveImage(attachment);
|
||||
if (!attachment) throw new DiscordjsTypeError(ErrorCodes.ReqResourceType);
|
||||
|
||||
const body = { image: attachment, name };
|
||||
|
||||
@@ -5,7 +5,7 @@ const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const Invite = require('../structures/Invite');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveInviteCode } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildInvites and stores their cache.
|
||||
@@ -124,7 +124,7 @@ class GuildInviteManager extends CachedManager {
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
if (typeof options === 'string') {
|
||||
const code = DataResolver.resolveInviteCode(options);
|
||||
const code = resolveInviteCode(options);
|
||||
if (!code) return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
|
||||
return this._fetchSingle({ code, cache: true });
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class GuildInviteManager extends CachedManager {
|
||||
}
|
||||
return this._fetchSingle({
|
||||
...options,
|
||||
code: DataResolver.resolveInviteCode(options.code),
|
||||
code: resolveInviteCode(options.code),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ class GuildInviteManager extends CachedManager {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(invite, reason) {
|
||||
const code = DataResolver.resolveInviteCode(invite);
|
||||
const code = resolveInviteCode(invite);
|
||||
|
||||
await this.client.rest.delete(Routes.invite(code), { reason });
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ const { GuildMember } = require('../structures/GuildMember');
|
||||
const Invite = require('../structures/Invite');
|
||||
const OAuth2Guild = require('../structures/OAuth2Guild');
|
||||
const { Role } = require('../structures/Role');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const Events = require('../util/Events');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField');
|
||||
@@ -179,7 +179,7 @@ class GuildManager extends CachedManager {
|
||||
const data = await this.client.rest.post(Routes.guilds(), {
|
||||
body: {
|
||||
name,
|
||||
icon: icon && (await DataResolver.resolveImage(icon)),
|
||||
icon: icon && (await resolveImage(icon)),
|
||||
verification_level: verificationLevel,
|
||||
default_message_notifications: defaultMessageNotifications,
|
||||
explicit_content_filter: explicitContentFilter,
|
||||
|
||||
@@ -6,7 +6,7 @@ const { GuildScheduledEventEntityType, Routes } = require('discord-api-types/v10
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildScheduledEvents and stores their cache.
|
||||
@@ -103,7 +103,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
description,
|
||||
entity_type: entityType,
|
||||
entity_metadata,
|
||||
image: image && (await DataResolver.resolveImage(image)),
|
||||
image: image && (await resolveImage(image)),
|
||||
},
|
||||
reason,
|
||||
});
|
||||
@@ -222,7 +222,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
description,
|
||||
entity_type: entityType,
|
||||
status,
|
||||
image: image && (await DataResolver.resolveImage(image)),
|
||||
image: image && (await resolveImage(image)),
|
||||
entity_metadata,
|
||||
},
|
||||
reason,
|
||||
|
||||
@@ -6,7 +6,7 @@ const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const { Role } = require('../structures/Role');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const { setPosition, resolveColor } = require('../util/Util');
|
||||
|
||||
@@ -140,7 +140,7 @@ class RoleManager extends CachedManager {
|
||||
if (permissions !== undefined) permissions = new PermissionsBitField(permissions);
|
||||
if (icon) {
|
||||
const guildEmojiURL = this.guild.emojis.resolve(icon)?.imageURL();
|
||||
icon = guildEmojiURL ? await DataResolver.resolveImage(guildEmojiURL) : await DataResolver.resolveImage(icon);
|
||||
icon = guildEmojiURL ? await resolveImage(guildEmojiURL) : await resolveImage(icon);
|
||||
if (typeof icon !== 'string') icon = undefined;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ class RoleManager extends CachedManager {
|
||||
let icon = options.icon;
|
||||
if (icon) {
|
||||
const guildEmojiURL = this.guild.emojis.resolve(icon)?.imageURL();
|
||||
icon = guildEmojiURL ? await DataResolver.resolveImage(guildEmojiURL) : await DataResolver.resolveImage(icon);
|
||||
icon = guildEmojiURL ? await resolveImage(guildEmojiURL) : await resolveImage(icon);
|
||||
if (typeof icon !== 'string') icon = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ const Team = require('./Team');
|
||||
const Application = require('./interfaces/Application');
|
||||
const ApplicationCommandManager = require('../managers/ApplicationCommandManager');
|
||||
const ApplicationFlagsBitField = require('../util/ApplicationFlagsBitField');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
@@ -227,8 +227,8 @@ class ClientApplication extends Application {
|
||||
role_connections_verification_url: roleConnectionsVerificationURL,
|
||||
install_params: installParams,
|
||||
flags: flags === undefined ? undefined : ApplicationFlagsBitField.resolve(flags),
|
||||
icon: icon && (await DataResolver.resolveImage(icon)),
|
||||
cover_image: coverImage && (await DataResolver.resolveImage(coverImage)),
|
||||
icon: icon && (await resolveImage(icon)),
|
||||
cover_image: coverImage && (await resolveImage(coverImage)),
|
||||
interactions_endpoint_url: interactionsEndpointURL,
|
||||
tags,
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const User = require('./User');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Represents the logged in client's Discord user.
|
||||
@@ -56,7 +56,7 @@ class ClientUser extends User {
|
||||
*/
|
||||
async edit({ username, avatar }) {
|
||||
const data = await this.client.rest.patch(Routes.user(), {
|
||||
body: { username, avatar: avatar && (await DataResolver.resolveImage(avatar)) },
|
||||
body: { username, avatar: avatar && (await resolveImage(avatar)) },
|
||||
});
|
||||
|
||||
this.client.token = data.token;
|
||||
|
||||
@@ -26,7 +26,7 @@ const PresenceManager = require('../managers/PresenceManager');
|
||||
const RoleManager = require('../managers/RoleManager');
|
||||
const StageInstanceManager = require('../managers/StageInstanceManager');
|
||||
const VoiceStateManager = require('../managers/VoiceStateManager');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const Status = require('../util/Status');
|
||||
const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField');
|
||||
const { discordSort, getSortableGroupTypes, resolvePartialEmoji } = require('../util/Util');
|
||||
@@ -862,11 +862,11 @@ class Guild extends AnonymousGuild {
|
||||
explicit_content_filter: explicitContentFilter,
|
||||
afk_channel_id: afkChannel && this.client.channels.resolveId(afkChannel),
|
||||
afk_timeout: afkTimeout,
|
||||
icon: icon && (await DataResolver.resolveImage(icon)),
|
||||
icon: icon && (await resolveImage(icon)),
|
||||
owner_id: owner && this.client.users.resolveId(owner),
|
||||
splash: splash && (await DataResolver.resolveImage(splash)),
|
||||
discovery_splash: discoverySplash && (await DataResolver.resolveImage(discoverySplash)),
|
||||
banner: banner && (await DataResolver.resolveImage(banner)),
|
||||
splash: splash && (await resolveImage(splash)),
|
||||
discovery_splash: discoverySplash && (await resolveImage(discoverySplash)),
|
||||
banner: banner && (await resolveImage(banner)),
|
||||
system_channel_id: systemChannel && this.client.channels.resolveId(systemChannel),
|
||||
system_channel_flags:
|
||||
systemChannelFlags === undefined ? undefined : SystemChannelFlagsBitField.resolve(systemChannelFlags),
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const { setTimeout, clearTimeout } = require('node:timers');
|
||||
const { RouteBases, Routes } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
/**
|
||||
@@ -126,7 +126,7 @@ class GuildTemplate extends Base {
|
||||
const data = await client.rest.post(Routes.template(this.code), {
|
||||
body: {
|
||||
name,
|
||||
icon: await DataResolver.resolveImage(icon),
|
||||
icon: await resolveImage(icon),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ const { lazy, isJSONEncodable } = require('@discordjs/util');
|
||||
const { MessageFlags } = require('discord-api-types/v10');
|
||||
const ActionRowBuilder = require('./ActionRowBuilder');
|
||||
const { DiscordjsRangeError, ErrorCodes } = require('../errors');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveFile } = require('../util/DataResolver');
|
||||
const MessageFlagsBitField = require('../util/MessageFlagsBitField');
|
||||
const { basename, verifyString } = require('../util/Util');
|
||||
|
||||
@@ -257,7 +257,7 @@ class MessagePayload {
|
||||
name = fileLike.name ?? findName(attachment);
|
||||
}
|
||||
|
||||
const { data, contentType } = await DataResolver.resolveFile(attachment);
|
||||
const { data, contentType } = await resolveFile(attachment);
|
||||
return { data, name, contentType };
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { Routes, WebhookType } = require('discord-api-types/v10');
|
||||
const MessagePayload = require('./MessagePayload');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
const getMessage = lazy(() => require('./Message').Message);
|
||||
|
||||
@@ -276,7 +276,7 @@ class Webhook {
|
||||
*/
|
||||
async edit({ name = this.name, avatar, channel, reason }) {
|
||||
if (avatar && !(typeof avatar === 'string' && avatar.startsWith('data:'))) {
|
||||
avatar = await DataResolver.resolveImage(avatar);
|
||||
avatar = await resolveImage(avatar);
|
||||
}
|
||||
channel &&= channel.id ?? channel;
|
||||
const data = await this.client.rest.patch(Routes.webhook(this.id, channel ? undefined : this.token), {
|
||||
|
||||
@@ -15,12 +15,19 @@ const getPartialGroupDMChannel = lazy(() => require('../structures/PartialGroupD
|
||||
const getForumChannel = lazy(() => require('../structures/ForumChannel'));
|
||||
const getMediaChannel = lazy(() => require('../structures/MediaChannel'));
|
||||
|
||||
/**
|
||||
* Extra options for creating a channel.
|
||||
* @typedef {Object} CreateChannelOptions
|
||||
* @property {boolean} [allowFromUnknownGuild] Whether to allow creating a channel from an unknown guild
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a discord.js channel from data received from the API.
|
||||
* @param {Client} client The client
|
||||
* @param {APIChannel} data The data of the channel to create
|
||||
* @param {Guild} [guild] The guild where this channel belongs
|
||||
* @param {Object} [extras] Extra information to supply for creating this channel
|
||||
* @param {CreateChannelOptions} [extras] Extra information to supply for creating this channel
|
||||
* @returns {BaseChannel} Any kind of channel.
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
@@ -8,133 +8,134 @@ const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const Invite = require('../structures/Invite');
|
||||
|
||||
/**
|
||||
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them.
|
||||
* Data that can be resolved to give an invite code. This can be:
|
||||
* * An invite code
|
||||
* * An invite URL
|
||||
* @typedef {string} InviteResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a template code. This can be:
|
||||
* * A template code
|
||||
* * A template URL
|
||||
* @typedef {string} GuildTemplateResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves the string to a code based on the passed regex.
|
||||
* @param {string} data The string to resolve
|
||||
* @param {RegExp} regex The RegExp used to extract the code
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
class DataResolver extends null {
|
||||
/**
|
||||
* Data that can be resolved to give an invite code. This can be:
|
||||
* * An invite code
|
||||
* * An invite URL
|
||||
* @typedef {string} InviteResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a template code. This can be:
|
||||
* * A template code
|
||||
* * A template URL
|
||||
* @typedef {string} GuildTemplateResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves the string to a code based on the passed regex.
|
||||
* @param {string} data The string to resolve
|
||||
* @param {RegExp} regex The RegExp used to extract the code
|
||||
* @returns {string}
|
||||
*/
|
||||
static resolveCode(data, regex) {
|
||||
return regex.exec(data)?.[1] ?? data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves InviteResolvable to an invite code.
|
||||
* @param {InviteResolvable} data The invite resolvable to resolve
|
||||
* @returns {string}
|
||||
*/
|
||||
static resolveInviteCode(data) {
|
||||
return this.resolveCode(data, Invite.InvitesPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves GuildTemplateResolvable to a template code.
|
||||
* @param {GuildTemplateResolvable} data The template resolvable to resolve
|
||||
* @returns {string}
|
||||
*/
|
||||
static resolveGuildTemplateCode(data) {
|
||||
const GuildTemplate = require('../structures/GuildTemplate');
|
||||
return this.resolveCode(data, GuildTemplate.GuildTemplatesPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>}
|
||||
*/
|
||||
static 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (Buffer.isBuffer(data)) 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 <warn>When provided a URL, discord.js will fetch the URL internally in order to create a Buffer.
|
||||
* This can pose a security risk when the URL has not been sanitized</warn>
|
||||
* @typedef {string|Buffer} BufferResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external Stream
|
||||
* @see {@link https://nodejs.org/api/stream.html}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ResolvedFile
|
||||
* @property {Buffer} data Buffer containing the file data
|
||||
* @property {string} [contentType] Content type of the file
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a BufferResolvable to a Buffer.
|
||||
* @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
|
||||
* @returns {Promise<ResolvedFile>}
|
||||
*/
|
||||
static async resolveFile(resource) {
|
||||
if (Buffer.isBuffer(resource)) return { data: resource };
|
||||
|
||||
if (typeof resource[Symbol.asyncIterator] === 'function') {
|
||||
const buffers = [];
|
||||
for await (const data of resource) buffers.push(Buffer.from(data));
|
||||
return { data: Buffer.concat(buffers) };
|
||||
}
|
||||
|
||||
if (typeof resource === 'string') {
|
||||
if (/^https?:\/\//.test(resource)) {
|
||||
const res = await fetch(resource);
|
||||
return { data: Buffer.from(await res.arrayBuffer()), contentType: res.headers.get('content-type') };
|
||||
}
|
||||
|
||||
const file = path.resolve(resource);
|
||||
|
||||
const stats = await fs.stat(file);
|
||||
if (!stats.isFile()) throw new DiscordjsError(ErrorCodes.FileNotFound, file);
|
||||
return { data: await fs.readFile(file) };
|
||||
}
|
||||
|
||||
throw new DiscordjsTypeError(ErrorCodes.ReqResourceType);
|
||||
}
|
||||
function resolveCode(data, regex) {
|
||||
return regex.exec(data)?.[1] ?? data;
|
||||
}
|
||||
|
||||
module.exports = DataResolver;
|
||||
/**
|
||||
* Resolves InviteResolvable to an invite code.
|
||||
* @param {InviteResolvable} data The invite resolvable to resolve
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
function resolveInviteCode(data) {
|
||||
return resolveCode(data, Invite.InvitesPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves GuildTemplateResolvable to a template code.
|
||||
* @param {GuildTemplateResolvable} data The template resolvable to resolve
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
function resolveGuildTemplateCode(data) {
|
||||
const GuildTemplate = require('../structures/GuildTemplate');
|
||||
return resolveCode(data, GuildTemplate.GuildTemplatesPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Buffer. This can be:
|
||||
* * A Buffer
|
||||
* * The path to a local file
|
||||
* * A URL <warn>When provided a URL, discord.js will fetch the URL internally in order to create a Buffer.
|
||||
* This can pose a security risk when the URL has not been sanitized</warn>
|
||||
* @typedef {string|Buffer} BufferResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external Stream
|
||||
* @see {@link https://nodejs.org/api/stream.html}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ResolvedFile
|
||||
* @property {Buffer} data Buffer containing the file data
|
||||
* @property {string} [contentType] Content-Type of the file
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a BufferResolvable to a Buffer.
|
||||
* @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
|
||||
* @returns {Promise<ResolvedFile>}
|
||||
* @private
|
||||
*/
|
||||
async function resolveFile(resource) {
|
||||
if (Buffer.isBuffer(resource)) return { data: resource };
|
||||
|
||||
if (typeof resource[Symbol.asyncIterator] === 'function') {
|
||||
const buffers = [];
|
||||
for await (const data of resource) buffers.push(Buffer.from(data));
|
||||
return { data: Buffer.concat(buffers) };
|
||||
}
|
||||
|
||||
if (typeof resource === 'string') {
|
||||
if (/^https?:\/\//.test(resource)) {
|
||||
const res = await fetch(resource);
|
||||
return { data: Buffer.from(await res.arrayBuffer()), contentType: res.headers.get('content-type') };
|
||||
}
|
||||
|
||||
const file = path.resolve(resource);
|
||||
|
||||
const stats = await fs.stat(file);
|
||||
if (!stats.isFile()) throw new DiscordjsError(ErrorCodes.FileNotFound, file);
|
||||
return { data: await fs.readFile(file) };
|
||||
}
|
||||
|
||||
throw new DiscordjsTypeError(ErrorCodes.ReqResourceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* @private
|
||||
*/
|
||||
function resolveBase64(data) {
|
||||
if (Buffer.isBuffer(data)) return `data:image/jpg;base64,${data.toString('base64')}`;
|
||||
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>}
|
||||
* @private
|
||||
*/
|
||||
async function resolveImage(image) {
|
||||
if (!image) return null;
|
||||
if (typeof image === 'string' && image.startsWith('data:')) {
|
||||
return image;
|
||||
}
|
||||
const file = await resolveFile(image);
|
||||
return resolveBase64(file.data);
|
||||
}
|
||||
|
||||
module.exports = { resolveCode, resolveInviteCode, resolveGuildTemplateCode, resolveImage, resolveBase64, resolveFile };
|
||||
|
||||
@@ -128,6 +128,7 @@ function resolvePartialEmoji(emoji) {
|
||||
* @property {string} name Error type
|
||||
* @property {string} message Message for the error
|
||||
* @property {string} stack Stack for the error
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user