Recipes
Embeds, Formatting & Attachments
Embed Builder
The Embed builder allows you to create rich embedded messages with titles, descriptions, fields, images, and more.
import { Embed, Command, Declare, type CommandContext } from 'seyfert';
@Declare({
name: 'embed',
description: 'Send a rich embed',
})
export default class EmbedCommand extends Command {
async run(ctx: CommandContext) {
const embed = new Embed()
.setTitle('Server Info')
.setDescription('Here is some information about this server.')
.setColor(0x5865F2)
.setAuthor({ name: ctx.author.username })
.setFooter({ text: 'Powered by Seyfert' })
.addFields(
{ name: 'Members', value: '1,234', inline: true },
{ name: 'Channels', value: '42', inline: true },
{ name: 'Created', value: '<t:1609459200:R>', inline: true },
)
.setImage('https://example.com/banner.png')
.setTimestamp()
.setURL('https://discord.gg/example');
await ctx.write({ embeds: [embed] });
}
}You can also pass a partial embed object to the constructor, which is useful for i18n:
const embed = new Embed(ctx.t.commands.help.embed.get())
.setColor('Blurple');Color Options
The setColor method accepts a numeric hex value or a named color string:
new Embed().setColor(0xFF0000); // Hex value
new Embed().setColor('Blue'); // Named color
new Embed().setColor('Blurple'); // Discord's brand colorFormatter Utilities
Seyfert provides a Formatter class with static methods for Discord markdown formatting:
import { Formatter } from 'seyfert';
import { TimestampStyle } from 'seyfert/lib/common';
// Text formatting
Formatter.bold('text'); // **text**
Formatter.italic('text'); // *text*
Formatter.underline('text'); // __text__
Formatter.strikeThrough('text'); // ~~text~~
Formatter.inlineCode('text'); // `text`
Formatter.codeBlock('const x = 1', 'ts'); // ```ts\nconst x = 1\n```
Formatter.spoiler('text'); // ||text||
Formatter.quote('text'); // > text
Formatter.blockQuote('text'); // >>> text
Formatter.hyperlink('Click here', 'https://example.com'); // [Click here](https://example.com)Mentions
Formatter.userMention('userId'); // <@userId>
Formatter.channelMention('channelId'); // <#channelId>
Formatter.roleMention('roleId'); // <@&roleId>Timestamps
Discord renders timestamps in the user's local timezone:
const date = new Date();
Formatter.timestamp(date, TimestampStyle.RelativeTime); // "2 hours ago"
Formatter.timestamp(date, TimestampStyle.LongDateShortTime); // "April 20, 2021 at 16:20"
Formatter.timestamp(date, TimestampStyle.LongDate); // "April 20, 2021"
Formatter.timestamp(date, TimestampStyle.ShortTime); // "16:20"Practical Example
import { Embed, Formatter, Command, Declare, type CommandContext } from 'seyfert';
import { TimestampStyle } from 'seyfert/lib/common';
@Declare({
name: 'userinfo',
description: 'Get user information',
})
export default class UserInfoCommand extends Command {
async run(ctx: CommandContext) {
const user = ctx.author;
const embed = new Embed()
.setTitle(Formatter.bold(user.username))
.setDescription(
[
`${Formatter.bold('ID:')} ${Formatter.inlineCode(user.id)}`,
`${Formatter.bold('Created:')} ${Formatter.timestamp(new Date(), TimestampStyle.RelativeTime)}`,
].join('\n')
)
.setColor(0x5865F2);
await ctx.write({ embeds: [embed] });
}
}Attachment Builder
Create file attachments from buffers or URLs:
import { AttachmentBuilder, Command, Declare, type CommandContext } from 'seyfert';
@Declare({
name: 'attach',
description: 'Send a file attachment',
})
export default class AttachCommand extends Command {
async run(ctx: CommandContext) {
const buffer = Buffer.from('Hello, World!');
const attachment = new AttachmentBuilder()
.setName('hello.txt')
.setFile('buffer', buffer);
await ctx.write({
content: 'Here is the file:',
files: [attachment],
});
}
}From a URL
const attachment = new AttachmentBuilder()
.setFile('url', 'https://example.com/image.png')
.setName('downloaded.png');Referencing in Embeds
You can reference an attachment within an embed using the attachment:// protocol:
const attachment = new AttachmentBuilder()
.setName('chart.png')
.setFile('buffer', imageBuffer);
const embed = new Embed()
.setTitle('Statistics')
.setImage('attachment://chart.png');Sending Components with Messages
For a complete guide on building and handling interactive components (buttons, select menus, modals), see the Components guide.
Quick Reference
// With embeds
await ctx.write({ embeds: [], components: [] });
// Ephemeral message (only visible to the user)
await ctx.write({
content: 'Only you can see this',
flags: MessageFlags.Ephemeral,
});
// Disable buttons after use
await ctx.editOrReply({
components: [
new ActionRow<Button>().addComponents(
new Button()
.setCustomId('done')
.setLabel('Done')
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
),
],
});
// Remove all components
await ctx.editOrReply({ components: [] });