embarassing ass typo

This commit is contained in:
2024-11-16 12:50:19 -06:00
parent 119ddfefd1
commit 7848ea0082
7 changed files with 124 additions and 122 deletions
+1 -1
View File
@@ -14,4 +14,4 @@ export { Message, type MessagePayload } from './types/message';
export { Embed } from './types/embed'; export { Embed } from './types/embed';
export { Emoji } from './types/emoji'; export { Emoji } from './types/emoji';
// Other // Other
export { createCommandHandler } from './types/hander'; export { createCommandHandler } from './types/handler';
+1 -1
View File
@@ -3,7 +3,7 @@ import { Gateway } from './connectors/gateway';
import { Processor } from './processor'; import { Processor } from './processor';
import { Expectation, fromDiscord, Intent, type ClientConfig } from '../types/common'; import { Expectation, fromDiscord, Intent, type ClientConfig } from '../types/common';
import { exists, isNil } from '../utils/index'; import { exists, isNil } from '../utils/index';
import type { Handler } from '../types/hander'; import type { Handler } from '../types/handler';
import { type DiscordMessage, Message } from '../types/message'; import { type DiscordMessage, Message } from '../types/message';
import { Guilds } from './caches/guilds'; import { Guilds } from './caches/guilds';
import { Messages } from './caches/messages'; import { Messages } from './caches/messages';
+18 -5
View File
@@ -1,8 +1,9 @@
import type { Client } from "./client"; import type { Client } from "./client";
import type { Context } from "../types/context"; import type { Context } from "../types/context";
import { HandlerType, type EventPayload } from "../types/common"; import { HandlerType, Trait, type EventPayload } from "../types/common";
import { BaseHandler, type Handler } from "../types/hander"; import { type CommandHandler, type Handler } from "../types/handler";
import type { API } from "./api"; import type { API } from "./api";
import type { ApplicationCommandOption } from "../types/applicationCommand";
export class Processor { export class Processor {
private handlers = { private handlers = {
@@ -55,11 +56,15 @@ export class Processor {
if (handlers) { if (handlers) {
for (const handler of handlers) { for (const handler of handlers) {
if (handler instanceof BaseHandler) { if (isCommandHandler(handler)) {
await Promise.resolve(handler.execute(context, argsOrPayload)); if (type === HandlerType.Events) {
throw new Error('Event handlers cannot be a CommandHandler');
}
await Promise.resolve(handler[Trait.execute](context!, argsOrPayload));
} else { } else {
// TODO: Fix ts error // TODO: Fix ts error
await Promise.resolve(handler(context, argsOrPayload)) await Promise.resolve(handler(context, argsOrPayload));
} }
} }
} }
@@ -93,3 +98,11 @@ export class Processor {
has: (event: string) => this.handlers[HandlerType.Interactions].has(event) ?? this.handlers[HandlerType.Interactions].get(event)?.length! > 0 has: (event: string) => this.handlers[HandlerType.Interactions].has(event) ?? this.handlers[HandlerType.Interactions].get(event)?.length! > 0
}; };
} }
const isCommandHandler = (handler: Handler): handler is CommandHandler<readonly ApplicationCommandOption[]> => {
if (typeof handler === 'object') {
return 'args' in handler && Trait.execute in handler;
} else {
return false;
}
}
+30 -29
View File
@@ -2,54 +2,55 @@ import { Trait } from "./common";
// Enum for Application Command Types // Enum for Application Command Types
export enum ApplicationCommandType { export enum ApplicationCommandType {
CHAT_INPUT = 1, ChatInput = 1,
USER = 2, User = 2,
MESSAGE = 3, Message = 3,
PRIMARY_ENTRY_POINT = 4, PrimaryEntryPoint = 4,
} }
// Enum for Application Command Option Types // Enum for Application Command Option Types
export enum ApplicationCommandOptionType { export enum ApplicationCommandOptionType {
SUB_COMMAND = 1, SubCommand = 1,
SUB_COMMAND_GROUP = 2, SubCommandGroup = 2,
STRING = 3, String = 3,
INTEGER = 4, Integer = 4,
BOOLEAN = 5, Boolean = 5,
USER = 6, User = 6,
CHANNEL = 7, Channel = 7,
ROLE = 8, Role = 8,
MENTIONABLE = 9, Mentionable = 9,
NUMBER = 10, Number = 10,
ATTACHMENT = 11, Attachment = 11,
} }
// Enum for Channel Types (if applicable for options) // Enum for Channel Types (if applicable for options)
export enum ChannelType { export enum ChannelType {
GUILD_TEXT = 0, GuildText = 0,
DM = 1, DM = 1,
GUILD_VOICE = 2, GuildVoice = 2,
GROUP_DM = 3, GroupDm = 3,
GUILD_CATEGORY = 4, GuildCategory = 4,
GUILD_NEWS = 5, GuildNews = 5,
GUILD_STORE = 6, GuildStore = 6,
GUILD_NEWS_THREAD = 10, GuildNewsThread = 10,
GUILD_PUBLIC_THREAD = 11, GuildPublicThread = 11,
GUILD_PRIVATE_THREAD = 12, GuildPrivateThread = 12,
GUILD_STAGE_VOICE = 13, GuildStageVoice = 13,
GUILD_DIRECTORY = 14, GuildDirectory = 14,
GUILD_FORUM = 15, GuildForum = 15,
} }
// Enum for Application Command Handler Types // Enum for Application Command Handler Types
export enum ApplicationCommandHandlerType { export enum ApplicationCommandHandlerType {
APP_HANDLER = 1, AppHandler = 1,
DISCORD_LAUNCH_ACTIVITY = 2, LaunchActivity = 2,
} }
// Define the ApplicationCommandOption type // Define the ApplicationCommandOption type
export type ApplicationCommandOption = { export type ApplicationCommandOption = {
type: ApplicationCommandOptionType; type: ApplicationCommandOptionType;
name: string; name: string;
id: string;
name_localizations?: Record<string, string> | null; name_localizations?: Record<string, string> | null;
description: string; description: string;
description_localizations?: Record<string, string> | null; description_localizations?: Record<string, string> | null;
-71
View File
@@ -1,71 +0,0 @@
import type { ApplicationCommandOption, ApplicationCommandOptionType } from "./applicationCommand";
import { Trait, type EventPayload } from "./common";
import type { Context } from "./context";
type PrimitiveTypeMap = {
[ApplicationCommandOptionType.STRING]: string;
[ApplicationCommandOptionType.INTEGER]: number;
[ApplicationCommandOptionType.BOOLEAN]: boolean;
[ApplicationCommandOptionType.NUMBER]: number;
[ApplicationCommandOptionType.USER]: string; // Could be a user ID or object depending on your use case
[ApplicationCommandOptionType.CHANNEL]: string; // Could be a channel ID or object
[ApplicationCommandOptionType.ROLE]: string; // Could be a role ID or object
[ApplicationCommandOptionType.MENTIONABLE]: string; // Could be a mentionable ID or object
[ApplicationCommandOptionType.ATTACHMENT]: string; // Could represent attachment IDs
[ApplicationCommandOptionType.SUB_COMMAND]: never; // Handled by `options`
[ApplicationCommandOptionType.SUB_COMMAND_GROUP]: never; // Handled by `options`
};
// Recursive type to map ApplicationCommandOption to arguments
type ArgsFromOptions<T extends readonly ApplicationCommandOption[]> = {
[Option in T[number] as Option['name']]: Option extends { options: readonly ApplicationCommandOption[] }
? ArgsFromOptions<Option['options']> // Recursive inference for subcommands
: Option['choices'] extends readonly { value: infer U }[]
? U // Infer from choices if defined
: Option['type'] extends keyof PrimitiveTypeMap
? PrimitiveTypeMap[Option['type']] // Otherwise, map from ApplicationCommandOptionType
: unknown;
};
export type BaseHandler<T extends readonly ApplicationCommandOption[]> = {
args: T;
[Trait.execute]: (context: Context, args: ArgsFromOptions<T>) => Promise<void> | void;
};
// Helper function to infer type of `args`
export function createCommandHandler<T extends readonly ApplicationCommandOption[]>(
handler: BaseHandler<T>
): BaseHandler<T> {
return handler as BaseHandler<T>;
}
const handler = createCommandHandler({
args: [
{
type: 3,
name: "name",
description: "The name of the user",
required: true
},
{
type: 3,
name: "age",
description: "The age of the user",
required: true,
choices: [
{ name: "18", value: "18" },
{ name: "19", value: "19" },
{ name: "20", value: "20" }
]
}
] as const,
[Trait.execute]: async (context, args) => {
console.log(args);
}
});
export type CommandHandlerFunction = (context: Context, args: any[]) => Promise<void> | void;
export type EventHandlerFunction = (context: Context | null, payload: EventPayload) => Promise<void> | void;
export type HandlerFunction = CommandHandlerFunction | EventHandlerFunction;
export type Handler = HandlerFunction | BaseHandler<any>;
+46
View File
@@ -0,0 +1,46 @@
import type { ApplicationCommandOption, ApplicationCommandOptionType } from "./applicationCommand";
import { Trait, type EventPayload } from "./common";
import type { Context } from "./context";
type PrimitiveTypeMap = {
[ApplicationCommandOptionType.String]: string;
[ApplicationCommandOptionType.Integer]: number;
[ApplicationCommandOptionType.Boolean]: boolean;
[ApplicationCommandOptionType.Number]: number;
[ApplicationCommandOptionType.User]: string; // Could be a user ID or object depending on your use case
[ApplicationCommandOptionType.Channel]: string; // Could be a channel ID or object
[ApplicationCommandOptionType.Role]: string; // Could be a role ID or object
[ApplicationCommandOptionType.Mentionable]: string; // Could be a mentionable ID or object
[ApplicationCommandOptionType.Attachment]: string; // Could represent attachment IDs
[ApplicationCommandOptionType.SubCommand]: never; // Handled by `options`
[ApplicationCommandOptionType.SubCommandGroup]: never; // Handled by `options`
};
// Recursive type to map ApplicationCommandOption to arguments
type ArgsFromOptions<T extends readonly ApplicationCommandOption[]> = {
[Option in T[number] as Option['id']]: Option extends { options: readonly ApplicationCommandOption[] }
? ArgsFromOptions<Option['options']> // Recursive inference for subcommands
: Option['choices'] extends readonly { value: infer U }[]
? U // Infer from choices if defined
: Option['type'] extends keyof PrimitiveTypeMap
? PrimitiveTypeMap[Option['type']] // Otherwise, map from ApplicationCommandOptionType
: unknown;
};
export type CommandHandler<T extends readonly ApplicationCommandOption[]> = {
args: T;
[Trait.execute]: (context: Context, args: ArgsFromOptions<T>) => Promise<void> | void;
};
// Helper function to infer type of `args`
export function createCommandHandler<T extends readonly ApplicationCommandOption[]>(
handler: CommandHandler<T>
): CommandHandler<T> {
return handler as CommandHandler<T>;
}
export type CommandHandlerFunction = (context: Context, args: any[]) => Promise<void> | void;
export type EventHandlerFunction = (context: Context | null, payload: EventPayload) => Promise<void> | void;
export type HandlerFunction = CommandHandlerFunction | EventHandlerFunction;
export type Handler = HandlerFunction | CommandHandler<readonly ApplicationCommandOption[]>;
+28 -15
View File
@@ -1,4 +1,5 @@
import { Client, type Context, createCommandHandler, Expectation, Intent, type MessagePayload, Trait } from '../src/index'; import { Client, type Context, createCommandHandler, Expectation, Intent, type MessagePayload, Trait } from '../src/index';
import { ApplicationCommandOptionType } from '../src/types/applicationCommand';
const client = new Client({ const client = new Client({
token: process.env.BOT_TOKEN!, token: process.env.BOT_TOKEN!,
@@ -20,32 +21,44 @@ client.chatCommands.register('ping', async (context: Context, args: any[]) => {
await context.editMessage(message, `Pong! Latency: ${time}ms`); await context.editMessage(message, `Pong! Latency: ${time}ms`);
}); });
const handler = createCommandHandler({ client.slashCommands.register('ping', createCommandHandler({
args: [ args: [
{ {
type: 3, type: ApplicationCommandOptionType.String,
name: "name", name: "Name",
description: "The name of the user", id: "name",
description: "Your name",
required: true required: true
}, },
{ {
type: 3, type: ApplicationCommandOptionType.Integer,
name: "age", name: "Age",
description: "The age of the user", id: "age",
required: true, description: "Your age",
required: true
},
{
type: ApplicationCommandOptionType.String,
name: "Favorite Animal",
id: "favorite_animal",
description: "Your favorite animal",
required: false,
choices: [ choices: [
{ name: "18", value: "18" }, { name: "Dog", value: "dog" },
{ name: "19", value: "19" }, { name: "Cat", value: "cat" },
{ name: "20", value: "20" } { name: "Bird", value: "bird" },
{ name: "Shark", value: "shark" },
{ name: "Elephant", value: "elephant" },
{ name: "Tiger", value: "Tiger" },
{ name: "Lion", value: "lion" },
{ name: "Bear", value: "Bear" }
] ]
} }
] as const, ] as const,
[Trait.execute]: async (context, args) => { [Trait.execute]: async (context, args) => {
context.reply(`You are ${args.name} and you are ${args.age} years old`, true); context.reply(`You are ${args.name} and you are ${args.age} years old and your favorite animal is ${args.favorite_animal}`, true);
} }
}); }));
client.slashCommands.register('ping', handler);
client.chatCommands.register('me', async (context: Context, _args: any[]) => { client.chatCommands.register('me', async (context: Context, _args: any[]) => {
// Note: Testing repeated hydration // Note: Testing repeated hydration