Skip to content

Commit

Permalink
feat: support components v2 and add message flags
Browse files Browse the repository at this point in the history
  • Loading branch information
Snazzah committed Feb 14, 2025
1 parent 0cd1c8f commit c789e7a
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 26 deletions.
115 changes: 111 additions & 4 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,30 @@ export enum InteractionResponseType {

/** Message flags for interaction responses. */
export enum InteractionResponseFlags {
/** Sends a message back to the invoker, similar to messages by Clyde. */
/**
* Sends a message back to the invoker, similar to messages by Clyde.
* @deprecated use MessageFlags.EPHEMERAL
*/
EPHEMERAL = 1 << 6
}

/** Message flags. */
export enum MessageFlags {
CROSSPOSTED = 1 << 0,
IS_CROSSPOST = 1 << 1,
SUPPRESS_EMBEDS = 1 << 2,
SOURCE_MESSAGE_DELETED = 1 << 3,
URGENT = 1 << 4,
HAS_THREAD = 1 << 5,
/** Sends a message back to the invoker, similar to messages by Clyde. */
EPHEMERAL = 1 << 6,
LOADING = 1 << 7,
FAILED_TO_MENTION_SOME_ROLES_IN_THREAD = 1 << 8,
SUPPRESS_NOTIFICATIONS = 1 << 12,
IS_VOICE_MESSAGE = 1 << 13,
HAS_SNAPSHOT = 1 << 14
}

/**
* An object mapping the types a command option can use.
*/
Expand Down Expand Up @@ -943,7 +963,15 @@ export enum ComponentType {
/** A user/role select component. */
MENTIONABLE_SELECT = 7,
/** A channel select component. */
CHANNEL_SELECT = 8
CHANNEL_SELECT = 8,

SECTION = 9,
TEXT_DISPLAY = 10,
THUMBNAIL = 11,
MEDIA_GALLERY = 12,
FILE = 13,
SEPARATOR = 14,
CONTAINER = 17
}

/** The types of component button styles. */
Expand Down Expand Up @@ -971,15 +999,94 @@ export enum TextInputStyle {
PARAGRAPH = 2
}

export interface UnfurledMediaItem {
url: string;
}

export interface BaseComponent {
type: ComponentType;
id?: number;
}

export interface SectionComponent extends BaseComponent {
type: ComponentType.SECTION;
components: TextDisplayComponent[];
accessory: ThumbnailComponent | AnyComponentButton;
}

export interface TextDisplayComponent extends BaseComponent {
type: ComponentType.TEXT_DISPLAY;
content: string;
}

export interface ThumbnailComponent extends BaseComponent {
type: ComponentType.THUMBNAIL;
media: UnfurledMediaItem;
description?: string;
spoiler?: boolean;
}

export interface MediaGalleryItem {
media: UnfurledMediaItem;
description?: string;
spoiler?: boolean;
}
export interface MediaGalleryComponent extends BaseComponent {
type: ComponentType.MEDIA_GALLERY;
items: MediaGalleryItem[];
}

export enum SeparatorSpacingSize {
SMALL = 1,
LARGE = 2
}

export interface SeparatorComponent extends BaseComponent {
type: ComponentType.SEPARATOR;
divider?: boolean;
spacing?: SeparatorSpacingSize;
}

export interface FileComponent extends BaseComponent {
type: ComponentType.FILE;
/** Only supports attachment:// references */
file: UnfurledMediaItem;
spoiler?: boolean;
}
export interface ContainerComponent extends BaseComponent {
type: ComponentType.CONTAINER;
accent_color?: number;
spoiler?: boolean;
components: (
| ComponentActionRow
| TextDisplayComponent
| SectionComponent
| MediaGalleryComponent
| SeparatorComponent
| FileComponent
)[];
}

/** Any component. */
export type AnyComponent = ComponentActionRow | AnyComponentButton | ComponentSelectMenu | ComponentTextInput;
export type AnyComponent =
| ComponentActionRow
| AnyComponentButton
| ComponentSelectMenu
| ComponentTextInput
| SectionComponent
| TextDisplayComponent
| SectionComponent
| MediaGalleryComponent
| SeparatorComponent
| FileComponent
| ContainerComponent;

/** A row of components. */
export interface ComponentActionRow {
/** The type of component to use. */
type: ComponentType.ACTION_ROW;
/** The components to show inside this row. */
components: (AnyComponentButton | ComponentSelectMenu | ComponentTextInput)[];
components: Exclude<AnyComponent, ComponentActionRow>[];
}

/** Any component button. */
Expand Down
6 changes: 3 additions & 3 deletions src/creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import {
AnyRequestData,
RawRequest,
InteractionResponseType,
InteractionResponseFlags,
PartialApplicationCommand,
BulkUpdateCommand,
CommandUser,
InteractionRequestData,
ApplicationCommandType,
CommandAutocompleteRequestData
CommandAutocompleteRequestData,
MessageFlags
} from './constants';
import { SlashCommand } from './command';
import { TypedEventEmitter } from './util/typedEmitter';
Expand Down Expand Up @@ -619,7 +619,7 @@ export class BaseSlashCreator extends (EventEmitter as any as new () => TypedEve
This command no longer exists.
This command should no longer show up in an hour if it has been deleted.
`,
flags: InteractionResponseFlags.EPHEMERAL
flags: MessageFlags.EPHEMERAL
}
}
});
Expand Down
21 changes: 6 additions & 15 deletions src/structures/interfaces/messageInteraction.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
AnyComponent,
InitialCallbackResponse,
InteractionResponseFlags,
InteractionResponseType
} from '../../constants';
import { AnyComponent, InitialCallbackResponse, MessageFlags, InteractionResponseType } from '../../constants';
import { BaseSlashCreator, ComponentRegisterCallback } from '../../creator';
import { RespondFunction } from '../../server';
import {
Expand Down Expand Up @@ -71,9 +66,9 @@ export class MessageInteractionContext<

const options = typeof content === 'string' ? { content } : content;
if (typeof options !== 'object') throw new Error('Message options is not an object.');
if (!options.content && !options.embeds && !options.files && !options.poll)
if (!options.content && !options.embeds && !options.files && !options.poll && !options.components)
throw new Error('No valid options were given.');
if (options.ephemeral && !options.flags) options.flags = InteractionResponseFlags.EPHEMERAL;
if (options.ephemeral && !options.flags) options.flags = MessageFlags.EPHEMERAL;

const allowedMentions = options.allowedMentions
? formatAllowedMentions(options.allowedMentions, this.creator.allowedMentions as FormattedAllowedMentions)
Expand Down Expand Up @@ -113,9 +108,9 @@ export class MessageInteractionContext<

const options = typeof content === 'string' ? { content } : content;
if (typeof options !== 'object') throw new Error('Message options is not an object.');
if (!options.content && !options.embeds && !options.files && !options.poll)
if (!options.content && !options.embeds && !options.files && !options.poll && !options.components)
throw new Error('No valid options were given.');
if (options.ephemeral && !options.flags) options.flags = InteractionResponseFlags.EPHEMERAL;
if (options.ephemeral && !options.flags) options.flags = MessageFlags.EPHEMERAL;

const allowedMentions = options.allowedMentions
? formatAllowedMentions(options.allowedMentions, this.creator.allowedMentions as FormattedAllowedMentions)
Expand Down Expand Up @@ -218,11 +213,7 @@ export class MessageInteractionContext<
*/
async defer(ephemeralOrFlags: number | boolean = 0): Promise<boolean | InitialCallbackResponse> {
const flags =
typeof ephemeralOrFlags === 'boolean'
? ephemeralOrFlags
? InteractionResponseFlags.EPHEMERAL
: 0
: ephemeralOrFlags;
typeof ephemeralOrFlags === 'boolean' ? (ephemeralOrFlags ? MessageFlags.EPHEMERAL : 0) : ephemeralOrFlags;
if (!this.initiallyResponded && !this.deferred) {
this.initiallyResponded = true;
this.deferred = true;
Expand Down
2 changes: 1 addition & 1 deletion test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ describe('[index]', () => {
expect(slashCreate.FastifyServer).to.be.a('function');
expect(slashCreate.GCFServer).to.be.a('function');
expect(slashCreate.GatewayServer).to.be.a('function');
expect(slashCreate.InteractionResponseFlags).to.be.a('object');
expect(slashCreate.InteractionType).to.be.a('object');
expect(slashCreate.InteractionResponseType).to.be.a('object');
expect(slashCreate.ApplicationCommandPermissionType).to.be.a('object');
expect(slashCreate.Member).to.be.a('function');
expect(slashCreate.Message).to.be.a('function');
expect(slashCreate.MessageFlags).to.be.a('object');
expect(slashCreate.Permissions).to.be.a('function');
expect(slashCreate.Server).to.be.a('function');
expect(slashCreate.SlashCommand).to.be.a('function');
Expand Down
6 changes: 3 additions & 3 deletions test/structures/interfaces/messageInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'mocha';
const expect = chai.expect;
import { createFollowUp, deleteMessage, editMessage } from '../../__util__/nock';

import { InteractionResponseFlags, InteractionResponseType } from '../../../src/constants';
import { MessageFlags, InteractionResponseType } from '../../../src/constants';
import { Message } from '../../../src/structures/message';
import {
creator,
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('MessageInteractionContext', () => {
async (treq) => {
expect(treq.body).to.deep.equal({
type: InteractionResponseType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE,
data: { flags: InteractionResponseFlags.EPHEMERAL }
data: { flags: MessageFlags.EPHEMERAL }
});
expect(treq.status).to.equal(200);
},
Expand Down Expand Up @@ -124,7 +124,7 @@ describe('MessageInteractionContext', () => {
parse: ['roles', 'users']
},
embeds: undefined,
flags: InteractionResponseFlags.EPHEMERAL,
flags: MessageFlags.EPHEMERAL,
tts: undefined,
components: undefined,
attachments: undefined,
Expand Down

0 comments on commit c789e7a

Please sign in to comment.