diff --git a/src/handler/events/interactionCreate.ts b/src/handler/events/interactionCreate.ts index 3768bed..a8b8a93 100644 --- a/src/handler/events/interactionCreate.ts +++ b/src/handler/events/interactionCreate.ts @@ -12,11 +12,12 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => { (> fromEvent(client, 'interactionCreate')) .pipe( - concatMap ( interaction => { + concatMap (async interaction => { + interaction.type if (interaction.isChatInputCommand()) { return of(Files.Commands.get(interaction.commandName)) .pipe( - filterTap(CommandType.Slash, mod => { + filterTap(CommandType.Slash, (mod) => { const ctx = Context.wrap(interaction); mod.execute(ctx, ['slash', interaction.options]); }), @@ -25,7 +26,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => { if (interaction.isContextMenuCommand()) { return of(Files.ContextMenuUser.get(interaction.commandName)) .pipe( - filterTap(CommandType.MenuUser, mod => { + filterTap(CommandType.MenuUser, (mod) => { mod.execute(interaction); }), ); @@ -33,7 +34,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => { if (interaction.isMessageContextMenuCommand()) { return of(Files.ContextMenuMsg.get(interaction.commandName)) .pipe( - filterTap(CommandType.MenuMsg, mod => { + filterTap(CommandType.MenuMsg, (mod, plugs) => { mod.execute(interaction); }), ); @@ -41,7 +42,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => { if (interaction.isButton()) { return of(Files.Buttons.get(interaction.customId)) .pipe( - filterTap(CommandType.Button, mod => { + filterTap(CommandType.Button, (mod, plugs) => { mod.execute(interaction); }) ); @@ -49,7 +50,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => { if (interaction.isSelectMenu()) { return of(Files.SelectMenus.get(interaction.customId)) .pipe( - filterTap(CommandType.MenuSelect, mod => { + filterTap(CommandType.MenuSelect, (mod, plugs) => { mod.execute(interaction); }) ); @@ -60,9 +61,9 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => { error(e){ throw e; }, - next(command) { - //log on each command emitted - console.log(command); + next(_command) { + //every command that gets triggered ends up here + //console.log(command); }, }); }; diff --git a/src/handler/events/messageEvent.ts b/src/handler/events/messageEvent.ts index 473c074..a5239f2 100644 --- a/src/handler/events/messageEvent.ts +++ b/src/handler/events/messageEvent.ts @@ -1,32 +1,44 @@ import type { Message } from 'discord.js'; -import { fromEvent, Observable, of, concatMap } from 'rxjs'; +import { fromEvent, Observable, of, concatMap, mergeMap } from 'rxjs'; +import { Err, Ok } from 'ts-results'; import { CommandType } from '../sern'; import Context from '../structures/context'; import type Wrapper from '../structures/wrapper'; import { fmt } from '../utilities/messageHelpers'; import * as Files from '../utilities/readFile'; -import { filterTap, ignoreNonBot } from './observableHandling'; +import { filterCorrectModule, filterTap, ignoreNonBot } from './observableHandling'; export const onMessageCreate = (wrapper : Wrapper) => { const { client, defaultPrefix } = wrapper; (> fromEvent( client, 'messageCreate')) - .pipe ( + .pipe( ignoreNonBot(defaultPrefix), - concatMap ( m => { + concatMap (async m => { const [ prefix, ...data ] = fmt(m, defaultPrefix); const posMod = Files.Commands.get(prefix) ?? Files.Alias.get(prefix); - + const ctx = Context.wrap(m); return of( posMod ) .pipe ( - filterTap(CommandType.Text, mod => { - const ctx = Context.wrap(m); - mod.execute(ctx, ['text', data]); + filterCorrectModule(CommandType.Text), + filterTap(CommandType.Text, async (mod,plugins) => { + const res = await Promise.all( + plugins.map(async pl => ({ + ...pl, + execute : await pl.execute([ctx, ['text', data] ], { + next : () => Ok.EMPTY, + stop : () => Err.EMPTY + }), + })) + + ); + if (res.every(pl => pl.execute.ok)) { + mod.execute(ctx, ['text', data]); + } }) ); }) ).subscribe ({ error(e) { - //log things throw e; }, next(command) { @@ -35,5 +47,4 @@ export const onMessageCreate = (wrapper : Wrapper) => { }, }); - }; diff --git a/src/handler/events/observableHandling.ts b/src/handler/events/observableHandling.ts index ec49434..a81ce90 100644 --- a/src/handler/events/observableHandling.ts +++ b/src/handler/events/observableHandling.ts @@ -1,19 +1,39 @@ import type { Awaitable, Message } from 'discord.js'; import type { CommandType } from '../sern'; -import type { Module } from '../structures/structxports'; import { Observable, throwError } from 'rxjs'; import type { ModuleDefs } from '../structures/modules/commands/moduleHandler'; import { SernError } from '../structures/errors'; import { isNotFromBot } from '../utilities/messageHelpers'; import type { PluggedModule } from '../structures/modules/module'; -import type { SernPlugin } from '../plugins/plugin'; +import type { EventPlugin, SernPlugin } from '../plugins/plugin'; export function match(plug: PluggedModule | undefined, type : CommandType) : boolean { return plug !== undefined && (plug.mod.type & type) != 0; } + +export function filterCorrectModule(cmdType : T) { + return (src : Observable) => + new Observable( subscriber => { + return src.subscribe({ + next(modul) { + if(match(modul, cmdType)) { + subscriber.next(modul); + } else { + if (modul === undefined) { + return throwError(() => SernError.UndefinedModule); + } + return throwError(() => SernError.MismatchModule); + } + }, + error: (e) => subscriber.error(e), + complete: () => subscriber.complete() + }); + }); +} + export function filterTap( cmdType : T, - tap: (mod : ModuleDefs[T], plugins : SernPlugin[]) => Awaitable + tap: (mod : ModuleDefs[T], plugins : EventPlugin[]) => Awaitable ) { return (src : Observable) => new Observable( subscriber => { @@ -21,7 +41,7 @@ export function filterTap( next(modul) { if(match(modul, cmdType)) { const asModT = modul!.mod; - tap(asModT, modul!.plugins); + tap(asModT, modul!.plugins as EventPlugin[]); subscriber.next(modul); } else { if (modul === undefined) { @@ -70,3 +90,6 @@ export function partition } + + + diff --git a/src/handler/events/readyEvent.ts b/src/handler/events/readyEvent.ts index c28e6aa..1cfbb09 100644 --- a/src/handler/events/readyEvent.ts +++ b/src/handler/events/readyEvent.ts @@ -31,17 +31,18 @@ export const onReady = ( wrapper : Wrapper ) => { }) return { res, plugged : { mod, plugins } } }) - }), - ); + }) + ); (concat(ready$,processCommandFiles$) as Observable<{ - res : Awaitable>, plugged : PluggedModule - }>).pipe( - mergeMap(async( {res, plugged} ) => ({ res:await res, plugged }) ) - ).subscribe( + res : Promise>, plugged : PluggedModule + }>) + .subscribe( ({ res, plugged: { mod, plugins }}) => { - if(res.ok) { + res.then( result => { + if(result.ok) { + console.log(`${mod.name!} has been registered`) registerModule(mod.name!, mod, plugins) } else { // TODO: add event emitter for command failures @@ -49,6 +50,7 @@ export const onReady = ( wrapper : Wrapper ) => { console.log(`Did not register command ${mod.name!}`) console.log(mod); } + }); }) } diff --git a/src/handler/plugins/plugin.ts b/src/handler/plugins/plugin.ts index df9b672..5635574 100644 --- a/src/handler/plugins/plugin.ts +++ b/src/handler/plugins/plugin.ts @@ -14,6 +14,8 @@ import type { Awaitable, Client } from "discord.js"; import type { Err, Ok, Result } from "ts-results"; import type { Module, Override, Wrapper } from "../.."; +import type { CommandType } from "../sern"; +import type { ModuleDefs } from "../structures/modules/commands/moduleHandler"; import type { BaseModule, PluggedModule } from "../structures/modules/module"; export enum PluginType { @@ -41,9 +43,12 @@ export type CommandPlugin = { ) => Awaitable> }>; -export type EventPlugin = { - type : PluginType.Event -} & BasePlugin; +export type EventPlugin = { + type : PluginType.Event, + modTy : T +} & Override, controller: Controller ) => Awaitable> +} >; export type SernPlugin = CommandPlugin diff --git a/src/handler/sern.ts b/src/handler/sern.ts index 2e67472..bb5cc9a 100644 --- a/src/handler/sern.ts +++ b/src/handler/sern.ts @@ -5,11 +5,10 @@ import type { import { ApplicationCommandType, Client, - MessageType, } from 'discord.js'; import type Wrapper from './structures/wrapper'; -import { fromEvent, throwError } from 'rxjs'; +import { fromEvent } from 'rxjs'; import { SernError } from './structures/errors'; import { onReady } from './events/readyEvent'; import { onMessageCreate } from './events/messageEvent'; @@ -31,8 +30,6 @@ function eventObserver(client: Client, events: DiscordEvent[] ) { }); } - - /** * @enum { number }; */ @@ -44,7 +41,6 @@ export enum CommandType { Button = 0b0010000, MenuSelect = 0b0100000, Both = 0b0000011, - Auto = 0b1000000 } export function cmdTypeToDjs(ty: CommandType) {