mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13: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
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
/* eslint-env jest */
|
||||
|
||||
const { DataResolver } = require('../src');
|
||||
const { resolveGuildTemplateCode } = require('../src');
|
||||
|
||||
describe('resolveGuildTemplateCode', () => {
|
||||
test('basic', () => {
|
||||
expect(DataResolver.resolveGuildTemplateCode('https://discord.new/abc')).toEqual('abc');
|
||||
expect(resolveGuildTemplateCode('https://discord.new/abc')).toEqual('abc');
|
||||
});
|
||||
});
|
||||
|
||||
53
packages/discord.js/typings/index.d.ts
vendored
53
packages/discord.js/typings/index.d.ts
vendored
@@ -1278,21 +1278,12 @@ export class ContextMenuCommandInteraction<Cached extends CacheType = CacheType>
|
||||
private resolveContextMenuOptions(data: APIApplicationCommandInteractionData): CommandInteractionOption<Cached>[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ResolvedFile {
|
||||
data: Buffer;
|
||||
contentType?: string;
|
||||
}
|
||||
|
||||
export class DataResolver extends null {
|
||||
private constructor();
|
||||
public static resolveBase64(data: Base64Resolvable): string;
|
||||
public static resolveCode(data: string, regex: RegExp): string;
|
||||
public static resolveFile(resource: BufferResolvable | Stream): Promise<ResolvedFile>;
|
||||
public static resolveImage(resource: BufferResolvable | Base64Resolvable): Promise<string | null>;
|
||||
public static resolveInviteCode(data: InviteResolvable): string;
|
||||
public static resolveGuildTemplateCode(data: GuildTemplateResolvable): string;
|
||||
}
|
||||
|
||||
export class DMChannel extends TextBasedChannelMixin(BaseChannel, false, [
|
||||
'bulkDelete',
|
||||
'fetchWebhooks',
|
||||
@@ -3266,6 +3257,7 @@ export class UserFlagsBitField extends BitField<UserFlagsString> {
|
||||
public static resolve(bit?: BitFieldResolvable<UserFlagsString, number>): number;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function basename(path: string, ext?: string): string;
|
||||
export function cleanContent(str: string, channel: TextBasedChannel): string;
|
||||
export function discordSort<Key, Value extends { rawPosition: number; id: Snowflake }>(
|
||||
@@ -3274,14 +3266,19 @@ export function discordSort<Key, Value extends { rawPosition: number; id: Snowfl
|
||||
export function cleanCodeBlockContent(text: string): string;
|
||||
export function fetchRecommendedShardCount(token: string, options?: FetchRecommendedShardCountOptions): Promise<number>;
|
||||
export function flatten(obj: unknown, ...props: Record<string, boolean | string>[]): unknown;
|
||||
/** @internal */
|
||||
export function makeError(obj: MakeErrorOptions): Error;
|
||||
/** @internal */
|
||||
export function makePlainError(err: Error): MakeErrorOptions;
|
||||
/** @internal */
|
||||
export function moveElementInArray(array: unknown[], element: unknown, newIndex: number, offset?: boolean): number;
|
||||
export function parseEmoji(text: string): PartialEmoji | null;
|
||||
export function resolveColor(color: ColorResolvable): number;
|
||||
/** @internal */
|
||||
export function resolvePartialEmoji(emoji: Snowflake): PartialEmojiOnlyId;
|
||||
export function resolvePartialEmoji(emoji: Emoji | EmojiIdentifierResolvable): PartialEmoji | null;
|
||||
export function verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string;
|
||||
/** @internal */
|
||||
export function setPosition<Item extends Channel | Role>(
|
||||
item: Item,
|
||||
position: number,
|
||||
@@ -3292,6 +3289,7 @@ export function setPosition<Item extends Channel | Role>(
|
||||
reason?: string,
|
||||
): Promise<{ id: Snowflake; position: number }[]>;
|
||||
export function parseWebhookURL(url: string): WebhookClientDataIdWithToken | null;
|
||||
/** @internal */
|
||||
export function transformResolved<Cached extends CacheType>(
|
||||
supportingData: SupportingInteractionResolvedData,
|
||||
data?: APIApplicationCommandInteractionData['resolved'],
|
||||
@@ -3319,11 +3317,18 @@ export interface MappedComponentTypes {
|
||||
[ComponentType.TextInput]: TextInputComponent;
|
||||
}
|
||||
|
||||
export interface ChannelCreateOptions {
|
||||
/** @internal */
|
||||
export interface CreateChannelOptions {
|
||||
allowFromUnknownGuild?: boolean;
|
||||
}
|
||||
|
||||
export function createChannel(client: Client<true>, data: APIChannel, options?: ChannelCreateOptions): Channel;
|
||||
/** @internal */
|
||||
export function createChannel(
|
||||
client: Client<true>,
|
||||
data: APIChannel,
|
||||
guild?: Guild,
|
||||
extras?: CreateChannelOptions,
|
||||
): Channel;
|
||||
|
||||
export function createComponent<Type extends keyof MappedComponentTypes>(
|
||||
data: APIMessageComponent & { type: Type },
|
||||
@@ -3374,6 +3379,19 @@ export class Formatters extends null {
|
||||
public static userMention: typeof userMention;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function resolveBase64(data: Base64Resolvable): string;
|
||||
/** @internal */
|
||||
export function resolveCode(data: string, regex: RegExp): string;
|
||||
/** @internal */
|
||||
export function resolveFile(resource: BufferResolvable | Stream): Promise<ResolvedFile>;
|
||||
/** @internal */
|
||||
export function resolveImage(resource: BufferResolvable | Base64Resolvable): Promise<string | null>;
|
||||
/** @internal */
|
||||
export function resolveInviteCode(data: InviteResolvable): string;
|
||||
/** @internal */
|
||||
export function resolveGuildTemplateCode(data: GuildTemplateResolvable): string;
|
||||
|
||||
export type ComponentData =
|
||||
| MessageActionRowComponentData
|
||||
| ModalActionRowComponentData
|
||||
@@ -3816,11 +3834,13 @@ export enum DiscordjsErrorCodes {
|
||||
GuildForumMessageRequired = 'GuildForumMessageRequired',
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface DiscordjsErrorFields<Name extends string> {
|
||||
readonly name: `${Name} [${DiscordjsErrorCodes}]`;
|
||||
get code(): DiscordjsErrorCodes;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function DiscordjsErrorMixin<Entity, Name extends string>(
|
||||
Base: Constructable<Entity>,
|
||||
name: Name,
|
||||
@@ -4369,10 +4389,13 @@ export class VoiceStateManager extends CachedManager<Snowflake, VoiceState, type
|
||||
// to each of those classes
|
||||
|
||||
export type Constructable<Entity> = abstract new (...args: any[]) => Entity;
|
||||
|
||||
/** @internal */
|
||||
export function PartialTextBasedChannel<Entity>(
|
||||
Base?: Constructable<Entity>,
|
||||
): Constructable<Entity & PartialTextBasedChannelFields<false>>;
|
||||
|
||||
/** @internal */
|
||||
export function TextBasedChannelMixin<
|
||||
Entity,
|
||||
InGuild extends boolean = boolean,
|
||||
@@ -4413,9 +4436,12 @@ export interface TextBasedChannelFields<InGuild extends boolean = boolean>
|
||||
setNSFW(nsfw?: boolean, reason?: string): Promise<this>;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function PartialWebhookMixin<Entity>(Base?: Constructable<Entity>): Constructable<Entity & PartialWebhookFields>;
|
||||
/** @internal */
|
||||
export function WebhookMixin<Entity>(Base?: Constructable<Entity>): Constructable<Entity & WebhookFields>;
|
||||
|
||||
/** @internal */
|
||||
export interface PartialWebhookFields {
|
||||
id: Snowflake;
|
||||
get url(): string;
|
||||
@@ -4430,6 +4456,7 @@ export interface PartialWebhookFields {
|
||||
): Promise<APIMessage | Message>;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface WebhookFields extends PartialWebhookFields {
|
||||
get createdAt(): Date;
|
||||
get createdTimestamp(): number;
|
||||
@@ -5979,6 +6006,7 @@ export interface LifetimeFilterOptions<Key, Value> {
|
||||
lifetime?: number;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface MakeErrorOptions {
|
||||
name: string;
|
||||
message: string;
|
||||
@@ -6433,6 +6461,7 @@ export interface StageInstanceEditOptions {
|
||||
privacyLevel?: StageInstancePrivacyLevel;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface SupportingInteractionResolvedData {
|
||||
client: Client;
|
||||
guild?: Guild;
|
||||
|
||||
Reference in New Issue
Block a user