diff --git a/rewrite/commandManager.ts b/rewrite/commandManager.ts index 34108c6..6b693f8 100644 --- a/rewrite/commandManager.ts +++ b/rewrite/commandManager.ts @@ -4,10 +4,11 @@ import type { UnicordArgumentDefinition, UnicordCommandHandler, UnicordCommandOptions, - UnicordHandler + UnicordHandler, } from '.'; import { UnicordCommandContext } from './context'; import type { UnicordEventProcessor } from './eventProcessor'; +import { Embed } from './types'; import { UnicordArgumentType, UnicordEventType } from './types/common'; type UnicordCommandDefinition = { @@ -46,32 +47,36 @@ export class UnicordCommandManager { 'help', async (context) => { // Just list chat commands for now - let reply = '## Available Commands:\n'; + const reply = new Embed().setTitle('Available Commands'); for (const [command, defs] of this.handlers[UnicordEventType.ChatCommands]) { - reply += `> \n`; - for (const def of defs) { - reply += `> **${command}**: ${def.options.description ?? 'No description'}\n`; - // List arguments + let fieldValue = def.options.description ?? 'No description'; + fieldValue += '\n'; + if (def.options.args.length > 0) { + fieldValue += `\n\`${command}`; for (const arg of def.options.args) { - reply += `> \`${arg.name}\` (${UnicordArgumentType[arg.type]}${ + fieldValue += arg.required ? ` <${arg.name}>` : ` `; + } + fieldValue += '`\n'; + for (const arg of def.options.args) { + fieldValue += `- \`${arg.name}\` (${UnicordArgumentType[arg.type]}${ arg.required ? ', required' : '' }): ${arg.description ?? 'No description'}\n`; } } - // Show usage - reply += `> \n`; - reply += `> \`${command}`; - for (const arg of def.options.args) { - reply += arg.required ? ` <${arg.name}>` : ` `; - } - reply += `\`\n`; + + fieldValue += '\n'; + + reply.fields.push({ + name: command, + value: fieldValue, + }); } } - await context.reply(reply); + await context.reply(reply.toMessage()); }, { description: 'Lists all available commands', diff --git a/rewrite/index.ts b/rewrite/index.ts index b504a31..5d5897b 100644 --- a/rewrite/index.ts +++ b/rewrite/index.ts @@ -126,3 +126,7 @@ export class Unicord { } export * from './types/common'; +// export * from './types/message'; +// export * from './types/channel'; +// export * from './types/guild'; +// export * from './types/embed'; diff --git a/rewrite/types/embed.ts b/rewrite/types/embed.ts new file mode 100644 index 0000000..7f9c308 --- /dev/null +++ b/rewrite/types/embed.ts @@ -0,0 +1,182 @@ +import { Message } from './message'; + +type EmbedFooter = { + text: string; + icon_url?: string; + proxy_icon_url?: string; +}; + +type EmbedImage = { + url?: string; + proxy_url?: string; + height?: number; + width?: number; +}; + +type EmbedAuthor = { + name: string; + url?: string; + icon_url?: string; + proxy_icon_url?: string; +}; + +type EmbedVideo = { + url?: string; + height?: number; + width?: number; +}; + +type EmbedField = { + name: string; + value: string; + inline?: boolean; +}; + +// === Embed Structure === + +// | Field | Type | Description | +// |--------------|--------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------| +// | title? | string | title of embed | +// | type? | string | [type of embed](/docs/resources/message#embed-object-embed-types) (always "rich" for webhook embeds) | +// | description? | string | description of embed | +// | url? | string | url of embed | +// | timestamp? | ISO8601 timestamp | timestamp of embed content | +// | color? | integer | color code of the embed | +// | footer? | [embed footer](/docs/resources/message#embed-object-embed-footer-structure) object | footer information | +// | image? | [embed image](/docs/resources/message#embed-object-embed-image-structure) object | image information | +// | thumbnail? | [embed thumbnail](/docs/resources/message#embed-object-embed-thumbnail-structure) object | thumbnail information | +// | video? | [embed video](/docs/resources/message#embed-object-embed-video-structure) object | video information | +// | provider? | [embed provider](/docs/resources/message#embed-object-embed-provider-structure) object | provider information | +// | author? | [embed author](/docs/resources/message#embed-object-embed-author-structure) object | author information | +// | fields? | array of [embed field](/docs/resources/message#embed-object-embed-field-structure) objects | fields information, max of 25 | + +export class Embed { + title?: string; + description?: string; + url?: string; + timestamp?: string; + color?: number; + footer?: EmbedFooter; + image?: EmbedImage; + thumbnail?: EmbedImage; + video?: EmbedVideo; + provider?: { + name?: string; + url?: string; + }; + author?: EmbedImage & { + name?: string; + }; + fields: EmbedField[]; + + constructor() { + this.fields = []; + } + + setTitle = (title: string) => { + this.title = title; + return this; + }; + + setDescription = (description: string) => { + this.description = description; + return this; + }; + + setUrl = (url: string) => { + this.url = url; + return this; + }; + + setTimestamp = (timestamp: string) => { + this.timestamp = timestamp; + return this; + }; + + setColor = (color: number | string) => { + this.color = typeof color === 'string' ? parseInt(`0x${color.replace('#', '')}`) : color; + return this; + }; + + setFooter = (footer: EmbedFooter) => { + this.footer = footer; + return this; + }; + + setImage = (image: EmbedImage) => { + this.image = image; + return this; + }; + + setThumbnail = (thumbnail: EmbedImage) => { + this.thumbnail = thumbnail; + return this; + }; + + setVideo = (video: EmbedVideo) => { + this.video = video; + return this; + }; + + setProvider = (provider: { name?: string; url?: string }) => { + this.provider = provider; + return this; + }; + + setAuthor = (author: EmbedAuthor) => { + this.author = author; + return this; + }; + + addField = (field: EmbedField) => { + this.fields.push(field); + return this; + }; + + addFields = (fields: EmbedField[]) => { + this.fields.push(...fields); + return this; + }; + + toMessage = () => { + return new Message().addEmbed(this); + }; + + toJSON = () => { + return { + title: this.title, + description: this.description, + url: this.url, + timestamp: this.timestamp, + color: this.color, + footer: this.footer, + image: this.image, + thumbnail: this.thumbnail, + video: this.video, + provider: this.provider, + author: this.author, + fields: this.fields + }; + }; +} + +export interface DiscordEmbed { + title?: string; + type?: string; + description?: string; + url?: string; + timestamp?: string; + color?: number; + footer?: EmbedFooter; + image?: EmbedImage; + thumbnail?: EmbedImage; + video?: EmbedVideo; + provider?: { + name?: string; + url?: string; + }; + author?: EmbedImage & { + name?: string; + }; + fields?: EmbedField[]; +} \ No newline at end of file diff --git a/rewrite/types/index.ts b/rewrite/types/index.ts index f9510d6..8007c6d 100644 --- a/rewrite/types/index.ts +++ b/rewrite/types/index.ts @@ -2,4 +2,5 @@ export * from './common'; export * from './user'; export * from './channel'; export * from './guild'; -export * from './message'; \ No newline at end of file +export * from './message'; +export * from './embed'; \ No newline at end of file diff --git a/rewrite/types/message.ts b/rewrite/types/message.ts index cd6c1ed..a81467f 100644 --- a/rewrite/types/message.ts +++ b/rewrite/types/message.ts @@ -2,7 +2,7 @@ import { exists, isNil } from '../utils'; import { UnicordGatewayObject } from './base'; import type { Channel } from './channel'; import { fromDiscord, Trait, type Expectation } from './common'; -// import type { Embed } from './embed'; +import type { DiscordEmbed, Embed } from './embed'; import type { Guild } from './guild'; import { User, type DiscordUser } from './user'; @@ -94,7 +94,7 @@ export type MessagePayload = Message & { author: User; channel_id: string; content: string; - // embeds: Embed[]; + embeds: Embed[]; components: Component[]; message_reference?: { id: string; @@ -110,7 +110,7 @@ export class Message extends UnicordGatewayObject { channel_id?: string; guild_id?: string; public content: string; - // public embeds: Embed[] = []; + public embeds: Embed[] = []; public components: Component[] = []; public message_reference?: { id: string; @@ -178,10 +178,10 @@ export class Message extends UnicordGatewayObject { return this; }; - // public addEmbed = (embed: Embed) => { - // this.embeds.push(embed); - // return this; - // }; + public addEmbed = (embed: Embed) => { + this.embeds.push(embed); + return this; + }; public addComponent = (content: Component | string, ...components: Component[]) => { if (typeof content === 'string') { @@ -223,7 +223,7 @@ export class Message extends UnicordGatewayObject { public toJSON = () => { return { content: this.content, - // embeds: this.embeds, + embeds: this.embeds, components: this.components, message_reference: this.message_reference ? { @@ -236,7 +236,6 @@ export class Message extends UnicordGatewayObject { }; } -// Raw API Object export type DiscordMessage = { id: string; channel_id: string; @@ -253,7 +252,7 @@ export type DiscordMessage = { mention_roles: string[]; mention_channels?: { id: string; guild_id: string; type: number; name: string }[]; attachments: { id: string; filename: string; url: string; proxy_url: string; size: number }[]; - // embeds: DiscordEmbed[]; + embeds: DiscordEmbed[]; reactions?: { count: number; me: boolean; emoji: Emoji }[]; nonce?: string | number; pinned: boolean; diff --git a/testing/inferface.rewrite.test.ts b/testing/inferface.rewrite.test.ts index ad613ac..6899abb 100644 --- a/testing/inferface.rewrite.test.ts +++ b/testing/inferface.rewrite.test.ts @@ -22,7 +22,7 @@ const client = new Unicord({ await context.reply(response); }, { - description: 'Ping command', + description: 'Say hello', args: [ { name: 'name', @@ -48,7 +48,7 @@ const client = new Unicord({ await context.reply(hydrated.channel.name ?? 'Unnamed Channel'); }, { - description: 'Channel command', + description: 'Get info about a channel', args: [], }, )