mirror of
https://github.com/sern-handler/handler
synced 2026-06-28 02:32:15 +00:00
refactor, add cron types, reinstante module loader
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { Result } from 'ts-results-es'
|
||||
|
||||
export * from './operators';
|
||||
export * from './functions';
|
||||
|
||||
export type _Module = {
|
||||
|
||||
@@ -72,8 +72,9 @@ async function composeRoot(
|
||||
//container should have no client or logger yet.
|
||||
const hasLogger = conf.exclude?.has('@sern/logger');
|
||||
if (!hasLogger) {
|
||||
__add_container('@sern/logger', new __Services.DefaultLogging);
|
||||
__add_container('@sern/logger', new __Services.DefaultLogging());
|
||||
}
|
||||
__add_container('@sern/errors', new __Services.DefaultErrorHandling());
|
||||
//Build the container based on the callback provided by the user
|
||||
conf.build(container as Container);
|
||||
|
||||
@@ -97,6 +98,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) {
|
||||
if(includeLogger) {
|
||||
__add_container('@sern/logger', new __Services.DefaultLogging);
|
||||
}
|
||||
__add_container('@sern/errors', new __Services.DefaultErrorHandling());
|
||||
await useContainerRaw().ready();
|
||||
} else {
|
||||
await composeRoot(useContainerRaw(), conf);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import path from 'node:path';
|
||||
import { existsSync } from 'fs';
|
||||
import { readdir } from 'fs/promises';
|
||||
import assert from 'node:assert';
|
||||
|
||||
import * as Id from './id'
|
||||
import type { _Module } from './_internal';
|
||||
|
||||
export const parseCallsite = (site: string) => {
|
||||
const pathobj = path.parse(site.replace(/file:\\?/, "")
|
||||
@@ -27,7 +29,6 @@ export const shouldHandle = (pth: string, filenam: string) => {
|
||||
* commonjs, javascript :
|
||||
* ```js
|
||||
* exports = commandModule({ })
|
||||
*
|
||||
* //or
|
||||
* exports.default = commandModule({ })
|
||||
* ```
|
||||
@@ -37,16 +38,33 @@ export const shouldHandle = (pth: string, filenam: string) => {
|
||||
export async function importModule<T>(absPath: string) {
|
||||
let fileModule = await import(absPath);
|
||||
|
||||
let commandModule = fileModule.default;
|
||||
let commandModule: _Module = fileModule.default;
|
||||
|
||||
assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`);
|
||||
if ('default' in commandModule) {
|
||||
commandModule = commandModule.default;
|
||||
commandModule = commandModule.default as _Module;
|
||||
}
|
||||
const p = path.parse(absPath)
|
||||
commandModule.name ??= p.name; commandModule.description ??= "...";
|
||||
commandModule.meta = {
|
||||
//@ts-ignore
|
||||
id: Id.create(commandModule.name, commandModule.type),
|
||||
absPath,
|
||||
};
|
||||
return { module: commandModule } as T;
|
||||
}
|
||||
|
||||
|
||||
export async function* readRecursive(dir: string): AsyncGenerator<string> {
|
||||
const files = await readdir(dir, { withFileTypes: true, recursive: true });
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(file.path, file.name);
|
||||
if(!file.name.startsWith('!') && !file.isDirectory()) {
|
||||
yield fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const fmtFileName = (fileName: string) => path.parse(fileName).name;
|
||||
|
||||
export const filename = (p: string) => fmtFileName(path.basename(p));
|
||||
|
||||
@@ -7,29 +7,16 @@ import type {
|
||||
} from '../types/core-modules';
|
||||
import { type _Module, partitionPlugins } from './_internal';
|
||||
import type { Awaitable } from '../types/utility';
|
||||
import callsites, { type CallSite } from 'callsites';
|
||||
import * as Files from './module-loading'
|
||||
import * as Id from './id'
|
||||
const get_callsite = (css: CallSite[]) => {
|
||||
return css.map(cs => cs.getFileName()).filter(Boolean)
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.0.0 The wrapper function to define command modules for sern
|
||||
* @param mod
|
||||
*/
|
||||
export function commandModule(mod: InputCommand): _Module {
|
||||
const [onEvent, plugins] = partitionPlugins(mod.plugins);
|
||||
const initCallsite = get_callsite(callsites()).at(-2);
|
||||
if(!initCallsite) throw Error("initCallsite is null");
|
||||
const { name, absPath } = Files.parseCallsite(initCallsite);
|
||||
mod.name ??= name; mod.description ??= '...'
|
||||
//@ts-ignore
|
||||
return {
|
||||
...mod,
|
||||
meta: {
|
||||
id: Id.create(mod.name, mod.type),
|
||||
absPath
|
||||
},
|
||||
onEvent,
|
||||
plugins,
|
||||
};
|
||||
@@ -41,17 +28,10 @@ export function commandModule(mod: InputCommand): _Module {
|
||||
*/
|
||||
export function eventModule(mod: InputEvent): _Module {
|
||||
const [onEvent, plugins] = partitionPlugins(mod.plugins);
|
||||
const initCallsite = get_callsite(callsites()).at(-2);
|
||||
if(!initCallsite) throw Error("initCallsite is null");
|
||||
const { name, absPath } = Files.parseCallsite(initCallsite);
|
||||
mod.name ??= name; mod.description ??= '...'
|
||||
|
||||
//@ts-ignore
|
||||
return {
|
||||
...mod,
|
||||
meta: {
|
||||
id: Id.create(mod.name, mod.type),
|
||||
absPath
|
||||
},
|
||||
plugins,
|
||||
onEvent,
|
||||
};
|
||||
|
||||
@@ -48,16 +48,17 @@ export enum EventType {
|
||||
/**
|
||||
* The EventType for handling discord events
|
||||
*/
|
||||
Discord = 1,
|
||||
Discord,
|
||||
/**
|
||||
* The EventType for handling sern events
|
||||
*/
|
||||
Sern = 2,
|
||||
Sern,
|
||||
/**
|
||||
* The EventType for handling external events.
|
||||
* Could be for example, `process` events, database events
|
||||
*/
|
||||
External = 3,
|
||||
External,
|
||||
Cron
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,13 +14,8 @@ import {
|
||||
pipe
|
||||
} from 'rxjs';
|
||||
import {
|
||||
callPlugin,
|
||||
everyPluginOk,
|
||||
filterMapTo,
|
||||
handleError,
|
||||
type VoidResult,
|
||||
resultPayload,
|
||||
arrayifySource,
|
||||
isAutocomplete,
|
||||
treeSearch,
|
||||
_Module,
|
||||
@@ -39,6 +34,7 @@ import { CommandType } from '../core/structures/enums'
|
||||
import type { Args } from '../types/utility';
|
||||
import { inspect } from 'node:util'
|
||||
import { disposeAll } from '../core/ioc/base';
|
||||
import { arrayifySource, callPlugin, everyPluginOk, filterMapTo, handleError } from '../core/operators';
|
||||
|
||||
|
||||
function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import type { Interaction } from 'discord.js';
|
||||
import { mergeMap, merge, concatMap } from 'rxjs';
|
||||
import { PayloadType } from '../core/structures/enums';
|
||||
import { filterTap } from '../core/operators'
|
||||
import { filterTap, sharedEventStream } from '../core/operators'
|
||||
import {
|
||||
isAutocomplete,
|
||||
isCommand,
|
||||
isMessageComponent,
|
||||
isModal,
|
||||
sharedEventStream,
|
||||
resultPayload,
|
||||
} from '../core/_internal';
|
||||
import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils';
|
||||
@@ -19,7 +18,7 @@ export function interactionHandler([emitter, err, log, client]: DependencyList)
|
||||
const handle = createInteractionHandler(interactionStream$, modules);
|
||||
|
||||
const interactionHandler$ = merge(handle(isMessageComponent),
|
||||
handle(isAutocomplete),
|
||||
handle(isAutocomplete),
|
||||
handle(isCommand),
|
||||
handle(isModal));
|
||||
return interactionHandler$
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { EMPTY, mergeMap, concatMap } from 'rxjs';
|
||||
import type { Message } from 'discord.js';
|
||||
import { sharedEventStream } from '../core/_internal';
|
||||
import type { DependencyList } from '../types/ioc';
|
||||
import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils';
|
||||
import { PayloadType, SernError } from '../core/structures/enums'
|
||||
import { resultPayload } from '../core/functions'
|
||||
import { filterTap } from '../core/operators'
|
||||
import { filterTap, sharedEventStream } from '../core/operators'
|
||||
|
||||
/**
|
||||
* Ignores messages from any person / bot except itself
|
||||
* @param prefix
|
||||
@@ -16,7 +16,7 @@ function isNonBot(prefix: string) {
|
||||
|
||||
function hasPrefix(prefix: string, content: string) {
|
||||
const prefixInContent = content.slice(0, prefix.length);
|
||||
return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent', }) === 0);
|
||||
return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0);
|
||||
}
|
||||
|
||||
export function messageHandler(
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs';
|
||||
import { concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs';
|
||||
import { _Module } from '../core/_internal';
|
||||
import { Logging } from '../core/interfaces';
|
||||
import type { DependencyList } from '../types/ioc';
|
||||
import { callInitPlugins } from './event-utils';
|
||||
|
||||
const once = (log: Logging | undefined) => pipe(
|
||||
tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }),
|
||||
first(),
|
||||
ignoreElements())
|
||||
const once = (log: Logging | undefined) =>
|
||||
pipe(tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }),
|
||||
first(),
|
||||
ignoreElements())
|
||||
|
||||
export function readyHandler(
|
||||
[sEmitter, , log, client]: DependencyList,
|
||||
@@ -15,7 +15,8 @@ export function readyHandler(
|
||||
//Todo: add module manager on on ready
|
||||
const ready$ = fromEvent(client!, 'ready').pipe(once(log));
|
||||
|
||||
return concat(ready$).pipe(callInitPlugins(sEmitter)).subscribe()
|
||||
return concat(ready$).pipe(callInitPlugins(sEmitter)).subscribe();
|
||||
|
||||
// const validModuleType = module.type >= 0 && module.type <= 1 << 10;
|
||||
// assert.ok(validModuleType,
|
||||
// `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`);
|
||||
|
||||
@@ -27,8 +27,7 @@ interface Wrapper {
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export function init(wrapper?: Wrapper) {
|
||||
wrapper ??= { commands: "./dist/commands", events: "./dist/events" };
|
||||
export function init(wrapper: Wrapper = { commands: "./dist/commands", events: "./dist/events" }) {
|
||||
const startTime = performance.now();
|
||||
const dependencies = Services('@sern/emitter',
|
||||
'@sern/errors',
|
||||
@@ -52,7 +51,7 @@ export function init(wrapper?: Wrapper) {
|
||||
logger?.info({ message: `sern: registered in ${time} s`, });
|
||||
if(presencePath.exists) {
|
||||
const setPresence = async (p: any) => {
|
||||
return (dependencies[4] as Client).user?.setPresence(p);
|
||||
return (dependencies[3] as Client).user?.setPresence(p);
|
||||
}
|
||||
presenceHandler(presencePath.path, setPresence).subscribe();
|
||||
}
|
||||
|
||||
@@ -163,6 +163,8 @@ export interface EventModuleDefs {
|
||||
[EventType.Sern]: SernEventCommand;
|
||||
[EventType.Discord]: DiscordEventCommand;
|
||||
[EventType.External]: ExternalEventCommand;
|
||||
//TODO
|
||||
[EventType.Cron]: ExternalEventCommand;
|
||||
}
|
||||
|
||||
export interface SernAutocompleteData
|
||||
|
||||
@@ -150,4 +150,8 @@ interface EventArgsMatrix {
|
||||
[PluginType.Control]: unknown[];
|
||||
[PluginType.Init]: [InitArgs<Processed<ExternalEventCommand>>];
|
||||
};
|
||||
[EventType.Cron]: {
|
||||
[PluginType.Control]: unknown[];
|
||||
[PluginType.Init]: [InitArgs<Processed<ExternalEventCommand>>];
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user