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
30 changes: 25 additions & 5 deletions packages/builders/__tests__/components/button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,17 @@ describe('Button Components', () => {
.setCustomId('custom')
.setLabel('test')
.setDisabled(true)
.setEmoji({ name: 'test' });
.setEmoji({ name: '🩵' });

button.toJSON();
}).not.toThrowError();

expect(() => {
const button = new PrimaryButtonBuilder()
.setCustomId('custom')
.setLabel('test')
.setDisabled(true)
.setEmoji({ id: '1234567890123456', name: 'test', animated: true });

button.toJSON();
}).not.toThrowError();
Expand All @@ -37,7 +47,7 @@ describe('Button Components', () => {
}).not.toThrowError();

expect(() => {
const button = new DangerButtonBuilder().setCustomId('custom').setEmoji({ name: 'ok' });
const button = new DangerButtonBuilder().setCustomId('custom').setEmoji({ name: '👌' });
button.toJSON();
}).not.toThrowError();

Expand All @@ -47,7 +57,7 @@ describe('Button Components', () => {
}).not.toThrowError();

expect(() => {
const button = new LinkButtonBuilder().setURL('https://discord.js.org').setEmoji({ name: 'ok' });
const button = new LinkButtonBuilder().setURL('https://discord.js.org').setEmoji({ name: '👌' });
button.toJSON();
}).not.toThrowError();

Expand All @@ -66,7 +76,17 @@ describe('Button Components', () => {

expect(() => {
// @ts-expect-error: Invalid emoji
const button = new PrimaryButtonBuilder().setEmoji('test');
const button = new PrimaryButtonBuilder().setEmoji('🩵');
button.toJSON();
}).toThrowError();

expect(() => {
const button = new PrimaryButtonBuilder()
.setCustomId('custom')
.setLabel('test')
.setDisabled(true)
.setEmoji({ id: '1234567890123456', name: '1' });
Copy link
Member

Choose a reason for hiding this comment

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

For custom emojis, does discord actually validate their name? Because when sending a message, we can still do <:_:[id]> no?

Copy link
Contributor

Choose a reason for hiding this comment

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

They don't validate, but (some) clients viewing the emote will grab the name from cache.

Still, they are documented as 2-32 long in name, you cannot name them as single chars, and our previous hacky workaround of ignoring this and using _ would break markdown in places.


button.toJSON();
}).toThrowError();

Expand All @@ -86,7 +106,7 @@ describe('Button Components', () => {
// @ts-expect-error: Invalid parameter for disabled
expect(() => new PrimaryButtonBuilder().setCustomId('hi').setDisabled(0).toJSON()).toThrowError();
// @ts-expect-error: Invalid emoji
expect(() => new PrimaryButtonBuilder().setCustomId('hi').setEmoji('foo').toJSON()).toThrowError();
expect(() => new PrimaryButtonBuilder().setCustomId('hi').setEmoji('🩵').toJSON()).toThrowError();

expect(() =>
new LinkButtonBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('Select Menu Components', () => {
.setLabel('test')
.setValue('test')
.setDefault(true)
.setEmoji({ name: 'test' })
.setEmoji({ name: '🩵' })
.setDescription('description');
expect(() => selectMenuWithId().addOptions(option).toJSON()).not.toThrowError();
expect(() => selectMenuWithId().setOptions(option).toJSON()).not.toThrowError();
Expand Down
17 changes: 15 additions & 2 deletions packages/builders/src/components/Assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,21 @@ export const emojiPredicate = z
animated: z.boolean().optional(),
})
.refine((data) => data.id !== undefined || data.name !== undefined, {
error: "Either 'id' or 'name' must be provided",
});
error: "Either 'id' or 'name' must be provided.",
})
.refine(
(data) => {
if (data.id !== undefined && data.name !== undefined) {
return data.name.length >= 2;
}

return true;
},
{
error: 'Custom emoji names must be at least 2 characters.',
path: ['name'],
},
);

const buttonPredicateBase = z.strictObject({
type: z.literal(ComponentType.Button),
Expand Down