refactor : change naming conventions to PascalCase

This commit is contained in:
Jacob Nguyen
2022-04-08 13:10:46 -05:00
parent e21508ca4f
commit 490d6403d7
11 changed files with 96 additions and 57 deletions

View File

@@ -6,19 +6,17 @@ import Context from '../structures/context';
import type Wrapper from '../structures/wrapper';
import * as Files from '../utilities/readFile';
import { filterTap } from './observableHandling';
import { filter } from 'rxjs';
export const onInteractionCreate = ( wrapper : Wrapper ) => {
const { client } = wrapper;
(<Observable<Interaction>> fromEvent(client, 'interactionCreate'))
.pipe(
filter( i => i.inGuild() ),
concatMap ( interaction => {
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]);
}),
@@ -27,7 +25,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
if (interaction.isContextMenuCommand()) {
return of(Files.ContextMenuUser.get(interaction.commandName))
.pipe(
filterTap(CommandType.MENU_USER, mod => {
filterTap(CommandType.MenuUser, mod => {
mod.execute(interaction);
}),
);
@@ -35,7 +33,7 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
if (interaction.isMessageContextMenuCommand()) {
return of(Files.ContextMenuMsg.get(interaction.commandName))
.pipe(
filterTap(CommandType.MENU_MSG, mod => {
filterTap(CommandType.MenuMsg, mod => {
mod.execute(interaction);
}),
);
@@ -43,7 +41,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 => {
mod.execute(interaction);
})
);
@@ -51,12 +49,12 @@ export const onInteractionCreate = ( wrapper : Wrapper ) => {
if (interaction.isSelectMenu()) {
return of(Files.SelectMenus.get(interaction.customId))
.pipe(
filterTap(CommandType.MENU_SELECT, mod => {
filterTap(CommandType.MenuSelect, mod => {
mod.execute(interaction);
})
);
}
else { return of(); }
else return of();
})
).subscribe({
error(e) {

View File

@@ -1,4 +1,4 @@
import type { ChatInputCommandInteraction, Message } from 'discord.js';
import type { Message } from 'discord.js';
import { fromEvent, Observable, of, concatMap } from 'rxjs';
import { CommandType } from '../sern';
import Context from '../structures/context';
@@ -18,7 +18,7 @@ export const onMessageCreate = (wrapper : Wrapper) => {
return of( posMod )
.pipe (
filterTap(CommandType.TEXT, mod => {
filterTap(CommandType.Text, mod => {
const ctx = Context.wrap(m);
mod.execute(ctx, ['text', data]);
})

View File

@@ -4,7 +4,7 @@ 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, isNotFromDM } from '../utilities/messageHelpers';
import { isNotFromBot } from '../utilities/messageHelpers';
export function match(mod: Module | undefined, type : CommandType) : boolean {
return mod !== undefined && (mod.type & type) != 0;
@@ -23,9 +23,9 @@ export function filterTap<T extends keyof ModuleDefs>(
subscriber.next(asModT);
} else {
if (modul === undefined) {
return throwError(() => SernError.UNDEFINED_MODULE);
return throwError(() => SernError.UndefinedModule);
}
return throwError(() => SernError.MISMATCH_MODULE_TYPE);
return throwError(() => SernError.MismatchModule);
}
},
error: (e) => subscriber.error(e),
@@ -40,7 +40,6 @@ export function ignoreNonBot(prefix : string) {
return src.subscribe({
next(m) {
const passAll = [
isNotFromDM,
isNotFromBot,
(m : Message) =>
m.content
@@ -59,5 +58,3 @@ export function ignoreNonBot(prefix : string) {
});
});
}

View File

@@ -42,8 +42,7 @@ const handler = ( name : string ) =>
},
[CommandType.MENU_SELECT] : mod => {
Files.SelectMenus.set(name, mod);
}
},
} as ModuleHandlers);
const registerModules = <T extends ModuleType >(name : string, mod : ModuleStates[T]) =>

View File

@@ -12,6 +12,8 @@ import { SernError } from './structures/errors';
import { onReady } from './events/readyEvent';
import { onMessageCreate } from './events/messageEvent';
import { onInteractionCreate } from './events/interactionCreate';
import type { Module } from '..';
import { Modified, Modifiers } from './structures/modifiers';
export function init( wrapper : Wrapper ) {
const { events, client } = wrapper;
@@ -21,6 +23,7 @@ export function init( wrapper : Wrapper ) {
onInteractionCreate ( wrapper );
}
//TODO : Add event listener for any other generic node js event emitter
function eventObserver(client: Client, events: DiscordEvent[] ) {
events.forEach( ( [event, cb] ) => {
if (event === 'ready') throw Error(SernError.RESERVED_EVENT);
@@ -29,17 +32,18 @@ function eventObserver(client: Client, events: DiscordEvent[] ) {
}
/**
* @enum { number };
*/
export enum CommandType {
TEXT = 0b000001,
SLASH = 0b000010,
MENU_USER = 0b000100,
MENU_MSG = 0b001000,
BUTTON = 0b010000,
MENU_SELECT= 0b100000,
BOTH = 0b000011,
ANY = 0b111111
Text = 0b0000001,
Slash = 0b0000010,
MenuUser = 0b0000100,
MenuMsg = 0b0001000,
Button = 0b0010000,
MenuSelect = 0b0100000,
Both = 0b0000011,
Auto = 0b1000000
}

View File

@@ -1,9 +1,12 @@
import type { APIGuildMember } from 'discord-api-types/v9';
import type {
Awaitable,
ChatInputCommandInteraction,
Guild,
GuildMember,
InteractionReplyOptions,
Message,
ReplyMessageOptions,
Snowflake,
TextBasedChannel,
User
@@ -17,8 +20,10 @@ function firstSome<T>(...args : Option<T>[]) : Nullish<T> {
}
return null;
}
//
//Will need refactoring after applying context in practice
//
export default class Context {
private constructor(
private oMsg: Option<Message> = None,
private oInterac: Option<ChatInputCommandInteraction> = None
@@ -71,7 +76,7 @@ export default class Context {
public get guild() : Guild {
return firstSome(
this.oMsg.map(m => m.guild!),
this.oMsg.map(m => m.guild),
this.oInterac.map(i => i.guild)
)!;
}
@@ -81,10 +86,13 @@ export default class Context {
this.oInterac.map(i => i.guildId)
)!;
}
public get member() : Nullish<GuildMember> {
/*
* interactions can return APIGuildMember if the guild it is emitted from is not cached
*/
public get member() : Nullish<GuildMember|APIGuildMember> {
return firstSome(
this.oMsg.andThen(m => Some(m.member!)),
this.oInterac.andThen(i => i.inCachedGuild() ? Some(i.member) : None)
this.oMsg.map(m => m.member),
this.oInterac.map(i => i.member)
);
}
/*
@@ -93,13 +101,19 @@ export default class Context {
public onInteraction(
onInteraction : ( interaction : ChatInputCommandInteraction ) => Awaitable<void>,
): Context {
this.oInterac.map(onInteraction);
if (this.oInterac.some) {
onInteraction(this.oInterac.val);
return Context.wrap(this.oInterac.val);
}
return this;
}
public onMessage(
onMessage : ( message : Message ) => Awaitable<void>
): Context {
this.oMsg.map( onMessage );
if (this.oMsg.some) {
onMessage(this.oMsg.val);
return Context.wrap(this.oMsg.val);
}
return this;
}
public takeInteractionValue<T>(
@@ -108,14 +122,28 @@ export default class Context {
if(this.oInterac.none) return null;
return extract(this.oInterac.val);
}
public takeMessageValue<T>(
extract : (message: Message) => T
): Nullish<T> {
if(this.oMsg.none) return null;
return extract(this.oMsg.val);
}
public reply(
content : Omit<InteractionReplyOptions, 'fetchReply'> | ReplyMessageOptions
): Promise<Context> {
return firstSome(
this.oInterac.map(async i => {
await i.reply( content as InteractionReplyOptions);
return new Context(Some(await i.fetchReply() as Message), Some(i))
}),
this.oMsg.map(async m => {
const reply = await m.reply( content as ReplyMessageOptions )
return new Context(Some(reply), this.oInterac);
})
)!;
}
}

View File

@@ -1,7 +1,7 @@
export enum SernError {
RESERVED_EVENT = 'Cannot register the reserved ready event. Please use the init property.',
NO_ALIAS = 'You cannot provide an array with elements to a slash command.',
NOT_VALID_MOD_TYPE = 'Detected an unknown module type',
UNDEFINED_MODULE = `A module could not be detected at`,
MISMATCH_MODULE_TYPE = `A module type mismatched with event emitted!`
ReservedEvent = 'Cannot register the reserved ready event. Please use the init property.',
NoAlias = 'You cannot provide an array with elements to a slash command.',
NonValidModuleType = 'Detected an unknown module type',
UndefinedModule = `A module could not be detected at`,
MismatchModule = `A module type mismatched with event emitted!`
}

View File

@@ -1,36 +1,40 @@
import type { ApplicationCommandOptionData, Awaitable, ButtonInteraction, ContextMenuCommandInteraction, MessageContextMenuCommandInteraction, SelectMenuInteraction } from 'discord.js';
import type { ApplicationCommandOptionData, AutocompleteInteraction, Awaitable, ButtonInteraction, ContextMenuCommandInteraction, MessageContextMenuCommandInteraction, SelectMenuInteraction } from 'discord.js';
import type { Override } from '../../../../types/handler';
import type { CommandType } from '../../../sern';
import type { BaseModule } from '../module';
type AutoComp = {
update : (ctx : AutocompleteInteraction) => Awaitable<void>
}
//possible refactoring to interfaces and not types
export type TextCommand = {
type : CommandType.TEXT;
type : CommandType.Text;
alias : string[] | [],
} & BaseModule;
export type SlashCommand = {
type : CommandType.SLASH;
type : CommandType.Slash;
options : ApplicationCommandOptionData[] | [],
} & BaseModule;
export type BothCommand = {
type : CommandType.BOTH;
type : CommandType.Both;
alias : string[] | [];
options : ApplicationCommandOptionData[] | [],
} & BaseModule;
export type ContextMenuUser = {
type : CommandType.MENU_USER;
type : CommandType.MenuUser;
} & Override<BaseModule, { execute : ( ctx: ContextMenuCommandInteraction ) => Awaitable<void> }>;
export type ContextMenuMsg = {
type : CommandType.MENU_MSG;
type : CommandType.MenuMsg;
} & Override<BaseModule, { execute : ( ctx: MessageContextMenuCommandInteraction ) => Awaitable<void> }>;
export type ButtonCommand = {
type : CommandType.BUTTON;
type : CommandType.Button;
} & Override<BaseModule, { execute : (ctx :ButtonInteraction ) => Awaitable<void> }>;
export type SelectMenuCommand = {
type : CommandType.MENU_SELECT;
type : CommandType.MenuSelect;
} & Override<BaseModule, { execute : (ctx : SelectMenuInteraction ) => Awaitable<void> }>;

View File

@@ -1,16 +1,24 @@
import { CommandType } from '../../../sern';
import type { TextCommand, BothCommand, ButtonCommand, SlashCommand, ContextMenuMsg, ContextMenuUser, SelectMenuCommand } from './module';
import type {
TextCommand,
BothCommand,
ButtonCommand,
SlashCommand,
ContextMenuMsg,
ContextMenuUser,
SelectMenuCommand
} from './module';
//https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union
// Explicit Module Definitions for mapping
export type ModuleDefs = {
[CommandType.TEXT] : TextCommand,
[CommandType.SLASH] : SlashCommand,
[CommandType.BOTH] : BothCommand,
[CommandType.MENU_MSG] : ContextMenuMsg,
[CommandType.MENU_USER] : ContextMenuUser,
[CommandType.BUTTON] : ButtonCommand,
[CommandType.MENU_SELECT] : SelectMenuCommand
[CommandType.Text] : TextCommand,
[CommandType.Slash] : SlashCommand,
[CommandType.Both] : BothCommand,
[CommandType.MenuMsg] : ContextMenuMsg,
[CommandType.MenuUser] : ContextMenuUser,
[CommandType.Button] : ButtonCommand,
[CommandType.MenuSelect] : SelectMenuCommand,
}
//Keys of ModuleDefs

View File

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

View File

@@ -21,6 +21,7 @@ export type Args = ParseType<{ text: string[]; slash: SlashOptions }>;
export type DiscordEvent =
ParseType< { [K in keyof ClientEvents ] : (...args : ClientEvents[K]) => Awaitable<void> }>;
export type SlashOptions = Omit<CommandInteractionOptionResolver, 'getMessage' | 'getFocused'>;
//https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l