From b26650818e2c193c326356359b38412117ea6186 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 17 May 2022 11:31:35 -0500 Subject: [PATCH] fix: Non-exhaustiveness led to commands not registering readyEvent.ts --- src/handler/events/interactionCreate.ts | 22 +++++++++------------- src/handler/events/messageEvent.ts | 4 ++-- src/handler/events/observableHandling.ts | 5 ++++- src/handler/events/readyEvent.ts | 21 +++++++++++++++++---- src/handler/utilities/predicates.ts | 7 ++++++- 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/handler/events/interactionCreate.ts b/src/handler/events/interactionCreate.ts index b2282da..f91f883 100644 --- a/src/handler/events/interactionCreate.ts +++ b/src/handler/events/interactionCreate.ts @@ -21,9 +21,6 @@ import { filterCorrectModule } from './observableHandling'; //TODO : atm, i have to cast for every interaction. is there a way to not cast? // maybe pass it through an observable function applicationCommandHandler(mod: Module | undefined, interaction: CommandInteraction) { - if (mod === undefined) { - return throwError(() => SernError.UndefinedModule); - } const mod$ = (cmdTy : T) => of(mod).pipe( filterCorrectModule(cmdTy) ); @@ -33,10 +30,11 @@ function applicationCommandHandler(mod: Module | undefined, interaction: Command const ctx = Context.wrap(i); return mod$(CommandType.Slash).pipe( concatMap(m => { + console.log(m); return of(m.onEvent.map(e => e.execute( [ctx, ['slash', i.options]], controller - ))).pipe(map(res => ({ m, res, execute() { m.execute(ctx, ['slash', i.options]); } }) )); + ))).pipe(map(res => ({ m, res, execute() { return m.execute(ctx, ['slash', i.options]); } }) )); }), ); }, @@ -49,7 +47,7 @@ function applicationCommandHandler(mod: Module | undefined, interaction: Command return of(m.onEvent.map(e => e.execute( [ctx], controller - ))).pipe(map(res => ({ m, res, execute() { m.execute(ctx); } }) )); + ))).pipe(map(res => ({ m, res, execute() { return m.execute(ctx); } }) )); }), ); }, @@ -60,7 +58,7 @@ function applicationCommandHandler(mod: Module | undefined, interaction: Command return of(m.onEvent.map(e => e.execute( [ctx], controller - ))).pipe(map(res => ({ m, res, execute() { m.execute(ctx); } }) )); + ))).pipe(map(res => ({ m, res, execute() { return m.execute(ctx); } }) )); }), ); }) @@ -71,9 +69,7 @@ function messageComponentInteractionHandler( mod: Module | undefined, interaction: MessageComponentInteraction, ) { - if (mod === undefined) { - return throwError(() => SernError.UndefinedModule); - } + 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 @@ -84,7 +80,7 @@ function messageComponentInteractionHandler( return of(m.onEvent.map(e => e.execute( [ctx], controller - ))).pipe(map(res => ({ m, res, execute() { m.execute(ctx); } }) )); + ))).pipe(map(res => ({ m, res, execute() { return m.execute(ctx); } }) )); }), ); }) @@ -94,7 +90,7 @@ function messageComponentInteractionHandler( return of(m.onEvent.map(e => e.execute( [ctx], controller - ))).pipe(map(res => ({ m, res, execute() { m.execute(ctx); } }) )); + ))).pipe(map(res => ({ m, res, execute() { return m.execute(ctx); } }) )); }), ); }) @@ -125,10 +121,10 @@ export function onInteractionCreate (wrapper: Wrapper) { }), ).subscribe({ next({m, res, execute}) { - // execute(); + console.log(res); }, error(err) { - return; + console.log(err); } }); diff --git a/src/handler/events/messageEvent.ts b/src/handler/events/messageEvent.ts index bac6f12..4671c90 100644 --- a/src/handler/events/messageEvent.ts +++ b/src/handler/events/messageEvent.ts @@ -1,5 +1,5 @@ import type { Message } from 'discord.js'; -import { concatMap, from, fromEvent, map, Observable, of } from 'rxjs'; +import { concatMap, filter, from, fromEvent, map, Observable, of } from 'rxjs'; import { Err } from 'ts-results'; import type { Args } from '../..'; import { CommandType, controller } from '../sern'; @@ -32,7 +32,7 @@ export const onMessageCreate = (wrapper: Wrapper) => { concatMap(payload => of(payload.mod).pipe( filterCorrectModule(CommandType.Text), // fix for BothCommand - map(textCommand => ({ ...payload, mod: textCommand })), + map(mod => ({ ...payload, mod })), ), ), ); diff --git a/src/handler/events/observableHandling.ts b/src/handler/events/observableHandling.ts index ffcf42c..7866a7d 100644 --- a/src/handler/events/observableHandling.ts +++ b/src/handler/events/observableHandling.ts @@ -6,10 +6,13 @@ import type { Module, ModuleDefs } from '../structures/module'; import { correctModuleType } from '../utilities/predicates'; export function filterCorrectModule(cmdType: T) { - return (src: Observable) => + return (src: Observable) => new Observable(subscriber => { return src.subscribe({ next(mod) { + if (mod === undefined) { + return throwError(() => SernError.UndefinedModule); + } if (correctModuleType(mod, cmdType)) { subscriber.next(mod); } else { diff --git a/src/handler/events/readyEvent.ts b/src/handler/events/readyEvent.ts index d1d4379..fe8d6a3 100644 --- a/src/handler/events/readyEvent.ts +++ b/src/handler/events/readyEvent.ts @@ -9,6 +9,8 @@ import type { Awaitable } from 'discord.js'; import type { Module } from '../structures/module'; import { match } from 'ts-pattern'; import { ApplicationCommandType, ComponentType } from 'discord.js'; +import { Err, Ok } from 'ts-results'; +import { SernError } from '../structures/errors'; export const onReady = (wrapper: Wrapper) => { const { client, commands } = wrapper; @@ -56,7 +58,10 @@ export const onReady = (wrapper: Wrapper) => { .subscribe(({ mod, cmdPluginsRes }) => { const loadedPluginsCorrectly = cmdPluginsRes.every(res => res.execute.ok); if (loadedPluginsCorrectly) { - registerModule(mod); + const res = registerModule(mod); + if(res.err) { + throw Error(SernError.NonValidModuleType); + } } else { console.log(`Failed to load command ${mod.name!}`); console.log(mod); @@ -64,30 +69,38 @@ export const onReady = (wrapper: Wrapper) => { }); }; -function registerModule(mod: Module) { +function registerModule(mod: Module) : Result { const name = mod.name!; - match(mod) + return match(mod) .with({ type: CommandType.Text }, mod => { mod.alias.forEach(a => Files.TextCommands.aliases.set(a, mod)); Files.TextCommands.text.set(name, mod); + return Ok.EMPTY; }) .with({ type: CommandType.Slash }, mod => { Files.ApplicationCommands[ApplicationCommandType.ChatInput].set(name, mod); + return Ok.EMPTY; }) .with({ type: CommandType.Both }, mod => { Files.BothCommands.set(name, mod); mod.alias.forEach(a => Files.TextCommands.aliases.set(a, mod)); + return Ok.EMPTY; }) .with({ type: CommandType.MenuUser }, mod => { Files.ApplicationCommands[ApplicationCommandType.User].set(name, mod); + return Ok.EMPTY; }) .with({ type: CommandType.MenuMsg }, mod => { Files.ApplicationCommands[ApplicationCommandType.Message].set(name, mod); + return Ok.EMPTY; }) .with({ type: CommandType.Button }, mod => { Files.ApplicationCommands[ComponentType.Button].set(name, mod); + return Ok.EMPTY; }) .with({ type: CommandType.MenuSelect }, mod => { Files.MessageCompCommands[ComponentType.SelectMenu].set(name, mod); - }); + return Ok.EMPTY; + }) + .otherwise(() => Err.EMPTY); } diff --git a/src/handler/utilities/predicates.ts b/src/handler/utilities/predicates.ts index 6157606..d4fd3c6 100644 --- a/src/handler/utilities/predicates.ts +++ b/src/handler/utilities/predicates.ts @@ -1,5 +1,5 @@ import type { Module, ModuleDefs } from '../structures/module'; -import type { ChatInputCommandInteraction, CommandInteraction } from 'discord.js'; +import type { Awaitable, ChatInputCommandInteraction, CommandInteraction } from 'discord.js'; import type { ButtonInteraction, MessageComponentInteraction, SelectMenuInteraction } from 'discord.js'; import type { MessageContextMenuCommandInteraction, UserContextMenuCommandInteraction } from 'discord.js'; @@ -27,4 +27,9 @@ export function isMessageCtxMenuCmd(i : CommandInteraction) : i is MessageContex export function isUserContextMenuCmd(i : CommandInteraction) : i is UserContextMenuCommandInteraction { return i.isUserContextMenuCommand(); +} + +function isPromise(promiseLike : Awaitable) : promiseLike is Promise { + const keys = new Set(Object.keys(promiseLike)); + return keys.has('then') && keys.has('catch'); } \ No newline at end of file