mirror of
https://github.com/jaronpate/unicord.git
synced 2026-10-18 21:47:40 +00:00
refactor: add default help command and embed structure
This commit is contained in:
+20
-15
@@ -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<Options extends UnicordCommandOptions> = {
|
||||
@@ -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}>` : ` <?${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}>` : ` <?${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',
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
@@ -3,3 +3,4 @@ export * from './user';
|
||||
export * from './channel';
|
||||
export * from './guild';
|
||||
export * from './message';
|
||||
export * from './embed';
|
||||
@@ -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<Message, DiscordMessage> {
|
||||
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<Message, DiscordMessage> {
|
||||
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<Message, DiscordMessage> {
|
||||
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<Message, DiscordMessage> {
|
||||
};
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -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: [],
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user