Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/builders/src/messages/Attachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export class AttachmentBuilder implements JSONEncodable<RESTAPIAttachment> {
* Creates a new attachment builder.
*
* @param data - The API data to create this attachment with
* @example
* ```ts
* const attachment = new AttachmentBuilder().setId(1).setFileData(':)').setFilename('smiley.txt')
* ```
* @remarks Please note that the `id` field is required, it's rather easy to miss!
*/
public constructor(data: Partial<RESTAPIAttachment> = {}) {
this.data = structuredClone(data);
Expand Down
1 change: 0 additions & 1 deletion packages/discord.js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ exports.ApplicationEmoji = require('./structures/ApplicationEmoji.js').Applicati
exports.ApplicationRoleConnectionMetadata =
require('./structures/ApplicationRoleConnectionMetadata.js').ApplicationRoleConnectionMetadata;
exports.Attachment = require('./structures/Attachment.js').Attachment;
exports.AttachmentBuilder = require('./structures/AttachmentBuilder.js').AttachmentBuilder;
exports.AutocompleteInteraction = require('./structures/AutocompleteInteraction.js').AutocompleteInteraction;
exports.AutoModerationActionExecution =
require('./structures/AutoModerationActionExecution.js').AutoModerationActionExecution;
Expand Down
17 changes: 10 additions & 7 deletions packages/discord.js/src/managers/ChannelManager.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const process = require('node:process');
const { lazy } = require('@discordjs/util');
const { lazy, isFileBodyEncodable, isJSONEncodable } = require('@discordjs/util');
const { Routes } = require('discord-api-types/v10');
const { BaseChannel } = require('../structures/BaseChannel.js');
const { MessagePayload } = require('../structures/MessagePayload.js');
Expand Down Expand Up @@ -147,7 +147,7 @@ class ChannelManager extends CachedManager {
* Creates a message in a channel.
*
* @param {TextChannelResolvable} channel The channel to send the message to
* @param {string|MessagePayload|MessageCreateOptions} options The options to provide
* @param {string|MessagePayload|MessageCreateOptions|JSONEncodable<RESTPostAPIChannelMessageJSONBody>|FileBodyEncodable<RESTPostAPIChannelMessageJSONBody>} options The options to provide
* @returns {Promise<Message>}
* @example
* // Send a basic message
Expand All @@ -174,18 +174,21 @@ class ChannelManager extends CachedManager {
* .catch(console.error);
*/
async createMessage(channel, options) {
let messagePayload;
let payload;

if (options instanceof MessagePayload) {
messagePayload = options.resolveBody();
payload = await options.resolveBody().resolveFiles();
} else if (isFileBodyEncodable(options)) {
payload = options.toFileBody();
} else if (isJSONEncodable(options)) {
payload = { body: options.toJSON() };
} else {
messagePayload = MessagePayload.create(this, options).resolveBody();
payload = await MessagePayload.create(this, options).resolveBody().resolveFiles();
}

const resolvedChannelId = this.resolveId(channel);
const resolvedChannel = this.resolve(channel);
const { body, files } = await messagePayload.resolveFiles();
const data = await this.client.rest.post(Routes.channelMessages(resolvedChannelId), { body, files });
const data = await this.client.rest.post(Routes.channelMessages(resolvedChannelId), payload);

return resolvedChannel?.messages._add(data) ?? new (getMessage())(this.client, data);
}
Expand Down
25 changes: 16 additions & 9 deletions packages/discord.js/src/managers/MessageManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { Collection } = require('@discordjs/collection');
const { makeURLSearchParams } = require('@discordjs/rest');
const { isFileBodyEncodable, isJSONEncodable } = require('@discordjs/util');
const { Routes } = require('discord-api-types/v10');
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
const { Message } = require('../structures/Message.js');
Expand Down Expand Up @@ -223,21 +224,27 @@ class MessageManager extends CachedManager {
* Edits a message, even if it's not cached.
*
* @param {MessageResolvable} message The message to edit
* @param {string|MessageEditOptions|MessagePayload} options The options to edit the message
* @param {string|MessageEditOptions|MessagePayload|FileBodyEncodable<RESTPatchAPIChannelMessageJSONBody>|JSONEncodable<RESTPatchAPIChannelMessageJSONBody>} options The options to edit the message
* @returns {Promise<Message>}
*/
async edit(message, options) {
const messageId = this.resolveId(message);
if (!messageId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');

const { body, files } = await (
options instanceof MessagePayload
? options
: MessagePayload.create(message instanceof Message ? message : this, options)
)
.resolveBody()
.resolveFiles();
const data = await this.client.rest.patch(Routes.channelMessage(this.channel.id, messageId), { body, files });
let payload;
if (options instanceof MessagePayload) {
payload = await options.resolveBody().resolveFiles();
} else if (isFileBodyEncodable(options)) {
payload = options.toFileBody();
} else if (isJSONEncodable(options)) {
payload = { body: options.toJSON() };
} else {
payload = await MessagePayload.create(message instanceof Message ? message : this, options)
.resolveBody()
.resolveFiles();
}

const data = await this.client.rest.patch(Routes.channelMessage(this.channel.id, messageId), payload);

const existing = this.cache.get(messageId);
if (existing) {
Expand Down
185 changes: 0 additions & 185 deletions packages/discord.js/src/structures/AttachmentBuilder.js

This file was deleted.

2 changes: 1 addition & 1 deletion packages/discord.js/src/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ class Message extends Base {
/**
* Edits the content of the message.
*
* @param {string|MessagePayload|MessageEditOptions} options The options to provide
* @param {string|MessageEditOptions|MessagePayload|FileBodyEncodable<RESTPatchAPIChannelMessageJSONBody>|JSONEncodable<RESTPatchAPIChannelMessageJSONBody>} options The options to provide
* @returns {Promise<Message>}
* @example
* // Update the content of a message
Expand Down
7 changes: 6 additions & 1 deletion packages/discord.js/src/structures/MessagePayload.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,13 @@ class MessagePayload {
waveform: file.waveform,
duration_secs: file.duration,
}));

// Only passable during edits
if (Array.isArray(this.options.attachments)) {
this.options.attachments.push(...(attachments ?? []));
this.options.attachments = this.options.attachments
// Note how we don't check for file body encodable, since we aren't expecting file data here
.map(attachment => (isJSONEncodable(attachment) ? attachment.toJSON() : attachment))
.concat(attachments ?? []);
Comment on lines +203 to +206
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like now that we overwrite this.options.attachments either way it should probably not be overwriting the options at all and instead be a const we assign or make attachments a let and modify in the if case.

Feels wrong to use this.options.attachments in the returned payload when it never will be the actual passed value at that point.

} else {
this.options.attachments = attachments;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class TextBasedChannel {
* @property {Array<(EmbedBuilder|Embed|APIEmbed)>} [embeds] The embeds for the message
* @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content
* (see {@link https://discord.com/developers/docs/resources/message#allowed-mentions-object here} for more details)
* @property {Array<(AttachmentBuilder|Attachment|AttachmentPayload|BufferResolvable)>} [files]
* @property {Array<(Attachment|AttachmentPayload|BufferResolvable|FileBodyEncodable<APIAttachment>|Stream)>} [files]
* The files to send with the message.
* @property {Array<(ActionRowBuilder|MessageTopLevelComponent|APIMessageTopLevelComponent)>} [components]
* Action rows containing interactive components for the message (buttons, select menus) and other
Expand Down Expand Up @@ -156,7 +156,7 @@ class TextBasedChannel {
/**
* Sends a message to this channel.
*
* @param {string|MessagePayload|MessageCreateOptions} options The options to provide
* @param {string|MessagePayload|MessageCreateOptions|JSONEncodable<RESTPostAPIChannelMessageJSONBody>|FileBodyEncodable<RESTPostAPIChannelMessageJSONBody>} options The options to provide
* @returns {Promise<Message>}
* @example
* // Send a basic message
Expand Down
10 changes: 10 additions & 0 deletions packages/discord.js/src/util/APITypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,13 @@
* @external WebhookType
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/WebhookType}
*/

/**
* @external RESTPostAPIChannelMessageJSONBody
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/RESTPostAPIChannelMessageJSONBody}
*/

/**
* @external RESTPatchAPIChannelMessageJSONBody
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/RESTPatchAPIChannelMessageJSONBody}
*/
Loading