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:
Jiralite
2023-12-05 18:15:08 +00:00
committed by GitHub
parent 62e31cb9ee
commit 2b8ac35e56
19 changed files with 215 additions and 177 deletions

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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: {

View File

@@ -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 };

View File

@@ -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 });
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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,
},

View File

@@ -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;

View File

@@ -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),

View File

@@ -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),
},
});

View File

@@ -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 };
}

View File

@@ -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), {

View File

@@ -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
*/

View File

@@ -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 };

View File

@@ -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
*/
/**

View File

@@ -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');
});
});

View File

@@ -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;