mirror of
https://github.com/sern-handler/handler
synced 2026-06-11 18:32:15 +00:00
feat(handler) : More work toward event plugins, added typings for it
This commit is contained in:
@@ -12,11 +12,12 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
|
||||
(<Observable<Interaction>> fromEvent(client, 'interactionCreate'))
|
||||
.pipe(
|
||||
concatMap ( interaction => {
|
||||
concatMap (async interaction => {
|
||||
interaction.type
|
||||
if (interaction.isChatInputCommand()) {
|
||||
return of(Files.Commands.get(interaction.commandName))
|
||||
.pipe(
|
||||
filterTap(CommandType.Slash, mod => {
|
||||
filterTap(CommandType.Slash, (mod) => {
|
||||
const ctx = Context.wrap(interaction);
|
||||
mod.execute(ctx, ['slash', interaction.options]);
|
||||
}),
|
||||
@@ -25,7 +26,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
if (interaction.isContextMenuCommand()) {
|
||||
return of(Files.ContextMenuUser.get(interaction.commandName))
|
||||
.pipe(
|
||||
filterTap(CommandType.MenuUser, mod => {
|
||||
filterTap(CommandType.MenuUser, (mod) => {
|
||||
mod.execute(interaction);
|
||||
}),
|
||||
);
|
||||
@@ -33,7 +34,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
if (interaction.isMessageContextMenuCommand()) {
|
||||
return of(Files.ContextMenuMsg.get(interaction.commandName))
|
||||
.pipe(
|
||||
filterTap(CommandType.MenuMsg, mod => {
|
||||
filterTap(CommandType.MenuMsg, (mod, plugs) => {
|
||||
mod.execute(interaction);
|
||||
}),
|
||||
);
|
||||
@@ -41,7 +42,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
if (interaction.isButton()) {
|
||||
return of(Files.Buttons.get(interaction.customId))
|
||||
.pipe(
|
||||
filterTap(CommandType.Button, mod => {
|
||||
filterTap(CommandType.Button, (mod, plugs) => {
|
||||
mod.execute(interaction);
|
||||
})
|
||||
);
|
||||
@@ -49,7 +50,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
if (interaction.isSelectMenu()) {
|
||||
return of(Files.SelectMenus.get(interaction.customId))
|
||||
.pipe(
|
||||
filterTap(CommandType.MenuSelect, mod => {
|
||||
filterTap(CommandType.MenuSelect, (mod, plugs) => {
|
||||
mod.execute(interaction);
|
||||
})
|
||||
);
|
||||
@@ -60,9 +61,9 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
error(e){
|
||||
throw e;
|
||||
},
|
||||
next(command) {
|
||||
//log on each command emitted
|
||||
console.log(command);
|
||||
next(_command) {
|
||||
//every command that gets triggered ends up here
|
||||
//console.log(command);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
import type { Message } from 'discord.js';
|
||||
import { fromEvent, Observable, of, concatMap } from 'rxjs';
|
||||
import { fromEvent, Observable, of, concatMap, mergeMap } from 'rxjs';
|
||||
import { Err, Ok } from 'ts-results';
|
||||
import { CommandType } from '../sern';
|
||||
import Context from '../structures/context';
|
||||
import type Wrapper from '../structures/wrapper';
|
||||
import { fmt } from '../utilities/messageHelpers';
|
||||
import * as Files from '../utilities/readFile';
|
||||
import { filterTap, ignoreNonBot } from './observableHandling';
|
||||
import { filterCorrectModule, filterTap, ignoreNonBot } from './observableHandling';
|
||||
|
||||
export const onMessageCreate = (wrapper : Wrapper) => {
|
||||
const { client, defaultPrefix } = wrapper;
|
||||
(<Observable<Message>> fromEvent( client, 'messageCreate'))
|
||||
.pipe (
|
||||
.pipe(
|
||||
ignoreNonBot(defaultPrefix),
|
||||
concatMap ( m => {
|
||||
concatMap (async m => {
|
||||
const [ prefix, ...data ] = fmt(m, defaultPrefix);
|
||||
const posMod = Files.Commands.get(prefix) ?? Files.Alias.get(prefix);
|
||||
|
||||
const ctx = Context.wrap(m);
|
||||
return of( posMod )
|
||||
.pipe (
|
||||
filterTap(CommandType.Text, mod => {
|
||||
const ctx = Context.wrap(m);
|
||||
mod.execute(ctx, ['text', data]);
|
||||
filterCorrectModule(CommandType.Text),
|
||||
filterTap(CommandType.Text, async (mod,plugins) => {
|
||||
const res = await Promise.all(
|
||||
plugins.map(async pl => ({
|
||||
...pl,
|
||||
execute : await pl.execute([ctx, ['text', data] ], {
|
||||
next : () => Ok.EMPTY,
|
||||
stop : () => Err.EMPTY
|
||||
}),
|
||||
}))
|
||||
|
||||
);
|
||||
if (res.every(pl => pl.execute.ok)) {
|
||||
mod.execute(ctx, ['text', data]);
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
).subscribe ({
|
||||
error(e) {
|
||||
//log things
|
||||
throw e;
|
||||
},
|
||||
next(command) {
|
||||
@@ -35,5 +47,4 @@ export const onMessageCreate = (wrapper : Wrapper) => {
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -1,19 +1,39 @@
|
||||
import type { Awaitable, Message } from 'discord.js';
|
||||
import type { CommandType } from '../sern';
|
||||
import type { Module } from '../structures/structxports';
|
||||
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 { PluggedModule } from '../structures/modules/module';
|
||||
import type { SernPlugin } from '../plugins/plugin';
|
||||
import type { EventPlugin, SernPlugin } from '../plugins/plugin';
|
||||
|
||||
export function match(plug: PluggedModule | undefined, type : CommandType) : boolean {
|
||||
return plug !== undefined && (plug.mod.type & type) != 0;
|
||||
}
|
||||
|
||||
export function filterCorrectModule<T extends keyof ModuleDefs>(cmdType : T) {
|
||||
return (src : Observable<PluggedModule|undefined>) =>
|
||||
new Observable<PluggedModule>( subscriber => {
|
||||
return src.subscribe({
|
||||
next(modul) {
|
||||
if(match(modul, cmdType)) {
|
||||
subscriber.next(modul);
|
||||
} else {
|
||||
if (modul === undefined) {
|
||||
return throwError(() => SernError.UndefinedModule);
|
||||
}
|
||||
return throwError(() => SernError.MismatchModule);
|
||||
}
|
||||
},
|
||||
error: (e) => subscriber.error(e),
|
||||
complete: () => subscriber.complete()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function filterTap<T extends keyof ModuleDefs>(
|
||||
cmdType : T,
|
||||
tap: (mod : ModuleDefs[T], plugins : SernPlugin[]) => Awaitable<void>
|
||||
tap: (mod : ModuleDefs[T], plugins : EventPlugin[]) => Awaitable<void>
|
||||
) {
|
||||
return (src : Observable<PluggedModule|undefined>) =>
|
||||
new Observable<PluggedModule|undefined>( subscriber => {
|
||||
@@ -21,7 +41,7 @@ export function filterTap<T extends keyof ModuleDefs>(
|
||||
next(modul) {
|
||||
if(match(modul, cmdType)) {
|
||||
const asModT = <ModuleDefs[T]> modul!.mod;
|
||||
tap(asModT, modul!.plugins);
|
||||
tap(asModT, modul!.plugins as EventPlugin[]);
|
||||
subscriber.next(modul);
|
||||
} else {
|
||||
if (modul === undefined) {
|
||||
@@ -70,3 +90,6 @@ export function partition<T,U extends T,V extends T>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -31,17 +31,18 @@ export const onReady = ( wrapper : Wrapper ) => {
|
||||
})
|
||||
return { res, plugged : <PluggedModule>{ mod, plugins } }
|
||||
})
|
||||
}),
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
(concat(ready$,processCommandFiles$) as Observable<{
|
||||
res : Awaitable<Result<void, void>>, plugged : PluggedModule
|
||||
}>).pipe(
|
||||
mergeMap(async( {res, plugged} ) => ({ res:await res, plugged }) )
|
||||
).subscribe(
|
||||
res : Promise<Result<void, void>>, plugged : PluggedModule
|
||||
}>)
|
||||
.subscribe(
|
||||
|
||||
({ res, plugged: { mod, plugins }}) => {
|
||||
if(res.ok) {
|
||||
res.then( result => {
|
||||
if(result.ok) {
|
||||
console.log(`${mod.name!} has been registered`)
|
||||
registerModule(mod.name!, mod, plugins)
|
||||
} else {
|
||||
// TODO: add event emitter for command failures
|
||||
@@ -49,6 +50,7 @@ export const onReady = ( wrapper : Wrapper ) => {
|
||||
console.log(`Did not register command ${mod.name!}`)
|
||||
console.log(mod);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +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 { CommandType } from "../sern";
|
||||
import type { ModuleDefs } from "../structures/modules/commands/moduleHandler";
|
||||
import type { BaseModule, PluggedModule } from "../structures/modules/module";
|
||||
|
||||
export enum PluginType {
|
||||
@@ -41,9 +43,12 @@ export type CommandPlugin = {
|
||||
) => Awaitable<Result<void,void>>
|
||||
}>;
|
||||
|
||||
export type EventPlugin = {
|
||||
type : PluginType.Event
|
||||
} & BasePlugin;
|
||||
export type EventPlugin<T extends CommandType = 1> = {
|
||||
type : PluginType.Event,
|
||||
modTy : T
|
||||
} & Override<BasePlugin, {
|
||||
execute : ( event : Parameters<ModuleDefs[T]['execute']>, controller: Controller ) => Awaitable<Result<void,void>>
|
||||
} >;
|
||||
|
||||
export type SernPlugin =
|
||||
CommandPlugin
|
||||
|
||||
@@ -5,11 +5,10 @@ import type {
|
||||
import {
|
||||
ApplicationCommandType,
|
||||
Client,
|
||||
MessageType,
|
||||
} from 'discord.js';
|
||||
|
||||
import type Wrapper from './structures/wrapper';
|
||||
import { fromEvent, throwError } from 'rxjs';
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { SernError } from './structures/errors';
|
||||
import { onReady } from './events/readyEvent';
|
||||
import { onMessageCreate } from './events/messageEvent';
|
||||
@@ -31,8 +30,6 @@ function eventObserver(client: Client, events: DiscordEvent[] ) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @enum { number };
|
||||
*/
|
||||
@@ -44,7 +41,6 @@ export enum CommandType {
|
||||
Button = 0b0010000,
|
||||
MenuSelect = 0b0100000,
|
||||
Both = 0b0000011,
|
||||
Auto = 0b1000000
|
||||
}
|
||||
|
||||
export function cmdTypeToDjs(ty: CommandType) {
|
||||
|
||||
Reference in New Issue
Block a user