refactor: change loading strategy, eliminate bloat

This commit is contained in:
Jacob Nguyen
2022-05-15 19:18:19 -05:00
parent 40a10bf32b
commit a76099cbcb
10 changed files with 72 additions and 107 deletions

View File

@@ -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);

View File

@@ -23,9 +23,9 @@ export const onMessageCreate = (wrapper: Wrapper) => {
ctx: Context.wrap(message), //TODO : check for BothCommand
args: <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),
};
}),
);

View File

@@ -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<T extends keyof ModuleDefs>(
plug: Module | undefined,

View File

@@ -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<T extends ModuleType>(name: string, mod: ModuleStates[T]) {
return (<HandlerCallback<CommandType>>handler(name)[mod.type])(mod);
function registerModule(mod : Module) {
const name = mod.name!;
match<Module>(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);
})
}

View File

@@ -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 {

View File

@@ -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<void>;
}
//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;
};

View File

@@ -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<K extends ModuleType> = (mod: ModuleStates[K]) => unknown;
//An object that acts as the mapped object to handler
export type ModuleHandlers = { [K in ModuleType]: HandlerCallback<K> };

View File

@@ -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<void>;
}

View File

@@ -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 };

View File

@@ -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<string, Module>();
export const ApplicationCommandStore = {
export const BothCommands = new Map<string, Module>();
export const ApplicationCommands = {
[ApplicationCommandType.User]: new Map<string, Module>(),
[ApplicationCommandType.Message]: new Map<string, Module>(),
[ApplicationCommandType.ChatInput]: new Map<string, Module>(),
} as { [K in ApplicationCommandType]: Map<string, Module> };
export const MessageCompCommandStore = {
export const MessageCompCommands = {
[ComponentType.Button]: new Map<string, Module>(),
[ComponentType.SelectMenu]: new Map<string, Module>(),
[ComponentType.TextInput]: new Map<string, Module>(),
};
export const TextCommandStore = {
export const TextCommands = {
text: new Map<string, Module>(),
aliases: new Map<string, Module>(),
};