Files
handler/src/commands.ts
Jacob Nguyen 43181bf916 style: pretty
2023-05-06 02:04:00 -05:00

93 lines
2.7 KiB
TypeScript

import { ClientEvents } from 'discord.js';
import { CommandType, EventType, PluginType } from './core/structures';
import { AnyEventPlugin, Plugin } from './types/plugin';
import { CommandModule, EventModule, InputCommand, InputEvent } from './types/module';
import { partition } from './core/functions';
import { filename, filePath } from './core/module-loading';
import { Awaitable } from './types/handler';
export const sernMeta = Symbol('@sern/meta');
const appBitField = 0b000000011111;
/*
* Generates a number based on CommandType.
* This corresponds to an ApplicationCommandType or ComponentType
* TextCommands are 0 as they aren't either or.
*/
function apiType(t: CommandType) {
if (t === CommandType.Both || t === CommandType.Modal) return 1;
const log = Math.log2(t);
return (appBitField & t) !== 0 ? log : log - 2;
}
/*
* Generates an id based on CommandType.
* A is for any ApplicationCommand. C is for any ComponentCommand
* Then, another number generated by apiType function is appended
*/
function uniqueId(t: CommandType) {
const am = (appBitField & t) !== 0 ? 'A' : 'C';
return am + apiType(t);
}
/**
* @since 1.0.0 The wrapper function to define command modules for sern
* @param mod
*/
export function commandModule(mod: InputCommand): CommandModule {
const [onEvent, plugins] = partition(
mod.plugins ?? [],
el => (el as Plugin).type === PluginType.Control,
);
const fullPath = filePath();
const name = mod.name ?? filename(fullPath);
return {
...mod,
description: mod.description ?? '...',
name,
onEvent,
plugins,
[sernMeta]: {
id: `${name}__${uniqueId(mod.type)}`,
fullPath,
},
} as CommandModule;
}
/**
* @since 1.0.0
* The wrapper function to define event modules for sern
* @param mod
*/
export function eventModule(mod: InputEvent): EventModule {
const [onEvent, plugins] = partition(
mod.plugins ?? [],
el => (el as Plugin).type === PluginType.Control,
);
const fullPath = filePath();
return {
name: mod.name ?? filename(fullPath),
onEvent,
plugins,
[sernMeta]: {
id: 'no-id',
fullPath,
},
...mod,
} as EventModule;
}
/** Create event modules from discord.js client events,
* This is an {@link eventModule} for discord events,
* where typings can be very bad.
* @Experimental
* @param mod
*/
export function discordEvent<T extends keyof ClientEvents>(mod: {
name: T;
plugins?: AnyEventPlugin[];
execute: (...args: ClientEvents[T]) => Awaitable<unknown>;
}) {
return eventModule({
type: EventType.Discord,
...mod,
});
}