Skip to content

Commit dfadcbc

Browse files
suneettipirnenialmeidxkyranetSpaceEEC
authored
refactor(attachment): don't return attachment builders from API (#7852)
Co-authored-by: Almeida <[email protected]> Co-authored-by: A. Román <[email protected]> Co-authored-by: SpaceEEC <[email protected]>
1 parent 546d486 commit dfadcbc

File tree

11 files changed

+166
-89
lines changed

11 files changed

+166
-89
lines changed

packages/discord.js/src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ exports.InviteStageInstance = require('./structures/InviteStageInstance');
123123
exports.InviteGuild = require('./structures/InviteGuild');
124124
exports.Message = require('./structures/Message').Message;
125125
exports.Attachment = require('./structures/Attachment');
126+
exports.AttachmentBuilder = require('./structures/AttachmentBuilder');
126127
exports.ModalBuilder = require('./structures/ModalBuilder');
127128
exports.MessageCollector = require('./structures/MessageCollector');
128129
exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction');

packages/discord.js/src/managers/GuildStickerManager.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class GuildStickerManager extends CachedManager {
4141

4242
/**
4343
* Creates a new custom sticker in the guild.
44-
* @param {BufferResolvable|Stream|FileOptions|Attachment} file The file for the sticker
44+
* @param {BufferResolvable|Stream|JSONEncodable<AttachmentPayload>} file The file for the sticker
4545
* @param {string} name The name for the sticker
4646
* @param {string} tags The Discord name of a unicode emoji representing the sticker's expression
4747
* @param {GuildStickerCreateOptions} [options] Options

packages/discord.js/src/structures/Attachment.js

+14-63
Original file line numberDiff line numberDiff line change
@@ -3,74 +3,30 @@
33
const Util = require('../util/Util');
44

55
/**
6-
* Represents an attachment.
6+
* @typedef {Object} AttachmentPayload
7+
* @property {?string} name The name of the attachment
8+
* @property {Stream|BufferResolvable} attachment The attachment in this payload
9+
* @property {?string} description The description of the attachment
10+
*/
11+
12+
/**
13+
* Represents an attachment
714
*/
815
class Attachment {
916
/**
10-
* @param {BufferResolvable|Stream} attachment The file
11-
* @param {string} [name=null] The name of the file, if any
12-
* @param {APIAttachment} [data] Extra data
17+
* @param {APIAttachment} data Attachment data
18+
* @private
1319
*/
14-
constructor(attachment, name = null, data) {
15-
this.attachment = attachment;
20+
constructor({ url, filename, ...data }) {
21+
this.attachment = url;
1622
/**
1723
* The name of this attachment
18-
* @type {?string}
24+
* @type {string}
1925
*/
20-
this.name = name;
26+
this.name = filename;
2127
if (data) this._patch(data);
2228
}
2329

24-
/**
25-
* Sets the description of this attachment.
26-
* @param {string} description The description of the file
27-
* @returns {Attachment} This attachment
28-
*/
29-
setDescription(description) {
30-
this.description = description;
31-
return this;
32-
}
33-
34-
/**
35-
* Sets the file of this attachment.
36-
* @param {BufferResolvable|Stream} attachment The file
37-
* @param {string} [name=null] The name of the file, if any
38-
* @returns {Attachment} This attachment
39-
*/
40-
setFile(attachment, name = null) {
41-
this.attachment = attachment;
42-
this.name = name;
43-
return this;
44-
}
45-
46-
/**
47-
* Sets the name of this attachment.
48-
* @param {string} name The name of the file
49-
* @returns {Attachment} This attachment
50-
*/
51-
setName(name) {
52-
this.name = name;
53-
return this;
54-
}
55-
56-
/**
57-
* Sets whether this attachment is a spoiler
58-
* @param {boolean} [spoiler=true] Whether the attachment should be marked as a spoiler
59-
* @returns {Attachment} This attachment
60-
*/
61-
setSpoiler(spoiler = true) {
62-
if (spoiler === this.spoiler) return this;
63-
64-
if (!spoiler) {
65-
while (this.spoiler) {
66-
this.name = this.name.slice('SPOILER_'.length);
67-
}
68-
return this;
69-
}
70-
this.name = `SPOILER_${this.name}`;
71-
return this;
72-
}
73-
7430
_patch(data) {
7531
/**
7632
* The attachment's id
@@ -164,8 +120,3 @@ class Attachment {
164120
}
165121

166122
module.exports = Attachment;
167-
168-
/**
169-
* @external APIAttachment
170-
* @see {@link https://discord.com/developers/docs/resources/channel#attachment-object}
171-
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
'use strict';
2+
3+
const Util = require('../util/Util');
4+
5+
/**
6+
* Represents an attachment builder
7+
*/
8+
class AttachmentBuilder {
9+
/**
10+
* @param {BufferResolvable|Stream} attachment The file
11+
* @param {APIAttachment} [data] Extra data
12+
*/
13+
constructor(attachment, data = {}) {
14+
/**
15+
* The file associated with this attachment.
16+
* @type {BufferResolvable|Stream}
17+
*/
18+
this.attachment = attachment;
19+
/**
20+
* The name of this attachment
21+
* @type {?string}
22+
*/
23+
this.name = data.name;
24+
/**
25+
* The description of the attachment
26+
* @type {?string}
27+
*/
28+
this.description = data.description;
29+
}
30+
31+
/**
32+
* Sets the description of this attachment.
33+
* @param {string} description The description of the file
34+
* @returns {AttachmentBuilder} This attachment
35+
*/
36+
setDescription(description) {
37+
this.description = description;
38+
return this;
39+
}
40+
41+
/**
42+
* Sets the file of this attachment.
43+
* @param {BufferResolvable|Stream} attachment The file
44+
* @returns {AttachmentBuilder} This attachment
45+
*/
46+
setFile(attachment) {
47+
this.attachment = attachment;
48+
return this;
49+
}
50+
51+
/**
52+
* Sets the name of this attachment.
53+
* @param {string} name The name of the file
54+
* @returns {AttachmentBuilder} This attachment
55+
*/
56+
setName(name) {
57+
this.name = name;
58+
return this;
59+
}
60+
61+
/**
62+
* Sets whether this attachment is a spoiler
63+
* @param {boolean} [spoiler=true] Whether the attachment should be marked as a spoiler
64+
* @returns {AttachmentBuilder} This attachment
65+
*/
66+
setSpoiler(spoiler = true) {
67+
if (spoiler === this.spoiler) return this;
68+
69+
if (!spoiler) {
70+
while (this.spoiler) {
71+
this.name = this.name.slice('SPOILER_'.length);
72+
}
73+
return this;
74+
}
75+
this.name = `SPOILER_${this.name}`;
76+
return this;
77+
}
78+
79+
/**
80+
* Whether or not this attachment has been marked as a spoiler
81+
* @type {boolean}
82+
* @readonly
83+
*/
84+
get spoiler() {
85+
return Util.basename(this.name).startsWith('SPOILER_');
86+
}
87+
88+
toJSON() {
89+
return Util.flatten(this);
90+
}
91+
92+
/**
93+
* Makes a new builder instance from a preexisting attachment structure.
94+
* @param {JSONEncodable<AttachmentPayload>} other The builder to construct a new instance from
95+
* @returns {AttachmentBuilder}
96+
*/
97+
static from(other) {
98+
return new AttachmentBuilder(other.attachment, {
99+
name: other.name,
100+
description: other.description,
101+
});
102+
}
103+
}
104+
105+
module.exports = AttachmentBuilder;
106+
107+
/**
108+
* @external APIAttachment
109+
* @see {@link https://discord.com/developers/docs/resources/channel#attachment-object}
110+
*/

packages/discord.js/src/structures/CommandInteraction.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class CommandInteraction extends Interaction {
133133
if (attachments) {
134134
result.attachments = new Collection();
135135
for (const attachment of Object.values(attachments)) {
136-
const patched = new Attachment(attachment.url, attachment.filename, attachment);
136+
const patched = new Attachment(attachment);
137137
result.attachments.set(attachment.id, patched);
138138
}
139139
}
@@ -189,7 +189,7 @@ class CommandInteraction extends Interaction {
189189
if (role) result.role = this.guild?.roles._add(role) ?? role;
190190

191191
const attachment = resolved.attachments?.[option.value];
192-
if (attachment) result.attachment = new Attachment(attachment.url, attachment.filename, attachment);
192+
if (attachment) result.attachment = new Attachment(attachment);
193193
}
194194

195195
return result;

packages/discord.js/src/structures/Message.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class Message extends Base {
159159
this.attachments = new Collection();
160160
if (data.attachments) {
161161
for (const attachment of data.attachments) {
162-
this.attachments.set(attachment.id, new Attachment(attachment.url, attachment.filename, attachment));
162+
this.attachments.set(attachment.id, new Attachment(attachment));
163163
}
164164
}
165165
} else {
@@ -644,7 +644,8 @@ class Message extends Base {
644644
* Only `MessageFlags.SuppressEmbeds` can be edited.
645645
* @property {Attachment[]} [attachments] An array of attachments to keep,
646646
* all attachments will be kept if omitted
647-
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to add to the message
647+
* @property {Array<JSONEncodable<AttachmentPayload>>|BufferResolvable[]|Attachment[]|AttachmentBuilder[]} [files]
648+
* Files to add to the message
648649
* @property {ActionRow[]|ActionRowOptions[]} [components]
649650
* Action rows containing interactive components for the message (buttons, select menus)
650651
*/

packages/discord.js/src/structures/MessagePayload.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ class MessagePayload {
224224

225225
/**
226226
* Resolves a single file into an object sendable to the API.
227-
* @param {BufferResolvable|Stream|FileOptions|Attachment} fileLike Something that could be resolved to a file
227+
* @param {BufferResolvable|Stream|JSONEncodable<AttachmentPayload>} fileLike Something that could
228+
* be resolved to a file
228229
* @returns {Promise<RawFile>}
229230
*/
230231
static async resolveFile(fileLike) {

packages/discord.js/src/structures/Webhook.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ class Webhook {
132132
* @typedef {Object} WebhookEditMessageOptions
133133
* @property {Embed[]|APIEmbed[]} [embeds] See {@link WebhookMessageOptions#embeds}
134134
* @property {string} [content] See {@link BaseMessageOptions#content}
135-
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] See {@link BaseMessageOptions#files}
135+
* @property {JSONEncodable<AttachmentPayload>|BufferResolvable[]|Attachment[]|AttachmentBuilder[]} [files]
136+
* See {@link BaseMessageOptions#files}
136137
* @property {MessageMentionOptions} [allowedMentions] See {@link BaseMessageOptions#allowedMentions}
137138
* @property {Attachment[]} [attachments] Attachments to send with the message
138139
* @property {ActionRow[]|ActionRowOptions[]} [components]

packages/discord.js/src/structures/interfaces/TextBasedChannel.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class TextBasedChannel {
6464
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to send with the message
6565
* @property {ActionRow[]|ActionRowOptions[]} [components]
6666
* Action rows containing interactive components for the message (buttons, select menus)
67-
* @property {Attachment[]} [attachments] Attachments to send in the message
67+
* @property {Array<JSONEncodable<AttachmentPayload>>} [attachments] Attachments to send in the message
6868
*/
6969

7070
/**

0 commit comments

Comments
 (0)