mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor(attachment): don't return attachment builders from API (#7852)
Co-authored-by: Almeida <almeidx@pm.me> Co-authored-by: A. Román <kyradiscord@gmail.com> Co-authored-by: SpaceEEC <spaceeec@yahoo.com>
This commit is contained in:
@@ -123,6 +123,7 @@ exports.InviteStageInstance = require('./structures/InviteStageInstance');
|
||||
exports.InviteGuild = require('./structures/InviteGuild');
|
||||
exports.Message = require('./structures/Message').Message;
|
||||
exports.Attachment = require('./structures/Attachment');
|
||||
exports.AttachmentBuilder = require('./structures/AttachmentBuilder');
|
||||
exports.ModalBuilder = require('./structures/ModalBuilder');
|
||||
exports.MessageCollector = require('./structures/MessageCollector');
|
||||
exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction');
|
||||
|
||||
@@ -41,7 +41,7 @@ class GuildStickerManager extends CachedManager {
|
||||
|
||||
/**
|
||||
* Creates a new custom sticker in the guild.
|
||||
* @param {BufferResolvable|Stream|FileOptions|Attachment} file The file for the sticker
|
||||
* @param {BufferResolvable|Stream|JSONEncodable<AttachmentPayload>} file The file for the sticker
|
||||
* @param {string} name The name for the sticker
|
||||
* @param {string} tags The Discord name of a unicode emoji representing the sticker's expression
|
||||
* @param {GuildStickerCreateOptions} [options] Options
|
||||
|
||||
@@ -3,74 +3,30 @@
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents an attachment.
|
||||
* @typedef {Object} AttachmentPayload
|
||||
* @property {?string} name The name of the attachment
|
||||
* @property {Stream|BufferResolvable} attachment The attachment in this payload
|
||||
* @property {?string} description The description of the attachment
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an attachment
|
||||
*/
|
||||
class Attachment {
|
||||
/**
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @param {string} [name=null] The name of the file, if any
|
||||
* @param {APIAttachment} [data] Extra data
|
||||
* @param {APIAttachment} data Attachment data
|
||||
* @private
|
||||
*/
|
||||
constructor(attachment, name = null, data) {
|
||||
this.attachment = attachment;
|
||||
constructor({ url, filename, ...data }) {
|
||||
this.attachment = url;
|
||||
/**
|
||||
* The name of this attachment
|
||||
* @type {?string}
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
this.name = filename;
|
||||
if (data) this._patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this attachment.
|
||||
* @param {string} description The description of the file
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setDescription(description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file of this attachment.
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @param {string} [name=null] The name of the file, if any
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setFile(attachment, name = null) {
|
||||
this.attachment = attachment;
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this attachment.
|
||||
* @param {string} name The name of the file
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setName(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this attachment is a spoiler
|
||||
* @param {boolean} [spoiler=true] Whether the attachment should be marked as a spoiler
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setSpoiler(spoiler = true) {
|
||||
if (spoiler === this.spoiler) return this;
|
||||
|
||||
if (!spoiler) {
|
||||
while (this.spoiler) {
|
||||
this.name = this.name.slice('SPOILER_'.length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
this.name = `SPOILER_${this.name}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The attachment's id
|
||||
@@ -164,8 +120,3 @@ class Attachment {
|
||||
}
|
||||
|
||||
module.exports = Attachment;
|
||||
|
||||
/**
|
||||
* @external APIAttachment
|
||||
* @see {@link https://discord.com/developers/docs/resources/channel#attachment-object}
|
||||
*/
|
||||
|
||||
110
packages/discord.js/src/structures/AttachmentBuilder.js
Normal file
110
packages/discord.js/src/structures/AttachmentBuilder.js
Normal file
@@ -0,0 +1,110 @@
|
||||
'use strict';
|
||||
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents an attachment builder
|
||||
*/
|
||||
class AttachmentBuilder {
|
||||
/**
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @param {APIAttachment} [data] Extra data
|
||||
*/
|
||||
constructor(attachment, data = {}) {
|
||||
/**
|
||||
* The file associated with this attachment.
|
||||
* @type {BufferResolvable|Stream}
|
||||
*/
|
||||
this.attachment = attachment;
|
||||
/**
|
||||
* The name of this attachment
|
||||
* @type {?string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
/**
|
||||
* The description of the attachment
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this attachment.
|
||||
* @param {string} description The description of the file
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setDescription(description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file of this attachment.
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setFile(attachment) {
|
||||
this.attachment = attachment;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this attachment.
|
||||
* @param {string} name The name of the file
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setName(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this attachment is a spoiler
|
||||
* @param {boolean} [spoiler=true] Whether the attachment should be marked as a spoiler
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setSpoiler(spoiler = true) {
|
||||
if (spoiler === this.spoiler) return this;
|
||||
|
||||
if (!spoiler) {
|
||||
while (this.spoiler) {
|
||||
this.name = this.name.slice('SPOILER_'.length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
this.name = `SPOILER_${this.name}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this attachment has been marked as a spoiler
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get spoiler() {
|
||||
return Util.basename(this.name).startsWith('SPOILER_');
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return Util.flatten(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a new builder instance from a preexisting attachment structure.
|
||||
* @param {JSONEncodable<AttachmentPayload>} other The builder to construct a new instance from
|
||||
* @returns {AttachmentBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new AttachmentBuilder(other.attachment, {
|
||||
name: other.name,
|
||||
description: other.description,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AttachmentBuilder;
|
||||
|
||||
/**
|
||||
* @external APIAttachment
|
||||
* @see {@link https://discord.com/developers/docs/resources/channel#attachment-object}
|
||||
*/
|
||||
@@ -133,7 +133,7 @@ class CommandInteraction extends Interaction {
|
||||
if (attachments) {
|
||||
result.attachments = new Collection();
|
||||
for (const attachment of Object.values(attachments)) {
|
||||
const patched = new Attachment(attachment.url, attachment.filename, attachment);
|
||||
const patched = new Attachment(attachment);
|
||||
result.attachments.set(attachment.id, patched);
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ class CommandInteraction extends Interaction {
|
||||
if (role) result.role = this.guild?.roles._add(role) ?? role;
|
||||
|
||||
const attachment = resolved.attachments?.[option.value];
|
||||
if (attachment) result.attachment = new Attachment(attachment.url, attachment.filename, attachment);
|
||||
if (attachment) result.attachment = new Attachment(attachment);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -159,7 +159,7 @@ class Message extends Base {
|
||||
this.attachments = new Collection();
|
||||
if (data.attachments) {
|
||||
for (const attachment of data.attachments) {
|
||||
this.attachments.set(attachment.id, new Attachment(attachment.url, attachment.filename, attachment));
|
||||
this.attachments.set(attachment.id, new Attachment(attachment));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -644,7 +644,8 @@ class Message extends Base {
|
||||
* Only `MessageFlags.SuppressEmbeds` can be edited.
|
||||
* @property {Attachment[]} [attachments] An array of attachments to keep,
|
||||
* all attachments will be kept if omitted
|
||||
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to add to the message
|
||||
* @property {Array<JSONEncodable<AttachmentPayload>>|BufferResolvable[]|Attachment[]|AttachmentBuilder[]} [files]
|
||||
* Files to add to the message
|
||||
* @property {ActionRow[]|ActionRowOptions[]} [components]
|
||||
* Action rows containing interactive components for the message (buttons, select menus)
|
||||
*/
|
||||
|
||||
@@ -224,7 +224,8 @@ class MessagePayload {
|
||||
|
||||
/**
|
||||
* Resolves a single file into an object sendable to the API.
|
||||
* @param {BufferResolvable|Stream|FileOptions|Attachment} fileLike Something that could be resolved to a file
|
||||
* @param {BufferResolvable|Stream|JSONEncodable<AttachmentPayload>} fileLike Something that could
|
||||
* be resolved to a file
|
||||
* @returns {Promise<RawFile>}
|
||||
*/
|
||||
static async resolveFile(fileLike) {
|
||||
|
||||
@@ -132,7 +132,8 @@ class Webhook {
|
||||
* @typedef {Object} WebhookEditMessageOptions
|
||||
* @property {Embed[]|APIEmbed[]} [embeds] See {@link WebhookMessageOptions#embeds}
|
||||
* @property {string} [content] See {@link BaseMessageOptions#content}
|
||||
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] See {@link BaseMessageOptions#files}
|
||||
* @property {JSONEncodable<AttachmentPayload>|BufferResolvable[]|Attachment[]|AttachmentBuilder[]} [files]
|
||||
* See {@link BaseMessageOptions#files}
|
||||
* @property {MessageMentionOptions} [allowedMentions] See {@link BaseMessageOptions#allowedMentions}
|
||||
* @property {Attachment[]} [attachments] Attachments to send with the message
|
||||
* @property {ActionRow[]|ActionRowOptions[]} [components]
|
||||
|
||||
@@ -64,7 +64,7 @@ class TextBasedChannel {
|
||||
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to send with the message
|
||||
* @property {ActionRow[]|ActionRowOptions[]} [components]
|
||||
* Action rows containing interactive components for the message (buttons, select menus)
|
||||
* @property {Attachment[]} [attachments] Attachments to send in the message
|
||||
* @property {Array<JSONEncodable<AttachmentPayload>>} [attachments] Attachments to send in the message
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
40
packages/discord.js/typings/index.d.ts
vendored
40
packages/discord.js/typings/index.d.ts
vendored
@@ -117,6 +117,7 @@ import {
|
||||
LocalizationMap,
|
||||
LocaleString,
|
||||
MessageActivityType,
|
||||
APIAttachment,
|
||||
} from 'discord-api-types/v10';
|
||||
import { ChildProcess } from 'node:child_process';
|
||||
import { EventEmitter } from 'node:events';
|
||||
@@ -1696,9 +1697,22 @@ export class Message<Cached extends boolean = boolean> extends Base {
|
||||
public inGuild(): this is Message<true> & this;
|
||||
}
|
||||
|
||||
export class Attachment {
|
||||
export class AttachmentBuilder {
|
||||
public constructor(attachment: BufferResolvable | Stream, name?: string, data?: RawAttachmentData);
|
||||
public attachment: BufferResolvable | Stream;
|
||||
public description: string | null;
|
||||
public name: string | null;
|
||||
public get spoiler(): boolean;
|
||||
public setDescription(description: string): this;
|
||||
public setFile(attachment: BufferResolvable | Stream, name?: string): this;
|
||||
public setName(name: string): this;
|
||||
public setSpoiler(spoiler?: boolean): this;
|
||||
public toJSON(): unknown;
|
||||
public static from(other: JSONEncodable<AttachmentPayload>): AttachmentBuilder;
|
||||
}
|
||||
|
||||
export class Attachment {
|
||||
private constructor(data: APIAttachment);
|
||||
public attachment: BufferResolvable | Stream;
|
||||
public contentType: string | null;
|
||||
public description: string | null;
|
||||
@@ -1711,10 +1725,6 @@ export class Attachment {
|
||||
public get spoiler(): boolean;
|
||||
public url: string;
|
||||
public width: number | null;
|
||||
public setDescription(description: string): this;
|
||||
public setFile(attachment: BufferResolvable | Stream, name?: string): this;
|
||||
public setName(name: string): this;
|
||||
public setSpoiler(spoiler?: boolean): this;
|
||||
public toJSON(): unknown;
|
||||
}
|
||||
|
||||
@@ -1838,7 +1848,9 @@ export class MessagePayload {
|
||||
options: string | MessageOptions | WebhookMessageOptions,
|
||||
extra?: MessageOptions | WebhookMessageOptions,
|
||||
): MessagePayload;
|
||||
public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | Attachment): Promise<RawFile>;
|
||||
public static resolveFile(
|
||||
fileLike: BufferResolvable | Stream | AttachmentPayload | JSONEncodable<AttachmentPayload>,
|
||||
): Promise<RawFile>;
|
||||
|
||||
public makeContent(): string | undefined;
|
||||
public resolveBody(): this;
|
||||
@@ -3199,7 +3211,7 @@ export class GuildStickerManager extends CachedManager<Snowflake, Sticker, Stick
|
||||
private constructor(guild: Guild, iterable?: Iterable<RawStickerData>);
|
||||
public guild: Guild;
|
||||
public create(
|
||||
file: BufferResolvable | Stream | FileOptions | Attachment,
|
||||
file: BufferResolvable | Stream | AttachmentPayload | JSONEncodable<AttachmentBuilder>,
|
||||
name: string,
|
||||
tags: string,
|
||||
options?: GuildStickerCreateOptions,
|
||||
@@ -3939,7 +3951,7 @@ export interface CommandInteractionOption<Cached extends CacheType = CacheType>
|
||||
member?: CacheTypeReducer<Cached, GuildMember, APIInteractionDataResolvedGuildMember>;
|
||||
channel?: CacheTypeReducer<Cached, GuildBasedChannel, APIInteractionDataResolvedChannel>;
|
||||
role?: CacheTypeReducer<Cached, Role, APIRole>;
|
||||
attachment?: Attachment;
|
||||
attachment?: AttachmentBuilder;
|
||||
message?: GuildCacheMessage<Cached>;
|
||||
}
|
||||
|
||||
@@ -3949,7 +3961,7 @@ export interface CommandInteractionResolvedData<Cached extends CacheType = Cache
|
||||
roles?: Collection<Snowflake, CacheTypeReducer<Cached, Role, APIRole>>;
|
||||
channels?: Collection<Snowflake, CacheTypeReducer<Cached, AnyChannel, APIInteractionDataResolvedChannel>>;
|
||||
messages?: Collection<Snowflake, CacheTypeReducer<Cached, Message, APIMessage>>;
|
||||
attachments?: Collection<Snowflake, Attachment>;
|
||||
attachments?: Collection<Snowflake, AttachmentBuilder>;
|
||||
}
|
||||
|
||||
export declare const Colors: {
|
||||
@@ -4241,7 +4253,7 @@ export interface FetchThreadsOptions {
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
export interface FileOptions {
|
||||
export interface AttachmentPayload {
|
||||
attachment: BufferResolvable | Stream;
|
||||
name?: string;
|
||||
description?: string;
|
||||
@@ -4672,10 +4684,10 @@ export type MessageChannelComponentCollectorOptions<T extends MessageComponentIn
|
||||
>;
|
||||
|
||||
export interface MessageEditOptions {
|
||||
attachments?: Attachment[];
|
||||
attachments?: JSONEncodable<AttachmentPayload>[];
|
||||
content?: string | null;
|
||||
embeds?: (JSONEncodable<APIEmbed> | APIEmbed)[] | null;
|
||||
files?: (FileOptions | BufferResolvable | Stream | Attachment)[];
|
||||
files?: (AttachmentPayload | BufferResolvable | Stream | AttachmentBuilder)[];
|
||||
flags?: BitFieldResolvable<MessageFlagsString, number>;
|
||||
allowedMentions?: MessageMentionOptions;
|
||||
components?: (
|
||||
@@ -4726,10 +4738,10 @@ export interface MessageOptions {
|
||||
| APIActionRowComponent<APIMessageActionRowComponent>
|
||||
)[];
|
||||
allowedMentions?: MessageMentionOptions;
|
||||
files?: (FileOptions | BufferResolvable | Stream | Attachment)[];
|
||||
files?: (Attachment | AttachmentBuilder | BufferResolvable | Stream)[];
|
||||
reply?: ReplyOptions;
|
||||
stickers?: StickerResolvable[];
|
||||
attachments?: Attachment[];
|
||||
attachments?: (Attachment | AttachmentBuilder)[];
|
||||
flags?: BitFieldResolvable<Extract<MessageFlagsString, 'SuppressEmbeds'>, number>;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ import {
|
||||
Interaction,
|
||||
InteractionCollector,
|
||||
Message,
|
||||
Attachment,
|
||||
AttachmentBuilder,
|
||||
MessageCollector,
|
||||
MessageComponentInteraction,
|
||||
MessageReaction,
|
||||
@@ -615,7 +615,7 @@ client.on('messageCreate', async message => {
|
||||
assertIsMessage(channel.send({}));
|
||||
assertIsMessage(channel.send({ embeds: [] }));
|
||||
|
||||
const attachment = new Attachment('file.png');
|
||||
const attachment = new AttachmentBuilder('file.png');
|
||||
const embed = new EmbedBuilder();
|
||||
assertIsMessage(channel.send({ files: [attachment] }));
|
||||
assertIsMessage(channel.send({ embeds: [embed] }));
|
||||
@@ -1492,8 +1492,8 @@ expectNotAssignable<ActionRowData<MessageActionRowComponentData>>({
|
||||
|
||||
declare const chatInputInteraction: ChatInputCommandInteraction;
|
||||
|
||||
expectType<Attachment>(chatInputInteraction.options.getAttachment('attachment', true));
|
||||
expectType<Attachment | null>(chatInputInteraction.options.getAttachment('attachment'));
|
||||
expectType<AttachmentBuilder>(chatInputInteraction.options.getAttachment('attachment', true));
|
||||
expectType<AttachmentBuilder | null>(chatInputInteraction.options.getAttachment('attachment'));
|
||||
|
||||
declare const modal: ModalBuilder;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user