style: Run prettier

This commit is contained in:
Jacob Nguyen
2022-05-19 22:54:46 -05:00
parent 3f64a8aa0a
commit 2d28800953
14 changed files with 154 additions and 126 deletions

View File

@@ -1,9 +1,4 @@
import type {
CommandInteraction,
Interaction,
MessageComponentInteraction,
SelectMenuInteraction,
} from 'discord.js';
import type { CommandInteraction, Interaction, MessageComponentInteraction, SelectMenuInteraction } from 'discord.js';
import { concatMap, fromEvent, map, Observable, of, throwError } from 'rxjs';
import type Wrapper from '../structures/wrapper';
import * as Files from '../utilities/readFile';
@@ -15,7 +10,8 @@ import type { Module } from '../structures/module';
import {
isButton,
isChatInputCommand,
isMessageCtxMenuCmd, isPromise,
isMessageCtxMenuCmd,
isPromise,
isSelectMenu,
isUserContextMenuCmd,
} from '../utilities/predicates';
@@ -24,34 +20,42 @@ import { CommandType } from '../structures/enums';
import type { Result } from 'ts-results';
function applicationCommandHandler(mod: Module | undefined, interaction: CommandInteraction) {
const mod$ = <T extends CommandType>(cmdTy : T) => of(mod).pipe(
filterCorrectModule(cmdTy)
const mod$ = <T extends CommandType>(cmdTy: T) => of(mod).pipe(
filterCorrectModule(cmdTy),
);
return match(interaction)
.when(isChatInputCommand, i => {
const ctx = Context.wrap(i);
//SUPPORT COMMANDTYPE.BOTH
return mod$(CommandType.Slash).pipe(
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx, ['slash', i.options]],
controller
)) ?? []).pipe(map(res => ({ mod, res, execute() { return m.execute(ctx, ['slash', i.options]); } }) ));
}),
);
const ctx = Context.wrap(i);
//SUPPORT COMMANDTYPE.BOTH
return mod$(CommandType.Slash).pipe(
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx, ['slash', i.options]],
controller,
)) ?? []).pipe(map(res => ({
mod, res, execute() {
return m.execute(ctx, ['slash', i.options]);
},
})));
}),
);
},
)
//Todo: refactor so that we dont have to have two separate branches. They're near identical!!
//Only thing that differs is type of interaction
.when(isMessageCtxMenuCmd, ctx => {
return mod$(CommandType.MenuMsg).pipe(
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx],
controller
)) ?? []).pipe(map(res => ({ mod, res, execute() { return m.execute(ctx); } }) ));
}),
);
return mod$(CommandType.MenuMsg).pipe(
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx],
controller,
)) ?? []).pipe(map(res => ({
mod, res, execute() {
return m.execute(ctx);
},
})));
}),
);
},
)
.when(isUserContextMenuCmd, ctx => {
@@ -59,8 +63,12 @@ function applicationCommandHandler(mod: Module | undefined, interaction: Command
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx],
controller
)) ?? []).pipe(map(res => ({ mod, res, execute() { return m.execute(ctx); } }) ));
controller,
)) ?? []).pipe(map(res => ({
mod, res, execute() {
return m.execute(ctx);
},
})));
}),
);
})
@@ -72,7 +80,7 @@ function messageComponentInteractionHandler(
interaction: MessageComponentInteraction,
) {
const mod$ = <T extends CommandType>(ty : T) => of(mod).pipe( filterCorrectModule(ty));
const mod$ = <T extends CommandType>(ty: T) => of(mod).pipe(filterCorrectModule(ty));
//Todo: refactor so that we dont have to have two separate branches. They're near identical!!
//Only thing that differs is type of interaction
return match(interaction)
@@ -81,25 +89,33 @@ function messageComponentInteractionHandler(
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx],
controller
)) ?? []).pipe(map(res => ({ mod, res, execute() { return m.execute(ctx); } }) ));
controller,
)) ?? []).pipe(map(res => ({
mod, res, execute() {
return m.execute(ctx);
},
})));
}),
);
})
.when(isSelectMenu, (ctx: SelectMenuInteraction) => {
return mod$(CommandType.MenuSelect).pipe(
return mod$(CommandType.MenuSelect).pipe(
concatMap(m => {
return of(m.onEvent?.map(e => e.execute(
[ctx],
controller
)) ?? []).pipe(map(res => ({ mod, res, execute() { return m.execute(ctx); } }) ));
controller,
)) ?? []).pipe(map(res => ({
mod, res, execute() {
return m.execute(ctx);
},
})));
}),
);
})
.otherwise(() => throwError(() => SernError.NotSupportedInteraction));
}
export function onInteractionCreate (wrapper: Wrapper) {
export function onInteractionCreate(wrapper: Wrapper) {
const { client } = wrapper;
const interactionEvent$ = <Observable<Interaction>>fromEvent(client, 'interactionCreate');
@@ -122,23 +138,27 @@ export function onInteractionCreate (wrapper: Wrapper) {
} else return throwError(() => SernError.NotSupportedInteraction);
}),
).subscribe({
async next({ mod, res : eventPluginRes, execute}) {
const ePlugArr : Result<void, void>[] = [];
for await ( const res of eventPluginRes) {
if(isPromise(res)) {
ePlugArr.push(res);
}
ePlugArr.push(res as Awaited<Result<void, void>>);
async next({ mod, res: eventPluginRes, execute }) {
const ePlugArr: Result<void, void>[] = [];
for await (const res of eventPluginRes) {
if (isPromise(res)) {
ePlugArr.push(res);
}
if(ePlugArr.every(e => e.ok)) {
await execute();
wrapper.sernEmitter?.emit('module.activate', { success: true, module: mod! });
} else {
wrapper.sernEmitter?.emit('module.activate', { success: false, module: mod!, reason : SernError.PluginFailure });
}
},
error(err) {
wrapper.sernEmitter?.emit('error', err);
ePlugArr.push(res as Awaited<Result<void, void>>);
}
});
if (ePlugArr.every(e => e.ok)) {
await execute();
wrapper.sernEmitter?.emit('module.activate', { success: true, module: mod! });
} else {
wrapper.sernEmitter?.emit('module.activate', {
success: false,
module: mod!,
reason: SernError.PluginFailure,
});
}
},
error(err) {
wrapper.sernEmitter?.emit('error', err);
},
});
}

View File

@@ -1,6 +1,5 @@
import type { Message } from 'discord.js';
import { concatMap, filter, from, fromEvent, map, Observable, of } from 'rxjs';
import { Err } from 'ts-results';
import { concatMap, from, fromEvent, map, Observable, of } from 'rxjs';
import type { Args } from '../..';
import { controller } from '../sern';
import Context from '../structures/context';
@@ -52,17 +51,21 @@ export const onMessageCreate = (wrapper: Wrapper) => {
);
processEventPlugins$.subscribe({
next({ mod, ctx, args, res }) {
next({ mod, ctx, args, res }) {
if (res.every(pl => pl.ok)) {
Promise.resolve(mod.execute(ctx, args)).then(() => {
wrapper.sernEmitter?.emit('module.activate', { success: true, module: mod! });
});
} else {
wrapper.sernEmitter?.emit('module.activate', { success: false, module: mod!, reason: SernError.PluginFailure });
}
},
error(e) {
wrapper.sernEmitter?.emit('error', e);
});
} else {
wrapper.sernEmitter?.emit('module.activate', {
success: false,
module: mod!,
reason: SernError.PluginFailure,
});
}
});
};
},
error(e) {
wrapper.sernEmitter?.emit('error', e);
},
});
};

View File

@@ -6,7 +6,7 @@ import type { Module, ModuleDefs } from '../structures/module';
import { correctModuleType } from '../utilities/predicates';
export function filterCorrectModule<T extends keyof ModuleDefs>(cmdType: T) {
return (src: Observable<Module|undefined>) =>
return (src: Observable<Module | undefined>) =>
new Observable<ModuleDefs[T]>(subscriber => {
return src.subscribe({
next(mod) {

View File

@@ -4,11 +4,11 @@ import * as Files from '../utilities/readFile';
import type Wrapper from '../structures/wrapper';
import { controller } from '../sern';
import type { Result } from 'ts-results';
import { Err, Ok } from 'ts-results';
import type { Awaitable } from 'discord.js';
import { ApplicationCommandType, ComponentType } from 'discord.js';
import type { Module } from '../structures/module';
import { match } from 'ts-pattern';
import { ApplicationCommandType, ComponentType } from 'discord.js';
import { Err, Ok } from 'ts-results';
import { SernError } from '../structures/errors';
import type { DefinitelyDefined } from '../../types/handler';
import { CommandType, PluginType } from '../structures/enums';
@@ -40,7 +40,7 @@ export const onReady = (wrapper: Wrapper) => {
(
concat(ready$, processPlugins$) as Observable<{
mod: DefinitelyDefined<Module, { name : string }>;
mod: DefinitelyDefined<Module, { name: string }>;
cmdPluginsRes: {
execute: Awaitable<Result<void, void>>;
type: PluginType.Command;
@@ -60,17 +60,21 @@ export const onReady = (wrapper: Wrapper) => {
const loadedPluginsCorrectly = cmdPluginsRes.every(res => res.execute.ok);
if (loadedPluginsCorrectly) {
const res = registerModule(mod);
if(res.err) {
if (res.err) {
throw Error(SernError.NonValidModuleType);
}
wrapper.sernEmitter?.emit('module.register', { success : true, module : mod } );
wrapper.sernEmitter?.emit('module.register', { success: true, module: mod });
} else {
wrapper.sernEmitter?.emit('module.register', { success : false, module : mod, reason : SernError.PluginFailure } );
wrapper.sernEmitter?.emit('module.register', {
success: false,
module: mod,
reason: SernError.PluginFailure,
});
}
});
};
function registerModule(mod: DefinitelyDefined<Module, { name: string }>) : Result<void, void> {
function registerModule(mod: DefinitelyDefined<Module, { name: string }>): Result<void, void> {
const name = mod.name;
return match<Module>(mod)
.with({ type: CommandType.Text }, mod => {

View File

@@ -17,7 +17,6 @@ import type { Module, Override } from '../..';
import type { BaseModule, ModuleDefs } from '../structures/module';
import type { PluginType } from '../structures/enums';
import type { ValueOf } from 'ts-pattern/dist/types/helpers';
import type { CommandType } from '../..';
export interface Controller {
@@ -26,7 +25,7 @@ export interface Controller {
}
type BasePlugin = Override<BaseModule, {
type : PluginType,
type: PluginType,
}>;
export type CommandPlugin = Override<BasePlugin, {
@@ -41,22 +40,23 @@ export type EventPlugin<T extends keyof ModuleDefs> = Override<BasePlugin, {
execute: (event: Parameters<ModuleDefs[T]['execute']>, controller: Controller) => Awaitable<Result<void, void>>;
}>;
export function plugins(...plug: CommandPlugin[]) : CommandPlugin[];
export function plugins<T extends keyof ModuleDefs>(...plug: EventPlugin<T>[]) : EventPlugin<T>[];
export function plugins(...plug: CommandPlugin[]): CommandPlugin[];
export function plugins<T extends keyof ModuleDefs>(...plug: EventPlugin<T>[]): EventPlugin<T>[];
export function plugins<T extends keyof ModuleDefs>(...plug: EventPlugin<T>[] | CommandPlugin[]) {
return plug;
}
type ModuleNoPlugins = ValueOf<{
[T in keyof ModuleDefs] : Omit<ModuleDefs[T], 'plugins'>
[T in keyof ModuleDefs]: Omit<ModuleDefs[T], 'plugins'>
}>
//TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH
export function sernModule(
plugins: (CommandPlugin)[], mod : ModuleNoPlugins
) : Module {
plugins: (CommandPlugin)[], mod: ModuleNoPlugins,
): Module {
return {
plugins,
...mod
...mod,
};
}

View File

@@ -15,9 +15,9 @@ import { isDiscordEvent } from './utilities/predicates';
export function init(wrapper: Wrapper) {
const { events, client } = wrapper;
if (events !== undefined) {
eventObserver(client, events);
}
if (events !== undefined) {
eventObserver(client, events);
}
onReady(wrapper);
onMessageCreate(wrapper);
onInteractionCreate(wrapper);
@@ -25,10 +25,10 @@ export function init(wrapper: Wrapper) {
function eventObserver(client: Client, events: (DiscordEvent | EventEmitterRegister)[]) {
events.forEach((event) => {
if(isDiscordEvent(event)) {
fromEvent(client, event[0], event[1]).subscribe();
if (isDiscordEvent(event)) {
fromEvent(client, event[0], event[1]).subscribe();
} else {
fromEvent(event[0], event[1], event[2]).subscribe();
fromEvent(event[0], event[1], event[2]).subscribe();
}
});
}

View File

@@ -1,27 +1,28 @@
import { EventEmitter } from 'events';
import type { Module } from './structures/module';
import type { Err } from 'ts-results';
type Payload =
{ success : true, module : Module }
| { success : false, module: Module | undefined, reason : string | Error }
{ success: true, module: Module }
| { success: false, module: Module | undefined, reason: string | Error }
type SernEventsMapping = {
['module.register'] : [ Payload ];
['module.activate'] : [ Payload ];
['error'] : [ Error | string ];
['module.register']: [Payload];
['module.activate']: [Payload];
['error']: [Error | string];
}
export default class SernEmitter extends EventEmitter {
public override on<T extends keyof SernEventsMapping>(eventName: T, listener: (...args: SernEventsMapping[T][]) => void): this {
return super.on(eventName,listener);
return super.on(eventName, listener);
}
public override once<T extends keyof SernEventsMapping>(eventName: T, listener: (...args: SernEventsMapping[T][]) => void): this {
return super.once(eventName,listener);
return super.once(eventName, listener);
}
public override emit<T extends keyof SernEventsMapping>(eventName: T, ...args : SernEventsMapping[T]): boolean {
return super.emit(eventName, ...args);
public override emit<T extends keyof SernEventsMapping>(eventName: T, ...args: SernEventsMapping[T]): boolean {
return super.emit(eventName, ...args);
}
}

View File

@@ -33,17 +33,6 @@ export default class Context {
this.oInterac = oInterac;
}
static wrap(wrappable: ChatInputCommandInteraction | Message): Context {
if ('token' in wrappable) {
return new Context(None, Some(wrappable));
}
return new Context(Some(wrappable), None);
}
public isEmpty() {
return this.oMsg.none && this.oInterac.none;
}
public get message() {
return this.oMsg.unwrap();
}
@@ -104,6 +93,17 @@ export default class Context {
);
}
static wrap(wrappable: ChatInputCommandInteraction | Message): Context {
if ('token' in wrappable) {
return new Context(None, Some(wrappable));
}
return new Context(Some(wrappable), None);
}
public isEmpty() {
return this.oMsg.none && this.oInterac.none;
}
/*
* Returns the underlying Context but allows for doing other operations
*/

View File

@@ -6,14 +6,13 @@ import type {
SelectMenuInteraction,
UserContextMenuCommandInteraction,
} from 'discord.js';
import type { Override } from '../../types/handler';
import type { Args } from '../../types/handler';
import type { Args, Override } from '../../types/handler';
import type { CommandPlugin, EventPlugin } from '../plugins/plugin';
import type Context from './context';
import { CommandType, PluginType } from './enums';
export interface BaseModule {
type : CommandType | PluginType
type: CommandType | PluginType;
name?: string;
description: string;
execute: (ctx: Context, args: Args) => Awaitable<void>;
@@ -56,7 +55,7 @@ export type ContextMenuMsg = Override<BaseModule, {
execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable<void>
}>;
export type ButtonCommand = Override<BaseModule,{
export type ButtonCommand = Override<BaseModule, {
type: CommandType.Button;
onEvent?: EventPlugin<CommandType.Button>[];
plugins?: CommandPlugin[];

View File

@@ -1,5 +1,6 @@
import Context from './context';
import type { BothCommand, Module, SlashCommand, TextCommand } from './module';
import type Wrapper from './wrapper';
export * from './enums';
export { Context, SlashCommand, TextCommand, BothCommand, Module, Wrapper };

View File

@@ -12,7 +12,7 @@ import type SernEmitter from '../sernEmitter';
*/
interface Wrapper {
readonly client: Client;
readonly sernEmitter? : SernEmitter
readonly sernEmitter?: SernEmitter;
readonly defaultPrefix?: string;
readonly commands: string;
readonly events?: (DiscordEvent | EventEmitterRegister)[];

View File

@@ -270,6 +270,10 @@ class FormatInner {
this.raw = raw;
}
static wrap(raw: string, what: string) {
return `${what}${raw}${what}`;
}
toString() {
return this.raw;
}
@@ -328,10 +332,6 @@ class FormatInner {
const ret = this.static.wrap(escaped, Strings[key]);
return new this.static(ret);
}
static wrap(raw: string, what: string) {
return `${what}${raw}${what}`;
}
}
/**

View File

@@ -12,7 +12,6 @@ import type {
import type { DiscordEvent, EventEmitterRegister } from '../..';
export function correctModuleType<T extends keyof ModuleDefs>(
plug: Module | undefined,
type: T,
@@ -24,26 +23,28 @@ export function isChatInputCommand(i: CommandInteraction): i is ChatInputCommand
return i.isChatInputCommand();
}
export function isButton(i : MessageComponentInteraction) : i is ButtonInteraction {
export function isButton(i: MessageComponentInteraction): i is ButtonInteraction {
return i.isButton();
}
export function isSelectMenu(i : MessageComponentInteraction) : i is SelectMenuInteraction {
export function isSelectMenu(i: MessageComponentInteraction): i is SelectMenuInteraction {
return i.isSelectMenu();
}
export function isMessageCtxMenuCmd(i : CommandInteraction) : i is MessageContextMenuCommandInteraction {
export function isMessageCtxMenuCmd(i: CommandInteraction): i is MessageContextMenuCommandInteraction {
return i.isMessageContextMenuCommand();
}
export function isUserContextMenuCmd(i : CommandInteraction) : i is UserContextMenuCommandInteraction {
export function isUserContextMenuCmd(i: CommandInteraction): i is UserContextMenuCommandInteraction {
return i.isUserContextMenuCommand();
}
export function isPromise<T>(promiseLike : Awaitable<T>) : promiseLike is Promise<T> {
export function isPromise<T>(promiseLike: Awaitable<T>): promiseLike is Promise<T> {
const keys = new Set(Object.keys(promiseLike));
return keys.has('then') && keys.has('catch');
}
export function isDiscordEvent(el : DiscordEvent | EventEmitterRegister) : el is DiscordEvent {
export function isDiscordEvent(el: DiscordEvent | EventEmitterRegister): el is DiscordEvent {
return el.length === 2;
}

View File

@@ -17,8 +17,7 @@ export type ParseType<T> = {
export type Args = ParseType<{ text: string[]; slash: SlashOptions }>;
export type DiscordEvent = ParseType<{ [K in keyof ClientEvents]: (...args: ClientEvents[K]) => Awaitable<void> }>;
export type EventEmitterRegister = [ emitter: EventEmitter, k : string, cb : (...args: unknown[]) => Awaitable<void>];
export type EventEmitterRegister = [emitter: EventEmitter, k: string, cb: (...args: unknown[]) => Awaitable<void>];
export type SlashOptions = Omit<CommandInteractionOptionResolver, 'getMessage' | 'getFocused'>;