Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 1 addition & 1 deletion packages/discord.js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"@discordjs/util": "workspace:^",
"@discordjs/ws": "^1.2.1",
"@sapphire/snowflake": "3.5.3",
"discord-api-types": "^0.37.119",
"discord-api-types": "^0.38.1",
"fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1",
"tslib": "^2.6.3",
Expand Down
9 changes: 9 additions & 0 deletions packages/discord.js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,14 @@ exports.CommandInteraction = require('./structures/CommandInteraction');
exports.Collector = require('./structures/interfaces/Collector');
exports.CommandInteractionOptionResolver = require('./structures/CommandInteractionOptionResolver');
exports.Component = require('./structures/Component');
exports.ContainerComponent = require('./structures/ContainerComponent');
exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction');
exports.DMChannel = require('./structures/DMChannel');
exports.Embed = require('./structures/Embed');
exports.EmbedBuilder = require('./structures/EmbedBuilder');
exports.Emoji = require('./structures/Emoji').Emoji;
exports.Entitlement = require('./structures/Entitlement').Entitlement;
exports.FileComponent = require('./structures/FileComponent');
exports.ForumChannel = require('./structures/ForumChannel');
exports.Guild = require('./structures/Guild').Guild;
exports.GuildAuditLogs = require('./structures/GuildAuditLogs');
Expand Down Expand Up @@ -161,6 +163,8 @@ exports.Attachment = require('./structures/Attachment');
exports.AttachmentBuilder = require('./structures/AttachmentBuilder');
exports.ModalBuilder = require('./structures/ModalBuilder');
exports.MediaChannel = require('./structures/MediaChannel');
exports.MediaGalleryComponent = require('./structures/MediaGalleryComponent');
exports.MediaGalleryItem = require('./structures/MediaGalleryItem');
exports.MessageCollector = require('./structures/MessageCollector');
exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction');
exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction');
Expand All @@ -180,6 +184,7 @@ exports.ReactionCollector = require('./structures/ReactionCollector');
exports.ReactionEmoji = require('./structures/ReactionEmoji');
exports.RichPresenceAssets = require('./structures/Presence').RichPresenceAssets;
exports.Role = require('./structures/Role').Role;
exports.SectionComponent = require('./structures/SectionComponent');
exports.SelectMenuBuilder = require('./structures/SelectMenuBuilder');
exports.ChannelSelectMenuBuilder = require('./structures/ChannelSelectMenuBuilder');
exports.MentionableSelectMenuBuilder = require('./structures/MentionableSelectMenuBuilder');
Expand All @@ -201,6 +206,7 @@ exports.RoleSelectMenuInteraction = require('./structures/RoleSelectMenuInteract
exports.StringSelectMenuInteraction = require('./structures/StringSelectMenuInteraction');
exports.UserSelectMenuInteraction = require('./structures/UserSelectMenuInteraction');
exports.SelectMenuOptionBuilder = require('./structures/SelectMenuOptionBuilder');
exports.SeparatorComponent = require('./structures/SeparatorComponent');
exports.SKU = require('./structures/SKU').SKU;
exports.StringSelectMenuOptionBuilder = require('./structures/StringSelectMenuOptionBuilder');
exports.StageChannel = require('./structures/StageChannel');
Expand All @@ -211,12 +217,15 @@ exports.StickerPack = require('./structures/StickerPack');
exports.Team = require('./structures/Team');
exports.TeamMember = require('./structures/TeamMember');
exports.TextChannel = require('./structures/TextChannel');
exports.TextDisplayComponent = require('./structures/TextDisplayComponent');
exports.TextInputBuilder = require('./structures/TextInputBuilder');
exports.TextInputComponent = require('./structures/TextInputComponent');
exports.ThreadChannel = require('./structures/ThreadChannel');
exports.ThreadMember = require('./structures/ThreadMember');
exports.ThreadOnlyChannel = require('./structures/ThreadOnlyChannel');
exports.ThumbnailComponent = require('./structures/ThumbnailComponent');
exports.Typing = require('./structures/Typing');
exports.UnfurledMediaItem = require('./structures/UnfurledMediaItem');
exports.User = require('./structures/User');
exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction');
exports.VoiceChannelEffect = require('./structures/VoiceChannelEffect');
Expand Down
9 changes: 9 additions & 0 deletions packages/discord.js/src/structures/Component.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ class Component {
this.data = data;
}

/**
* The id of this component
* @type {number}
* @readonly
*/
get id() {
return this.data.id;
}

/**
* The type of the component
* @type {ComponentType}
Expand Down
60 changes: 60 additions & 0 deletions packages/discord.js/src/structures/ContainerComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict';

const Component = require('./Component');
const { createComponent } = require('../util/Components');

/**
* Represents a container component
* @extends {Component}
*/
class ContainerComponent extends Component {
constructor({ components, ...data }) {
super(data);

/**
* The components in this container
* @type {Component[]}
* @readonly
*/
this.components = components.map(component => createComponent(component));
}

/**
* The accent color of this container
* @type {?number}
* @readonly
*/
get accentColor() {
return this.data.accent_color ?? null;
}

/**
* The hex accent color of this container
* @type {?string}
* @readonly
*/
get hexAccentColor() {
return typeof this.data.accent_color === 'number'
? `#${this.data.accent_color.toString(16).padStart(6, '0')}`
: (this.data.accent_color ?? null);
}

/**
* Whether this container is spoilered
* @type {boolean}
* @readonly
*/
get spoiler() {
return this.data.spoiler ?? false;
}

/**
* Returns the API-compatible JSON for this component
* @returns {APIContainerComponent}
*/
toJSON() {
return { ...this.data, components: this.components.map(component => component.toJSON()) };
}
}

module.exports = ContainerComponent;
40 changes: 40 additions & 0 deletions packages/discord.js/src/structures/FileComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';

const Component = require('./Component');
const UnfurledMediaItem = require('./UnfurledMediaItem');

/**
* Represents a file component
* @extends {Component}
*/
class FileComponent extends Component {
constructor({ file, ...data }) {
super(data);

/**
* The media associated with this file
* @type {UnfurledMediaItem}
* @readonly
*/
this.file = new UnfurledMediaItem(file);
}

/**
* Whether this thumbnail is spoilered
* @type {boolean}
* @readonly
*/
get spoiler() {
return this.data.spoiler ?? false;
}

/**
* Returns the API-compatible JSON for this component
* @returns {APIFileComponent}
*/
toJSON() {
return { ...this.data, file: this.file.toJSON() };
}
}

module.exports = FileComponent;
31 changes: 31 additions & 0 deletions packages/discord.js/src/structures/MediaGalleryComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const Component = require('./Component');
const MediaGalleryItem = require('./MediaGalleryItem');

/**
* Represents a media gallery component
* @extends {Component}
*/
class MediaGalleryComponent extends Component {
constructor({ items, ...data }) {
super(data);

/**
* The items in this media gallery
* @type {MediaGalleryItem[]}
* @readonly
*/
this.items = items.map(item => new MediaGalleryItem(item));
}

/**
* Returns the API-compatible JSON for this component
* @returns {APIMediaGalleryComponent}
*/
toJSON() {
return { ...this.data, items: this.items.map(item => item.toJSON()) };
}
}

module.exports = MediaGalleryComponent;
51 changes: 51 additions & 0 deletions packages/discord.js/src/structures/MediaGalleryItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

const UnfurledMediaItem = require('./UnfurledMediaItem');

/**
* Represents an item in a media gallery
*/
class MediaGalleryItem {
constructor({ media, ...data }) {
/**
* The API data associated with this component
* @type {APIMediaGalleryItem}
*/
this.data = data;

/**
* The media associated with this media gallery item
* @type {UnfurledMediaItem}
* @readonly
*/
this.media = new UnfurledMediaItem(media);
}

/**
* The description of this media gallery item
* @type {?string}
* @readonly
*/
get description() {
return this.data.description ?? null;
}

/**
* Whether this media gallery item is spoilered
* @type {boolean}
* @readonly
*/
get spoiler() {
return this.data.spoiler ?? false;
}

/**
* Returns the API-compatible JSON for this component
* @returns {APIMediaGalleryItem}
*/
toJSON() {
return { ...this.data, media: this.media.toJSON() };
}
}

module.exports = MediaGalleryItem;
20 changes: 17 additions & 3 deletions packages/discord.js/src/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
MessageFlags,
PermissionFlagsBits,
MessageReferenceType,
ComponentType,
} = require('discord-api-types/v10');
const Attachment = require('./Attachment');
const Base = require('./Base');
Expand Down Expand Up @@ -151,10 +152,10 @@ class Message extends Base {

if ('components' in data) {
/**
* An array of action rows in the message.
* An array of components in the message.
* <info>This property requires the {@link GatewayIntentBits.MessageContent} privileged intent
* in a guild for messages that do not mention the client.</info>
* @type {ActionRow[]}
* @type {Component[]}
*/
this.components = data.components.map(component => createComponent(component));
} else {
Expand Down Expand Up @@ -1055,7 +1056,20 @@ class Message extends Base {
* @returns {?MessageActionRowComponent}
*/
resolveComponent(customId) {
return this.components.flatMap(row => row.components).find(component => component.customId === customId) ?? null;
return (
this.components
.flatMap(component => {
switch (component.type) {
case ComponentType.ActionRow:
return component.components;
case ComponentType.Section:
return [component.accessory];
default:
return [component];
}
})
.find(component => component.customId === customId) ?? null
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const { lazy } = require('@discordjs/util');
const { ComponentType } = require('discord-api-types/v10');
const BaseInteraction = require('./BaseInteraction');
const InteractionWebhook = require('./InteractionWebhook');
const InteractionResponses = require('./interfaces/InteractionResponses');
Expand Down Expand Up @@ -79,12 +80,21 @@ class MessageComponentInteraction extends BaseInteraction {

/**
* The component which was interacted with
* @type {MessageActionRowComponent|APIMessageActionRowComponent}
* @type {MessageActionRowComponent|APIComponentInActionRow}
* @readonly
*/
get component() {
return this.message.components
.flatMap(row => row.components)
.flatMap(component => {
switch (component.type) {
case ComponentType.ActionRow:
return component.components;
case ComponentType.Section:
return [component.accessory];
default:
return [component];
}
})
.find(component => (component.customId ?? component.custom_id) === this.customId);
}

Expand Down
3 changes: 1 addition & 2 deletions packages/discord.js/src/structures/MessagePayload.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const { Buffer } = require('node:buffer');
const { lazy, isJSONEncodable } = require('@discordjs/util');
const { DiscordSnowflake } = require('@sapphire/snowflake');
const { MessageFlags, MessageReferenceType } = require('discord-api-types/v10');
const ActionRowBuilder = require('./ActionRowBuilder');
const { DiscordjsError, DiscordjsRangeError, ErrorCodes } = require('../errors');
const { resolveFile } = require('../util/DataResolver');
const MessageFlagsBitField = require('../util/MessageFlagsBitField');
Expand Down Expand Up @@ -149,7 +148,7 @@ class MessagePayload {
}

const components = this.options.components?.map(component =>
(isJSONEncodable(component) ? component : new ActionRowBuilder(component)).toJSON(),
isJSONEncodable(component) ? component.toJSON() : this.target.client.options.jsonTransformer(component),
);

let username;
Expand Down
Loading