From a76099cbcbe412978aa897f89500a8d9f41c99d6 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 15 May 2022 19:18:19 -0500 Subject: [PATCH] refactor: change loading strategy, eliminate bloat --- src/handler/events/interactionCreate.ts | 8 +- src/handler/events/messageEvent.ts | 6 +- src/handler/events/observableHandling.ts | 3 +- src/handler/events/readyEvent.ts | 77 ++++++++----------- src/handler/plugins/plugin.ts | 3 +- .../{modules/commands => }/module.ts | 29 +++++-- .../modules/commands/moduleHandler.ts | 32 -------- src/handler/structures/modules/module.ts | 9 --- src/handler/structures/structxports.ts | 2 +- src/handler/utilities/readFile.ts | 10 +-- 10 files changed, 72 insertions(+), 107 deletions(-) rename src/handler/structures/{modules/commands => }/module.ts (68%) delete mode 100644 src/handler/structures/modules/commands/moduleHandler.ts delete mode 100644 src/handler/structures/modules/module.ts diff --git a/src/handler/events/interactionCreate.ts b/src/handler/events/interactionCreate.ts index aa739bb..03944d9 100644 --- a/src/handler/events/interactionCreate.ts +++ b/src/handler/events/interactionCreate.ts @@ -17,7 +17,7 @@ import type { Args } from '../../types/handler'; import type { MessageComponentInteraction } from 'discord.js'; import { ComponentType } from 'discord.js'; import type { UnionToTuple } from '../utilities/resolveParameters'; -import type { Module } from '../structures/modules/commands/module'; +import type { Module } from '../structures/module'; import type { EventPlugin } from '../plugins/plugin'; @@ -90,13 +90,13 @@ export const onInteractionCreate = (wrapper: Wrapper) => { concatMap(interaction => { if (interaction.isCommand()) { const modul = - Files.ApplicationCommandStore[interaction.commandType].get(interaction.commandName) ?? - Files.BothCommand.get(interaction.commandName); + Files.ApplicationCommands[interaction.commandType].get(interaction.commandName) ?? + Files.BothCommands.get(interaction.commandName); return applicationCommandHandler(modul, interaction); } if (interaction.isMessageComponent()) { const modul = Files - .MessageCompCommandStore[interaction.componentType] + .MessageCompCommands[interaction.componentType] .get(interaction.customId); return messageComponentInteractionHandler(modul, interaction); } else return throwError(() => SernError.NotSupportedInteraction); diff --git a/src/handler/events/messageEvent.ts b/src/handler/events/messageEvent.ts index abe60d5..9771dd6 100644 --- a/src/handler/events/messageEvent.ts +++ b/src/handler/events/messageEvent.ts @@ -23,9 +23,9 @@ export const onMessageCreate = (wrapper: Wrapper) => { ctx: Context.wrap(message), //TODO : check for BothCommand args: ['text', rest], mod: - Files.ApplicationCommandStore[1].get(prefix) ?? - Files.BothCommand.get(prefix) ?? - Files.TextCommandStore.aliases.get(prefix), + Files.ApplicationCommands[1].get(prefix) ?? + Files.BothCommands.get(prefix) ?? + Files.TextCommands.aliases.get(prefix), }; }), ); diff --git a/src/handler/events/observableHandling.ts b/src/handler/events/observableHandling.ts index 6dbc0d1..2a61009 100644 --- a/src/handler/events/observableHandling.ts +++ b/src/handler/events/observableHandling.ts @@ -1,9 +1,8 @@ import type { Message } from 'discord.js'; 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 { Module } from '../structures/modules/commands/module'; +import type { Module, ModuleDefs } from '../structures/module'; export function correctModuleType( plug: Module | undefined, diff --git a/src/handler/events/readyEvent.ts b/src/handler/events/readyEvent.ts index 091d824..31d263d 100644 --- a/src/handler/events/readyEvent.ts +++ b/src/handler/events/readyEvent.ts @@ -2,17 +2,13 @@ import { concat, concatMap, from, fromEvent, map, Observable, of, skip, take } f import { basename } from 'path'; import * as Files from '../utilities/readFile'; import type Wrapper from '../structures/wrapper'; -import type { - HandlerCallback, - ModuleHandlers, - ModuleStates, - ModuleType, -} from '../structures/modules/commands/moduleHandler'; -import { CommandType } from '../sern'; +import { CommandType, controller } from '../sern'; import type { PluginType } from '../plugins/plugin'; -import { Err, Ok, Result } from 'ts-results'; +import type { Result } from 'ts-results'; import type { Awaitable } from 'discord.js'; -import type { Module } from '../structures/modules/commands/module'; +import type { Module } from '../structures/module'; +import { match, P } from 'ts-pattern'; +import { ApplicationCommandType, ComponentType } from 'discord.js'; export const onReady = (wrapper: Wrapper) => { const { client, commands } = wrapper; @@ -32,10 +28,7 @@ export const onReady = (wrapper: Wrapper) => { return { ...plug, name: plug?.name ?? 'Unnamed Plugin', - execute: plug.execute(client, mod, { - next: () => Ok.EMPTY, - stop: () => Err.EMPTY, - }), + execute: plug.execute(client, mod, controller), }; }); return of({ mod, cmdPluginsRes }); @@ -63,7 +56,7 @@ export const onReady = (wrapper: Wrapper) => { .subscribe(({ mod, cmdPluginsRes }) => { const loadedPluginsCorrectly = cmdPluginsRes.every(res => res.execute.ok); if (loadedPluginsCorrectly) { - registerModule(mod.name!, mod); + registerModule(mod); } else { console.log(`Failed to load command ${mod.name!}`); console.log(mod); @@ -71,34 +64,30 @@ export const onReady = (wrapper: Wrapper) => { }); }; -function handler(name: string): ModuleHandlers { - return { - [CommandType.Text]: (mod) => { - mod.alias.forEach(a => Files.TextCommandStore.aliases.set(a, mod)); - Files.TextCommandStore.text.set(name, mod); - }, - [CommandType.Slash]: (mod) => { - Files.ApplicationCommandStore[1].set(name, mod); - }, - [CommandType.Both]: (mod) => { - Files.BothCommand.set(name, mod); - mod.alias.forEach(a => Files.TextCommandStore.aliases.set(a, mod)); - }, - [CommandType.MenuUser]: (mod) => { - Files.ApplicationCommandStore[2].set(name, mod); - }, - [CommandType.MenuMsg]: (mod) => { - Files.ApplicationCommandStore[3].set(name, mod); - }, - [CommandType.Button]: (mod) => { - Files.MessageCompCommandStore[2].set(name, mod); - }, - [CommandType.MenuSelect]: (mod) => { - Files.MessageCompCommandStore[2].set(name, mod); - }, - }; -} - -function registerModule(name: string, mod: ModuleStates[T]) { - return (>handler(name)[mod.type])(mod); +function registerModule(mod : Module) { + const name = mod.name!; + match(mod) + .with({type : CommandType.Text }, mod => { + mod.alias.forEach(a => Files.TextCommands.aliases.set(a, mod)); + Files.TextCommands.text.set(name, mod); + }) + .with({ type : CommandType.Slash }, mod => { + Files.ApplicationCommands[ApplicationCommandType.ChatInput].set(name, mod); + }) + .with( { type : CommandType.Both }, mod => { + Files.BothCommands.set(name, mod); + mod.alias.forEach(a => Files.TextCommands.aliases.set(a, mod)); + }) + .with( { type : CommandType.MenuUser }, mod => { + Files.ApplicationCommands[ApplicationCommandType.User].set(name, mod); + }) + .with( { type : CommandType.MenuMsg }, mod => { + Files.ApplicationCommands[ApplicationCommandType.Message].set(name, mod); + }) + .with( { type : CommandType.Button }, mod => { + Files.ApplicationCommands[ComponentType.Button].set(name, mod); + }) + .with( { type: CommandType.MenuSelect }, mod => { + Files.MessageCompCommands[ComponentType.SelectMenu].set(name, mod); + }) } diff --git a/src/handler/plugins/plugin.ts b/src/handler/plugins/plugin.ts index 73724d7..9297a0b 100644 --- a/src/handler/plugins/plugin.ts +++ b/src/handler/plugins/plugin.ts @@ -14,9 +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 { ModuleDefs } from '../structures/modules/commands/moduleHandler'; -import type { BaseModule } from '../structures/modules/module'; import type { CommandType } from '../sern'; +import type { BaseModule, ModuleDefs } from '../structures/module'; export interface Controller { diff --git a/src/handler/structures/modules/commands/module.ts b/src/handler/structures/module.ts similarity index 68% rename from src/handler/structures/modules/commands/module.ts rename to src/handler/structures/module.ts index 8726b5a..edcce53 100644 --- a/src/handler/structures/modules/commands/module.ts +++ b/src/handler/structures/module.ts @@ -4,12 +4,19 @@ import type { ButtonInteraction, MessageContextMenuCommandInteraction, SelectMenuInteraction, + UserContextMenuCommandInteraction, } from 'discord.js'; -import type { Override } from '../../../../types/handler'; -import type { CommandType } from '../../../sern'; -import type { BaseModule } from '../module'; -import type { UserContextMenuCommandInteraction } from 'discord.js'; -import type { CommandPlugin, EventPlugin } from '../../../plugins/plugin'; +import type { Override } from '../../types/handler'; +import type { Args } from '../../types/handler'; +import type { CommandType } from '../sern'; +import type { CommandPlugin, EventPlugin } from '../plugins/plugin'; +import type Context from './context'; + +export interface BaseModule { + name?: string; + description: string; + execute: (ctx: Context, args: Args) => Awaitable; +} //possible refactoring types into interfaces and not types export type TextCommand = { @@ -66,3 +73,15 @@ export type Module = | ContextMenuMsg | ButtonCommand | SelectMenuCommand; + +//https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union +// Explicit Module Definitions for mapping +export type ModuleDefs = { + [CommandType.Text]: TextCommand; + [CommandType.Slash]: SlashCommand; + [CommandType.Both]: BothCommand; + [CommandType.MenuMsg]: ContextMenuMsg; + [CommandType.MenuUser]: ContextMenuUser; + [CommandType.Button]: ButtonCommand; + [CommandType.MenuSelect]: SelectMenuCommand; +}; \ No newline at end of file diff --git a/src/handler/structures/modules/commands/moduleHandler.ts b/src/handler/structures/modules/commands/moduleHandler.ts deleted file mode 100644 index 71be268..0000000 --- a/src/handler/structures/modules/commands/moduleHandler.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { CommandType } from '../../../sern'; -import type { - BothCommand, - ButtonCommand, - ContextMenuMsg, - ContextMenuUser, - SelectMenuCommand, - SlashCommand, - TextCommand, -} from './module'; -//https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union -// Explicit Module Definitions for mapping -export type ModuleDefs = { - [CommandType.Text]: TextCommand; - [CommandType.Slash]: SlashCommand; - [CommandType.Both]: BothCommand; - [CommandType.MenuMsg]: ContextMenuMsg; - [CommandType.MenuUser]: ContextMenuUser; - [CommandType.Button]: ButtonCommand; - [CommandType.MenuSelect]: SelectMenuCommand; -}; - -//Keys of ModuleDefs -export type ModuleType = keyof ModuleDefs; -// The keys mapped to a constructed union with its type -export type ModuleStates = { - [K in ModuleType]: { type: K } & ModuleDefs[K]; -}; -// A handler callback that is called on each ModuleDef -export type HandlerCallback = (mod: ModuleStates[K]) => unknown; -//An object that acts as the mapped object to handler -export type ModuleHandlers = { [K in ModuleType]: HandlerCallback }; diff --git a/src/handler/structures/modules/module.ts b/src/handler/structures/modules/module.ts deleted file mode 100644 index 9cac8e6..0000000 --- a/src/handler/structures/modules/module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Awaitable } from 'discord.js'; -import type { Args } from '../../..'; -import type Context from '../context'; - -export interface BaseModule { - name?: string; - description: string; - execute: (ctx: Context, args: Args) => Awaitable; -} diff --git a/src/handler/structures/structxports.ts b/src/handler/structures/structxports.ts index 70bdc7a..5cc9686 100644 --- a/src/handler/structures/structxports.ts +++ b/src/handler/structures/structxports.ts @@ -1,5 +1,5 @@ import Context from './context'; -import type { BothCommand, Module, SlashCommand, TextCommand } from './modules/commands/module'; +import type { BothCommand, Module, SlashCommand, TextCommand } from './module'; import type Wrapper from './wrapper'; export { Context, SlashCommand, TextCommand, BothCommand, Module, Wrapper }; diff --git a/src/handler/utilities/readFile.ts b/src/handler/utilities/readFile.ts index 4f1dace..60b92ea 100644 --- a/src/handler/utilities/readFile.ts +++ b/src/handler/utilities/readFile.ts @@ -2,21 +2,21 @@ import { ApplicationCommandType, ComponentType } from 'discord.js'; import { readdirSync, statSync } from 'fs'; import { join } from 'path'; import { from, Observable } from 'rxjs'; -import type { Module } from '../structures/modules/commands/module'; +import type { Module } from '../structures/module'; -export const BothCommand = new Map(); -export const ApplicationCommandStore = { +export const BothCommands = new Map(); +export const ApplicationCommands = { [ApplicationCommandType.User]: new Map(), [ApplicationCommandType.Message]: new Map(), [ApplicationCommandType.ChatInput]: new Map(), } as { [K in ApplicationCommandType]: Map }; -export const MessageCompCommandStore = { +export const MessageCompCommands = { [ComponentType.Button]: new Map(), [ComponentType.SelectMenu]: new Map(), [ComponentType.TextInput]: new Map(), }; -export const TextCommandStore = { +export const TextCommands = { text: new Map(), aliases: new Map(), };