mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
chore(module.ts) Move Command Modules to different file, change context objs to class counterparts
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
import type {
|
||||
CommandInteraction,
|
||||
Interaction,
|
||||
Message
|
||||
} from 'discord.js';
|
||||
import { None, Option } from 'ts-results';
|
||||
|
||||
export class Context {
|
||||
export default class Context {
|
||||
private msg: Option<Message> = None;
|
||||
private interac: Option<CommandInteraction> = None;
|
||||
private interac: Option<Interaction> = None;
|
||||
|
||||
constructor(message : Option<Message>, interaction: Option<CommandInteraction> ) {
|
||||
constructor(message : Option<Message>, interaction: Option<Interaction> ) {
|
||||
this.msg = message;
|
||||
this.interac = interaction
|
||||
this.interac = interaction;
|
||||
}
|
||||
|
||||
get messageUnchecked() {
|
||||
return this.msg.unwrap();
|
||||
}
|
||||
@@ -25,3 +26,4 @@ export class Context {
|
||||
return this.interac;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
28
src/handler/module.ts
Normal file
28
src/handler/module.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { Visibility, possibleOutput, Arg } from '../types/handler';
|
||||
import type { CommandType } from './sern';
|
||||
import type Context from './context' ;
|
||||
import type { Awaitable } from 'discord.js';
|
||||
import type { Ok } from 'ts-results';
|
||||
import type * as Utils from './utilities/preprocessors/args';
|
||||
|
||||
/**
|
||||
* An object that gets imported and acts as a command.
|
||||
* @typedef {object} Module<T=string>
|
||||
* @property {string} desc
|
||||
* @property {Visibility} visibility
|
||||
* @property {CommandType} type
|
||||
* @property {(eventParams : Context, args : Ok<T=string) => Awaitable<possibleOutput | void>)} execute
|
||||
* @prop {(ctx: Context, args: Arg) => Utils.ArgType<T>} parse
|
||||
*/
|
||||
|
||||
interface Module<T = string> {
|
||||
alias: string[];
|
||||
desc: string;
|
||||
visibility: Visibility;
|
||||
type: CommandType;
|
||||
test: boolean;
|
||||
execute: (eventParams: Context, args: Ok<T>) => Awaitable<possibleOutput | void>;
|
||||
parse?: (ctx: Context, args: Arg) => Utils.ArgType<T>;
|
||||
}
|
||||
|
||||
export default Module;
|
||||
@@ -1,16 +1,11 @@
|
||||
import * as Files from './utilities/readFile';
|
||||
import type * as Utils from './utilities/preprocessors/args';
|
||||
|
||||
import type {
|
||||
possibleOutput,
|
||||
Visibility,
|
||||
Context,
|
||||
Arg
|
||||
} from '../types/handler';
|
||||
|
||||
import type {
|
||||
ApplicationCommandOptionData,
|
||||
Awaitable,
|
||||
Client,
|
||||
CommandInteraction,
|
||||
Message
|
||||
@@ -20,7 +15,8 @@ import { Ok, None, Some } from 'ts-results';
|
||||
import { isNotFromBot, hasPrefix, fmt } from './utilities/messageHelpers';
|
||||
import Logger, { sEvent } from './logger';
|
||||
import { AllTrue } from './utilities/higherOrders';
|
||||
|
||||
import type Module from './module';
|
||||
import Context from './context';
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
@@ -101,7 +97,7 @@ export class Handler {
|
||||
if (name === undefined) return `Could not find ${interaction.commandName} command!`;
|
||||
|
||||
if (module.mod.type < CommandType.SLASH) return 'This is not a slash command';
|
||||
const context = { message: None, interaction: Some(interaction) };
|
||||
const context = new Context(None, Some(interaction));
|
||||
const parsedArgs = module.mod.parse?.(context, ['slash', interaction.options]) ?? Ok('');
|
||||
|
||||
if (parsedArgs.err) return parsedArgs.val;
|
||||
@@ -148,10 +144,7 @@ export class Handler {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const context = {
|
||||
message: Some(message),
|
||||
interaction: None,
|
||||
};
|
||||
const context = new Context ( Some(message), None );
|
||||
const args = message.content.slice(this.prefix.length).trim().split(/s+/g);
|
||||
const parsedArgs = module.mod.parse?.(context, ['text', args]) ?? Ok(args);
|
||||
if (parsedArgs.err) return parsedArgs.val;
|
||||
@@ -296,25 +289,7 @@ export interface Wrapper {
|
||||
readonly privateServers: { test: boolean; id: string }[];
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that gets imported and acts as a command.
|
||||
* @typedef {object} Module<T=string>
|
||||
* @property {string} desc
|
||||
* @property {Visibility} visibility
|
||||
* @property {CommandType} type
|
||||
* @property {(eventParams : Context, args : Ok<T=string>) => Awaitable<possibleOutput | void>)} execute
|
||||
* @prop {(ctx: Context, args: Arg) => Utils.ArgType<T>} parse
|
||||
*/
|
||||
|
||||
export interface Module<T = string> {
|
||||
alias: string[];
|
||||
desc: string;
|
||||
visibility: Visibility;
|
||||
type: CommandType;
|
||||
test: boolean;
|
||||
execute: (eventParams: Context, args: Ok<T>) => Awaitable<possibleOutput | void>;
|
||||
parse?: (ctx: Context, args: Arg) => Utils.ArgType<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @enum { number };
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
function toTimeString<T extends string | number | symbol>(
|
||||
unix: bigint | number,
|
||||
units: Record<T, bigint>,
|
||||
isFromNow: boolean = false,
|
||||
isFromNow = false,
|
||||
limit?: number
|
||||
) {
|
||||
if (typeof unix === 'number') unix = BigInt(unix);
|
||||
@@ -255,7 +255,7 @@
|
||||
const date = new Date(unix);
|
||||
const timestamp = formatDate(date);
|
||||
let ret = FrozenTimestampStyles[style];
|
||||
for (let [key, value] of Object.entries(timestamp)) {
|
||||
for (const [key, value] of Object.entries(timestamp)) {
|
||||
ret = ret.split(`{${key}}`).join(value);
|
||||
}
|
||||
return ret;
|
||||
@@ -361,7 +361,7 @@
|
||||
static timestamp(
|
||||
unix: number | Date | string,
|
||||
format: TimestampStyles = TimestampStyles.BOTH_SHORT,
|
||||
isSeconds: boolean = false
|
||||
isSeconds = false
|
||||
) {
|
||||
if (typeof unix === 'string') unix = Number(unix);
|
||||
if (unix instanceof Date) unix = unix.getTime();
|
||||
@@ -375,7 +375,7 @@
|
||||
static date(
|
||||
unix: number | Date | string,
|
||||
format: TimestampStyles = TimestampStyles.BOTH_SHORT,
|
||||
isSeconds: boolean = false
|
||||
isSeconds = false
|
||||
) {
|
||||
if (typeof unix === 'string') unix = Number(unix);
|
||||
if (unix instanceof Date) unix = unix.getTime();
|
||||
@@ -592,7 +592,7 @@
|
||||
|
||||
match<T extends DiscordRegexMatch>(
|
||||
type: DiscordRegexNames,
|
||||
onlyFirst: boolean = false
|
||||
onlyFirst = false
|
||||
): DiscordRegexPayload<T> {
|
||||
const regex = DiscordRegex[type];
|
||||
if (regex === undefined) {
|
||||
@@ -698,7 +698,7 @@
|
||||
static match(
|
||||
raw: string,
|
||||
what: DiscordRegexNames,
|
||||
onlyFirst: boolean = false
|
||||
onlyFirst = false
|
||||
) {
|
||||
return new this(raw).match(what, onlyFirst);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { ApplicationCommandOptionData } from 'discord.js';
|
||||
import type * as Sern from '../sern';
|
||||
import type Module from '../module';
|
||||
|
||||
import { readdirSync, statSync } from 'fs';
|
||||
import { basename, join } from 'path';
|
||||
|
||||
export type CommandVal = {
|
||||
mod: Sern.Module<unknown> & { name : string };
|
||||
mod: Module<unknown> & { name : string };
|
||||
options: ApplicationCommandOptionData[];
|
||||
};
|
||||
|
||||
@@ -32,20 +33,20 @@ export const fmtFileName = (n: string) => n.substring(0, n.length - 3);
|
||||
/**
|
||||
*
|
||||
* @param {Sern.Handler} handler an instance of Sern.Handler
|
||||
* @returns {Promise<{ name: string; mod: Sern.Module<unknown>; absPath: string; }[]>} data from command files
|
||||
* @returns {Promise<{ name: string; mod: Module<unknown>; absPath: string; }[]>} data from command files
|
||||
*/
|
||||
|
||||
export async function buildData(handler: Sern.Handler): Promise<
|
||||
{
|
||||
name: string;
|
||||
mod: Sern.Module<unknown>;
|
||||
mod: Module<unknown>;
|
||||
absPath: string;
|
||||
}[]
|
||||
> {
|
||||
const commandDir = handler.commandDir;
|
||||
return Promise.all(
|
||||
(await getCommands(commandDir)).map(async (absPath) => {
|
||||
return { name: basename(absPath), mod: (await import(absPath)).default as Sern.Module<unknown>, absPath };
|
||||
return { name: basename(absPath), mod: (await import(absPath)).default as Module<unknown>, absPath };
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
import type { Option } from 'ts-results';
|
||||
|
||||
import type {
|
||||
CommandInteraction,
|
||||
CommandInteractionOptionResolver,
|
||||
Message,
|
||||
MessagePayload,
|
||||
MessageOptions,
|
||||
} from 'discord.js';
|
||||
|
||||
import type * as Sern from '../handler/sern';
|
||||
import type Module from '../handler/module';
|
||||
|
||||
export type Visibility = 'private' | 'public';
|
||||
|
||||
// Anything that can be sent in a `<TextChannel>#send` or `<CommandInteraction>#reply`
|
||||
export type possibleOutput<T = string> = T | (MessagePayload & MessageOptions);
|
||||
export type execute = Sern.Module<unknown>['execute'];
|
||||
export type execute = Module<unknown>['execute'];
|
||||
// Thanks @cursorsdottsx
|
||||
export type ParseType<T> = {
|
||||
[K in keyof T]: T[K] extends unknown ? [k: K, args: T[K]] : never;
|
||||
}[keyof T];
|
||||
|
||||
// A Sern.Module['delegate'] will carry a Context Parameter
|
||||
export type Context = {
|
||||
message: Option<Message>;
|
||||
interaction: Option<CommandInteraction>;
|
||||
};
|
||||
|
||||
export type Arg = ParseType<{ text: string[]; slash: SlashOptions }>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user