import type Wrapper from './structures/wrapper'; import { Err, Ok } from 'ts-results-es'; import { ExternalEventEmitters } from './utilities/readFile'; import type { EventEmitter } from 'events'; import { processEvents } from './events/userDefinedEventsHandling'; import { CommandType, EventType, PluginType } from './structures/enums'; import type { CommandPlugin, EventModuleCommandPluginDefs, EventModuleEventPluginDefs, EventPlugin, InputCommandModule, InputEventModule, } from './plugins/plugin'; import { SernError } from './structures/errors'; import InteractionHandler from './events/interactionHandler'; import ReadyHandler from './events/readyHandler'; import MessageHandler from './events/messageHandler'; import type { CommandModule, EventModule } from '../types/module'; import type { ModuleStore } from './structures/moduleStore'; import type { Client } from 'discord.js'; import type { ModuleConfig, ModuleManagerConstructor } from './contracts/moduleManager'; /** * * @param wrapper Options to pass into sern. * Function to start the handler up * @example * ```ts title="src/index.ts" * Sern.init({ * client, * defaultPrefix: '!', * commands: 'dist/commands', * }) * ``` */ export function init(wrapper: Wrapper) { const { events } = wrapper; if (events !== undefined) { processEvents(wrapper, events); } new ReadyHandler(wrapper); new MessageHandler(wrapper); new InteractionHandler(wrapper); } /** * * @param emitter Any external event emitter. * The object will be stored in a map, and then fetched by the name of the instance's class. * As there are infinite possibilities to adding external event emitters, * Most types aren't provided and are as narrow as possibly can. * @example * ```ts title="src/index.ts" * //Add this before initiating Sern! * Sern.addExternal(new Level()) * ``` * @example * ```ts title="events/level.ts" * export default eventModule({ * emitter: 'Level', * type : EventType.External, * name: 'error', * execute(args) { * console.log(args) * } * }) * ``` */ export function addExternal(emitter: T) { if (ExternalEventEmitters.has(emitter.constructor.name)) { throw Error(`${emitter.constructor.name} already exists!`); } ExternalEventEmitters.set(emitter.constructor.name, emitter); } /** * The object passed into every plugin to control a command's behavior */ export const controller = { next: () => Ok.EMPTY, stop: () => Err.EMPTY, }; /** * The wrapper function to define command modules for sern * @param mod */ 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; } /** * The wrapper function to define event modules for sern * @param mod */ export function eventModule(mod: InputEventModule): EventModule { const onEvent: EventModuleEventPluginDefs[EventType][] = []; const plugins: EventModuleCommandPluginDefs[EventType][] = []; const hasPlugins = mod.plugins && mod.plugins.length > 0; if (hasPlugins) { throw Error( SernError.NotSupportedYet + `: Plugins on event listeners are not supported yet`, ); } return { ...mod, onEvent, plugins, } as EventModule; } export function ModuleConfiguration( moduleManager : ModuleManagerConstructor, moduleStore: T, ) : ModuleConfig { return ( client: Client ) => new moduleManager(client, moduleStore); }