meocord 1.2.1 → 1.2.2
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/CHANGELOG.md +35 -0
- package/README.md +152 -140
- package/dist/cjs/_shared/meocord.app-CHjdCAA_.cjs +496 -0
- package/dist/cjs/_shared/theme-BdtbtMZX.cjs +176 -0
- package/dist/cjs/common/index.cjs +16 -0
- package/dist/cjs/core/index.cjs +35 -0
- package/dist/cjs/decorator/index.cjs +360 -0
- package/dist/cjs/enum/index.cjs +20 -0
- package/dist/cjs/interface/index.cjs +2 -0
- package/dist/esm/bin/generator.js +92 -0
- package/dist/esm/bin/helper/controller-generator.helper.js +105 -0
- package/dist/esm/bin/helper/guard-generator.helper.js +33 -0
- package/dist/esm/bin/helper/service-generator.helper.js +33 -0
- package/dist/esm/bin/meocord.js +333 -0
- package/dist/esm/common/index.js +2 -0
- package/dist/esm/common/logger.js +72 -0
- package/dist/{core/index.d.ts → esm/common/theme.js} +8 -2
- package/dist/esm/core/index.js +1 -0
- package/dist/esm/core/meocord-factory.js +28 -0
- package/dist/esm/core/meocord.app.js +267 -0
- package/dist/esm/decorator/app.decorator.js +99 -0
- package/dist/esm/decorator/command-builder.decorator.js +32 -0
- package/dist/esm/decorator/container.js +6 -0
- package/dist/esm/decorator/controller.decorator.js +218 -0
- package/dist/esm/decorator/guard.decorator.js +165 -0
- package/dist/esm/decorator/index.js +6 -0
- package/dist/esm/decorator/service.decorator.js +58 -0
- package/dist/esm/enum/controller.enum.js +43 -0
- package/dist/esm/enum/index.js +1 -0
- package/dist/esm/interface/index.js +1 -0
- package/dist/esm/package.json.js +5 -0
- package/dist/esm/util/common.util.js +68 -0
- package/dist/esm/util/embed.util.js +13 -0
- package/dist/esm/util/generator-cli.util.js +107 -0
- package/dist/{util → esm/util}/json.util.js +10 -6
- package/dist/esm/util/meocord-cli.util.js +172 -0
- package/dist/esm/util/meocord-config-loader.util.js +48 -0
- package/dist/esm/util/tsconfig.util.js +83 -0
- package/dist/{util → esm/util}/wait.util.js +5 -1
- package/dist/{common/logger.d.ts → types/common/index.d.ts} +30 -1
- package/dist/{core/meocord.app.d.ts → types/core/index.d.ts} +30 -2
- package/dist/types/decorator/index.d.ts +425 -0
- package/dist/types/enum/index.d.ts +18 -0
- package/dist/{interface → types/interface}/index.d.ts +11 -7
- package/package.json +64 -48
- package/webpack.config.js +2 -2
- package/dist/bin/generator.d.ts +0 -29
- package/dist/bin/generator.js +0 -17
- package/dist/bin/helper/controller-generator.helper.d.ts +0 -67
- package/dist/bin/helper/controller-generator.helper.js +0 -50
- package/dist/bin/helper/guard-generator.helper.d.ts +0 -32
- package/dist/bin/helper/guard-generator.helper.js +0 -25
- package/dist/bin/helper/service-generator.helper.d.ts +0 -32
- package/dist/bin/helper/service-generator.helper.js +0 -25
- package/dist/bin/meocord.d.ts +0 -19
- package/dist/bin/meocord.js +0 -34
- package/dist/common/index.d.ts +0 -19
- package/dist/common/index.js +0 -17
- package/dist/common/logger.js +0 -17
- package/dist/common/theme.d.ts +0 -24
- package/dist/common/theme.js +0 -17
- package/dist/core/index.js +0 -17
- package/dist/core/meocord-factory.d.ts +0 -24
- package/dist/core/meocord-factory.js +0 -17
- package/dist/core/meocord.app.js +0 -17
- package/dist/decorator/app.decorator.d.ts +0 -59
- package/dist/decorator/app.decorator.js +0 -61
- package/dist/decorator/command-builder.decorator.d.ts +0 -39
- package/dist/decorator/command-builder.decorator.js +0 -35
- package/dist/decorator/container.d.ts +0 -20
- package/dist/decorator/container.js +0 -17
- package/dist/decorator/controller.decorator.d.ts +0 -125
- package/dist/decorator/controller.decorator.js +0 -113
- package/dist/decorator/guard.decorator.d.ts +0 -101
- package/dist/decorator/guard.decorator.js +0 -94
- package/dist/decorator/index.d.ts +0 -23
- package/dist/decorator/index.js +0 -17
- package/dist/decorator/service.decorator.d.ts +0 -36
- package/dist/decorator/service.decorator.js +0 -36
- package/dist/enum/controller.enum.d.ts +0 -42
- package/dist/enum/controller.enum.js +0 -19
- package/dist/enum/index.d.ts +0 -18
- package/dist/enum/index.js +0 -17
- package/dist/interface/command-decorator.interface.d.ts +0 -43
- package/dist/interface/command-decorator.interface.js +0 -1
- package/dist/interface/index.js +0 -1
- package/dist/util/common.util.d.ts +0 -40
- package/dist/util/common.util.js +0 -38
- package/dist/util/embed.util.d.ts +0 -19
- package/dist/util/embed.util.js +0 -17
- package/dist/util/generator-cli.util.d.ts +0 -65
- package/dist/util/generator-cli.util.js +0 -49
- package/dist/util/index.d.ts +0 -18
- package/dist/util/index.js +0 -17
- package/dist/util/json.util.d.ts +0 -27
- package/dist/util/meocord-cli.util.d.ts +0 -62
- package/dist/util/meocord-cli.util.js +0 -50
- package/dist/util/meocord-config-loader.util.d.ts +0 -32
- package/dist/util/meocord-config-loader.util.js +0 -34
- package/dist/util/tsconfig.util.d.ts +0 -29
- package/dist/util/tsconfig.util.js +0 -32
- package/dist/util/wait.util.d.ts +0 -18
- /package/dist/{bin → esm/bin}/builder-template/builder/context-menu.builder.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/builder/slash.builder.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/button.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/context-menu.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/message.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/modal-submit.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/reaction.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/select-menu.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/controller/slash.controller.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/guard.template +0 -0
- /package/dist/{bin → esm/bin}/builder-template/service.template +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { createJiti } from 'jiti';
|
|
4
|
+
import { fixJSON } from './json.util.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Loads the MeoCord configuration file (meocord.config.ts) directly at runtime
|
|
8
|
+
* using jiti, without a separate compilation step.
|
|
9
|
+
*
|
|
10
|
+
* @returns {MeoCordConfig | undefined} The loaded configuration object, or undefined if loading fails.
|
|
11
|
+
*/ function loadMeoCordConfig() {
|
|
12
|
+
const configPath = path.resolve(process.cwd(), 'meocord.config.ts');
|
|
13
|
+
if (!existsSync(configPath)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
// Read user's tsconfig.json to extract path aliases for jiti
|
|
18
|
+
const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json');
|
|
19
|
+
const aliases = {};
|
|
20
|
+
if (existsSync(tsConfigPath)) {
|
|
21
|
+
const tsConfig = JSON.parse(fixJSON(readFileSync(tsConfigPath, 'utf-8')));
|
|
22
|
+
const paths = tsConfig?.compilerOptions?.paths;
|
|
23
|
+
if (paths) {
|
|
24
|
+
for (const [key, values] of Object.entries(paths)){
|
|
25
|
+
// Convert TS path alias format "@src/*" -> ["./src/*"] to jiti alias format
|
|
26
|
+
const aliasKey = key.replace('/*', '');
|
|
27
|
+
const aliasValue = path.resolve(process.cwd(), values[0].replace('/*', ''));
|
|
28
|
+
aliases[aliasKey] = aliasValue;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const jiti = createJiti(import.meta.url, {
|
|
33
|
+
interopDefault: true,
|
|
34
|
+
alias: aliases,
|
|
35
|
+
moduleCache: false
|
|
36
|
+
});
|
|
37
|
+
return jiti(configPath);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (error instanceof Error) {
|
|
40
|
+
console.error(`[MeoCord] Failed to load config: ${error.message}`);
|
|
41
|
+
} else {
|
|
42
|
+
console.error(`[MeoCord] Failed to load config: Unknown error`);
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { loadMeoCordConfig };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import { Logger } from '../common/logger.js';
|
|
4
|
+
import '../common/theme.js';
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
|
+
import { fixJSON } from './json.util.js';
|
|
7
|
+
|
|
8
|
+
const logger = new Logger();
|
|
9
|
+
/**
|
|
10
|
+
* Prepares and modifies the project's `tsconfig.json` file for usage with tools like Webpack.
|
|
11
|
+
* - Verifies the existence of `tsconfig.json`.
|
|
12
|
+
* - Fixes invalid JSON if necessary by correcting formatting issues like comments or trailing commas.
|
|
13
|
+
* - Updates paths in `compilerOptions` and other sections to absolute paths.
|
|
14
|
+
* - Removes the `noEmit` option if present in `compilerOptions`.
|
|
15
|
+
* - Writes the modified `tsconfig.json` to a temporary location.
|
|
16
|
+
*
|
|
17
|
+
* @returns {string} The absolute path to the generated temporary `tsconfig.json`.
|
|
18
|
+
* @throws {Error} When `tsconfig.json` is missing or cannot be fixed/parsing fails.
|
|
19
|
+
*/ function prepareModifiedTsConfig() {
|
|
20
|
+
const tsConfigPath = path.resolve(process.cwd(), 'tsconfig.json');
|
|
21
|
+
// Ensure tsconfig.json exists
|
|
22
|
+
if (!existsSync(tsConfigPath)) {
|
|
23
|
+
throw new Error(`tsconfig.json not found in: ${process.cwd()}`);
|
|
24
|
+
}
|
|
25
|
+
const tsConfigContent = readFileSync(tsConfigPath, 'utf-8');
|
|
26
|
+
let parsedConfig;
|
|
27
|
+
try {
|
|
28
|
+
parsedConfig = JSON.parse(tsConfigContent);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
logger.warn('Invalid JSON detected in tsconfig.json!', error);
|
|
31
|
+
logger.log('Attempting to fix JSON...');
|
|
32
|
+
try {
|
|
33
|
+
const fixedContent = fixJSON(tsConfigContent);
|
|
34
|
+
parsedConfig = JSON.parse(fixedContent);
|
|
35
|
+
writeFileSync(tsConfigPath, fixedContent, 'utf-8');
|
|
36
|
+
logger.info('Fixed and updated tsconfig.json successfully.');
|
|
37
|
+
} catch (fixError) {
|
|
38
|
+
throw new Error(`Failed to parse tsconfig.json, even after attempting to fix: ${fixError instanceof Error ? fixError.message : fixError}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Process compilerOptions
|
|
42
|
+
if (parsedConfig?.compilerOptions) {
|
|
43
|
+
const pathOptions = [
|
|
44
|
+
'outDir',
|
|
45
|
+
'rootDir',
|
|
46
|
+
'baseUrl',
|
|
47
|
+
'tsBuildInfoFile'
|
|
48
|
+
];
|
|
49
|
+
// Convert relative paths to absolute paths in `compilerOptions`
|
|
50
|
+
pathOptions.forEach((option)=>{
|
|
51
|
+
if (parsedConfig.compilerOptions[option]) {
|
|
52
|
+
parsedConfig.compilerOptions[option] = path.resolve(process.cwd(), parsedConfig.compilerOptions[option]);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const additionalKeys = [
|
|
56
|
+
'include',
|
|
57
|
+
'exclude',
|
|
58
|
+
'typeRoots'
|
|
59
|
+
];
|
|
60
|
+
// Convert relative paths to absolute paths in additional keys
|
|
61
|
+
additionalKeys.forEach((key)=>{
|
|
62
|
+
if (parsedConfig[key]) {
|
|
63
|
+
parsedConfig[key] = parsedConfig[key].map((p)=>path.resolve(process.cwd(), p));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Resolve path mappings in `paths` if present
|
|
67
|
+
if (parsedConfig.compilerOptions.paths) {
|
|
68
|
+
Object.keys(parsedConfig.compilerOptions.paths).forEach((alias)=>{
|
|
69
|
+
parsedConfig.compilerOptions.paths[alias] = parsedConfig.compilerOptions.paths[alias].map((p)=>path.resolve(process.cwd(), p));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// Remove `noEmit` option if it exists
|
|
73
|
+
if ('noEmit' in parsedConfig.compilerOptions) {
|
|
74
|
+
delete parsedConfig.compilerOptions.noEmit;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Write the modified configuration to a temporary location for usage
|
|
78
|
+
const tempTsConfigPath = path.resolve(path.join(tmpdir(), 'modified-tsconfig.json'));
|
|
79
|
+
writeFileSync(tempTsConfigPath, JSON.stringify(parsedConfig, null, 2));
|
|
80
|
+
return tempTsConfigPath;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { prepareModifiedTsConfig };
|
|
@@ -14,4 +14,8 @@
|
|
|
14
14
|
*
|
|
15
15
|
* You should have received a copy of the GNU General Public License
|
|
16
16
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
-
*/
|
|
17
|
+
*/ function wait(ms) {
|
|
18
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { wait as default };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ColorResolvable } from 'discord.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* MeoCord Framework
|
|
3
5
|
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
@@ -15,7 +17,7 @@
|
|
|
15
17
|
* You should have received a copy of the GNU General Public License
|
|
16
18
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
19
|
*/
|
|
18
|
-
|
|
20
|
+
declare class Logger {
|
|
19
21
|
private context?;
|
|
20
22
|
private readonly colorMap;
|
|
21
23
|
constructor(context?: string | undefined);
|
|
@@ -28,3 +30,30 @@ export declare class Logger {
|
|
|
28
30
|
private formatMessage;
|
|
29
31
|
private logWithContext;
|
|
30
32
|
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* MeoCord Framework
|
|
36
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
37
|
+
*
|
|
38
|
+
* This program is free software: you can redistribute it and/or modify
|
|
39
|
+
* it under the terms of the GNU General Public License as published by
|
|
40
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
41
|
+
* (at your option) any later version.
|
|
42
|
+
*
|
|
43
|
+
* This program is distributed in the hope that it will be useful,
|
|
44
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
45
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
46
|
+
* GNU General Public License for more details.
|
|
47
|
+
*
|
|
48
|
+
* You should have received a copy of the GNU General Public License
|
|
49
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
declare class Theme {
|
|
53
|
+
static successColor: ColorResolvable;
|
|
54
|
+
static infoColor: ColorResolvable;
|
|
55
|
+
static errorColor: ColorResolvable;
|
|
56
|
+
static warningColor: ColorResolvable;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { Logger, Theme };
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { ServiceIdentifier } from 'inversify';
|
|
2
|
+
import { Client, ActivityOptions } from 'discord.js';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* MeoCord Framework
|
|
3
6
|
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
@@ -15,8 +18,8 @@
|
|
|
15
18
|
* You should have received a copy of the GNU General Public License
|
|
16
19
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
20
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
declare class MeoCordApp {
|
|
20
23
|
private readonly controllers;
|
|
21
24
|
private readonly discordClient;
|
|
22
25
|
private discordToken;
|
|
@@ -34,3 +37,28 @@ export declare class MeoCordApp {
|
|
|
34
37
|
private handleReaction;
|
|
35
38
|
private gracefulShutdown;
|
|
36
39
|
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* MeoCord Framework
|
|
43
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
44
|
+
*
|
|
45
|
+
* This program is free software: you can redistribute it and/or modify
|
|
46
|
+
* it under the terms of the GNU General Public License as published by
|
|
47
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
48
|
+
* (at your option) any later version.
|
|
49
|
+
*
|
|
50
|
+
* This program is distributed in the hope that it will be useful,
|
|
51
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
52
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
53
|
+
* GNU General Public License for more details.
|
|
54
|
+
*
|
|
55
|
+
* You should have received a copy of the GNU General Public License
|
|
56
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
declare class MeoCordFactory {
|
|
60
|
+
private static logger;
|
|
61
|
+
static create(target: ServiceIdentifier): MeoCordApp;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { MeoCordFactory };
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { CommandType } from '../enum/index.js';
|
|
2
|
+
import { SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder, ContextMenuCommandBuilder, ButtonInteraction, StringSelectMenuInteraction, ChatInputCommandInteraction, UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, ModalSubmitInteraction, OmitPartialGroupDMChannel, Message, MessageReaction, PartialMessageReaction, ClientOptions, ActivityOptions } from 'discord.js';
|
|
3
|
+
import { ReactionHandlerOptions, GuardInterface } from '../interface/index.js';
|
|
4
|
+
import { ServiceIdentifier, Container } from 'inversify';
|
|
5
|
+
import 'webpack';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* MeoCord Framework
|
|
9
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
10
|
+
*
|
|
11
|
+
* This program is free software: you can redistribute it and/or modify
|
|
12
|
+
* it under the terms of the GNU General Public License as published by
|
|
13
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
14
|
+
* (at your option) any later version.
|
|
15
|
+
*
|
|
16
|
+
* This program is distributed in the hope that it will be useful,
|
|
17
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19
|
+
* GNU General Public License for more details.
|
|
20
|
+
*
|
|
21
|
+
* You should have received a copy of the GNU General Public License
|
|
22
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `@Service()` decorator to mark a class as a service that can be injected into controllers or used as standalone services.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* @Service()
|
|
31
|
+
* class MyService {
|
|
32
|
+
* constructor(private anotherService: AnotherService) {}
|
|
33
|
+
*
|
|
34
|
+
* doSomething() {
|
|
35
|
+
* this.anotherService.alsoDoSomething()
|
|
36
|
+
* console.log('Hello, World!')
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
* @returns A decorator function to apply to the class.
|
|
41
|
+
*/
|
|
42
|
+
declare function Service<T>(): (target: new (...args: any[]) => T) => void;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* MeoCord Framework
|
|
46
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
47
|
+
*
|
|
48
|
+
* This program is free software: you can redistribute it and/or modify
|
|
49
|
+
* it under the terms of the GNU General Public License as published by
|
|
50
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
51
|
+
* (at your option) any later version.
|
|
52
|
+
*
|
|
53
|
+
* This program is distributed in the hope that it will be useful,
|
|
54
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
55
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
56
|
+
* GNU General Public License for more details.
|
|
57
|
+
*
|
|
58
|
+
* You should have received a copy of the GNU General Public License
|
|
59
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Base interface for a command builder.
|
|
64
|
+
*/
|
|
65
|
+
interface CommandBuilderBase<T extends CommandType.SLASH | CommandType.CONTEXT_MENU = CommandType.SLASH | CommandType.CONTEXT_MENU> {
|
|
66
|
+
/**
|
|
67
|
+
* Builds the command structure using the specified command name.
|
|
68
|
+
*
|
|
69
|
+
* @param commandName - The name of the command.
|
|
70
|
+
* @returns A SlashCommandBuilder or ContextMenuCommandBuilder instance.
|
|
71
|
+
*/
|
|
72
|
+
build: (commandName: string) => T extends CommandType.SLASH ? SlashCommandBuilder | SlashCommandSubcommandsOnlyBuilder : T extends CommandType.CONTEXT_MENU ? ContextMenuCommandBuilder : never;
|
|
73
|
+
}
|
|
74
|
+
type CommandBuilderConstructor<T extends CommandType.SLASH | CommandType.CONTEXT_MENU> = new () => CommandBuilderBase<T>;
|
|
75
|
+
/**
|
|
76
|
+
* Command metadata describing a registered command method.
|
|
77
|
+
*/
|
|
78
|
+
interface CommandMetadata<T extends string = string> {
|
|
79
|
+
methodName: string;
|
|
80
|
+
builder: ReturnType<CommandBuilderBase['build']> | undefined;
|
|
81
|
+
type: CommandType;
|
|
82
|
+
regex?: RegExp;
|
|
83
|
+
dynamicParams?: T[];
|
|
84
|
+
}
|
|
85
|
+
type CommandInteractionType<CBC extends CommandType.SLASH | CommandType.CONTEXT_MENU, T extends CommandBuilderConstructor<CBC> | CommandType> = T extends CommandType.BUTTON ? ButtonInteraction : T extends CommandType.SELECT_MENU ? StringSelectMenuInteraction : T extends CommandBuilderConstructor<CommandType.SLASH> ? ChatInputCommandInteraction : T extends CommandBuilderConstructor<CommandType.CONTEXT_MENU> ? UserContextMenuCommandInteraction | MessageContextMenuCommandInteraction : T extends CommandType.MODAL_SUBMIT ? ModalSubmitInteraction : never;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* MeoCord Framework
|
|
89
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
90
|
+
*
|
|
91
|
+
* This program is free software: you can redistribute it and/or modify
|
|
92
|
+
* it under the terms of the GNU General Public License as published by
|
|
93
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
94
|
+
* (at your option) any later version.
|
|
95
|
+
*
|
|
96
|
+
* This program is distributed in the hope that it will be useful,
|
|
97
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
98
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
99
|
+
* GNU General Public License for more details.
|
|
100
|
+
*
|
|
101
|
+
* You should have received a copy of the GNU General Public License
|
|
102
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* This decorator is used to mark a class as a Discord command builder that later can be registered on the `@Command` decorator.
|
|
107
|
+
* It defines the command type using metadata and dynamically makes the class injectable if it isn't already.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* @CommandBuilder(CommandType.SLASH)
|
|
112
|
+
* export class MySlashCommand implements CommandBuilderBase {
|
|
113
|
+
* build(commandName: string): SlashCommandBuilder {
|
|
114
|
+
* return new SlashCommandBuilder().setName(commandName).setDescription('A sample slash command')
|
|
115
|
+
* }
|
|
116
|
+
* }
|
|
117
|
+
*```
|
|
118
|
+
*
|
|
119
|
+
* @param commandType - The type of the command, specified from the `CommandType` enum.
|
|
120
|
+
* @returns A decorator function that makes the target class injectable
|
|
121
|
+
* and assigns the `commandType` metadata.
|
|
122
|
+
*/
|
|
123
|
+
declare function CommandBuilder<T extends CommandType.SLASH | CommandType.CONTEXT_MENU>(commandType: T): (target: new () => CommandBuilderBase<T>) => void;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* MeoCord Framework
|
|
127
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
128
|
+
*
|
|
129
|
+
* This program is free software: you can redistribute it and/or modify
|
|
130
|
+
* it under the terms of the GNU General Public License as published by
|
|
131
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
132
|
+
* (at your option) any later version.
|
|
133
|
+
*
|
|
134
|
+
* This program is distributed in the hope that it will be useful,
|
|
135
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
136
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
137
|
+
* GNU General Public License for more details.
|
|
138
|
+
*
|
|
139
|
+
* You should have received a copy of the GNU General Public License
|
|
140
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Decorator to register message handlers in the controller.
|
|
145
|
+
*
|
|
146
|
+
* @param keyword - An optional keyword to filter messages this handler should respond to.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* @MessageHandler('hello')
|
|
151
|
+
* async handleHelloMessage(message: Message) {
|
|
152
|
+
* await message.reply('Hello! How can I help you?');
|
|
153
|
+
* }
|
|
154
|
+
*
|
|
155
|
+
* @MessageHandler()
|
|
156
|
+
* async handleAnyMessage(message: Message) {
|
|
157
|
+
* console.log(`Received a message: ${message.content}`);
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
declare function MessageHandler<T extends OmitPartialGroupDMChannel<Message<boolean>>, R extends void | Promise<void>>(keyword?: string): (target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<(message: T) => R>) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Decorator to register reaction handlers in the controller.
|
|
164
|
+
*
|
|
165
|
+
* @param emoji - Optional emoji name to filter reactions this handler should respond to.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* @ReactionHandler('👍')
|
|
170
|
+
* async handleThumbsUpReaction(reaction: MessageReaction, { user }: ReactionHandlerOptions) {
|
|
171
|
+
* console.log(`User ${user.username} reacted with 👍`);
|
|
172
|
+
* }
|
|
173
|
+
*
|
|
174
|
+
* @ReactionHandler()
|
|
175
|
+
* async handleAnyReaction(reaction: MessageReaction, { user }: ReactionHandlerOptions) {
|
|
176
|
+
* console.log(`User ${user.username} reacted with ${reaction.emoji.name}`);
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare function ReactionHandler<T extends MessageReaction | PartialMessageReaction, R extends void | Promise<void>>(emoji?: string): (target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<(reaction: T, options: ReactionHandlerOptions) => R> | TypedPropertyDescriptor<(reaction: T) => R>) => void;
|
|
181
|
+
/**
|
|
182
|
+
* Retrieves reaction handlers metadata from a given controller.
|
|
183
|
+
*
|
|
184
|
+
* @param controller - The controller class instance.
|
|
185
|
+
* @returns An array of reaction handler metadata objects.
|
|
186
|
+
*/
|
|
187
|
+
declare function getReactionHandlers(controller: any): {
|
|
188
|
+
emoji: string | undefined;
|
|
189
|
+
method: string;
|
|
190
|
+
}[];
|
|
191
|
+
/**
|
|
192
|
+
* Retrieves message handlers metadata from a given controller.
|
|
193
|
+
*
|
|
194
|
+
* @param controller - The controller class instance.
|
|
195
|
+
* @returns An array of message handler method names.
|
|
196
|
+
*/
|
|
197
|
+
declare function getMessageHandlers(controller: any): {
|
|
198
|
+
keyword: string | undefined;
|
|
199
|
+
method: string;
|
|
200
|
+
}[];
|
|
201
|
+
/**
|
|
202
|
+
* Decorator to register command methods in a controller.
|
|
203
|
+
*
|
|
204
|
+
* @param commandName - The name or pattern of the command.
|
|
205
|
+
* @param builderOrType - A command builder class or a command type from `CommandType`.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* @Command('help', CommandType.SLASH)
|
|
210
|
+
* public async handleHelp(interaction: ChatInputCommandInteraction) {
|
|
211
|
+
* await interaction.reply('This is the help command!')
|
|
212
|
+
* }
|
|
213
|
+
*
|
|
214
|
+
* @Command('stats-{id}', CommandType.BUTTON)
|
|
215
|
+
* public async handleStats(message: ButtonInteraction, { id }) {
|
|
216
|
+
* await message.reply(`Fetching stats for ID: ${id}`);
|
|
217
|
+
* }
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
declare function Command<CBC extends CommandType.SLASH | CommandType.CONTEXT_MENU, T extends CommandBuilderConstructor<CBC> | CommandType>(commandName: string, builderOrType: T): <P extends Record<string, any>, R extends Promise<void> | void>(target: object, propertyKey: string, _descriptor: TypedPropertyDescriptor<(interaction: CommandInteractionType<CBC, T>, params: P) => R> | TypedPropertyDescriptor<(interaction: CommandInteractionType<CBC, T>) => R>) => void;
|
|
221
|
+
/**
|
|
222
|
+
* Retrieves the command map for a given controller.
|
|
223
|
+
*
|
|
224
|
+
* @param controller - The controller class instance.
|
|
225
|
+
* @returns A record containing command metadata indexed by command names.
|
|
226
|
+
*/
|
|
227
|
+
declare function getCommandMap<T extends string>(controller: any): Record<string, CommandMetadata<T>[]>;
|
|
228
|
+
/**
|
|
229
|
+
* Decorator to mark a class as a controller that can later be registered to the App class `(app.ts)` using the `@MeoCord` decorator.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* @Controller()
|
|
234
|
+
* export class PingSlashController {
|
|
235
|
+
* constructor(private pingService: PingService) {}
|
|
236
|
+
*
|
|
237
|
+
* @Command('ping', PingCommandBuilder)
|
|
238
|
+
* async ping(interaction: ChatInputCommandInteraction) {
|
|
239
|
+
* const response = await this.pingService.handlePing()
|
|
240
|
+
* await interaction.reply(response)
|
|
241
|
+
* }
|
|
242
|
+
* }
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
declare function Controller(): (target: any) => void;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* MeoCord Framework
|
|
249
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
250
|
+
*
|
|
251
|
+
* This program is free software: you can redistribute it and/or modify
|
|
252
|
+
* it under the terms of the GNU General Public License as published by
|
|
253
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
254
|
+
* (at your option) any later version.
|
|
255
|
+
*
|
|
256
|
+
* This program is distributed in the hope that it will be useful,
|
|
257
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
258
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
259
|
+
* GNU General Public License for more details.
|
|
260
|
+
*
|
|
261
|
+
* You should have received a copy of the GNU General Public License
|
|
262
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* `@Guard()` decorator to mark a class as a Guard that later can be added on `@UseGuard` decorator.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```typescript
|
|
270
|
+
* @Guard()
|
|
271
|
+
export class ButtonInteractionGuard implements GuardInterface {
|
|
272
|
+
private readonly logger = new Logger(ButtonInteractionGuard.name)
|
|
273
|
+
|
|
274
|
+
async canActivate(context: ButtonInteraction, { ownerId }: { ownerId: string }): Promise<boolean> {
|
|
275
|
+
if (context.user.id !== ownerId) {
|
|
276
|
+
this.logger.error(
|
|
277
|
+
`User with id ${context.user.id} is not allowed to use this command that initiated by user with id ${ownerId}.`,
|
|
278
|
+
)
|
|
279
|
+
const embed = generateErrorEmbed(
|
|
280
|
+
`Hi <@${context.user.id}>, this command can only be used by the person who initiated it: <@${ownerId}>.`,
|
|
281
|
+
)
|
|
282
|
+
await context.reply({
|
|
283
|
+
embeds: [embed],
|
|
284
|
+
flags: MessageFlagsBitField.Flags.Ephemeral,
|
|
285
|
+
})
|
|
286
|
+
return false
|
|
287
|
+
}
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
declare function Guard(): (target: any) => void;
|
|
294
|
+
/**
|
|
295
|
+
* Type for a guard with parameters.
|
|
296
|
+
* This type defines a guard that requires additional parameters (other than the default constructor).
|
|
297
|
+
*/
|
|
298
|
+
interface GuardWithParams {
|
|
299
|
+
/**
|
|
300
|
+
* The guard class that needs to be instantiated.
|
|
301
|
+
*/
|
|
302
|
+
provide: new (...args: any[]) => GuardInterface;
|
|
303
|
+
/**
|
|
304
|
+
* Parameters to be passed to the guard during instantiation.
|
|
305
|
+
*/
|
|
306
|
+
params: Record<string, any>;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* `@UseGuard()` decorator to apply one or more guards to methods.
|
|
310
|
+
* Guards are used to handle permission checks before executing a method.
|
|
311
|
+
* Each guard must use `@Guard` decorator and implement the `canActivate` method, which determines
|
|
312
|
+
* whether the method should be allowed to execute based on the provided context (Interaction, Message, or Reaction) and arguments.
|
|
313
|
+
* This decorator ensures that all guards pass validation before calling the original method.
|
|
314
|
+
* Supports guards that are parameterized (accepting additional parameters).
|
|
315
|
+
*
|
|
316
|
+
* @param guards - One or more guard classes to apply. These can be regular guards or guards with additional parameters.
|
|
317
|
+
* - If providing a guard with parameters, it should be an object with:
|
|
318
|
+
* - `provide`: The guard class to instantiate. Must implement `GuardInterface`.
|
|
319
|
+
* - `params`: A record of key-value pairs to be passed as additional properties to the guard instance.
|
|
320
|
+
* @returns A method decorator function that applies the guards to the method.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* // Method-level usage
|
|
325
|
+
* @Command('profile-{id}', CommandType.BUTTON)
|
|
326
|
+
* @UseGuard(
|
|
327
|
+
* { provide: RateLimiterGuard, params: { limit: 2, window: 3000 } },
|
|
328
|
+
* ButtonInteractionGuard
|
|
329
|
+
* )
|
|
330
|
+
* async showProfileById(interaction: ButtonInteraction, { id }: { id: string }) {
|
|
331
|
+
* await interaction.reply(`Profile ID: ${id}`)
|
|
332
|
+
* }
|
|
333
|
+
*
|
|
334
|
+
* // Class-level usage
|
|
335
|
+
* @Controller()
|
|
336
|
+
* @UseGuard(GlobalGuard)
|
|
337
|
+
* class MyController {
|
|
338
|
+
* @Command('ping', CommandType.SLASH)
|
|
339
|
+
* async ping(interaction: ChatInputCommandInteraction) {
|
|
340
|
+
* await interaction.reply('Pong!')
|
|
341
|
+
* }
|
|
342
|
+
* }
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
declare function UseGuard(...guards: ((new (...args: any[]) => GuardInterface) | GuardWithParams)[]): any;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* MeoCord Framework
|
|
349
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
350
|
+
*
|
|
351
|
+
* This program is free software: you can redistribute it and/or modify
|
|
352
|
+
* it under the terms of the GNU General Public License as published by
|
|
353
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
354
|
+
* (at your option) any later version.
|
|
355
|
+
*
|
|
356
|
+
* This program is distributed in the hope that it will be useful,
|
|
357
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
358
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
359
|
+
* GNU General Public License for more details.
|
|
360
|
+
*
|
|
361
|
+
* You should have received a copy of the GNU General Public License
|
|
362
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
363
|
+
*/
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* `@MeoCord()` decorator for initializing and setting up the MeoCord application.
|
|
367
|
+
*
|
|
368
|
+
* @param {Object} options - The decorator options.
|
|
369
|
+
* @param {ServiceIdentifier[]} options.controllers - The list of controllers to be registered.
|
|
370
|
+
* @param {ClientOptions} options.clientOptions - The Discord client options for initializing the bot.
|
|
371
|
+
* @param {ActivityOptions[]} [options.activities] - Optional activities for the bot.
|
|
372
|
+
* @param {ServiceIdentifier[]} [options.services] - Optional services to be registered.
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```typescript
|
|
376
|
+
* @MeoCord({
|
|
377
|
+
* controllers: [PingSlashController],
|
|
378
|
+
* clientOptions: {
|
|
379
|
+
* intents: [
|
|
380
|
+
* GatewayIntentBits.Guilds,
|
|
381
|
+
* GatewayIntentBits.GuildMembers,
|
|
382
|
+
* GatewayIntentBits.GuildMessages,
|
|
383
|
+
* GatewayIntentBits.GuildMessageReactions,
|
|
384
|
+
* GatewayIntentBits.MessageContent,
|
|
385
|
+
* ],
|
|
386
|
+
* partials: [Partials.Message, Partials.Channel, Partials.Reaction],
|
|
387
|
+
* },
|
|
388
|
+
* activities: [{
|
|
389
|
+
* name: `${sample(['Genshin', 'ZZZ'])} with Romeo`,
|
|
390
|
+
* type: ActivityType.Playing,
|
|
391
|
+
* url: 'https://enka.network/u/824957678/',
|
|
392
|
+
* }],
|
|
393
|
+
* services: [MyStandaloneService],
|
|
394
|
+
* })
|
|
395
|
+
* class MyApp {}
|
|
396
|
+
* ```
|
|
397
|
+
**/
|
|
398
|
+
declare function MeoCord(options: {
|
|
399
|
+
controllers: ServiceIdentifier[];
|
|
400
|
+
clientOptions: ClientOptions;
|
|
401
|
+
activities?: ActivityOptions[];
|
|
402
|
+
services?: ServiceIdentifier[];
|
|
403
|
+
}): (target: any) => void;
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* MeoCord Framework
|
|
407
|
+
* Copyright (C) 2025 Ukasyah Rahmatullah Zada
|
|
408
|
+
*
|
|
409
|
+
* This program is free software: you can redistribute it and/or modify
|
|
410
|
+
* it under the terms of the GNU General Public License as published by
|
|
411
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
412
|
+
* (at your option) any later version.
|
|
413
|
+
*
|
|
414
|
+
* This program is distributed in the hope that it will be useful,
|
|
415
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
416
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
417
|
+
* GNU General Public License for more details.
|
|
418
|
+
*
|
|
419
|
+
* You should have received a copy of the GNU General Public License
|
|
420
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
421
|
+
*/
|
|
422
|
+
|
|
423
|
+
declare const mainContainer: Container;
|
|
424
|
+
|
|
425
|
+
export { Command, CommandBuilder, Controller, Guard, MeoCord, MessageHandler, ReactionHandler, Service, UseGuard, getCommandMap, getMessageHandlers, getReactionHandlers, mainContainer };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare enum CommandType {
|
|
2
|
+
SLASH = "SLASH",
|
|
3
|
+
BUTTON = "BUTTON",
|
|
4
|
+
CONTEXT_MENU = "CONTEXT_MENU",
|
|
5
|
+
SELECT_MENU = "SELECT_MENU",
|
|
6
|
+
MODAL_SUBMIT = "MODAL_SUBMIT"
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Enum representing actions that can be performed on a message reaction.
|
|
10
|
+
*/
|
|
11
|
+
declare enum ReactionHandlerAction {
|
|
12
|
+
/** Reaction added to a message. */
|
|
13
|
+
ADD = "ADD",
|
|
14
|
+
/** Reaction removed from a message. */
|
|
15
|
+
REMOVE = "REMOVE"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { CommandType, ReactionHandlerAction };
|