command-ts 0.0.1 → 0.0.2-dev.20260105052257
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -0
- package/LICENSE +1 -1
- package/out/function/CTSError.d.ts +3 -0
- package/out/function/CTSError.js +10 -0
- package/out/function/debug.d.ts +25 -0
- package/out/function/debug.js +73 -0
- package/out/function/index.d.ts +4 -0
- package/out/function/index.js +20 -0
- package/out/function/read-dir.d.ts +2 -0
- package/out/function/read-dir.js +38 -0
- package/out/function/visual.d.ts +1 -0
- package/out/function/visual.js +60 -0
- package/out/handler/button/index.d.ts +3 -0
- package/out/handler/button/index.js +7 -0
- package/out/handler/command/autocomplete.d.ts +3 -0
- package/out/handler/command/autocomplete.js +4 -0
- package/out/handler/command/execute.d.ts +3 -0
- package/out/handler/command/execute.js +45 -0
- package/out/handler/command/fetch-command.d.ts +2 -0
- package/out/handler/command/fetch-command.js +23 -0
- package/out/handler/command/index.d.ts +3 -0
- package/out/handler/command/index.js +22 -0
- package/out/handler/command/register.d.ts +3 -0
- package/out/handler/command/register.js +15 -0
- package/out/handler/event/fetch-event.d.ts +2 -0
- package/out/handler/event/fetch-event.js +27 -0
- package/out/handler/event/index.d.ts +3 -0
- package/out/handler/event/index.js +11 -0
- package/out/handler/event/on-event.d.ts +2 -0
- package/out/handler/event/on-event.js +23 -0
- package/out/handler/index.d.ts +3 -0
- package/out/handler/index.js +36 -0
- package/out/handler/modal/index.d.ts +3 -0
- package/out/handler/modal/index.js +7 -0
- package/out/handler/selectmenu/channel.d.ts +3 -0
- package/out/handler/selectmenu/channel.js +7 -0
- package/out/handler/selectmenu/index.d.ts +3 -0
- package/out/handler/selectmenu/index.js +7 -0
- package/out/handler/selectmenu/mentionable.d.ts +3 -0
- package/out/handler/selectmenu/mentionable.js +7 -0
- package/out/handler/selectmenu/role.d.ts +3 -0
- package/out/handler/selectmenu/role.js +7 -0
- package/out/handler/selectmenu/string.d.ts +3 -0
- package/out/handler/selectmenu/string.js +7 -0
- package/out/handler/selectmenu/user.d.ts +3 -0
- package/out/handler/selectmenu/user.js +7 -0
- package/out/index.d.ts +4 -1
- package/out/index.js +20 -1
- package/out/type.d.ts +26 -0
- package/out/type.js +28 -0
- package/package.json +17 -10
- package/src/function/CTSError.ts +6 -0
- package/src/function/debug.ts +97 -0
- package/src/function/index.ts +4 -0
- package/src/function/read-dir.ts +46 -0
- package/src/function/visual.ts +69 -0
- package/src/handler/button/index.ts +7 -0
- package/src/handler/command/autocomplete.ts +4 -0
- package/src/handler/command/execute.ts +48 -0
- package/src/handler/command/fetch-command.ts +27 -0
- package/src/handler/command/index.ts +26 -0
- package/src/handler/command/register.ts +15 -0
- package/src/handler/event/fetch-event.ts +35 -0
- package/src/handler/event/index.ts +11 -0
- package/src/handler/event/on-event.ts +25 -0
- package/src/handler/index.ts +33 -0
- package/src/handler/modal/index.ts +7 -0
- package/src/handler/selectmenu/channel.ts +7 -0
- package/src/handler/selectmenu/index.ts +7 -0
- package/src/handler/selectmenu/mentionable.ts +7 -0
- package/src/handler/selectmenu/role.ts +7 -0
- package/src/handler/selectmenu/string.ts +7 -0
- package/src/handler/selectmenu/user.ts +7 -0
- package/src/index.ts +4 -0
- package/src/type.ts +81 -0
- package/tsconfig.json +8 -0
- package/README.md +0 -32
package/out/index.d.ts
CHANGED
package/out/index.js
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
17
|
+
exports.version = void 0;
|
|
18
|
+
var package_json_1 = require("../package.json");
|
|
19
|
+
Object.defineProperty(exports, "version", { enumerable: true, get: function () { return package_json_1.version; } });
|
|
20
|
+
__exportStar(require("./function"), exports);
|
|
21
|
+
__exportStar(require("./handler"), exports);
|
|
22
|
+
__exportStar(require("./type"), exports);
|
package/out/type.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AutocompleteInteraction, ChannelSelectMenuInteraction, ChatInputCommandInteraction, Client, ClientEvents, ContextMenuCommandInteraction, MentionableSelectMenuInteraction, RESTPostAPIApplicationCommandsJSONBody, RoleSelectMenuInteraction, StringSelectMenuInteraction, UserSelectMenuInteraction, ModalSubmitInteraction, ButtonInteraction, CommandInteraction, PrimaryEntryPointCommandInteraction } from "discord.js";
|
|
2
|
+
export type Options = {
|
|
3
|
+
client: Client;
|
|
4
|
+
debug?: boolean;
|
|
5
|
+
event?: PathOR<keyof ClientEvents, ((...arg: any) => any) | Array<(...arg: any) => any>>;
|
|
6
|
+
command?: PathOR<string, Command>;
|
|
7
|
+
button?: PathOR<string, (interaction: ButtonInteraction) => any>;
|
|
8
|
+
modal?: PathOR<string, (interaction: ModalSubmitInteraction) => any>;
|
|
9
|
+
selectmenu?: SelectMenu | string;
|
|
10
|
+
middleware?: Array<Middleware> | Middleware;
|
|
11
|
+
};
|
|
12
|
+
export type SelectMenu = {
|
|
13
|
+
StringSelectMenu?: PathOR<string, (interaction: StringSelectMenuInteraction) => any>;
|
|
14
|
+
UserSelectMenu?: PathOR<string, (interaction: UserSelectMenuInteraction) => any>;
|
|
15
|
+
RoleSelectMenu?: PathOR<string, (interaction: RoleSelectMenuInteraction) => any>;
|
|
16
|
+
MentionableSelectMenu?: PathOR<string, (interaction: MentionableSelectMenuInteraction) => any>;
|
|
17
|
+
ChannelSelectMenu?: PathOR<string, (interaction: ChannelSelectMenuInteraction) => any>;
|
|
18
|
+
};
|
|
19
|
+
export type PathOR<key extends string, value extends any> = Map<key, value> | string;
|
|
20
|
+
export type StopFunction = (reason?: string) => void;
|
|
21
|
+
export type Command = {
|
|
22
|
+
data: RESTPostAPIApplicationCommandsJSONBody;
|
|
23
|
+
autocomplete?: (interaction: AutocompleteInteraction) => any;
|
|
24
|
+
run: (interaction: ChatInputCommandInteraction | ContextMenuCommandInteraction | PrimaryEntryPointCommandInteraction) => any;
|
|
25
|
+
};
|
|
26
|
+
export type Middleware = (command: Command, interaction: CommandInteraction, stop: StopFunction) => any;
|
package/out/type.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/*
|
|
4
|
+
export type Handler = {
|
|
5
|
+
events?: string
|
|
6
|
+
commands?: string | CommandHandler
|
|
7
|
+
components?: string | ComponentHandler
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type CommandHandler = {
|
|
11
|
+
ChatInput?: string
|
|
12
|
+
Context?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ComponentHandler = {
|
|
16
|
+
Button?: string
|
|
17
|
+
Modal?: string
|
|
18
|
+
SelectMenu?: string | SelectMenuComponentHandler
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type SelectMenuComponentHandler = {
|
|
22
|
+
StringSelectMenu?: string
|
|
23
|
+
UserSelectMenu?: string
|
|
24
|
+
RoleSelectMenu?: string
|
|
25
|
+
MentionableSelectMenu?: string
|
|
26
|
+
ChannelSelectMenu?: string
|
|
27
|
+
}
|
|
28
|
+
*/
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "command-ts",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2-dev.20260105052257",
|
|
4
4
|
"description": "A package for handling discord.js commands with TypeScript.",
|
|
5
|
-
"author": "
|
|
6
|
-
"homepage": "https://github.com/
|
|
5
|
+
"author": "xcfio",
|
|
6
|
+
"homepage": "https://github.com/xcfio/command-ts#readme",
|
|
7
7
|
"main": "out/index.js",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"keywords": [
|
|
@@ -13,26 +13,33 @@
|
|
|
13
13
|
],
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "https://github.com/
|
|
16
|
+
"url": "https://github.com/xcfio/command-ts"
|
|
17
17
|
},
|
|
18
18
|
"bugs": {
|
|
19
|
-
"url": "https://github.com/
|
|
20
|
-
"email": "
|
|
19
|
+
"url": "https://github.com/xcfio/command-ts/issues",
|
|
20
|
+
"email": "omarfaruksxp@gmail.com"
|
|
21
21
|
},
|
|
22
22
|
"funding": {
|
|
23
23
|
"type": "patreon",
|
|
24
|
-
"url": "https://www.patreon.com/
|
|
24
|
+
"url": "https://www.patreon.com/xcfio"
|
|
25
25
|
},
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public",
|
|
28
28
|
"tag": "latest"
|
|
29
29
|
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"colorette": "^2.0.20",
|
|
32
|
+
"lodash": "^4.17.21"
|
|
33
|
+
},
|
|
30
34
|
"devDependencies": {
|
|
31
|
-
"@types/
|
|
35
|
+
"@types/lodash": "^4.17.14",
|
|
36
|
+
"@types/node": "^25.0.0",
|
|
37
|
+
"discord.js": "^14.17.2",
|
|
38
|
+
"typescript": "^5.7.2"
|
|
32
39
|
},
|
|
33
40
|
"scripts": {
|
|
34
|
-
"fmt": "prettier --config
|
|
35
|
-
"lint": "prettier --config
|
|
41
|
+
"fmt": "prettier --config=../../.prettierrc --write src/",
|
|
42
|
+
"lint": "prettier --config=../../.prettierrc --check src/",
|
|
36
43
|
"build": "(node --eval \"require('node:fs').rmSync('out', { recursive: true, force: true })\" || true) && tsc",
|
|
37
44
|
"test": "tsc --noEmit",
|
|
38
45
|
"dev": "tsc --watch"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { blue, green, yellow, red, gray } from "colorette"
|
|
2
|
+
import { IsDebugEnabled } from "../handler"
|
|
3
|
+
import { inspect } from "node:util"
|
|
4
|
+
|
|
5
|
+
export const enum LogLevel {
|
|
6
|
+
DEBUG = 0,
|
|
7
|
+
INFO = 1,
|
|
8
|
+
WARN = 2,
|
|
9
|
+
ERROR = 3
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type LoggerConfig = {
|
|
13
|
+
minLevel: LogLevel
|
|
14
|
+
includeTimestamp: boolean
|
|
15
|
+
dateFormat: Intl.DateTimeFormatOptions
|
|
16
|
+
timeFormat: Intl.DateTimeFormatOptions
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const defaultConfig: LoggerConfig = {
|
|
20
|
+
minLevel: LogLevel.DEBUG,
|
|
21
|
+
includeTimestamp: true,
|
|
22
|
+
dateFormat: {
|
|
23
|
+
year: "numeric",
|
|
24
|
+
month: "2-digit",
|
|
25
|
+
day: "2-digit"
|
|
26
|
+
},
|
|
27
|
+
timeFormat: {
|
|
28
|
+
hour: "2-digit",
|
|
29
|
+
minute: "2-digit",
|
|
30
|
+
second: "2-digit",
|
|
31
|
+
hour12: false
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const getTimestamp = (config: LoggerConfig): string => {
|
|
36
|
+
if (!config.includeTimestamp) return ""
|
|
37
|
+
|
|
38
|
+
const date = new Date()
|
|
39
|
+
const dateStr = date.toLocaleDateString(undefined, config.dateFormat)
|
|
40
|
+
const timeStr = date.toLocaleTimeString(undefined, config.timeFormat)
|
|
41
|
+
return `[${dateStr} ${timeStr}]`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const shouldLog = (level: string, config: LoggerConfig): boolean => {
|
|
45
|
+
const levelMap: Record<string, LogLevel> = {
|
|
46
|
+
DEBUG: LogLevel.DEBUG,
|
|
47
|
+
INFO: LogLevel.INFO,
|
|
48
|
+
WARN: LogLevel.WARN,
|
|
49
|
+
ERROR: LogLevel.ERROR
|
|
50
|
+
}
|
|
51
|
+
return levelMap[level] >= config.minLevel
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const formatArgs = (args: unknown[]) => {
|
|
55
|
+
if (args.length === 0) return ""
|
|
56
|
+
let str = ""
|
|
57
|
+
|
|
58
|
+
for (const obj of args) {
|
|
59
|
+
str += inspect(obj, { colors: true, depth: Infinity })
|
|
60
|
+
str += " "
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return str
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const createLog = (config: LoggerConfig) => {
|
|
67
|
+
return (
|
|
68
|
+
level: keyof typeof LogLevel,
|
|
69
|
+
color: (str: string) => string,
|
|
70
|
+
message: unknown,
|
|
71
|
+
...args: unknown[]
|
|
72
|
+
): void => {
|
|
73
|
+
if (shouldLog(level, config)) {
|
|
74
|
+
const timestamp = getTimestamp(config)
|
|
75
|
+
const levelStr = color(`[${level}]`)
|
|
76
|
+
const formattedArgs = formatArgs(args)
|
|
77
|
+
|
|
78
|
+
if (IsDebugEnabled) console.log(`${blue(timestamp)} ${levelStr} ${message} ${formattedArgs}`)
|
|
79
|
+
if (level === "WARN") process.emitWarning(`${message}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const createLogger = (customConfig: Partial<LoggerConfig> = {}) => {
|
|
85
|
+
const config = { ...defaultConfig, ...customConfig }
|
|
86
|
+
const log = createLog(config)
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
debug: (message: unknown, ...args: unknown[]) => log("DEBUG", gray, message, ...args),
|
|
90
|
+
info: (message: unknown, ...args: unknown[]) => log("INFO", green, message, ...args),
|
|
91
|
+
warn: (message: unknown, ...args: unknown[]) => log("WARN", yellow, message, ...args),
|
|
92
|
+
error: (message: unknown, ...args: unknown[]) => log("ERROR", red, message, ...args)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const debug = createLogger()
|
|
97
|
+
export { createLogger }
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readdirSync } from "node:fs"
|
|
2
|
+
import { join } from "node:path"
|
|
3
|
+
|
|
4
|
+
export function GetFilePaths(directory: string, nesting?: boolean): string[] {
|
|
5
|
+
let file_paths: string[] = []
|
|
6
|
+
|
|
7
|
+
if (!directory) return file_paths
|
|
8
|
+
|
|
9
|
+
const files = readdirSync(directory, { withFileTypes: true })
|
|
10
|
+
|
|
11
|
+
for (const file of files) {
|
|
12
|
+
const file_path = join(directory, file.name)
|
|
13
|
+
|
|
14
|
+
if (file.isFile()) {
|
|
15
|
+
file_paths.push(file_path)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (nesting && file.isDirectory()) {
|
|
19
|
+
file_paths = [...file_paths, ...GetFilePaths(file_path, true)]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return file_paths
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function GetFolderPaths(directory: string, nesting?: boolean): string[] {
|
|
27
|
+
let folder_paths: string[] = []
|
|
28
|
+
|
|
29
|
+
if (!directory) return folder_paths
|
|
30
|
+
|
|
31
|
+
const folders = readdirSync(directory, { withFileTypes: true })
|
|
32
|
+
|
|
33
|
+
for (const folder of folders) {
|
|
34
|
+
const folder_path = join(directory, folder.name)
|
|
35
|
+
|
|
36
|
+
if (folder.isDirectory()) {
|
|
37
|
+
folder_paths.push(folder_path)
|
|
38
|
+
|
|
39
|
+
if (nesting) {
|
|
40
|
+
folder_paths = [...folder_paths, ...GetFolderPaths(folder_path, true)]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return folder_paths
|
|
46
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { cyan, magenta } from "colorette"
|
|
2
|
+
import path from "path"
|
|
3
|
+
|
|
4
|
+
export function GenerateList(type: string, filePaths: string[], srcDir: string): string {
|
|
5
|
+
const x: string[] = []
|
|
6
|
+
const commandCount = filePaths.length
|
|
7
|
+
|
|
8
|
+
// Create directory structure from file paths
|
|
9
|
+
const directoryStructure: Record<string, any> = {}
|
|
10
|
+
|
|
11
|
+
for (const filePath of filePaths) {
|
|
12
|
+
// Skip files not in src directory
|
|
13
|
+
if (!filePath.startsWith(srcDir)) continue
|
|
14
|
+
|
|
15
|
+
// Get relative path from src
|
|
16
|
+
const relativePath = filePath.substring(srcDir.length + 1)
|
|
17
|
+
const pathParts = relativePath.split(path.sep)
|
|
18
|
+
|
|
19
|
+
// File name without extension
|
|
20
|
+
const fileName = path.basename(pathParts[pathParts.length - 1], ".ts")
|
|
21
|
+
|
|
22
|
+
// Build directory structure
|
|
23
|
+
let currentLevel = directoryStructure
|
|
24
|
+
|
|
25
|
+
// Process each directory in the path
|
|
26
|
+
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
27
|
+
const part = pathParts[i]
|
|
28
|
+
|
|
29
|
+
if (!currentLevel[part]) {
|
|
30
|
+
currentLevel[part] = { __files: [] }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
currentLevel = currentLevel[part]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Add file to the current directory
|
|
37
|
+
currentLevel.__files.push(fileName)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Generate formatted command list from directory structure
|
|
41
|
+
function processStructure(structure: Record<string, any>, level: number = 0): void {
|
|
42
|
+
// Process directories first
|
|
43
|
+
for (const dir in structure) {
|
|
44
|
+
if (dir === "__files") continue
|
|
45
|
+
|
|
46
|
+
const indent = " ".repeat(level)
|
|
47
|
+
x.push(`${indent}├─ ${cyan(dir)}`)
|
|
48
|
+
|
|
49
|
+
// Process subdirectories and files
|
|
50
|
+
processStructure(structure[dir], level + 1)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Process files
|
|
54
|
+
if (structure.__files) {
|
|
55
|
+
const indent = " ".repeat(level)
|
|
56
|
+
for (const file of structure.__files) {
|
|
57
|
+
x.push(`${indent}├─ ${cyan(file)}`)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Generate command list
|
|
63
|
+
processStructure(directoryStructure)
|
|
64
|
+
|
|
65
|
+
// Add summary at the beginning
|
|
66
|
+
x.unshift(`Loaded ${magenta(commandCount.toString())} ${type}:`)
|
|
67
|
+
|
|
68
|
+
return x.join("\n")
|
|
69
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Command, Middleware, StopFunction } from "../../type"
|
|
2
|
+
import { debug } from "../../function"
|
|
3
|
+
import { Interaction } from "discord.js"
|
|
4
|
+
|
|
5
|
+
export async function execute(commands: Map<string, Command>, interaction: Interaction, middleware: Array<Middleware>) {
|
|
6
|
+
if (!interaction.isCommand()) return
|
|
7
|
+
|
|
8
|
+
const command = commands.get(interaction.commandName)
|
|
9
|
+
if (!command) return
|
|
10
|
+
|
|
11
|
+
const { run } = command
|
|
12
|
+
if (!run || typeof run !== "function") {
|
|
13
|
+
return debug.warn(`Command ${interaction.commandName} does not have a run function`, { command })
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (middleware && middleware.length) {
|
|
17
|
+
let ShouldStop = false
|
|
18
|
+
let reason
|
|
19
|
+
|
|
20
|
+
const stop: StopFunction = (text?: string) => {
|
|
21
|
+
ShouldStop = true
|
|
22
|
+
if (text) {
|
|
23
|
+
reason = text
|
|
24
|
+
} else {
|
|
25
|
+
reason = "No reason provided"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let index = 0
|
|
30
|
+
|
|
31
|
+
for (; index < middleware.length; index++) {
|
|
32
|
+
const fn = middleware[index]
|
|
33
|
+
await fn(command, interaction, stop)
|
|
34
|
+
if (ShouldStop) break
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (ShouldStop) {
|
|
38
|
+
return debug.info(`A middleware stopped execution`, { index, reason })
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
await run(interaction)
|
|
44
|
+
} catch (error) {
|
|
45
|
+
debug.error(`Error in command ${interaction.commandName} (${interaction.id})`, { error })
|
|
46
|
+
throw error
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GetFilePaths, debug, GenerateList } from "../../function"
|
|
2
|
+
import { Command } from "../../type"
|
|
3
|
+
|
|
4
|
+
export function ftc_command(data: string) {
|
|
5
|
+
const files = GetFilePaths(data, true).filter((path) => path.endsWith(".js") || path.endsWith(".ts"))
|
|
6
|
+
const commands = new Map<string, Command>()
|
|
7
|
+
|
|
8
|
+
for (const file of files) {
|
|
9
|
+
const command: Command = require(file)
|
|
10
|
+
if (!("data" in command)) {
|
|
11
|
+
debug.warn(`Ignoring: Command ${file} does not export "data".`, { command })
|
|
12
|
+
continue
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!("run" in command)) {
|
|
16
|
+
debug.warn(`Ignoring: Command ${file} does not export "run".`, { command })
|
|
17
|
+
continue
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
commands.set(command.data.name, command)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
debug.debug(`${GenerateList("commands", files, data)}`)
|
|
24
|
+
debug.debug(`Found ${commands.size} commands`, { commands })
|
|
25
|
+
|
|
26
|
+
return commands
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { autocomplete } from "./autocomplete"
|
|
2
|
+
import { ftc_command } from "./fetch-command"
|
|
3
|
+
import { debug } from "../../function"
|
|
4
|
+
import { register } from "./register"
|
|
5
|
+
import { Options } from "../../type"
|
|
6
|
+
import { execute } from "./execute"
|
|
7
|
+
import { Client, InteractionType } from "discord.js"
|
|
8
|
+
import { isMap } from "lodash"
|
|
9
|
+
|
|
10
|
+
export function command_handler(
|
|
11
|
+
data: NonNullable<Options["command"]>,
|
|
12
|
+
client: Client,
|
|
13
|
+
middleware: Options["middleware"]
|
|
14
|
+
) {
|
|
15
|
+
if (middleware) middleware = typeof middleware === "function" ? [middleware] : middleware
|
|
16
|
+
const commands = isMap(data) ? data : ftc_command(data)
|
|
17
|
+
|
|
18
|
+
client.on("ready", async (client) => await register(commands, client))
|
|
19
|
+
client.on("interactionCreate", async (interaction) => {
|
|
20
|
+
debug.info(`Command handler triggered`, { id: interaction.id, type: InteractionType[interaction.type] })
|
|
21
|
+
await execute(commands, interaction, middleware ?? ([] as any))
|
|
22
|
+
await autocomplete(commands, interaction)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
debug.info("Command handler loaded")
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Client } from "discord.js"
|
|
2
|
+
import { Command } from "../../type"
|
|
3
|
+
import { debug } from "../../function"
|
|
4
|
+
|
|
5
|
+
export async function register(commands: Map<string, Command>, client: Client<true>) {
|
|
6
|
+
const cmd = Array.from(commands.values()).map((c) => c.data)
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
await client.application.commands.set(cmd)
|
|
10
|
+
debug.info(`Successfully reloaded ${cmd.length} application (/) commands.`)
|
|
11
|
+
} catch (error: any) {
|
|
12
|
+
debug.error(`Error reloading application (/) commands`)
|
|
13
|
+
throw error
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { GetFolderPaths, GetFilePaths, debug, GenerateList } from "../../function"
|
|
2
|
+
import { ClientEvents } from "discord.js"
|
|
3
|
+
|
|
4
|
+
export function ftc_event(data: string) {
|
|
5
|
+
const EventFolderPaths = GetFolderPaths(data)
|
|
6
|
+
const FilePaths = []
|
|
7
|
+
const event = new Map<keyof ClientEvents, Array<(...arg: any) => any>>()
|
|
8
|
+
|
|
9
|
+
for (const EventFolderPath of EventFolderPaths) {
|
|
10
|
+
const eventName = EventFolderPath.replace(/\\/g, "/").split("/").pop() as string
|
|
11
|
+
|
|
12
|
+
const EventFilePaths = GetFilePaths(EventFolderPath, true).filter(
|
|
13
|
+
(path) => path.endsWith(".js") || path.endsWith(".ts")
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
const fun: Array<(...arg: any) => any> = []
|
|
17
|
+
for (const EventFilePath of EventFilePaths) {
|
|
18
|
+
const obj = require(EventFilePath)
|
|
19
|
+
const fn = typeof obj === "function" ? obj : obj.default
|
|
20
|
+
|
|
21
|
+
if (typeof fn !== "function") {
|
|
22
|
+
debug.warn(`Ignoring: Event ${EventFilePath} does not export a function.`, { obj })
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
FilePaths.push(EventFilePath)
|
|
27
|
+
fun.push(fn)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
event.set(eventName as any, fun)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
debug.debug(`${GenerateList("events", FilePaths, data)}`)
|
|
34
|
+
return event
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ftc_event } from "./fetch-event"
|
|
2
|
+
import { debug } from "../../function"
|
|
3
|
+
import { Options } from "../../type"
|
|
4
|
+
import { OnEvent } from "./on-event"
|
|
5
|
+
import { Client } from "discord.js"
|
|
6
|
+
import { isMap } from "lodash"
|
|
7
|
+
|
|
8
|
+
export function event_handler(data: NonNullable<Options["event"]>, client: Client) {
|
|
9
|
+
OnEvent(client, isMap(data) ? data : ftc_event(data))
|
|
10
|
+
debug.info("Event handler loaded")
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { debug, CTSError } from "../../function"
|
|
2
|
+
import { Client, ClientEvents } from "discord.js"
|
|
3
|
+
import { isMap } from "lodash"
|
|
4
|
+
|
|
5
|
+
export function OnEvent(
|
|
6
|
+
client: Client,
|
|
7
|
+
map: Map<keyof ClientEvents, ((...arg: any) => any) | Array<(...arg: any) => any>>
|
|
8
|
+
) {
|
|
9
|
+
if (!isMap(map)) {
|
|
10
|
+
debug.error("Event handler must be a Map", { received: map })
|
|
11
|
+
throw new CTSError("Event handler must be a Map")
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
for (const [name, fn] of map) {
|
|
15
|
+
const func = typeof fn === "function" ? [fn] : fn
|
|
16
|
+
for (const fn of func) {
|
|
17
|
+
if (typeof fn === "function") {
|
|
18
|
+
client.on(name, (...arg) => fn(...arg, client))
|
|
19
|
+
} else {
|
|
20
|
+
debug.error("Event handler must be a function", `name: ${name}`, `function: ${fn}`)
|
|
21
|
+
throw new CTSError("Event handler must be a function")
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { selectmenu_handler } from "./selectmenu"
|
|
2
|
+
import { CTSError, debug } from "../function"
|
|
3
|
+
import { command_handler } from "./command"
|
|
4
|
+
import { button_handler } from "./button"
|
|
5
|
+
import { event_handler } from "./event"
|
|
6
|
+
import { modal_handler } from "./modal"
|
|
7
|
+
import { Options } from "../type"
|
|
8
|
+
import { version } from "discord.js"
|
|
9
|
+
|
|
10
|
+
export let IsDebugEnabled = false
|
|
11
|
+
|
|
12
|
+
export function handler({ debug: dbg, client, event, command, button, modal, selectmenu, middleware }: Options) {
|
|
13
|
+
const djs = Number(version.split(".").reduce((x, y, i) => (i === 2 ? x : `${x}.${y}`)))
|
|
14
|
+
IsDebugEnabled = typeof dbg === "boolean" ? dbg : false
|
|
15
|
+
|
|
16
|
+
if (djs < 14 || djs > 15) {
|
|
17
|
+
debug.warn("Your discord.js version might not be fully supported by command-ts handler")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!client) {
|
|
21
|
+
debug.error("Client is required", { received: client })
|
|
22
|
+
throw new CTSError("Client is required")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (event) event_handler(event, client)
|
|
26
|
+
if (button) button_handler(button, client)
|
|
27
|
+
if (modal) modal_handler(modal, client)
|
|
28
|
+
if (selectmenu) selectmenu_handler(selectmenu, client)
|
|
29
|
+
if (command) command_handler(command, client, middleware)
|
|
30
|
+
debug.info("All Handler loaded")
|
|
31
|
+
// if (interaction_validator) interaction_validator_handler(interaction_validator, client)
|
|
32
|
+
// if (message_validator) message_validator_handler(message_validator, client)
|
|
33
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Client } from "discord.js"
|
|
2
|
+
import { SelectMenu } from "../../type"
|
|
3
|
+
import { debug } from "../../function"
|
|
4
|
+
|
|
5
|
+
export function mentionable_handler(data: SelectMenu["MentionableSelectMenu"], client: Client) {
|
|
6
|
+
debug.info("Mentionable select menu handler loaded")
|
|
7
|
+
}
|