mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
instal eslint and prettierconfic, applied to files
This commit is contained in:
6
.eslintrc
Normal file
6
.eslintrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"extends": ["plugin:@typescript-eslint/recommended"],
|
||||
"parserOptions": { "ecmaVersion": "esnext", "sourceType": "" },
|
||||
"rules": {}
|
||||
}
|
||||
7
.prettierrc
Normal file
7
.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"semi": true,
|
||||
"trailingComma": "all",
|
||||
"singleQuote": true,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2
|
||||
}
|
||||
2267
package-lock.json
generated
2267
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -4,18 +4,23 @@
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"compile": "tsc",
|
||||
"watch" : "tsc -w"
|
||||
"watch": "tsc -w",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"format": "eslint src/**/*.ts --fix"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^5.10.2",
|
||||
"discord.js": "^13.6.0",
|
||||
"eslint": "^8.8.0",
|
||||
"prettier": "^2.5.1",
|
||||
"ts-results": "^3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,159 +1,159 @@
|
||||
import type { Arg, Context, ParseType, Visibility } from "../types/handler/handler";
|
||||
import { Files } from "./utils/readFile"
|
||||
import type { ApplicationCommandOptionData, Awaitable, Client, CommandInteraction, CommandInteractionOptionResolver, Message} from "discord.js";
|
||||
import * as Files from "./utils/readFile"
|
||||
import type { ApplicationCommandOptionData, Awaitable, Client, CommandInteraction, Message } from "discord.js";
|
||||
import type { possibleOutput } from "../types/handler/handler"
|
||||
import { Ok, Result, None, Some } from "ts-results";
|
||||
import type { Utils } from "./utils/preprocessors/args";
|
||||
import type * as Utils from "./utils/preprocessors/args";
|
||||
import { CtxHandler } from "./utils/ctxHandler";
|
||||
|
||||
export namespace Sern {
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
export class Handler {
|
||||
private wrapper: Wrapper;
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {Wrapper} wrapper Some data that is required to run sern handler
|
||||
*/
|
||||
export class Handler {
|
||||
private wrapper: Sern.Wrapper;
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Sern.Wrapper} wrapper Some data that is required to run sern handler
|
||||
*/
|
||||
constructor(
|
||||
wrapper : Sern.Wrapper,
|
||||
) {
|
||||
this.wrapper = wrapper;
|
||||
this.wrapper.client
|
||||
.on("ready", async () => {
|
||||
if (this.wrapper.init !== undefined) this.wrapper.init(this);
|
||||
await Files.registerModules(this);
|
||||
})
|
||||
constructor(
|
||||
wrapper: Wrapper,
|
||||
) {
|
||||
this.wrapper = wrapper;
|
||||
this.wrapper.client
|
||||
.on("ready", async () => {
|
||||
if (this.wrapper.init !== undefined) this.wrapper.init(this);
|
||||
await Files.registerModules(this);
|
||||
})
|
||||
|
||||
.on("messageCreate", async message => {
|
||||
if (CtxHandler.isBot(message) || !CtxHandler.hasPrefix(message,this.prefix)) return;
|
||||
let tryFmt = CtxHandler.fmt(message, this.prefix)
|
||||
const commandName = tryFmt.shift()!;
|
||||
const module = Files.Commands.get(commandName) ?? Files.Alias.get(commandName)
|
||||
if(module === undefined) {
|
||||
message.channel.send("Unknown legacy command")
|
||||
return;
|
||||
}
|
||||
let cmdResult = (await this.commandResult(module?.mod, message, tryFmt.join(" ")))
|
||||
if (cmdResult === undefined) return;
|
||||
|
||||
message.channel.send(cmdResult)
|
||||
|
||||
})
|
||||
|
||||
.on("interactionCreate", async interaction => {
|
||||
if(!interaction.isCommand()) return;
|
||||
const module = Files.Commands.get(interaction.commandName);
|
||||
let res = await this.interactionResult(module, interaction);
|
||||
if (res === undefined) return;
|
||||
await interaction.reply(res);
|
||||
})
|
||||
}
|
||||
|
||||
private async interactionResult(
|
||||
module: { mod: Sern.Module<unknown>, options: ApplicationCommandOptionData[]} | undefined,
|
||||
interaction: CommandInteraction) : Promise<possibleOutput | undefined> {
|
||||
|
||||
if (module === undefined) return "Unknown slash command!";
|
||||
const name = Array.from(Files.Commands.keys()).find(it => it === interaction.commandName)!;
|
||||
|
||||
(await this.client.guilds.fetch(this.privateServerId))
|
||||
.commands
|
||||
.create({
|
||||
name,
|
||||
description : module.mod.desc,
|
||||
options: module.options
|
||||
});
|
||||
|
||||
if(module.mod.type < CommandType.SLASH) return "This is not a slash command";
|
||||
const context = {text: None, slash: Some(interaction)}
|
||||
const parsedArgs = module.mod.parse?.(context, ["slash", interaction.options ] ) ?? Ok("");
|
||||
if(parsedArgs.err) return parsedArgs.val;
|
||||
const fn = await module.mod.delegate(context, parsedArgs);
|
||||
return fn?.val;
|
||||
}
|
||||
|
||||
private async commandResult(module: Sern.Module<unknown> | undefined, message: Message, args : string) : Promise<possibleOutput| undefined> {
|
||||
if (module === undefined) return "Unknown legacy command";
|
||||
if (module.visibility === "private" && message.guildId !== this.privateServerId) {
|
||||
return "This command is not availible in this guild!"
|
||||
.on("messageCreate", async message => {
|
||||
if (CtxHandler.isBot(message) || !CtxHandler.hasPrefix(message, this.prefix)) return;
|
||||
const tryFmt = CtxHandler.fmt(message, this.prefix)
|
||||
const commandName = tryFmt.shift()!;
|
||||
const module = Files.Commands.get(commandName) ?? Files.Alias.get(commandName)
|
||||
if (module === undefined) {
|
||||
message.channel.send("Unknown legacy command")
|
||||
return;
|
||||
}
|
||||
if (module.type === CommandType.SLASH) return `This may be a slash command and not a legacy command`
|
||||
const context = {text: Some(message), slash: None}
|
||||
const parsedArgs = module.parse?.(context, ["text", args] ) ?? Ok("");
|
||||
if(parsedArgs.err) return parsedArgs.val;
|
||||
let fn = await module.delegate(context, parsedArgs)
|
||||
return fn?.val
|
||||
}
|
||||
/**
|
||||
* @readonly
|
||||
* @returns {string} prefix used for legacy commands
|
||||
*/
|
||||
get prefix() : string {
|
||||
return this.wrapper.prefix;
|
||||
}
|
||||
/**
|
||||
* @readonly
|
||||
* @returns {string} directory of your commands folder
|
||||
*/
|
||||
get commandDir() : string {
|
||||
return this.wrapper.commands;
|
||||
}
|
||||
/**
|
||||
* @readonly
|
||||
* @returns {Client<boolean>} discord.js client
|
||||
*/
|
||||
get client() : Client<boolean> {
|
||||
return this.wrapper.client
|
||||
}
|
||||
/**
|
||||
* @readonly
|
||||
* @returns {string} private server id for testing or personal use
|
||||
*/
|
||||
get privateServerId(): string {
|
||||
return this.wrapper.privateServerId;
|
||||
}
|
||||
|
||||
|
||||
const cmdResult = (await this.commandResult(module?.mod, message, tryFmt.join(" ")))
|
||||
if (cmdResult === undefined) return;
|
||||
|
||||
message.channel.send(cmdResult)
|
||||
|
||||
})
|
||||
|
||||
.on("interactionCreate", async interaction => {
|
||||
if (!interaction.isCommand()) return;
|
||||
const module = Files.Commands.get(interaction.commandName);
|
||||
const res = await this.interactionResult(module, interaction);
|
||||
if (res === undefined) return;
|
||||
await interaction.reply(res);
|
||||
})
|
||||
}
|
||||
|
||||
private async interactionResult(
|
||||
module: { mod: Module<unknown>, options: ApplicationCommandOptionData[] } | undefined,
|
||||
interaction: CommandInteraction): Promise<possibleOutput | undefined> {
|
||||
|
||||
if (module === undefined) return "Unknown slash command!";
|
||||
const name = Array.from(Files.Commands.keys()).find(it => it === interaction.commandName)!;
|
||||
|
||||
(await this.client.guilds.fetch(this.privateServerId))
|
||||
.commands
|
||||
.create({
|
||||
name,
|
||||
description: module.mod.desc,
|
||||
options: module.options
|
||||
});
|
||||
|
||||
if (module.mod.type < CommandType.SLASH) return "This is not a slash command";
|
||||
const context = { text: None, slash: Some(interaction) }
|
||||
const parsedArgs = module.mod.parse?.(context, ["slash", interaction.options]) ?? Ok("");
|
||||
if (parsedArgs.err) return parsedArgs.val;
|
||||
const fn = await module.mod.delegate(context, parsedArgs);
|
||||
return fn?.val;
|
||||
}
|
||||
|
||||
private async commandResult(module: Module<unknown> | undefined, message: Message, args: string): Promise<possibleOutput | undefined> {
|
||||
if (module === undefined) return "Unknown legacy command";
|
||||
if (module.visibility === "private" && message.guildId !== this.privateServerId) {
|
||||
return "This command is not availible in this guild!"
|
||||
}
|
||||
if (module.type === CommandType.SLASH) return `This may be a slash command and not a legacy command`
|
||||
const context = { text: Some(message), slash: None }
|
||||
const parsedArgs = module.parse?.(context, ["text", args]) ?? Ok("");
|
||||
if (parsedArgs.err) return parsedArgs.val;
|
||||
const fn = await module.delegate(context, parsedArgs)
|
||||
return fn?.val
|
||||
}
|
||||
/**
|
||||
* An object to be passed into Sern.Handler constructor.
|
||||
* ```ts
|
||||
* new Sern.Handler({
|
||||
* client, // Discord.js client instance
|
||||
* prefix : "!", // an example prefix
|
||||
* commands: "", //commands directory
|
||||
* init : () => console.log("Bot is ready") // function called on ready
|
||||
* privateServerId : "" // a server id that can be used for private or test server
|
||||
* })
|
||||
* ```
|
||||
* @readonly
|
||||
* @returns {string} prefix used for legacy commands
|
||||
*/
|
||||
export interface Wrapper {
|
||||
readonly client : Client,
|
||||
readonly prefix: string,
|
||||
readonly commands : string
|
||||
init? : (handler : Sern.Handler) => void,
|
||||
readonly privateServerId : string
|
||||
get prefix(): string {
|
||||
return this.wrapper.prefix;
|
||||
}
|
||||
/**
|
||||
* @interface - Modules that are used in command files
|
||||
*/
|
||||
export interface Module<T = string> {
|
||||
alias: string[],
|
||||
desc : string,
|
||||
visibility : Visibility,
|
||||
type: CommandType,
|
||||
delegate : ( eventParams : Context , args: Ok<T> ) => Awaitable<Result<possibleOutput, string > | void>
|
||||
parse? : (ctx: Context, args: ParseType<Arg> ) => Utils.ArgType<T>
|
||||
* @readonly
|
||||
* @returns {string} directory of your commands folder
|
||||
*/
|
||||
get commandDir(): string {
|
||||
return this.wrapper.commands;
|
||||
}
|
||||
/**
|
||||
* @enum { number };
|
||||
* @readonly
|
||||
* @returns {Client<boolean>} discord.js client
|
||||
*/
|
||||
export enum CommandType {
|
||||
TEXT = 1,
|
||||
SLASH = 2,
|
||||
get client(): Client<boolean> {
|
||||
return this.wrapper.client
|
||||
}
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
* @returns {string} private server id for testing or personal use
|
||||
*/
|
||||
get privateServerId(): string {
|
||||
return this.wrapper.privateServerId;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* An object to be passed into Sern.Handler constructor.
|
||||
* ```ts
|
||||
* new Sern.Handler({
|
||||
* client, // Discord.js client instance
|
||||
* prefix : "!", // an example prefix
|
||||
* commands: "", //commands directory
|
||||
* init : () => console.log("Bot is ready") // function called on ready
|
||||
* privateServerId : "" // a server id that can be used for private or test server
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export interface Wrapper {
|
||||
readonly client: Client,
|
||||
readonly prefix: string,
|
||||
readonly commands: string
|
||||
init?: (handler: Handler) => void,
|
||||
readonly privateServerId: string
|
||||
}
|
||||
/**
|
||||
* @interface - Modules that are used in command files
|
||||
*/
|
||||
export interface Module<T = string> {
|
||||
alias: string[],
|
||||
desc: string,
|
||||
visibility: Visibility,
|
||||
type: CommandType,
|
||||
delegate: (eventParams: Context, args: Ok<T>) => Awaitable<Result<possibleOutput, string> | void>
|
||||
parse?: (ctx: Context, args: ParseType<Arg>) => Utils.ArgType<T>
|
||||
}
|
||||
/**
|
||||
* @enum { number };
|
||||
*/
|
||||
export enum CommandType {
|
||||
TEXT = 1,
|
||||
SLASH = 2,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ export class CtxHandler {
|
||||
|
||||
static hasPrefix(message: Message, prefix: string) {
|
||||
return (message.content.slice(0, prefix.length).toLowerCase().trim()) === prefix;
|
||||
}
|
||||
}
|
||||
|
||||
static fmt(msg: Message, prefix: string) : string[] {
|
||||
static fmt(msg: Message, prefix: string): string[] {
|
||||
return msg.content.slice(prefix.length).trim().split(/\s+/g)
|
||||
}
|
||||
}
|
||||
@@ -2,68 +2,68 @@ import { Err, Ok, Result } from "ts-results";
|
||||
import type { possibleOutput } from "../../../types/handler/handler";
|
||||
|
||||
|
||||
export namespace Utils {
|
||||
/**
|
||||
* Wrapper type taking `Ok(T)` or `Err(possibleOutput)` e.g `Result<T, possibleOutput`
|
||||
*/
|
||||
export type ArgType<T> = Result<T, possibleOutput>
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - if `Number.parseInt` returns NaN
|
||||
* @returns {ArgType<number>} Attempts to use `Number.parseInt()` on `arg`
|
||||
*/
|
||||
export function parseInt(arg: string, onFailure: possibleOutput): ArgType<number> {
|
||||
const val = Number.parseInt(arg);
|
||||
return val === NaN ? Err(onFailure) : Ok(val);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - If cannot parse `arg` into boolean.
|
||||
* @param { {yesRegex: RegExp, noRegex: RegExp} } regexes - default regexes: yes : `/^(?:y(?:es)?|👍)$/i`, no : /^(?:n(?:o)?|👎)$/i
|
||||
* @returns { ArgType<boolean> } attemps to parse `args` as a boolean
|
||||
*/
|
||||
export function parseBool(
|
||||
arg: string,
|
||||
onFailure: possibleOutput = `Cannot parse "${arg}" as a boolean`,
|
||||
regexes : {yesRegex: RegExp, noRegex: RegExp} = { yesRegex : /^(?:y(?:es)?|👍)$/i , noRegex : /^(?:n(?:o)?|👎)$/i }
|
||||
): ArgType<boolean> {
|
||||
if(arg.match(regexes.yesRegex)) return Ok(true);
|
||||
if(arg.match(regexes.noRegex)) return Ok(false);
|
||||
return Err(onFailure);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {string} sep - default separator = " "
|
||||
* @returns {Ok<string[]>}
|
||||
*/
|
||||
export function toArr(arg: string, sep: string = " ") : ArgType<string[]> {
|
||||
return Ok(arg.split(sep));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - delegates `Utils.parseInt`
|
||||
* @returns {ArgType<number>}
|
||||
*/
|
||||
export function toPositiveInt(arg: string, onFailure: possibleOutput) : ArgType<number> {
|
||||
return Utils.parseInt(arg, onFailure).andThen( num => Ok(num > 0 ? num :-num))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - delegates `Utils.parseInt`
|
||||
* @returns {ArgType<number>}
|
||||
*/
|
||||
export function toNegativeInt(arg: string, onFailure: possibleOutput) : ArgType<number> {
|
||||
return Utils.parseInt(arg, onFailure).andThen( num => Ok(num > 0 ? -num : num))
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type taking `Ok(T)` or `Err(possibleOutput)` e.g `Result<T, possibleOutput`
|
||||
*/
|
||||
export type ArgType<T> = Result<T, possibleOutput>
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - if `Number.parseInt` returns NaN
|
||||
* @returns {ArgType<number>} Attempts to use `Number.parseInt()` on `arg`
|
||||
*/
|
||||
export function parseInt(arg: string, onFailure: possibleOutput): ArgType<number> {
|
||||
const val = Number.parseInt(arg);
|
||||
return val === NaN ? Err(onFailure) : Ok(val);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - If cannot parse `arg` into boolean.
|
||||
* @param { {yesRegex: RegExp, noRegex: RegExp} } regexes - default regexes: yes : `/^(?:y(?:es)?|👍)$/i`, no : /^(?:n(?:o)?|👎)$/i
|
||||
* @returns { ArgType<boolean> } attemps to parse `args` as a boolean
|
||||
*/
|
||||
export function parseBool(
|
||||
arg: string,
|
||||
onFailure: possibleOutput = `Cannot parse "${arg}" as a boolean`,
|
||||
regexes: { yesRegex: RegExp, noRegex: RegExp } = { yesRegex: /^(?:y(?:es)?|👍)$/i, noRegex: /^(?:n(?:o)?|👎)$/i }
|
||||
): ArgType<boolean> {
|
||||
if (arg.match(regexes.yesRegex)) return Ok(true);
|
||||
if (arg.match(regexes.noRegex)) return Ok(false);
|
||||
return Err(onFailure);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {string} sep - default separator = " "
|
||||
* @returns {Ok<string[]>}
|
||||
*/
|
||||
export function toArr(arg: string, sep = " "): ArgType<string[]> {
|
||||
return Ok(arg.split(sep));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - delegates `Utils.parseInt`
|
||||
* @returns {ArgType<number>}
|
||||
*/
|
||||
export function toPositiveInt(arg: string, onFailure: possibleOutput): ArgType<number> {
|
||||
return parseInt(arg, onFailure).andThen(num => Ok(num > 0 ? num : -num))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} arg - command arguments
|
||||
* @param {possibleOutput} onFailure - delegates `parseInt`
|
||||
* @returns {ArgType<number>}
|
||||
*/
|
||||
export function toNegativeInt(arg: string, onFailure: possibleOutput): ArgType<number> {
|
||||
return parseInt(arg, onFailure).andThen(num => Ok(num > 0 ? -num : num))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,62 +1,57 @@
|
||||
import type { ApplicationCommandOptionData, CommandInteractionOption } from "discord.js";
|
||||
import type { ApplicationCommandOptionData } from "discord.js";
|
||||
import { readdirSync, statSync } from "fs";
|
||||
import { basename, join } from "path";
|
||||
import type { Sern } from "../sern";
|
||||
import type * as Sern from "../sern";
|
||||
|
||||
export namespace Files {
|
||||
export const Commands = new Map<string, { mod: Sern.Module<unknown>, options: ApplicationCommandOptionData[] }>();
|
||||
export const Alias = new Map<string, { mod: Sern.Module<unknown>, options: ApplicationCommandOptionData[] }>();
|
||||
export const Commands = new Map<string, { mod: Sern.Module<unknown>, options: ApplicationCommandOptionData[] }>();
|
||||
export const Alias = new Map<string, { mod: Sern.Module<unknown>, options: ApplicationCommandOptionData[] }>();
|
||||
|
||||
//courtesy of Townsy#0001 on Discord
|
||||
async function readPath(dir: string, arrayOfFiles: string[] = []): Promise<string[]> {
|
||||
try {
|
||||
const files = readdirSync(dir);
|
||||
for (const file of files) {
|
||||
if (statSync(dir + "/" + file).isDirectory()) {
|
||||
//courtesy of Townsy#0001 on Discord
|
||||
async function readPath(dir: string, arrayOfFiles: string[] = []): Promise<string[]> {
|
||||
try {
|
||||
const files = readdirSync(dir);
|
||||
for (const file of files) {
|
||||
if (statSync(dir + "/" + file).isDirectory()) {
|
||||
await readPath(dir + "/" + file, arrayOfFiles)
|
||||
} else {
|
||||
arrayOfFiles.push(join(dir, "/", file));
|
||||
}
|
||||
}
|
||||
} catch(err) {
|
||||
throw err;
|
||||
} else {
|
||||
arrayOfFiles.push(join(dir, "/", file));
|
||||
}
|
||||
}
|
||||
|
||||
return arrayOfFiles;
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
export async function registerModules(handler : Sern.Handler) : Promise<void> {
|
||||
const commandDir = handler.commandDir;
|
||||
Promise.all((await getCommands(commandDir)).map(async absPath => {
|
||||
return { name : basename(absPath), mod: ( await import(absPath)).default as Sern.Module<unknown>, absPath }
|
||||
})).then( async modArr => {
|
||||
for ( const { name, mod, absPath } of modArr) {
|
||||
switch (mod.type) {
|
||||
case 1 : Commands.set(name.substring(0, name.length-3), { mod, options: [] }); break;
|
||||
case 2 : {
|
||||
const options = ((await import(absPath)).options as ApplicationCommandOptionData[])
|
||||
Commands.set(name.substring(0, name.length - 3), { mod, options : options ?? [] });
|
||||
} break;
|
||||
case 1 | 2 : {
|
||||
const options = ((await import(absPath)).options as ApplicationCommandOptionData[])
|
||||
Commands.set(name.substring(0, name.length-3),{mod, options : options ?? [] } );
|
||||
} break;
|
||||
default : throw Error(`${name}.js is not a valid module type.`);
|
||||
}
|
||||
|
||||
if(mod.alias.length > 0) {
|
||||
for ( const alias of mod.alias) {
|
||||
Alias.set(alias, {mod, options : []})
|
||||
}
|
||||
}
|
||||
return arrayOfFiles;
|
||||
}
|
||||
|
||||
export async function registerModules(handler: Sern.Handler): Promise<void> {
|
||||
const commandDir = handler.commandDir;
|
||||
Promise.all((await getCommands(commandDir)).map(async absPath => {
|
||||
return { name: basename(absPath), mod: (await import(absPath)).default as Sern.Module<unknown>, absPath }
|
||||
})).then(async modArr => {
|
||||
for (const { name, mod, absPath } of modArr) {
|
||||
switch (mod.type) {
|
||||
case 1: Commands.set(name.substring(0, name.length - 3), { mod, options: [] }); break;
|
||||
case 2:
|
||||
case 1 | 2: {
|
||||
const options = ((await import(absPath)).options as ApplicationCommandOptionData[])
|
||||
Commands.set(name.substring(0, name.length - 3), { mod, options: options ?? [] });
|
||||
} break;
|
||||
default: throw Error(`${name}.js is not a valid module type.`);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
export async function getCommands(dir: string) : Promise<string[]> {
|
||||
return readPath(join(process.cwd(), dir ))
|
||||
}
|
||||
|
||||
if (mod.alias.length > 0) {
|
||||
for (const alias of mod.alias) {
|
||||
Alias.set(alias, { mod, options: [] })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
export async function getCommands(dir: string): Promise<string[]> {
|
||||
return readPath(join(process.cwd(), dir))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Sern } from "./handler/sern";
|
||||
import { Utils } from "./handler/utils/preprocessors/args"
|
||||
import * as Sern from "./handler/sern";
|
||||
import * as Utils from "./handler/utils/preprocessors/args"
|
||||
import * as Types from "./types/handler/handler"
|
||||
module.exports = { Sern, Utils, Types };
|
||||
export { Sern, Utils, Types };
|
||||
export { Sern, Utils, Types };
|
||||
|
||||
18
src/types/handler/handler.d.ts
vendored
18
src/types/handler/handler.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
import type { Option } from 'ts-results';
|
||||
import type { CommandInteraction, CommandInteractionOptionResolver, Message, MessagePayload, MessageOptions} from 'discord.js';
|
||||
import type { Option } from 'ts-results'
|
||||
import type { CommandInteraction, CommandInteractionOptionResolver, Message, MessagePayload, MessageOptions } from 'discord.js';
|
||||
import type { Sern } from '../../handler/sern';
|
||||
|
||||
export type Visibility = "private" | "public"
|
||||
@@ -11,17 +11,17 @@ export type delegate = Sern.Module<unknown>["delegate"]
|
||||
|
||||
/// Thanks @cursorsdottsx
|
||||
export type ParseType<T> = {
|
||||
[K in keyof T] : T[K] extends unknown ? [k : K, args: T[K] ] : never;
|
||||
[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 = {
|
||||
text : Option<Message>,
|
||||
slash : Option<CommandInteraction>
|
||||
text: Option<Message>,
|
||||
slash: Option<CommandInteraction>
|
||||
}
|
||||
export interface Arg {
|
||||
text : string;
|
||||
slash : SlashOptions
|
||||
};
|
||||
text: string;
|
||||
slash: SlashOptions
|
||||
}
|
||||
// TypeAlias for interaction.options
|
||||
export type SlashOptions = Omit<CommandInteractionOptionResolver, "getMessage" | "getFocused">;
|
||||
export type SlashOptions = Omit<CommandInteractionOptionResolver, "getMessage" | "getFocused">;
|
||||
Reference in New Issue
Block a user