mirror of
https://github.com/sern-handler/handler
synced 2026-06-15 12:22:14 +00:00
feat : partitioning command stores for better event mapping, more
refactoring
This commit is contained in:
@@ -1,19 +1,23 @@
|
||||
|
||||
import type { Interaction } from 'discord.js';
|
||||
import { fromEvent, Observable, of, concatMap } from 'rxjs';
|
||||
import { fromEvent, Observable, of, concatMap, map, tap } from 'rxjs';
|
||||
import { CommandType } from '../sern';
|
||||
import Context from '../structures/context';
|
||||
import type Wrapper from '../structures/wrapper';
|
||||
import * as Files from '../utilities/readFile';
|
||||
import { filterTap } from './observableHandling';
|
||||
|
||||
|
||||
|
||||
|
||||
export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
const { client } = wrapper;
|
||||
|
||||
(<Observable<Interaction>> fromEvent(client, 'interactionCreate'))
|
||||
.pipe(
|
||||
concatMap (async interaction => {
|
||||
interaction.type
|
||||
const interactionEvent = (<Observable<Interaction>> fromEvent(client, 'interactionCreate'))
|
||||
|
||||
interactionEvent.pipe(
|
||||
tap(console.log)
|
||||
).subscribe()
|
||||
/** concatMap (async interaction => {
|
||||
if (interaction.isChatInputCommand()) {
|
||||
return of(Files.Commands.get(interaction.commandName))
|
||||
.pipe(
|
||||
@@ -56,6 +60,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
);
|
||||
}
|
||||
else return of();
|
||||
|
||||
})
|
||||
).subscribe({
|
||||
error(e){
|
||||
@@ -66,5 +71,6 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
|
||||
//console.log(command);
|
||||
},
|
||||
});
|
||||
**/
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Message } from 'discord.js';
|
||||
import { fromEvent, Observable, of, concatMap, map, from, every, concatAll, tap, switchMap } from 'rxjs';
|
||||
import { fromEvent, Observable, of, concatMap, map, from, every, concatAll, tap } from 'rxjs';
|
||||
import { Err, Ok } from 'ts-results';
|
||||
import type { Args } from '../..';
|
||||
import { CommandType } from '../sern';
|
||||
@@ -13,12 +13,13 @@ import { isEventPlugin } from './readyEvent';
|
||||
export const onMessageCreate = (wrapper : Wrapper) => {
|
||||
const { client, defaultPrefix } = wrapper;
|
||||
if (defaultPrefix === undefined) return;
|
||||
|
||||
const messageEvent$ = (<Observable<Message>> fromEvent( client, 'messageCreate'));
|
||||
|
||||
const processMessage$ = messageEvent$.pipe(
|
||||
ignoreNonBot(defaultPrefix),
|
||||
map(message => {
|
||||
const [prefix, ...rest] = fmt(message, defaultPrefix);
|
||||
console.log(prefix, rest)
|
||||
return {
|
||||
ctx : Context.wrap(message),
|
||||
args : <Args>['text', rest],
|
||||
@@ -47,6 +48,7 @@ export const onMessageCreate = (wrapper : Wrapper) => {
|
||||
}));
|
||||
return from(res).pipe(map(res => ({ plugged, ctx, args, res })))
|
||||
}));
|
||||
|
||||
processEventPlugins$.subscribe( ( { plugged, ctx, args, res } ) => {
|
||||
if(res.every( pl => pl.ok)) {
|
||||
Promise.resolve(plugged.mod.execute(ctx, args)).then(() =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Awaitable, Message } from 'discord.js';
|
||||
import type { Awaitable, InteractionType, Message } from 'discord.js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import type { ModuleDefs } from '../structures/modules/commands/moduleHandler';
|
||||
import { SernError } from '../structures/errors';
|
||||
@@ -33,7 +33,8 @@ export function filterCorrectModule<T extends keyof ModuleDefs>(cmdType : T) {
|
||||
});
|
||||
}
|
||||
|
||||
export function filterTap<T extends keyof ModuleDefs>(
|
||||
|
||||
/** export function filterTap<T extends keyof ModuleDefs>(
|
||||
cmdType : T,
|
||||
tap: (mod : ModuleDefs[T], plugins : EventPlugin[]) => Awaitable<void>
|
||||
) {
|
||||
@@ -57,7 +58,7 @@ export function filterTap<T extends keyof ModuleDefs>(
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
**/
|
||||
export function ignoreNonBot(prefix : string) {
|
||||
return (src : Observable<Message>) =>
|
||||
new Observable<Message>(subscriber => {
|
||||
@@ -82,6 +83,7 @@ export function ignoreNonBot(prefix : string) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function partition<T,U extends T>(
|
||||
condition : (el : T) => el is U,
|
||||
array : T[]
|
||||
|
||||
@@ -2,13 +2,15 @@ import {concatMap, from, fromEvent, map, take,concat, skip, Observable, of,
|
||||
import { basename } from 'path';
|
||||
import * as Files from '../utilities/readFile';
|
||||
import type Wrapper from '../structures/wrapper';
|
||||
import type { HandlerCallback, ModuleHandlers, ModuleStates, ModuleType } from '../structures/modules/commands/moduleHandler';
|
||||
import type { ApplicationModules, HandlerCallback, MessageCompModules, ModDefs, ModuleCbs, ModuleHandlers, ModuleStates, ModuleType, StateMachine, TextCommandModules, ModuleHandler } from '../structures/modules/commands/moduleHandler';
|
||||
import { CommandType } from '../sern';
|
||||
import { CommandPlugin, EventPlugin, PluginType, SernPlugin } from '../plugins/plugin';
|
||||
import { partition } from './observableHandling';
|
||||
import { match, partition } from './observableHandling';
|
||||
import { Err, Ok, Result } from 'ts-results';
|
||||
import type { PluggedModule } from '../structures/modules/module';
|
||||
import type { Awaitable } from 'discord.js';
|
||||
import { SernError } from '../structures/errors';
|
||||
import type { ContextMenuMsg, ContextMenuUser, Module, SlashCommand } from '../structures/modules/commands/module';
|
||||
|
||||
export const onReady = ( wrapper : Wrapper ) => {
|
||||
|
||||
@@ -56,54 +58,60 @@ export const onReady = ( wrapper : Wrapper ) => {
|
||||
)
|
||||
),
|
||||
)
|
||||
.subscribe(({ plugged : { mod, plugins }, cmdPluginsRes }) => {
|
||||
registerModule(mod.name!, mod, plugins)
|
||||
.subscribe(({ plugged, cmdPluginsRes }) => {
|
||||
const loadedPluginsCorrectly = cmdPluginsRes.every(res => res.execute.ok);
|
||||
const { mod, plugins } = plugged;
|
||||
if(loadedPluginsCorrectly) {
|
||||
registerModule(mod.name!, mod, plugins);
|
||||
}
|
||||
else {
|
||||
console.log(`Failed to load command ${mod.name!}`)
|
||||
console.log(mod)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Refactor : ? Possibly repetitive and verbose.
|
||||
const handler = ( name : string ) =>
|
||||
({
|
||||
function handler( name : string ) : ModuleHandlers {
|
||||
return {
|
||||
[CommandType.Text] : (mod, plugins) => {
|
||||
mod.alias.forEach ( a => Files.Alias.set(a,{ mod, plugins}));
|
||||
Files.Commands.set( name, { mod, plugins } );
|
||||
Files.ApplicationCommandStore[1].set( name, { mod, plugins } );
|
||||
},
|
||||
[CommandType.Slash]: (mod, plugins) => {
|
||||
Files.Commands.set( name , { mod, plugins });
|
||||
Files.ApplicationCommandStore[1].set( name , { mod, plugins });
|
||||
},
|
||||
[CommandType.Both] :( mod, plugins )=> {
|
||||
Files.Commands.set ( name,{ mod, plugins});
|
||||
Files.ApplicationCommandStore[1].set ( name,{ mod, plugins});
|
||||
mod.alias.forEach (a => Files.Alias.set(a, {mod,plugins}));
|
||||
},
|
||||
[CommandType.MenuUser] : (mod, plugins) => {
|
||||
Files.ContextMenuUser.set ( name, {mod, plugins} );
|
||||
Files.ApplicationCommandStore[2].set ( name, {mod, plugins} );
|
||||
},
|
||||
[CommandType.MenuMsg] : (mod,plugins) => {
|
||||
Files.ContextMenuMsg.set (name, {mod, plugins} );
|
||||
Files.ApplicationCommandStore[3].set (name, {mod, plugins} );
|
||||
},
|
||||
[CommandType.Button] : (mod,plugins) => {
|
||||
Files.Buttons.set(name, {mod, plugins});
|
||||
Files.MessageCompCommandStore[2].set(name, {mod, plugins});
|
||||
},
|
||||
[CommandType.MenuSelect] : ( mod, plugins ) => {
|
||||
Files.SelectMenus.set(name, { mod, plugins });
|
||||
Files.MessageCompCommandStore[2].set(name, { mod, plugins });
|
||||
},
|
||||
} as ModuleHandlers);
|
||||
}
|
||||
|
||||
function registerModule <T extends ModuleType> (
|
||||
name : string,
|
||||
mod : ModuleStates[T],
|
||||
plugins : SernPlugin[]
|
||||
) {
|
||||
return (<HandlerCallback<T>> handler(name)[mod.type])(mod, plugins);
|
||||
}
|
||||
|
||||
|
||||
function isCmdPlugin (p : SernPlugin) : p is CommandPlugin {
|
||||
return (p.type & PluginType.Command) !== 0;
|
||||
}
|
||||
export function isEventPlugin( p : SernPlugin) : p is EventPlugin {
|
||||
return (p.type & PluginType.Event) !== 0;
|
||||
}
|
||||
|
||||
|
||||
function registerModule <T extends ModuleType> (
|
||||
name : string,
|
||||
mod : ModuleStates[T],
|
||||
plugins : SernPlugin[]
|
||||
) {
|
||||
return (<HandlerCallback<T>> handler(name)[mod.type])(mod, plugins);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { EventPlugin, SernPlugin } from '../../../plugins/plugin';
|
||||
import type { SernPlugin } from '../../../plugins/plugin';
|
||||
import { CommandType } from '../../../sern';
|
||||
import type {
|
||||
TextCommand,
|
||||
@@ -21,11 +21,13 @@ export type ModuleDefs = {
|
||||
[CommandType.MenuSelect] : SelectMenuCommand;
|
||||
}
|
||||
|
||||
|
||||
//Keys of ModuleDefs
|
||||
export type ModuleType = keyof ModuleDefs;
|
||||
// The keys mapped to a constructed union with its type
|
||||
export type ModuleStates = {
|
||||
[ K in ModuleType ] : { type : K } & ModuleDefs[K] };
|
||||
[ K in ModuleType ] : { type : K } & ModuleDefs[K]
|
||||
};
|
||||
// A handler callback that is called on each ModuleDef
|
||||
export type HandlerCallback<K extends ModuleType> =
|
||||
( mod: ModuleStates[K], plugins : SernPlugin[] ) => unknown;
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
import { ApplicationCommandType, ComponentType, InteractionType, MessageComponentInteraction, MessageComponentType } from 'discord.js';
|
||||
import { readdirSync, statSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { from, Observable } from 'rxjs';
|
||||
import { SernError } from '../structures/errors';
|
||||
import type { PluggedModule } from '../structures/modules/module';
|
||||
|
||||
//We can look into lazily loading modules once everything is set
|
||||
|
||||
// A little ambigious, but ChatInput map stores text commands also.
|
||||
export const ApplicationCommandStore = {
|
||||
[ApplicationCommandType.User] : new Map<string, PluggedModule>(),
|
||||
[ApplicationCommandType.Message] : new Map<string, PluggedModule>(),
|
||||
[ApplicationCommandType.ChatInput] : new Map<string, PluggedModule>(),
|
||||
} as {[K in ApplicationCommandType] : Map<string, PluggedModule> }
|
||||
|
||||
export const MessageCompCommandStore = {
|
||||
[ComponentType.Button] : new Map<string, PluggedModule>(),
|
||||
[ComponentType.SelectMenu] : new Map<string, PluggedModule>()
|
||||
}
|
||||
export const TextCommandStore = {
|
||||
[420] : new Map<string, PluggedModule>() // Aliases
|
||||
}
|
||||
|
||||
export const Alias = new Map<string, PluggedModule>();
|
||||
|
||||
export const ContextMenuUser = new Map<string, PluggedModule>();
|
||||
export const ContextMenuMsg = new Map<string, PluggedModule>();
|
||||
export const Commands = new Map<string, PluggedModule>();
|
||||
export const Alias = new Map<string, PluggedModule>();
|
||||
export const Buttons = new Map<string, PluggedModule>();
|
||||
export const SelectMenus = new Map<string, PluggedModule>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user