diff --git a/src/handler/events/interactionCreate.ts b/src/handler/events/interactionCreate.ts index 2a54b90..cc9ac94 100644 --- a/src/handler/events/interactionCreate.ts +++ b/src/handler/events/interactionCreate.ts @@ -20,66 +20,63 @@ import { CommandType } from '../structures/enums'; import type { Result } from 'ts-results'; function applicationCommandHandler(mod: Module | undefined, interaction: CommandInteraction) { - const mod$ = (cmdTy: T) => of(mod).pipe( - filterCorrectModule(cmdTy), - ); - return match(interaction) - .when(isChatInputCommand, i => { + const mod$ = (cmdTy: T) => of(mod).pipe(filterCorrectModule(cmdTy)); + return ( + match(interaction) + .when(isChatInputCommand, i => { const ctx = Context.wrap(i); //SUPPORT COMMANDTYPE.BOTH return mod$(CommandType.Slash).pipe( concatMap(m => { - return of(m.onEvent?.map(e => e.execute( - [ctx, ['slash', i.options]], - controller, - )) ?? []).pipe(map(res => ({ - mod, res, execute() { - return m.execute(ctx, ['slash', i.options]); - }, - }))); + return of(m.onEvent?.map(e => e.execute([ctx, ['slash', i.options]], controller)) ?? []).pipe( + map(res => ({ + mod, + res, + execute() { + return m.execute(ctx, ['slash', i.options]); + }, + })), + ); }), ); - }, - ) - //Todo: refactor so that we dont have to have two separate branches. They're near identical!! - //Only thing that differs is type of interaction - .when(isMessageCtxMenuCmd, ctx => { + }) + //Todo: refactor so that we dont have to have two separate branches. They're near identical!! + //Only thing that differs is type of interaction + .when(isMessageCtxMenuCmd, ctx => { return mod$(CommandType.MenuMsg).pipe( concatMap(m => { - return of(m.onEvent?.map(e => e.execute( - [ctx], - controller, - )) ?? []).pipe(map(res => ({ - mod, res, execute() { - return m.execute(ctx); - }, - }))); + return of(m.onEvent?.map(e => e.execute([ctx], controller)) ?? []).pipe( + map(res => ({ + mod, + res, + execute() { + return m.execute(ctx); + }, + })), + ); }), ); - }, - ) - .when(isUserContextMenuCmd, ctx => { - return mod$(CommandType.MenuUser).pipe( - concatMap(m => { - return of(m.onEvent?.map(e => e.execute( - [ctx], - controller, - )) ?? []).pipe(map(res => ({ - mod, res, execute() { - return m.execute(ctx); - }, - }))); - }), - ); - }) - .run(); + }) + .when(isUserContextMenuCmd, ctx => { + return mod$(CommandType.MenuUser).pipe( + concatMap(m => { + return of(m.onEvent?.map(e => e.execute([ctx], controller)) ?? []).pipe( + map(res => ({ + mod, + res, + execute() { + return m.execute(ctx); + }, + })), + ); + }), + ); + }) + .run() + ); } -function messageComponentInteractionHandler( - mod: Module | undefined, - interaction: MessageComponentInteraction, -) { - +function messageComponentInteractionHandler(mod: Module | undefined, interaction: MessageComponentInteraction) { const mod$ = (ty: T) => of(mod).pipe(filterCorrectModule(ty)); //Todo: refactor so that we dont have to have two separate branches. They're near identical!! //Only thing that differs is type of interaction @@ -87,28 +84,30 @@ function messageComponentInteractionHandler( .when(isButton, ctx => { return mod$(CommandType.Button).pipe( concatMap(m => { - return of(m.onEvent?.map(e => e.execute( - [ctx], - controller, - )) ?? []).pipe(map(res => ({ - mod, res, execute() { - return m.execute(ctx); - }, - }))); + return of(m.onEvent?.map(e => e.execute([ctx], controller)) ?? []).pipe( + map(res => ({ + mod, + res, + execute() { + return m.execute(ctx); + }, + })), + ); }), ); }) .when(isSelectMenu, (ctx: SelectMenuInteraction) => { return mod$(CommandType.MenuSelect).pipe( concatMap(m => { - return of(m.onEvent?.map(e => e.execute( - [ctx], - controller, - )) ?? []).pipe(map(res => ({ - mod, res, execute() { - return m.execute(ctx); - }, - }))); + return of(m.onEvent?.map(e => e.execute([ctx], controller)) ?? []).pipe( + map(res => ({ + mod, + res, + execute() { + return m.execute(ctx); + }, + })), + ); }), ); }) @@ -131,34 +130,33 @@ export function onInteractionCreate(wrapper: Wrapper) { return applicationCommandHandler(modul, interaction); } if (interaction.isMessageComponent()) { - const modul = Files - .MessageCompCommands[interaction.componentType] - .get(interaction.customId); + const modul = Files.MessageCompCommands[interaction.componentType].get(interaction.customId); return messageComponentInteractionHandler(modul, interaction); } else return throwError(() => SernError.NotSupportedInteraction); }), - ).subscribe({ - async next({ mod, res: eventPluginRes, execute }) { - const ePlugArr: Result[] = []; - for await (const res of eventPluginRes) { - if (isPromise(res)) { - ePlugArr.push(res); + ) + .subscribe({ + async next({ mod, res: eventPluginRes, execute }) { + const ePlugArr: Result[] = []; + for await (const res of eventPluginRes) { + if (isPromise(res)) { + ePlugArr.push(res); + } + ePlugArr.push(res as Awaited>); } - ePlugArr.push(res as Awaited>); - } - if (ePlugArr.every(e => e.ok)) { - await execute(); - wrapper.sernEmitter?.emit('module.activate', { success: true, module: mod! }); - } else { - wrapper.sernEmitter?.emit('module.activate', { - success: false, - module: mod!, - reason: SernError.PluginFailure, - }); - } - }, - error(err) { - wrapper.sernEmitter?.emit('error', err); - }, - }); -} \ No newline at end of file + if (ePlugArr.every(e => e.ok)) { + await execute(); + wrapper.sernEmitter?.emit('module.activate', { success: true, module: mod! }); + } else { + wrapper.sernEmitter?.emit('module.activate', { + success: false, + module: mod!, + reason: SernError.PluginFailure, + }); + } + }, + error(err) { + wrapper.sernEmitter?.emit('error', err); + }, + }); +} diff --git a/src/handler/events/messageEvent.ts b/src/handler/events/messageEvent.ts index b10505a..24753fb 100644 --- a/src/handler/events/messageEvent.ts +++ b/src/handler/events/messageEvent.ts @@ -23,16 +23,14 @@ export const onMessageCreate = (wrapper: Wrapper) => { return { ctx: Context.wrap(message), //TODO : check for BothCommand args: ['text', rest], - mod: - Files.BothCommands.get(prefix) ?? - Files.TextCommands.aliases.get(prefix), + mod: Files.BothCommands.get(prefix) ?? Files.TextCommands.aliases.get(prefix), }; }), ); const ensureModuleType$ = processMessage$.pipe( concatMap(payload => of(payload.mod).pipe( - //SUPPORT COMMANDTYPE.BOTH + //SUPPORT COMMAND TYPE.BOTH filterCorrectModule(CommandType.Text), map(mod => ({ ...payload, mod })), ), diff --git a/src/handler/events/observableHandling.ts b/src/handler/events/observableHandling.ts index afabebc..b9efc35 100644 --- a/src/handler/events/observableHandling.ts +++ b/src/handler/events/observableHandling.ts @@ -47,4 +47,3 @@ export function ignoreNonBot(prefix: string) { }); }); } - diff --git a/src/handler/events/readyEvent.ts b/src/handler/events/readyEvent.ts index 1c8e22f..a058161 100644 --- a/src/handler/events/readyEvent.ts +++ b/src/handler/events/readyEvent.ts @@ -26,14 +26,15 @@ export const onReady = (wrapper: Wrapper) => { }), ); const processPlugins$ = processCommandFiles$.pipe( - concatMap((mod) => { - const cmdPluginsRes = mod.plugins?.map(plug => { - return { - ...plug, - name: plug?.name ?? 'Unnamed Plugin', - execute: plug.execute(client, mod, controller), - }; - }) ?? []; + concatMap(mod => { + const cmdPluginsRes = + mod.plugins?.map(plug => { + return { + ...plug, + name: plug?.name ?? 'Unnamed Plugin', + execute: plug.execute(client, mod, controller), + }; + }) ?? []; return of({ mod, cmdPluginsRes }); }), ); diff --git a/src/handler/plugins/plugin.ts b/src/handler/plugins/plugin.ts index c13ce45..d361fa4 100644 --- a/src/handler/plugins/plugin.ts +++ b/src/handler/plugins/plugin.ts @@ -18,27 +18,35 @@ import type { BaseModule, ModuleDefs } from '../structures/module'; import type { PluginType } from '../structures/enums'; import type { ValueOf } from 'ts-pattern/dist/types/helpers'; - export interface Controller { next: () => Ok; stop: () => Err; } -type BasePlugin = Override; +type BasePlugin = Override< + BaseModule, + { + type: PluginType; + } +>; -export type CommandPlugin = Override Awaitable>; -}>; +export type CommandPlugin = Override< + BasePlugin, + { + type: PluginType.Command; + execute: (wrapper: Client, module: Module, controller: Controller) => Awaitable>; + } +>; //TODO: rn adding the modType check a little hackish. Find better way to determine the // module type of the event plugin -export type EventPlugin = Override, controller: Controller) => Awaitable>; -}>; +export type EventPlugin = Override< + BasePlugin, + { + type: PluginType.Event; + execute: (event: Parameters, controller: Controller) => Awaitable>; + } +>; export function plugins(...plug: CommandPlugin[]): CommandPlugin[]; export function plugins(...plug: EventPlugin[]): EventPlugin[]; @@ -47,16 +55,14 @@ export function plugins(...plug: EventPlugin[] | } type ModuleNoPlugins = ValueOf<{ - [T in keyof ModuleDefs]: Omit -}> + [T in keyof ModuleDefs]: Omit; +}>; //TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH -export function sernModule( - plugins: (CommandPlugin)[], mod: ModuleNoPlugins, -): Module { +export function sernModule(plugins: CommandPlugin[], mod: ModuleNoPlugins): Module { return { plugins, ...mod, }; -} \ No newline at end of file +} diff --git a/src/handler/sern.ts b/src/handler/sern.ts index bea58df..1f49ae6 100644 --- a/src/handler/sern.ts +++ b/src/handler/sern.ts @@ -24,7 +24,7 @@ export function init(wrapper: Wrapper) { } function eventObserver(client: Client, events: (DiscordEvent | EventEmitterRegister)[]) { - events.forEach((event) => { + events.forEach(event => { if (isDiscordEvent(event)) { fromEvent(client, event[0], event[1]).subscribe(); } else { diff --git a/src/handler/sernEmitter.ts b/src/handler/sernEmitter.ts index 7f81c05..26aea13 100644 --- a/src/handler/sernEmitter.ts +++ b/src/handler/sernEmitter.ts @@ -2,22 +2,27 @@ import { EventEmitter } from 'events'; import type { Module } from './structures/module'; type Payload = - { success: true, module: Module } - | { success: false, module: Module | undefined, reason: string | Error } + | { success: true; module: Module } + | { success: false; module: Module | undefined; reason: string | Error }; type SernEventsMapping = { ['module.register']: [Payload]; ['module.activate']: [Payload]; ['error']: [Error | string]; -} +}; export default class SernEmitter extends EventEmitter { - - public override on(eventName: T, listener: (...args: SernEventsMapping[T][]) => void): this { + public override on( + eventName: T, + listener: (...args: SernEventsMapping[T][]) => void, + ): this { return super.on(eventName, listener); } - public override once(eventName: T, listener: (...args: SernEventsMapping[T][]) => void): this { + public override once( + eventName: T, + listener: (...args: SernEventsMapping[T][]) => void, + ): this { return super.once(eventName, listener); } @@ -25,5 +30,3 @@ export default class SernEmitter extends EventEmitter { return super.emit(eventName, ...args); } } - - diff --git a/src/handler/structures/module.ts b/src/handler/structures/module.ts index 070d237..b8a5c49 100644 --- a/src/handler/structures/module.ts +++ b/src/handler/structures/module.ts @@ -19,55 +19,76 @@ export interface BaseModule { } //possible refactoring types into interfaces and not types -export type TextCommand = Override[] - plugins?: CommandPlugin[]; - alias?: string[]; -}>; +export type TextCommand = Override< + BaseModule, + { + type: CommandType.Text; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + alias?: string[]; + } +>; -export type SlashCommand = Override[] - plugins?: CommandPlugin[]; - options?: ApplicationCommandOptionData[]; -}>; +export type SlashCommand = Override< + BaseModule, + { + type: CommandType.Slash; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + options?: ApplicationCommandOptionData[]; + } +>; -export type BothCommand = Override[] - plugins?: CommandPlugin[] - alias?: string[]; - options?: ApplicationCommandOptionData[]; -}>; +export type BothCommand = Override< + BaseModule, + { + type: CommandType.Both; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + alias?: string[]; + options?: ApplicationCommandOptionData[]; + } +>; -export type ContextMenuUser = Override[]; - plugins?: CommandPlugin[]; - execute: (ctx: UserContextMenuCommandInteraction) => Awaitable -}> +export type ContextMenuUser = Override< + BaseModule, + { + type: CommandType.MenuUser; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + execute: (ctx: UserContextMenuCommandInteraction) => Awaitable; + } +>; -export type ContextMenuMsg = Override[]; - plugins?: CommandPlugin[]; - execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable -}>; +export type ContextMenuMsg = Override< + BaseModule, + { + type: CommandType.MenuMsg; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable; + } +>; -export type ButtonCommand = Override[]; - plugins?: CommandPlugin[]; - execute: (ctx: ButtonInteraction) => Awaitable -}>; +export type ButtonCommand = Override< + BaseModule, + { + type: CommandType.Button; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + execute: (ctx: ButtonInteraction) => Awaitable; + } +>; -export type SelectMenuCommand = Override[]; - plugins?: CommandPlugin[]; - execute: (ctx: SelectMenuInteraction) => Awaitable -}>; +export type SelectMenuCommand = Override< + BaseModule, + { + type: CommandType.MenuSelect; + onEvent?: EventPlugin[]; + plugins?: CommandPlugin[]; + execute: (ctx: SelectMenuInteraction) => Awaitable; + } +>; export type Module = | TextCommand @@ -88,4 +109,4 @@ export type ModuleDefs = { [CommandType.MenuUser]: ContextMenuUser; [CommandType.Button]: ButtonCommand; [CommandType.MenuSelect]: SelectMenuCommand; -}; \ No newline at end of file +}; diff --git a/src/handler/utilities/markup.ts b/src/handler/utilities/markup.ts index f41ccb1..daf5971 100644 --- a/src/handler/utilities/markup.ts +++ b/src/handler/utilities/markup.ts @@ -657,37 +657,43 @@ class MatchInner { while ((match = regex.exec(this.raw))) { const result: DiscordRegexMatch = { matched: match[0], species: type }; switch (type) { - case DiscordRegexNames.EMOJI: { - result.name = match[1] as string; - result.id = match[2] as string; - result.animated = this.raw.startsWith('( plug: Module | undefined, type: T, @@ -47,4 +46,3 @@ export function isPromise(promiseLike: Awaitable): promiseLike is Promise< export function isDiscordEvent(el: DiscordEvent | EventEmitterRegister): el is DiscordEvent { return el.length === 2; } - diff --git a/src/types/handler.ts b/src/types/handler.ts index 35fd0c6..e9e393b 100644 --- a/src/types/handler.ts +++ b/src/types/handler.ts @@ -19,12 +19,9 @@ export type Args = ParseType<{ text: string[]; slash: SlashOptions }>; export type DiscordEvent = ParseType<{ [K in keyof ClientEvents]: (...args: ClientEvents[K]) => Awaitable }>; export type EventEmitterRegister = [emitter: EventEmitter, k: string, cb: (...args: unknown[]) => Awaitable]; - export type SlashOptions = Omit; //https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l export type Override = Omit & T2; export type DefinitelyDefined = T & Override; - -