feat: Finishing up autocomplete, need to test

This commit is contained in:
Jacob Nguyen
2022-05-22 18:54:20 -05:00
parent 77856ce5d0
commit d50b8013ee
4 changed files with 100 additions and 33 deletions

View File

@@ -12,7 +12,7 @@ import { match } from 'ts-pattern';
import { SernError } from '../structures/errors';
import Context from '../structures/context';
import { controller } from '../sern';
import type { Module } from '../structures/module';
import type { AutocompleteCommand, Module, SlashCommand } from '../structures/module';
import {
isButton,
isChatInputCommand,
@@ -24,6 +24,7 @@ import {
import { filterCorrectModule } from './observableHandling';
import { CommandType } from '../structures/enums';
import type { Result } from 'ts-results';
import type { AutocompleteInteraction } from 'discord.js';
function applicationCommandHandler(mod: Module | undefined, interaction: CommandInteraction) {
const mod$ = <T extends CommandType>(cmdTy: T) => of(mod).pipe(filterCorrectModule(cmdTy));
@@ -126,21 +127,53 @@ function messageComponentInteractionHandler(
.otherwise(() => throwError(() => SernError.NotSupportedInteraction));
}
function modalHandler(modul : Module|undefined, ctx: ModalSubmitInteraction) {
return of(modul).pipe(
filterCorrectModule(CommandType.Modal),
concatMap(mod => {
return of(mod.onEvent?.map(e => e.execute([ctx], controller)) ?? []).pipe(
map(res => ({
mod,
res,
execute() {
return mod.execute(ctx);
},
})),
);
})
)
function modalHandler(modul: Module | undefined, ctx: ModalSubmitInteraction) {
return of(modul).pipe(
filterCorrectModule(CommandType.Modal),
concatMap(mod => {
return of(mod.onEvent?.map(e => e.execute([ctx], controller)) ?? []).pipe(
map(res => ({
mod,
res,
execute() {
return mod.execute(ctx);
},
})),
);
}),
);
}
function autoCmpHandler(mod: Module | undefined, interaction: AutocompleteInteraction) {
return of(mod).pipe(
filterCorrectModule(CommandType.Slash),
concatMap(mod => {
const choice = interaction.options.getFocused(true);
const selectedOption = mod.options?.find(
o => o.autocomplete && o.command.name === choice.name,
);
if (selectedOption !== undefined && selectedOption.autocomplete) {
return of(
selectedOption.command.onEvent?.map(e =>
e.execute([interaction], controller),
) ?? [],
).pipe(
map(res => ({
mod,
res,
execute() {
return selectedOption.command.execute(interaction);
},
})),
);
}
return throwError(
() =>
SernError.NotSupportedInteraction +
` There is probably no autocomplete tag for this option`,
);
}),
);
}
export function onInteractionCreate(wrapper: Wrapper) {
@@ -171,6 +204,7 @@ export function onInteractionCreate(wrapper: Wrapper) {
}
if (interaction.isAutocomplete()) {
const modul = Files.ApplicationCommands[1].get(interaction.commandName);
return autoCmpHandler(modul, interaction);
}
return of();
}),

View File

@@ -14,6 +14,7 @@
import type { Awaitable, Client } from 'discord.js';
import type { Err, Ok, Result } from 'ts-results';
import type { Module, Override } from '../..';
import { CommandType } from '../..';
import type { BaseModule, ModuleDefs } from '../structures/module';
import type { PluginType } from '../structures/enums';
import type { ValueOf } from 'ts-pattern/dist/types/helpers';
@@ -68,8 +69,10 @@ type ModuleNoPlugins = ValueOf<{
//TODO: I WANT BETTER TYPINGS AHHHHHHHHHHHHHHH
export function sernModule(plugins: CommandPlugin[], mod: ModuleNoPlugins): Module {
return {
plugins,
...mod,
};
if (mod.type !== CommandType.Autocomplete)
return {
plugins,
...mod,
};
else return mod;
}

View File

@@ -2,13 +2,14 @@
* @enum { number };
*/
enum CommandType {
Text = 0b0000001,
Slash = 0b0000010,
MenuUser = 0b0000100,
MenuMsg = 0b0001000,
Button = 0b0010000,
MenuSelect = 0b0100000,
Modal = 0b1000000,
Text = 0b00000001,
Slash = 0b00000010,
MenuUser = 0b00000100,
MenuMsg = 0b00001000,
Button = 0b00010000,
MenuSelect = 0b00100000,
Modal = 0b01000000,
Autocomplete = 0b10000000,
Both = 0b0000011,
}

View File

@@ -1,4 +1,5 @@
import type {
ApplicationCommandAutocompleteOption,
ApplicationCommandOptionData,
Awaitable,
ButtonInteraction,
@@ -11,6 +12,8 @@ import type { Args, Override } from '../../types/handler';
import type { CommandPlugin, EventPlugin } from '../plugins/plugin';
import type Context from './context';
import { CommandType, PluginType } from './enums';
import type { AutocompleteInteraction } from 'discord.js';
import type { ApplicationCommandOptionType } from 'discord.js';
export interface BaseModule {
type: CommandType | PluginType;
@@ -36,7 +39,7 @@ export type SlashCommand = Override<
type: CommandType.Slash;
onEvent?: EventPlugin<CommandType.Slash>[];
plugins?: CommandPlugin[];
options?: ApplicationCommandOptionData[];
options?: OptionsData[];
}
>;
@@ -47,7 +50,7 @@ export type BothCommand = Override<
onEvent?: EventPlugin<CommandType.Both>[];
plugins?: CommandPlugin[];
alias?: string[];
options?: ApplicationCommandOptionData[];
options?: OptionsData[];
}
>;
@@ -94,12 +97,24 @@ export type SelectMenuCommand = Override<
export type ModalSubmitCommand = Override<
BaseModule,
{
type : CommandType.Modal;
type: CommandType.Modal;
onEvent?: EventPlugin<CommandType.Modal>[];
plugins?: CommandPlugin[];
execute : (ctx: ModalSubmitInteraction) => Awaitable<void>;
execute: (ctx: ModalSubmitInteraction) => Awaitable<void>;
}
>;
// Autocomplete commands are a little different
// They can't have command plugins as they are
// in conjunction with chat input commands
// TODO: possibly in future, allow Autocmp commands in separate files?
export type AutocompleteCommand = Override<
BaseModule,
{
type: CommandType.Autocomplete;
onEvent?: EventPlugin<CommandType.Autocomplete>[];
execute: (ctx: AutocompleteInteraction) => Awaitable<void>;
}
>;
export type Module =
@@ -110,7 +125,8 @@ export type Module =
| ContextMenuMsg
| ButtonCommand
| SelectMenuCommand
| ModalSubmitCommand;
| ModalSubmitCommand
| AutocompleteCommand;
//https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union
// Explicit Module Definitions for mapping
@@ -122,5 +138,18 @@ export type ModuleDefs = {
[CommandType.MenuUser]: ContextMenuUser;
[CommandType.Button]: ButtonCommand;
[CommandType.MenuSelect]: SelectMenuCommand;
[CommandType.Modal] : ModalSubmitCommand;
[CommandType.Modal]: ModalSubmitCommand;
[CommandType.Autocomplete]: AutocompleteCommand;
};
type OptionsData =
| Exclude<ApplicationCommandOptionData, ApplicationCommandAutocompleteOption>
| {
required?: boolean;
autocomplete: true;
type:
| ApplicationCommandOptionType.String
| ApplicationCommandOptionType.Number
| ApplicationCommandOptionType.Integer;
command: AutocompleteCommand;
};