mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
feat: Add more plugin definitions
This commit is contained in:
@@ -11,21 +11,18 @@
|
||||
* Plugins are reminiscent of middleware in express.
|
||||
*/
|
||||
|
||||
import type { Awaitable, Client } from 'discord.js';
|
||||
import type { AutocompleteInteraction, Awaitable, Client, ClientEvents } from 'discord.js';
|
||||
import type { Err, Ok, Result } from 'ts-results';
|
||||
import type { DefinitelyDefined, Module, Override } from '../..';
|
||||
import type { CommandType } from '../..';
|
||||
import type {
|
||||
BaseModule,
|
||||
EventModule,
|
||||
CommandModuleDefs,
|
||||
CommandModule,
|
||||
} from '../structures/module';
|
||||
import { PluginType } from '../structures/enums';
|
||||
import type { CommandType, DefinitelyDefined, Override, SernEventsMapping } from '../..';
|
||||
import { EventType, PluginType } from '../..';
|
||||
import type { BaseModule, CommandModuleDefs, EventModuleDefs } from '../structures/module';
|
||||
import type { EventEmitter } from 'events';
|
||||
import type { ExternalEventCommand, SernEventCommand } from '../structures/events';
|
||||
import type {
|
||||
DiscordEventCommand,
|
||||
ExternalEventCommand,
|
||||
SernEventCommand,
|
||||
} from '../structures/events';
|
||||
import type SernEmitter from '../sernEmitter';
|
||||
import type { AutocompleteInteraction } from 'discord.js';
|
||||
|
||||
export interface Controller {
|
||||
next: () => Ok<void>;
|
||||
@@ -53,6 +50,17 @@ export type CommandPlugin<T extends keyof CommandModuleDefs = keyof CommandModul
|
||||
>;
|
||||
}[T];
|
||||
|
||||
export type DiscordEmitterPlugin = Override<
|
||||
BasePlugin,
|
||||
{
|
||||
type: PluginType.Command;
|
||||
execute: (
|
||||
wrapper: Client,
|
||||
module: DefinitelyDefined<DiscordEventCommand, 'name' | 'description'>,
|
||||
controller: Controller,
|
||||
) => Awaitable<Result<void, void>>;
|
||||
}
|
||||
>;
|
||||
export type ExternalEmitterPlugin<T extends EventEmitter = EventEmitter> = Override<
|
||||
BasePlugin,
|
||||
{
|
||||
@@ -84,7 +92,7 @@ export type AutocompletePlugin = Override<
|
||||
execute: (
|
||||
autocmp: AutocompleteInteraction,
|
||||
controlller: Controller,
|
||||
) => Awaitable<void | unknown>;
|
||||
) => Awaitable<Result<void, void>>;
|
||||
}
|
||||
>;
|
||||
|
||||
@@ -101,77 +109,74 @@ export type EventPlugin<T extends keyof CommandModuleDefs = keyof CommandModuleD
|
||||
>;
|
||||
}[T];
|
||||
|
||||
// Syntactic sugar on hold
|
||||
// export function plugins<T extends keyof ModuleDefs>(
|
||||
// ...plug: (EventPlugin<T> | CommandPlugin<T>)[]
|
||||
// ) {
|
||||
// return plug;
|
||||
// }
|
||||
export type SernEventPlugin<T extends keyof SernEventsMapping = keyof SernEventsMapping> = Override<
|
||||
BasePlugin,
|
||||
{
|
||||
name?: T;
|
||||
type: PluginType.Event;
|
||||
execute: (
|
||||
args: SernEventsMapping[T],
|
||||
controller: Controller,
|
||||
) => Awaitable<Result<void, void>>;
|
||||
}
|
||||
>;
|
||||
|
||||
export type ModuleNoPlugins = {
|
||||
[T in keyof CommandModuleDefs]: Omit<CommandModuleDefs[T], 'plugins' | 'onEvent'>;
|
||||
export type ExternalEventPlugin = Override<
|
||||
BasePlugin,
|
||||
{
|
||||
type: PluginType.Event;
|
||||
execute: (args: unknown[], controller: Controller) => Awaitable<Result<void, void>>;
|
||||
}
|
||||
>;
|
||||
|
||||
export type DiscordEventPlugin<T extends keyof ClientEvents = keyof ClientEvents> = Override<
|
||||
BasePlugin,
|
||||
{
|
||||
name?: T;
|
||||
type: PluginType.Event;
|
||||
execute: (args: ClientEvents[T], controller: Controller) => Awaitable<Result<void, void>>;
|
||||
}
|
||||
>;
|
||||
|
||||
export type CommandModuleNoPlugins = {
|
||||
[T in CommandType]: Omit<CommandModuleDefs[T], 'plugins' | 'onEvent'>;
|
||||
};
|
||||
export type EventModulesNoPlugins = {
|
||||
[T in EventType]: Omit<EventModuleDefs[T], 'plugins' | 'onEvent'>;
|
||||
};
|
||||
/**
|
||||
* Event Module Event Plugins
|
||||
*/
|
||||
export type EventModuleEventPluginDefs = {
|
||||
[EventType.Discord]: DiscordEventPlugin;
|
||||
[EventType.Sern]: SernEventPlugin;
|
||||
[EventType.External]: ExternalEventPlugin;
|
||||
};
|
||||
|
||||
function isEventPlugin<T extends CommandType>(
|
||||
e: CommandPlugin<T> | EventPlugin<T>,
|
||||
): e is EventPlugin<T> {
|
||||
return e.type === PluginType.Event;
|
||||
}
|
||||
function isCommandPlugin<T extends CommandType>(
|
||||
e: CommandPlugin<T> | EventPlugin<T>,
|
||||
): e is CommandPlugin<T> {
|
||||
return !isEventPlugin(e);
|
||||
}
|
||||
/**
|
||||
* Event Module Command Plugins
|
||||
*/
|
||||
export type EventModuleCommandPluginDefs = {
|
||||
[EventType.Discord]: DiscordEmitterPlugin;
|
||||
[EventType.Sern]: SernEmitterPlugin;
|
||||
[EventType.External]: ExternalEmitterPlugin;
|
||||
};
|
||||
|
||||
export type EventModulePlugin<T extends EventType> =
|
||||
| EventModuleEventPluginDefs[T]
|
||||
| EventModuleCommandPluginDefs[T];
|
||||
|
||||
export type CommandModulePlugin<T extends CommandType> = EventPlugin<T> | CommandPlugin<T>;
|
||||
//TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH
|
||||
// Maybe add overlaods
|
||||
|
||||
export function sernModule<T extends CommandType.Slash = CommandType.Slash>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.Slash],
|
||||
): Module;
|
||||
export function sernModule<T extends CommandType.Text = CommandType.Text>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.Text],
|
||||
): Module;
|
||||
export function sernModule<T extends CommandType.Button = CommandType.Button>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.Button],
|
||||
): Module;
|
||||
export function sernModule<T extends CommandType.Both = CommandType.Both>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.Both],
|
||||
): Module;
|
||||
export function sernModule<T extends CommandType.MenuUser = CommandType.MenuUser>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.MenuMsg],
|
||||
): Module;
|
||||
export function sernModule<T extends CommandType.MenuSelect = CommandType.MenuSelect>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.MenuSelect],
|
||||
): Module;
|
||||
/**
|
||||
* User inputs this type. Sern processes behind the scenes for better usage
|
||||
*/
|
||||
export type InputCommandModule = {
|
||||
[T in CommandType]: CommandModuleNoPlugins[T] & { plugins?: CommandModulePlugin<T>[] };
|
||||
}[CommandType];
|
||||
|
||||
export function sernModule<T extends CommandType.Modal = CommandType.Modal>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.Modal],
|
||||
): Module;
|
||||
|
||||
export function sernModule<T extends CommandType.MenuUser = CommandType.MenuUser>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[CommandType.MenuUser],
|
||||
): Module;
|
||||
export function sernModule<T extends keyof CommandModuleDefs = keyof CommandModuleDefs>(
|
||||
plugin: (CommandPlugin<T> | EventPlugin<T>)[],
|
||||
mod: ModuleNoPlugins[T],
|
||||
): CommandModule {
|
||||
const onEvent = plugin.filter(isEventPlugin);
|
||||
const plugins = plugin.filter(isCommandPlugin);
|
||||
return {
|
||||
onEvent,
|
||||
plugins,
|
||||
...mod,
|
||||
} as CommandModule;
|
||||
}
|
||||
|
||||
export function eventModule<T extends keyof EventModule>(): EventModule {
|
||||
return {} as EventModule;
|
||||
}
|
||||
export type InputEventModule = {
|
||||
[T in EventType]: EventModulesNoPlugins[T] & { plugins?: EventModulePlugin<T>[] };
|
||||
}[EventType];
|
||||
|
||||
@@ -6,6 +6,16 @@ import { Err, Ok } from 'ts-results';
|
||||
import { ExternalEventEmitters } from './utilities/readFile';
|
||||
import type { EventEmitter } from 'events';
|
||||
import { processEvents } from './events/userDefinedEventsHandling';
|
||||
import type { CommandModule, EventModule } from './structures/module';
|
||||
import { EventType, PluginType } from './structures/enums';
|
||||
import type {
|
||||
CommandPlugin,
|
||||
EventModuleCommandPluginDefs,
|
||||
EventModuleEventPluginDefs,
|
||||
EventPlugin,
|
||||
InputCommandModule,
|
||||
InputEventModule,
|
||||
} from './plugins/plugin';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -27,7 +37,7 @@ export function init(wrapper: Wrapper) {
|
||||
* @param emitter Any external event emitter.
|
||||
* The object will be stored in a map, and then fetched by the name of the emitter provided.
|
||||
* As there are infinite possibilities to adding external event emitters,
|
||||
* Most types arent provided and are as narrow as possibly can.
|
||||
* Most types aren't provided and are as narrow as possibly can.
|
||||
*/
|
||||
export function addExternal<T extends EventEmitter>(emitter: T) {
|
||||
if (ExternalEventEmitters.has(emitter.constructor.name)) {
|
||||
@@ -40,3 +50,38 @@ export const controller = {
|
||||
next: () => Ok.EMPTY,
|
||||
stop: () => Err.EMPTY,
|
||||
};
|
||||
|
||||
export function commandModule(mod: InputCommandModule): CommandModule {
|
||||
const onEvent: EventPlugin[] = [];
|
||||
const plugins: CommandPlugin[] = [];
|
||||
for (const pl of mod.plugins ?? []) {
|
||||
if (pl.type === PluginType.Event) {
|
||||
onEvent.push(pl);
|
||||
} else {
|
||||
plugins.push(pl as CommandPlugin);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...mod,
|
||||
onEvent,
|
||||
plugins,
|
||||
} as CommandModule;
|
||||
}
|
||||
export function eventModule(mod: InputEventModule): EventModule {
|
||||
const onEvent: EventModuleEventPluginDefs[EventType][] = [];
|
||||
const plugins: EventModuleCommandPluginDefs[EventType][] = [];
|
||||
for (const pl of mod.plugins ?? []) {
|
||||
if (pl.type === PluginType.Event) {
|
||||
onEvent.push(pl);
|
||||
} else {
|
||||
plugins.push(pl);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...mod,
|
||||
onEvent,
|
||||
plugins,
|
||||
} as EventModule;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Override, SernEventsMapping } from '../../types/handler';
|
||||
import type { BaseModule, EventModuleDefs } from './module';
|
||||
import type { BaseModule } from './module';
|
||||
import type {
|
||||
DiscordEmitterPlugin,
|
||||
DiscordEventPlugin,
|
||||
ExternalEmitterPlugin,
|
||||
ExternalEventPlugin,
|
||||
SernEmitterPlugin,
|
||||
@@ -26,7 +27,7 @@ export type DiscordEventCommand<T extends keyof ClientEvents = keyof ClientEvent
|
||||
{
|
||||
name?: T;
|
||||
type: EventType.Discord;
|
||||
onEvent: DiscordEventCommand[];
|
||||
onEvent: DiscordEventPlugin[];
|
||||
plugins: DiscordEmitterPlugin[];
|
||||
execute(...args: ClientEvents[T]): Awaitable<void | unknown>;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,13 @@ export function isExternalEvent(el: EventModule): el is ExternalEventCommand {
|
||||
return !isDiscordEvent(el) && !isSernEvent(el);
|
||||
}
|
||||
|
||||
export function isEventModule(module: Module): module is EventModule {
|
||||
return [EventType.Sern, EventType.Discord, EventType.External].includes(module.type);
|
||||
}
|
||||
// export function isEventPlugin<T extends CommandType>(
|
||||
// e: CommandModulePlugin<T>,
|
||||
// ): e is EventPlugin<T> {
|
||||
// return e.type === PluginType.Event;
|
||||
// }
|
||||
// export function isCommandPlugin<T extends CommandType>(
|
||||
// e: CommandModulePlugin<T>,
|
||||
// ): e is CommandPlugin<T> {
|
||||
// return !isEventPlugin(e);
|
||||
// }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import SernEmitter from './handler/sernEmitter';
|
||||
export { eventModule, commandModule } from './handler/sern';
|
||||
export * as Sern from './handler/sern';
|
||||
export * from './types/handler';
|
||||
export * from './handler/structures/structxports';
|
||||
|
||||
Reference in New Issue
Block a user