feat : add typings for ctx menus

This commit is contained in:
Jacob Nguyen
2022-03-26 02:34:36 -05:00
parent f8c5bfc6c3
commit b0d4f96900
9 changed files with 72 additions and 46 deletions

View File

@@ -1,9 +1,10 @@
import type { Interaction } from "discord.js";
import { map, filter, fromEvent, Observable, of, tap, concatMap} from "rxjs";
import { None, Some } from "ts-results";
import { CommandType } from "../sern";
import Context from "../structures/context";
import type Wrapper from "../structures/wrapper";
import type { ChatInputCommandInteraction, CommandInteraction, Interaction } from 'discord.js';
import { map, filter, fromEvent, Observable, of, tap, concatMap} from 'rxjs';
import { None, Some } from 'ts-results';
import type { SlashCommand } from '../..';
import { CommandType } from '../sern';
import Context from '../structures/context';
import type Wrapper from '../structures/wrapper';
import * as Files from '../utilities/readFile';
@@ -17,17 +18,22 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
if (interaction.isChatInputCommand()) {
return of(interaction.commandName).pipe(
map ( name => Files.Commands.get(name) ),
filter( mod => mod !== undefined && (mod.type & CommandType.SLASH) != 0),
filter( mod => mod !== undefined
&& (mod.type & CommandType.SLASH) != 0
),
tap ( mod => {
const ctx = new Context(None, Some(interaction));
mod!.execute(ctx, ['slash', interaction.options]);
(mod as SlashCommand)!.execute(ctx, ['slash', interaction.options]);
}),
)
);
}
if (interaction.isContextMenuCommand()) {
return of()
return of();
}
else { return of() }
if (interaction.isMessageContextMenuCommand()) {
return of();
}
else { return of(); }
})
).subscribe({
error(e) {
@@ -39,6 +45,6 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
},
})
}
});
};

View File

@@ -1,11 +1,11 @@
import type { Message } from "discord.js";
import { map, filter, fromEvent, Observable, of, concatMap, tap } from "rxjs";
import { None, Some } from "ts-results";
import { CommandType } from "../sern";
import type { TextCommand } from "../structures/commands/module";
import Context from "../structures/context";
import type Wrapper from "../structures/wrapper";
import { isNotFromDM, isNotFromBot, hasPrefix, fmt } from "../utilities/messageHelpers";
import type { Message } from 'discord.js';
import { map, filter, fromEvent, Observable, of, concatMap, tap } from 'rxjs';
import { None, Some } from 'ts-results';
import { CommandType } from '../sern';
import type { TextCommand } from '../structures/commands/module';
import Context from '../structures/context';
import type Wrapper from '../structures/wrapper';
import { isNotFromDM, isNotFromBot, hasPrefix, fmt } from '../utilities/messageHelpers';
import * as Files from '../utilities/readFile';
export const onMessageCreate = (wrapper : Wrapper) => {
@@ -26,7 +26,7 @@ export const onMessageCreate = (wrapper : Wrapper) => {
),
filter( ([mod]) => mod !== undefined && (mod.type & CommandType.TEXT) != 0 ),
tap ( ([ mod, ctx, args ]) => {
(mod as TextCommand)!.execute(ctx, ['text', args])
(mod as TextCommand)!.execute(ctx, ['text', args]);
}),
)
)
@@ -40,7 +40,7 @@ export const onMessageCreate = (wrapper : Wrapper) => {
//log on each command emitted
console.log(command);
},
})
});
}
};

View File

@@ -1,10 +1,10 @@
import { concatMap, first, from, fromEvent, map, pipe, tap } from "rxjs";
import { concatMap, first, from, fromEvent, pipe, tap } from 'rxjs';
import { basename } from 'path';
import * as Files from '../utilities/readFile';
import type Wrapper from '../structures/wrapper';
import type { Modules } from "../structures/structxports";
import type { HandlerCallback, ModuleHandlers, ModuleStates, ModuleType } from "../structures/commands/moduleHandler";
import { CommandType } from "../sern";
import type { Module } from '../structures/structxports';
import type { HandlerCallback, ModuleHandlers, ModuleStates, ModuleType } from '../structures/commands/moduleHandler';
import { CommandType } from '../sern';
export const onReady = ( wrapper : Wrapper ) => {
const { client, init, commands, } = wrapper;
@@ -25,7 +25,7 @@ export const onReady = ( wrapper : Wrapper ) => {
// log stuff?
}
});
}
};
const handler = ( name : string ) =>
({
@@ -39,19 +39,26 @@ const handler = ( name : string ) =>
[CommandType.BOTH] : mod => {
Files.Commands.set ( name, mod);
mod.alias.forEach (a => Files.Alias.set(a, mod));
},
[CommandType.MENU_USER] : mod => {
Files.Commands.set ( name, mod );
},
[CommandType.MENU_MSG] : mod => {
Files.Commands.set (name, mod );
}
} as ModuleHandlers);
const registerModules = <T extends ModuleType >(name : string, mod : ModuleStates[T]) =>
(handler(name)[mod.type] as HandlerCallback<T>)(mod);
function setCommands ( { mod, absPath } : { mod : Modules.Module, absPath : string } ) {
function setCommands ( { mod, absPath } : { mod : Module, absPath : string } ) {
const name = mod.name ?? Files.fmtFileName(basename(absPath));
registerModules(name, mod);
}
async function createCommandCache(
arr: Promise<{mod: Modules.Module, absPath: string}[]>
arr: Promise<{mod: Module, absPath: string}[]>
) {
from(await arr).subscribe ( setCommands );
}

View File

@@ -112,7 +112,9 @@ export class Handler {
* @enum { number };
*/
export enum CommandType {
TEXT = 0b0001,
SLASH = 0b0010,
BOTH = 0b0011
TEXT = 0b0001,
SLASH = 0b0010,
MENU_USER = 0b0100,
MENU_MSG = 0b1000,
BOTH = 0b0011,
}

View File

@@ -1,7 +1,7 @@
import type { ApplicationCommandOptionData, Awaitable, ChatInputCommandInteraction, Interaction } from "discord.js";
import type { Args, Override } from "../../../types/handler";
import type { CommandType } from "../../sern";
import type Context from "../context";
import type { ApplicationCommandOptionData, Awaitable, ChatInputCommandInteraction, ContextMenuCommandInteraction, Interaction, MessageContextMenuCommandInteraction } from 'discord.js';
import type { Args, Override } from '../../../types/handler';
import type { CommandType } from '../../sern';
import type Context from '../context';
type executeSlash = { execute : (ctx : Context<ChatInputCommandInteraction>, args: Args) => Awaitable<void> };
@@ -26,9 +26,18 @@ export type BothCommand = {
options : ApplicationCommandOptionData[] | [],
} & Override<BaseModule, executeSlash>;
export type ContextMenuUser = {
type : CommandType.MENU_USER;
} & Override<BaseModule, { execute : ( ctx: Context<ContextMenuCommandInteraction> ) => Awaitable<void> }>;
export type ContextMenuMsg = {
type : CommandType.MENU_MSG;
} & Override<BaseModule, { execute : ( ctx: Context<MessageContextMenuCommandInteraction> ) => Awaitable<void> }>;
export type Module =
TextCommand
| SlashCommand
| BothCommand;
| BothCommand
| ContextMenuUser
| ContextMenuMsg;

View File

@@ -1,5 +1,5 @@
import { CommandType } from "../../sern";
import type { TextCommand, BothCommand, SlashCommand, BaseModule } from "./module";
import { CommandType } from '../../sern';
import type { TextCommand, BothCommand, SlashCommand, BaseModule, ContextMenuMsg, ContextMenuUser } from './module';
//https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union
@@ -8,6 +8,8 @@ export type ModuleDefs = {
[CommandType.TEXT] : TextCommand,
[CommandType.SLASH] : SlashCommand,
[CommandType.BOTH] : BothCommand,
[CommandType.MENU_MSG] : ContextMenuMsg,
[CommandType.MENU_USER] : ContextMenuUser
}
//Keys of ModuleDefs

View File

@@ -37,13 +37,13 @@ export default class Context<I extends Interaction = Interaction> {
return firstSome(
this.message.andThen(m => Some(m.channel)),
this.interaction.andThen(i => Some(i.channel))
)
);
}
public get user() {
return firstSome(
this.message.andThen(m => Some(m.author)),
this.interaction.andThen(i => Some(i.user))
)
);
}
}

View File

@@ -39,7 +39,7 @@ export async function buildData(commandDir: string ): Promise<
return Promise.all(
getCommands(commandDir).map( async (absPath) => {
const mod = (await import(absPath)).module as Module;
if (mod === undefined) throw Error(`${SernError.UNDEFINED_MODULE} ${absPath}`)
if (mod === undefined) throw Error(`${SernError.UNDEFINED_MODULE} ${absPath}`);
return { mod, absPath };
}),
);

View File

@@ -7,11 +7,11 @@ import type {
Awaitable,
} from 'discord.js';
import type { Modules } from '../handler/structures/structxports';
import type { Module } from '../handler/structures/structxports';
// Anything that can be sent in a `<TextChannel>#send` or `<CommandInteraction>#reply`
export type possibleOutput<T = string> = T | (MessagePayload & MessageOptions);
export type execute = Modules.Module['execute'];
export type execute = Module['execute'];
// Thanks @cursorsdottsx
export type ParseType<T> = {