import { Message, ClientEvents } from "discord.js"; import { EsModuleClass, isModuleClass } from "../util"; export type CommandType = "prefix" | "mention"; export interface ICommand extends CommandOptions { action : MessageCommand; } export interface CommandOptions { type: CommandType; pattern: string | RegExp; documentation?: CommandDocumentation; auth?: boolean; allowDM?: boolean; } export interface CommandDocumentation { description: string; example: string; } export type MessageCommand = (data: ICommandData) => void | Promise; export interface ICommandData { message: Message; contents: string | RegExpMatchArray; } export type BotEvent = (data: BotEventData, ...params: unknown[]) => void | Promise; export interface BotEventData { actionsDone: boolean; } interface CustomEventType { message: [string]; indirectMention: [string]; directMention: [string]; postMessage: [string]; } const customEvents : Set = new Set(["directMention", "indirectMention", "message", "postMessage"]); export type EventType = keyof ClientEvents | keyof CustomEventType; export function isCustomEvent(s: string): s is keyof CustomEventType { return customEvents.has(s as keyof CustomEventType); } export interface IPlugin { PLUGIN_TYPE?: string; botCommands?: ICommand[]; botEvents?: { [action in EventType]?: BotEvent }; start?(): Promise; } export function Command(opts: CommandOptions) : MethodDecorator { return function(target: unknown, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor): void { if(!descriptor.value) throw new Error("The decorator value must be initialized!"); const plg = target as IPlugin; if (!plg.botCommands) plg.botCommands = []; plg.botCommands.push({ action: descriptor.value as unknown as MessageCommand, ...opts }); }; } export function Event(type: EventType): MethodDecorator { return function(target: unknown, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor): void { if(!descriptor.value) throw new Error("The decorator value must be initialized!"); const plg = target as IPlugin; if(!plg.botEvents) plg.botEvents = {}; plg.botEvents[type] = descriptor.value as unknown as BotEvent; }; } export const PLUGIN_TYPE_DESCRIPTOR = "PLUGIN_TYPE_DESCRIPTOR"; export function Plugin(base: T): void { base.prototype.PLUGIN_TYPE = PLUGIN_TYPE_DESCRIPTOR; } export function isPlugin(obj: unknown): obj is EsModuleClass { return isModuleClass(obj) && obj.prototype.PLUGIN_TYPE == PLUGIN_TYPE_DESCRIPTOR; }