@kotori-bot/loader 1.2.0 → 1.3.0
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/README.md +5 -0
- package/lib/consts.d.ts +5 -1
- package/lib/consts.js +6 -2
- package/lib/index.d.ts +3 -2
- package/lib/index.js +19 -7
- package/lib/loader.d.ts +25 -5
- package/lib/loader.js +203 -76
- package/lib/log.d.ts +2 -2
- package/lib/log.js +9 -9
- package/lib/runner.d.ts +29 -0
- package/lib/runner.js +183 -0
- package/package.json +19 -7
- package/lib/global.d.ts +0 -25
- package/lib/global.js +0 -53
- package/lib/modules.d.ts +0 -18
- package/lib/modules.js +0 -84
package/README.md
ADDED
package/lib/consts.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export declare const DEV_FILE = ".ts";
|
|
2
2
|
export declare const BUILD_FILE = ".js";
|
|
3
|
-
export declare const DEV_IMPORT = "./src/index.ts";
|
|
4
3
|
export declare const DEV_CODE_DIRS = "./src/";
|
|
4
|
+
export declare const DEV_IMPORT = "./src/index.ts";
|
|
5
|
+
export declare const BUILD_CONFIG_NAME = "kotori.yml";
|
|
6
|
+
export declare const DEV_CONFIG_NAME = "kotori.dev.yml";
|
|
7
|
+
export declare const SUPPORTS_VERSION: RegExp;
|
|
8
|
+
export declare const SUPPORTS_HALF_VERSION: RegExp;
|
package/lib/consts.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.SUPPORTS_HALF_VERSION = exports.SUPPORTS_VERSION = exports.DEV_CONFIG_NAME = exports.BUILD_CONFIG_NAME = exports.DEV_IMPORT = exports.DEV_CODE_DIRS = exports.BUILD_FILE = exports.DEV_FILE = void 0;
|
|
4
4
|
exports.DEV_FILE = '.ts';
|
|
5
5
|
exports.BUILD_FILE = '.js';
|
|
6
|
-
exports.DEV_IMPORT = './src/index.ts';
|
|
7
6
|
exports.DEV_CODE_DIRS = './src/';
|
|
7
|
+
exports.DEV_IMPORT = `${exports.DEV_CODE_DIRS}index.ts`;
|
|
8
|
+
exports.BUILD_CONFIG_NAME = 'kotori.yml';
|
|
9
|
+
exports.DEV_CONFIG_NAME = 'kotori.dev.yml';
|
|
10
|
+
exports.SUPPORTS_VERSION = /(1\.1\.0)/;
|
|
11
|
+
exports.SUPPORTS_HALF_VERSION = /(x\.x\.(.*?))/;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
export * from './loader';
|
|
2
|
+
export * from './consts';
|
|
3
|
+
export * from '@kotori-bot/logger';
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
2
|
/*
|
|
7
3
|
* @Author: Hotaru biyuehuya@gmail.com
|
|
8
4
|
* @Blog: https://hotaru.icu
|
|
9
5
|
* @Date: 2023-10-29 16:20:51
|
|
10
6
|
* @LastEditors: Hotaru biyuehuya@gmail.com
|
|
11
|
-
* @LastEditTime:
|
|
7
|
+
* @LastEditTime: 2024-02-06 19:03:21
|
|
12
8
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
21
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
__exportStar(require("./loader"), exports);
|
|
25
|
+
__exportStar(require("./consts"), exports);
|
|
26
|
+
__exportStar(require("@kotori-bot/logger"), exports);
|
package/lib/loader.d.ts
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { Container, Symbols } from '@kotori-bot/core';
|
|
2
|
+
import Logger from '@kotori-bot/logger';
|
|
3
|
+
import Runner from './runner';
|
|
4
|
+
declare module '@kotori-bot/core' {
|
|
5
|
+
interface Context {
|
|
6
|
+
readonly baseDir: Runner['baseDir'];
|
|
7
|
+
readonly options: Runner['options'];
|
|
8
|
+
readonly [Symbols.modules]: Runner[typeof Symbols.modules];
|
|
9
|
+
useAll(): void;
|
|
10
|
+
watcher(): void;
|
|
11
|
+
logger: Logger;
|
|
12
|
+
}
|
|
13
|
+
interface GlobalConfig {
|
|
14
|
+
dirs: string[];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export declare class Loader extends Container {
|
|
3
18
|
private ctx;
|
|
4
|
-
|
|
19
|
+
private loadCount;
|
|
20
|
+
private failLoadCount;
|
|
21
|
+
constructor(options?: {
|
|
22
|
+
dir?: string;
|
|
23
|
+
mode?: string;
|
|
24
|
+
});
|
|
5
25
|
run(): void;
|
|
6
26
|
private handleError;
|
|
7
27
|
private catchError;
|
|
8
28
|
private listenMessage;
|
|
9
29
|
private loadAllModule;
|
|
10
|
-
private
|
|
30
|
+
private loadAllService;
|
|
11
31
|
private checkUpdate;
|
|
12
32
|
}
|
|
13
|
-
export default
|
|
33
|
+
export default Loader;
|
package/lib/loader.js
CHANGED
|
@@ -1,130 +1,257 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Loader = void 0;
|
|
6
30
|
/*
|
|
7
31
|
* @Author: hotaru biyuehuya@gmail.com
|
|
8
32
|
* @Blog: https://hotaru.icu
|
|
9
33
|
* @Date: 2023-06-24 15:12:55
|
|
10
34
|
* @LastEditors: Hotaru biyuehuya@gmail.com
|
|
11
|
-
* @LastEditTime:
|
|
35
|
+
* @LastEditTime: 2024-02-06 21:05:17
|
|
12
36
|
*/
|
|
13
37
|
const core_1 = require("@kotori-bot/core");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
38
|
+
const path_1 = __importDefault(require("path"));
|
|
39
|
+
const fs_1 = __importDefault(require("fs"));
|
|
40
|
+
const logger_1 = __importDefault(require("@kotori-bot/logger"));
|
|
41
|
+
const runner_1 = __importStar(require("./runner"));
|
|
16
42
|
const log_1 = __importDefault(require("./log"));
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
43
|
+
const consts_1 = require("./consts");
|
|
44
|
+
function getRunnerConfig(file, dir) {
|
|
45
|
+
const handle = (baseDir) => {
|
|
46
|
+
if (!fs_1.default.existsSync(baseDir.modules))
|
|
47
|
+
fs_1.default.mkdirSync(baseDir.modules);
|
|
48
|
+
if (!fs_1.default.existsSync(baseDir.logs))
|
|
49
|
+
fs_1.default.mkdirSync(baseDir.logs);
|
|
50
|
+
return baseDir;
|
|
26
51
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
52
|
+
const options = {
|
|
53
|
+
mode: file === consts_1.DEV_CONFIG_NAME ? 'dev' : 'build'
|
|
54
|
+
};
|
|
55
|
+
if (dir)
|
|
56
|
+
return {
|
|
57
|
+
baseDir: handle({ root: dir, modules: path_1.default.join(dir, 'modules'), logs: path_1.default.join(dir, 'logs') }),
|
|
58
|
+
options
|
|
59
|
+
};
|
|
60
|
+
let root = path_1.default.resolve(__dirname, '..').replace('loader', 'kotori');
|
|
61
|
+
let count = 0;
|
|
62
|
+
while (!fs_1.default.existsSync(path_1.default.join(root, file))) {
|
|
63
|
+
if (count > 5) {
|
|
64
|
+
logger_1.default.fatal(`cannot find file ${file} `);
|
|
65
|
+
process.exit();
|
|
66
|
+
}
|
|
67
|
+
root = path_1.default.join(root, '..');
|
|
68
|
+
count += 1;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
baseDir: handle({ root, modules: path_1.default.join(root, 'modules'), logs: path_1.default.join(root, 'logs') }),
|
|
72
|
+
options
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/* eslint consistent-return: 0 */
|
|
76
|
+
function getCoreConfig(file, baseDir) {
|
|
77
|
+
try {
|
|
78
|
+
const result1 = core_1.Tsu.Object({
|
|
79
|
+
global: core_1.Tsu.Object({
|
|
80
|
+
dirs: core_1.Tsu.Array(core_1.Tsu.String()).default([]),
|
|
81
|
+
lang: runner_1.localeTypeSchema.default(core_1.DEFAULT_CORE_CONFIG.global.lang),
|
|
82
|
+
'command-prefix': core_1.Tsu.String().default(core_1.DEFAULT_CORE_CONFIG.global['command-prefix'])
|
|
83
|
+
}),
|
|
84
|
+
plugin: core_1.Tsu.Object({})
|
|
85
|
+
.index(core_1.Tsu.Object({
|
|
86
|
+
filter: core_1.Tsu.Object({}).default({})
|
|
87
|
+
}).default({ filter: {} }))
|
|
88
|
+
.default(core_1.DEFAULT_CORE_CONFIG.plugin)
|
|
89
|
+
})
|
|
90
|
+
.default({ global: Object.assign(core_1.DEFAULT_CORE_CONFIG.global), plugin: core_1.DEFAULT_CORE_CONFIG.plugin })
|
|
91
|
+
.parse((0, core_1.loadConfig)(path_1.default.join(baseDir.root, file), 'yaml'));
|
|
92
|
+
return core_1.Tsu.Object({
|
|
93
|
+
adapter: core_1.Tsu.Object({})
|
|
94
|
+
.index(core_1.Tsu.Object({
|
|
95
|
+
extends: core_1.Tsu.String(),
|
|
96
|
+
master: core_1.Tsu.Union([core_1.Tsu.Number(), core_1.Tsu.String()]),
|
|
97
|
+
lang: runner_1.localeTypeSchema.default(result1.global.lang),
|
|
98
|
+
'command-prefix': core_1.Tsu.String().default(result1.global['command-prefix'])
|
|
99
|
+
}))
|
|
100
|
+
.default(core_1.DEFAULT_CORE_CONFIG.adapter)
|
|
101
|
+
}).parse(result1);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (!(err instanceof core_1.TsuError))
|
|
105
|
+
throw err;
|
|
106
|
+
logger_1.default.fatal(`file ${file} format error: ${err.message}`);
|
|
107
|
+
process.exit();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
class Loader extends core_1.Container {
|
|
30
111
|
ctx;
|
|
31
|
-
|
|
112
|
+
loadCount = 0;
|
|
113
|
+
failLoadCount = 0;
|
|
114
|
+
constructor(options) {
|
|
32
115
|
super();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
116
|
+
const file = options && options.mode === 'dev' ? consts_1.DEV_CONFIG_NAME : consts_1.BUILD_CONFIG_NAME;
|
|
117
|
+
const runnerConfig = getRunnerConfig(file, options?.dir);
|
|
118
|
+
const ctx = new core_1.Core(getCoreConfig(file, runnerConfig.baseDir));
|
|
119
|
+
ctx.provide('runner', new runner_1.default(ctx, runnerConfig));
|
|
120
|
+
ctx.mixin('runner', ['baseDir', 'options', 'useAll', 'watcher']);
|
|
121
|
+
core_1.Container.setInstance(ctx);
|
|
122
|
+
this.ctx = core_1.Container.getInstance();
|
|
36
123
|
}
|
|
37
124
|
run() {
|
|
38
|
-
(0, log_1.default)(this.ctx.
|
|
125
|
+
(0, log_1.default)(this.ctx.pkg, this.ctx);
|
|
39
126
|
this.catchError();
|
|
40
127
|
this.listenMessage();
|
|
41
128
|
this.loadAllModule();
|
|
42
129
|
this.checkUpdate();
|
|
43
130
|
}
|
|
44
131
|
handleError(err, prefix) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.ctx.logger.tag(prefix, 'default', prefix === 'UCE' ? 'cyanBG' : 'greenBG').error(err);
|
|
132
|
+
if (!(err instanceof core_1.KotoriError)) {
|
|
133
|
+
this.ctx.logger.label(prefix).error(err);
|
|
48
134
|
return;
|
|
49
135
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
136
|
+
({
|
|
137
|
+
DatabaseError: () => this.ctx.logger.label('database').warn(err.message, err.stack),
|
|
138
|
+
ModuleError: () => this.ctx.logger.label('module').error(err.message, err.stack),
|
|
139
|
+
UnknownError: () => this.ctx.logger.error(err.name, err.stack),
|
|
140
|
+
DevError: () => this.ctx.logger.label('error').debug(err.name, err.stack)
|
|
141
|
+
})[err.name]();
|
|
56
142
|
}
|
|
57
143
|
catchError() {
|
|
58
|
-
process.on('uncaughtExceptionMonitor', err => this.handleError(err, '
|
|
59
|
-
process.on('unhandledRejection', err => this.handleError(err, '
|
|
60
|
-
process.on('SIGINT', () =>
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
this.ctx.logger.debug('Run info: develop with debuing...');
|
|
144
|
+
process.on('uncaughtExceptionMonitor', (err) => this.handleError(err, 'sync'));
|
|
145
|
+
process.on('unhandledRejection', (err) => this.handleError(err, 'async'));
|
|
146
|
+
process.on('SIGINT', () => process.exit());
|
|
147
|
+
this.ctx.logger.debug('run info: develop with debuing...');
|
|
64
148
|
}
|
|
65
149
|
listenMessage() {
|
|
66
|
-
|
|
67
|
-
|
|
150
|
+
this.ctx.on('connect', (data) => {
|
|
151
|
+
const { type, mode, normal, address, adapter } = data;
|
|
152
|
+
let msg;
|
|
153
|
+
if (type === 'connect') {
|
|
154
|
+
switch (mode) {
|
|
155
|
+
case 'ws':
|
|
156
|
+
msg = `${normal ? 'Connect' : 'Reconnect'} server to ${address}`;
|
|
157
|
+
break;
|
|
158
|
+
case 'ws-reverse':
|
|
159
|
+
msg = `server ${normal ? 'start' : 'restart'} at ${address}`;
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
msg = `ready completed about ${address}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
switch (mode) {
|
|
167
|
+
case 'ws':
|
|
168
|
+
msg = `disconnect server from ${address}${normal ? '' : ' unexpectedly'}`;
|
|
169
|
+
break;
|
|
170
|
+
case 'ws-reverse':
|
|
171
|
+
msg = `server stop at ${address}${normal ? '' : ' unexpectedly'}`;
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
msg = `dispose completed about ${address}`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
this.ctx.logger.label([adapter.platform, adapter.identity])[normal ? 'info' : 'warn'](msg);
|
|
178
|
+
});
|
|
179
|
+
this.ctx.on('status', (data) => {
|
|
180
|
+
const { status, adapter } = data;
|
|
181
|
+
this.ctx.logger.label([adapter.platform, adapter.identity]).info(status);
|
|
182
|
+
});
|
|
183
|
+
this.ctx.on('ready_module', (data) => {
|
|
184
|
+
if (!data.module || typeof data.module === 'string')
|
|
68
185
|
return;
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
186
|
+
this.loadCount += 1;
|
|
187
|
+
const { name, version, author } = data.module.pkg;
|
|
188
|
+
if (data.error) {
|
|
189
|
+
this.failLoadCount += 1;
|
|
190
|
+
this.ctx.logger.warn(`failed to load module ${name}`);
|
|
191
|
+
if (data.error instanceof core_1.KotoriError) {
|
|
192
|
+
process.emit('uncaughtExceptionMonitor', data.error);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
this.ctx.logger.warn(data.error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this.ctx.logger.info(`loaded module ${name} version: ${version} ${Array.isArray(author) ? `authors: ${author.join(',')}` : `author: ${author}`}`);
|
|
200
|
+
}
|
|
201
|
+
const requiredVersion = data.module.pkg.peerDependencies['kotori-bot'];
|
|
202
|
+
if (!requiredVersion.includes('workspace') &&
|
|
203
|
+
(!consts_1.SUPPORTS_VERSION.exec(requiredVersion) || requiredVersion !== this.ctx.pkg.version)) {
|
|
204
|
+
if (consts_1.SUPPORTS_HALF_VERSION.exec(requiredVersion)) {
|
|
205
|
+
this.ctx.logger.warn(`incomplete supported module version: ${requiredVersion}`);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
this.ctx.logger.error(`unsupported module version: ${requiredVersion}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (this.loadCount !== this.ctx.get('runner')[core_1.Symbols.modules].size)
|
|
75
212
|
return;
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
|
|
79
|
-
this.ctx.on('load_all_module', data => {
|
|
80
|
-
const failed = data.expected - data.reality;
|
|
81
|
-
this.ctx.logger.info(`Loaded ${data.reality} modules (plugins)${failed > 0 ? `, failed to load ${failed} modules` : ''}`);
|
|
82
|
-
this.loadAllAdapter();
|
|
213
|
+
this.ctx.logger.info(`loaded ${this.loadCount - this.failLoadCount} modules successfully${this.failLoadCount > 0 ? `, failed to load ${this.failLoadCount} modules` : ''} `);
|
|
214
|
+
this.loadAllService();
|
|
215
|
+
this.ctx.emit('ready');
|
|
83
216
|
});
|
|
84
217
|
}
|
|
85
218
|
loadAllModule() {
|
|
86
|
-
this.ctx.
|
|
87
|
-
if ((0, global_1.isDev)())
|
|
88
|
-
this.ctx.watchFile();
|
|
219
|
+
this.ctx.useAll();
|
|
89
220
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
221
|
+
loadAllService() {
|
|
222
|
+
/* load database before adapters */
|
|
223
|
+
const adapters = this.ctx[core_1.Symbols.adapter];
|
|
224
|
+
Object.keys(this.ctx.config.adapter).forEach((botName) => {
|
|
93
225
|
const botConfig = this.ctx.config.adapter[botName];
|
|
94
|
-
|
|
95
|
-
|
|
226
|
+
const array = adapters.get(botConfig.extends);
|
|
227
|
+
if (!array) {
|
|
228
|
+
this.ctx.logger.warn(`cannot find adapter '${botConfig.extends}' for ${botName}`);
|
|
96
229
|
return;
|
|
97
230
|
}
|
|
98
|
-
const array = adapters[botConfig.extends];
|
|
99
231
|
const isSchema = array[1]?.parseSafe(botConfig);
|
|
100
|
-
if (isSchema && !isSchema.value)
|
|
232
|
+
if (isSchema && !isSchema.value)
|
|
101
233
|
return;
|
|
102
|
-
|
|
234
|
+
/* adapter donot support hot reload, so no extends for context */
|
|
103
235
|
const bot = new array[0](this.ctx, isSchema ? isSchema.data : botConfig, botName);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}); /*
|
|
108
|
-
const adapters: Adapter[] = [];
|
|
109
|
-
Object.values(this.ctx.botStack).forEach(apis => {
|
|
110
|
-
apis.forEach(api => adapters.push(api.adapter));
|
|
111
|
-
}); */
|
|
112
|
-
// this.ctx.emit({ type: 'adapters', adapters });
|
|
236
|
+
this.ctx.on('ready', () => bot.start());
|
|
237
|
+
});
|
|
238
|
+
/* load custom services after adapters */
|
|
113
239
|
}
|
|
114
240
|
async checkUpdate() {
|
|
115
|
-
const { version } = this.ctx.
|
|
241
|
+
const { version } = this.ctx.pkg;
|
|
116
242
|
const res = await this.ctx.http
|
|
117
243
|
.get('https://hotaru.icu/api/agent/?url=https://raw.githubusercontent.com/kotorijs/kotori/master/packages/kotori/package.json')
|
|
118
|
-
.catch(() => this.ctx.logger.error('
|
|
244
|
+
.catch(() => this.ctx.logger.error('get update failed, please check your network'));
|
|
119
245
|
if (!res || !core_1.Tsu.Object({ version: core_1.Tsu.String() }).check(res)) {
|
|
120
|
-
this.ctx.logger.
|
|
246
|
+
this.ctx.logger.warn(`detection update failed`);
|
|
121
247
|
}
|
|
122
248
|
else if (version === res.version) {
|
|
123
|
-
this.ctx.logger.
|
|
249
|
+
this.ctx.logger.info('kotori is currently the latest version');
|
|
124
250
|
}
|
|
125
251
|
else {
|
|
126
|
-
this.ctx.logger.warn(`
|
|
252
|
+
this.ctx.logger.warn(`the current version of Kotori is ${version}, and the latest version is ${res.version}. please go to ${"https://github.com/kotorijs/kotori" /* GLOBAL.REPO */} to update`);
|
|
127
253
|
}
|
|
128
254
|
}
|
|
129
255
|
}
|
|
130
|
-
exports.
|
|
256
|
+
exports.Loader = Loader;
|
|
257
|
+
exports.default = Loader;
|
package/lib/log.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Context
|
|
2
|
-
export declare function loadInfo(info:
|
|
1
|
+
import type { Context } from '@kotori-bot/core';
|
|
2
|
+
export declare function loadInfo(info: Context['pkg'], ctx: Context): void;
|
|
3
3
|
export default loadInfo;
|
package/lib/log.js
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loadInfo = void 0;
|
|
4
4
|
function loadInfo(info, ctx) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
██╗ ██╗ ██████╗ ████████╗ ██████╗ ██████╗ ██╗
|
|
8
|
-
██║ ██╔╝██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗██║
|
|
9
|
-
█████╔╝ ██║ ██║ ██║ ██║ ██║██████╔╝██║
|
|
10
|
-
██╔═██╗ ██║ ██║ ██║ ██║ ██║██╔══██╗██║
|
|
11
|
-
██║ ██╗╚██████╔╝ ██║ ╚██████╔╝██║ ██║██║
|
|
12
|
-
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
|
|
5
|
+
process.stdout.write('Kotori Bot is loading...');
|
|
6
|
+
process.stdout.write(`
|
|
7
|
+
██╗ ██╗ ██████╗ ████████╗ ██████╗ ██████╗ ██╗
|
|
8
|
+
██║ ██╔╝██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗██║
|
|
9
|
+
█████╔╝ ██║ ██║ ██║ ██║ ██║██████╔╝██║
|
|
10
|
+
██╔═██╗ ██║ ██║ ██║ ██║ ██║██╔══██╗██║
|
|
11
|
+
██║ ██╗╚██████╔╝ ██║ ╚██████╔╝██║ ██║██║
|
|
12
|
+
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
|
|
13
13
|
`);
|
|
14
14
|
ctx.logger.info(`Kotori Bot Version: ${info.version} License: ${info.license}`);
|
|
15
15
|
ctx.logger.info(`Kotori Bot By ${info.author}`);
|
|
16
|
-
ctx.logger.info(`Copyright © 2023 ${info.author} All rights reserved
|
|
16
|
+
ctx.logger.info(`Copyright © 2023 - 2024 ${info.author} All rights reserved`);
|
|
17
17
|
}
|
|
18
18
|
exports.loadInfo = loadInfo;
|
|
19
19
|
exports.default = loadInfo;
|
package/lib/runner.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Context, ModuleConfig, ModuleInstance, Symbols } from '@kotori-bot/core';
|
|
2
|
+
interface BaseDir {
|
|
3
|
+
root: string;
|
|
4
|
+
modules: string;
|
|
5
|
+
logs: string;
|
|
6
|
+
}
|
|
7
|
+
interface Options {
|
|
8
|
+
mode: 'dev' | 'build';
|
|
9
|
+
}
|
|
10
|
+
interface RunnerConfig {
|
|
11
|
+
baseDir: BaseDir;
|
|
12
|
+
options: Options;
|
|
13
|
+
}
|
|
14
|
+
export declare const localeTypeSchema: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"en_US">, import("@kotori-bot/core").LiteralParser<"ja_JP">]>, import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"zh_TW">, import("@kotori-bot/core").AnyParser<any>]>]>;
|
|
15
|
+
export declare class Runner {
|
|
16
|
+
readonly baseDir: BaseDir;
|
|
17
|
+
readonly options: Options;
|
|
18
|
+
private ctx;
|
|
19
|
+
private isDev;
|
|
20
|
+
readonly [Symbols.modules]: Set<[ModuleInstance, ModuleConfig]>;
|
|
21
|
+
constructor(ctx: Context, config: RunnerConfig);
|
|
22
|
+
private getDirFiles;
|
|
23
|
+
private getModuleRootDir;
|
|
24
|
+
private getModuleList;
|
|
25
|
+
private moduleQuick;
|
|
26
|
+
useAll(): void;
|
|
27
|
+
watcher(): void;
|
|
28
|
+
}
|
|
29
|
+
export default Runner;
|
package/lib/runner.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Runner = exports.localeTypeSchema = void 0;
|
|
30
|
+
const fs_1 = __importStar(require("fs"));
|
|
31
|
+
const path_1 = __importDefault(require("path"));
|
|
32
|
+
const core_1 = require("@kotori-bot/core");
|
|
33
|
+
const logger_1 = __importStar(require("@kotori-bot/logger"));
|
|
34
|
+
const consts_1 = require("./consts");
|
|
35
|
+
exports.localeTypeSchema = core_1.Tsu.Union([
|
|
36
|
+
core_1.Tsu.Union([core_1.Tsu.Literal('en_US'), core_1.Tsu.Literal('ja_JP')]),
|
|
37
|
+
core_1.Tsu.Union([core_1.Tsu.Literal('zh_TW'), core_1.Tsu.Any()])
|
|
38
|
+
]);
|
|
39
|
+
const modulePackageSchema = core_1.Tsu.Object({
|
|
40
|
+
name: core_1.Tsu.String().regexp(/kotori-plugin-[a-z]([a-z,0-9]{3,13})\b/),
|
|
41
|
+
version: core_1.Tsu.String(),
|
|
42
|
+
description: core_1.Tsu.String(),
|
|
43
|
+
main: core_1.Tsu.String(),
|
|
44
|
+
license: core_1.Tsu.Literal('GPL-3.0'),
|
|
45
|
+
keywords: core_1.Tsu.Custom((val) => Array.isArray(val) && val.includes('kotori') && val.includes('chatbot') && val.includes('kotori-plugin')),
|
|
46
|
+
author: core_1.Tsu.Union([core_1.Tsu.String(), core_1.Tsu.Array(core_1.Tsu.String())]),
|
|
47
|
+
peerDependencies: core_1.Tsu.Object({
|
|
48
|
+
'kotori-bot': core_1.Tsu.String()
|
|
49
|
+
}),
|
|
50
|
+
kotori: core_1.Tsu.Object({
|
|
51
|
+
enforce: core_1.Tsu.Union([core_1.Tsu.Literal('pre'), core_1.Tsu.Literal('post')]).optional(),
|
|
52
|
+
meta: core_1.Tsu.Object({
|
|
53
|
+
language: core_1.Tsu.Array(exports.localeTypeSchema).default([])
|
|
54
|
+
}).default({ language: [] })
|
|
55
|
+
}).default({
|
|
56
|
+
enforce: undefined,
|
|
57
|
+
meta: { language: [] }
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
function moduleLoadOrder(pkg) {
|
|
61
|
+
if (pkg.name.includes(core_1.DATABASE_PREFIX))
|
|
62
|
+
return 1;
|
|
63
|
+
if (pkg.name.includes(core_1.ADAPTER_PREFIX))
|
|
64
|
+
return 2;
|
|
65
|
+
// if (CORE_MODULES.includes(pkg.name)) return 3;
|
|
66
|
+
if (pkg.kotori.enforce === 'pre')
|
|
67
|
+
return 4;
|
|
68
|
+
if (!pkg.kotori.enforce)
|
|
69
|
+
return 5;
|
|
70
|
+
return 6;
|
|
71
|
+
}
|
|
72
|
+
class Runner {
|
|
73
|
+
baseDir;
|
|
74
|
+
options;
|
|
75
|
+
ctx;
|
|
76
|
+
isDev;
|
|
77
|
+
[core_1.Symbols.modules] = new Set();
|
|
78
|
+
constructor(ctx, config) {
|
|
79
|
+
this.ctx = ctx;
|
|
80
|
+
/* handle config */
|
|
81
|
+
this.baseDir = config.baseDir;
|
|
82
|
+
this.options = config.options;
|
|
83
|
+
this.isDev = this.options.mode === 'dev';
|
|
84
|
+
if (this.isDev)
|
|
85
|
+
this.watcher();
|
|
86
|
+
const loggerOptions = {
|
|
87
|
+
level: this.isDev ? logger_1.LoggerLevel.TRACE : logger_1.LoggerLevel.INFO,
|
|
88
|
+
label: [],
|
|
89
|
+
transports: new logger_1.ConsoleTransport()
|
|
90
|
+
};
|
|
91
|
+
const logger = Object.assign(new logger_1.default(), { ctx: this.ctx });
|
|
92
|
+
ctx.provide('logger', logger.extends(new Proxy(loggerOptions, {
|
|
93
|
+
get: (target, prop, receiver) => {
|
|
94
|
+
if (prop === 'label') {
|
|
95
|
+
return logger.ctx.identity ? [logger.ctx.identity, ...target.label] : target.label;
|
|
96
|
+
}
|
|
97
|
+
return Reflect.get(target, prop, receiver);
|
|
98
|
+
}
|
|
99
|
+
})));
|
|
100
|
+
ctx.inject('logger');
|
|
101
|
+
}
|
|
102
|
+
getDirFiles(rootDir) {
|
|
103
|
+
const files = fs_1.default.readdirSync(rootDir);
|
|
104
|
+
const list = [];
|
|
105
|
+
files.forEach((fileName) => {
|
|
106
|
+
const file = path_1.default.join(rootDir, fileName);
|
|
107
|
+
if (fs_1.default.statSync(file).isDirectory()) {
|
|
108
|
+
list.push(...this.getDirFiles(file));
|
|
109
|
+
}
|
|
110
|
+
if (path_1.default.parse(file).ext !== (this.isDev ? consts_1.DEV_FILE : consts_1.BUILD_FILE))
|
|
111
|
+
return;
|
|
112
|
+
list.push(path_1.default.resolve(file));
|
|
113
|
+
});
|
|
114
|
+
return list;
|
|
115
|
+
}
|
|
116
|
+
getModuleRootDir() {
|
|
117
|
+
const moduleRootDir = [];
|
|
118
|
+
[
|
|
119
|
+
...this.ctx.config.global.dirs.map((dir) => path_1.default.resolve(this.ctx.baseDir.root, dir)),
|
|
120
|
+
this.ctx.baseDir.modules
|
|
121
|
+
].forEach((dir) => {
|
|
122
|
+
if (fs_1.default.existsSync(dir) && fs_1.default.statSync(dir).isDirectory())
|
|
123
|
+
moduleRootDir.push(dir);
|
|
124
|
+
});
|
|
125
|
+
return moduleRootDir;
|
|
126
|
+
}
|
|
127
|
+
getModuleList(rootDir) {
|
|
128
|
+
fs_1.default.readdirSync(rootDir).forEach(async (fileName) => {
|
|
129
|
+
const dir = path_1.default.join(rootDir, fileName);
|
|
130
|
+
if (!fs_1.default.statSync(dir).isDirectory())
|
|
131
|
+
return;
|
|
132
|
+
if (rootDir !== this.ctx.baseDir.modules && !fileName.startsWith(core_1.PLUGIN_PREFIX))
|
|
133
|
+
return;
|
|
134
|
+
const packagePath = path_1.default.join(dir, 'package.json');
|
|
135
|
+
let pkg;
|
|
136
|
+
if (!fs_1.default.existsSync(packagePath))
|
|
137
|
+
return;
|
|
138
|
+
try {
|
|
139
|
+
pkg = JSON.parse(fs_1.default.readFileSync(packagePath).toString());
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
throw new core_1.DevError(`illegal package.json ${packagePath}`);
|
|
143
|
+
}
|
|
144
|
+
const result = modulePackageSchema.parseSafe(pkg);
|
|
145
|
+
if (!result.value) {
|
|
146
|
+
if (rootDir !== this.ctx.baseDir.modules)
|
|
147
|
+
return;
|
|
148
|
+
throw new core_1.DevError(`package.json format error ${packagePath}: ${result.error.message}`);
|
|
149
|
+
}
|
|
150
|
+
pkg = result.data;
|
|
151
|
+
const devMode = this.isDev && (0, fs_1.existsSync)(path_1.default.resolve(dir, consts_1.DEV_IMPORT));
|
|
152
|
+
const main = path_1.default.resolve(dir, devMode ? consts_1.DEV_IMPORT : pkg.main);
|
|
153
|
+
if (!fs_1.default.existsSync(main))
|
|
154
|
+
throw new core_1.DevError(`cannot find ${main}`);
|
|
155
|
+
const dirs = path_1.default.join(dir, devMode ? consts_1.DEV_CODE_DIRS : path_1.default.dirname(pkg.main));
|
|
156
|
+
const files = fs_1.default.statSync(dirs).isDirectory() ? this.getDirFiles(dirs) : [];
|
|
157
|
+
this[core_1.Symbols.modules].add([
|
|
158
|
+
{ pkg, main, files },
|
|
159
|
+
this.ctx.config.plugin[(0, core_1.stringRightSplit)(pkg.name, core_1.PLUGIN_PREFIX)] || {}
|
|
160
|
+
]);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
moduleQuick(instance, config) {
|
|
164
|
+
this.ctx.use(instance, config);
|
|
165
|
+
}
|
|
166
|
+
useAll() {
|
|
167
|
+
this.getModuleRootDir().forEach((dir) => this.getModuleList(dir));
|
|
168
|
+
const modules = [];
|
|
169
|
+
this[core_1.Symbols.modules].forEach((val) => modules.push(val));
|
|
170
|
+
modules
|
|
171
|
+
.sort((el1, el2) => moduleLoadOrder(el1[0].pkg) - moduleLoadOrder(el2[0].pkg))
|
|
172
|
+
.forEach((el) => this.moduleQuick(...el));
|
|
173
|
+
}
|
|
174
|
+
watcher() {
|
|
175
|
+
this[core_1.Symbols.modules].forEach((data) => data[0].files.forEach((file) => fs_1.default.watchFile(file, async () => {
|
|
176
|
+
this.ctx.logger.debug(`file happen changed, module ${data[0].pkg.name} is reloading...`);
|
|
177
|
+
this.ctx.dispose(data[0]);
|
|
178
|
+
this.moduleQuick(...data);
|
|
179
|
+
})));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.Runner = Runner;
|
|
183
|
+
exports.default = Runner;
|
package/package.json
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kotori-bot/loader",
|
|
3
|
-
"version": "v1.
|
|
3
|
+
"version": "v1.3.0",
|
|
4
4
|
"description": "Loader For KotoriBot",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"author": "Hotaru <biyuehuya@gmail.com>",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@kotori-bot/core": "^v1.
|
|
9
|
+
"@kotori-bot/core": "^v1.2.0",
|
|
10
|
+
"@kotori-bot/logger": "^v1.1.1"
|
|
10
11
|
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"kotori",
|
|
14
|
+
"chatbot",
|
|
15
|
+
"loader"
|
|
16
|
+
],
|
|
11
17
|
"files": [
|
|
12
|
-
"lib"
|
|
18
|
+
"lib",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"README.md"
|
|
13
21
|
],
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/kotorijs/kotori/issues"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/kotorijs/kotori.git"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://kotori.js.org"
|
|
18
30
|
}
|
package/lib/global.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { BaseDir } from '@kotori-bot/core';
|
|
2
|
-
export declare const isDev: () => boolean;
|
|
3
|
-
export declare const CONFIG_FILE: () => "kotori.dev.yml" | "kotori.yml";
|
|
4
|
-
export declare const getBaseDir: () => {
|
|
5
|
-
root: any;
|
|
6
|
-
modules: string;
|
|
7
|
-
};
|
|
8
|
-
export declare const getGlobalConfig: (baseDir: BaseDir) => import("@kotori-bot/core").ObjectParserInfer<{
|
|
9
|
-
global: import("@kotori-bot/core").IntersectionParser<[import("@kotori-bot/core").ObjectParser<{
|
|
10
|
-
dirs: import("@kotori-bot/core").ArrayParser<import("@kotori-bot/core").StringParser>;
|
|
11
|
-
}>, import("@kotori-bot/core").ObjectParser<{
|
|
12
|
-
lang: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"en_US">, import("@kotori-bot/core").LiteralParser<"ja_JP">]>, import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"zh_CN">, import("@kotori-bot/core").LiteralParser<"zh_TW">]>]>;
|
|
13
|
-
'command-prefix': import("@kotori-bot/core").StringParser;
|
|
14
|
-
}>]>;
|
|
15
|
-
adapter: import("@kotori-bot/core").Parser<import("@kotori-bot/core").IndexObject<import("@kotori-bot/core").ObjectParserInfer<{
|
|
16
|
-
extends: import("@kotori-bot/core").StringParser;
|
|
17
|
-
master: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").NumberParser, import("@kotori-bot/core").StringParser]>;
|
|
18
|
-
}> & import("@kotori-bot/core").ObjectParserInfer<{
|
|
19
|
-
lang: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"en_US">, import("@kotori-bot/core").LiteralParser<"ja_JP">]>, import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"zh_CN">, import("@kotori-bot/core").LiteralParser<"zh_TW">]>]>;
|
|
20
|
-
'command-prefix': import("@kotori-bot/core").StringParser;
|
|
21
|
-
}>>>;
|
|
22
|
-
plugin: import("@kotori-bot/core").Parser<import("@kotori-bot/core").IndexObject<import("@kotori-bot/core").ObjectParserInfer<{
|
|
23
|
-
priority: import("@kotori-bot/core").NumberParser;
|
|
24
|
-
}>>>;
|
|
25
|
-
}>;
|
package/lib/global.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getGlobalConfig = exports.getBaseDir = exports.CONFIG_FILE = exports.isDev = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const core_1 = require("@kotori-bot/core");
|
|
10
|
-
const isDev = () => globalThis.env_mode === 'dev';
|
|
11
|
-
exports.isDev = isDev;
|
|
12
|
-
const CONFIG_FILE = () => ((0, exports.isDev)() ? 'kotori.dev.yml' : 'kotori.yml');
|
|
13
|
-
exports.CONFIG_FILE = CONFIG_FILE;
|
|
14
|
-
const getBaseDir = () => {
|
|
15
|
-
const { env_dir: envDir } = globalThis;
|
|
16
|
-
if (envDir) {
|
|
17
|
-
return {
|
|
18
|
-
root: envDir,
|
|
19
|
-
modules: path_1.default.join(envDir, 'modules'),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
let root = path_1.default.resolve(__dirname, '..').replace('loader', 'kotori');
|
|
23
|
-
let count = 0;
|
|
24
|
-
while (!fs_1.default.existsSync(path_1.default.join(root, (0, exports.CONFIG_FILE)()))) {
|
|
25
|
-
if (count > 5)
|
|
26
|
-
throw new core_1.CoreError(`cannot find kotori-bot global ${exports.CONFIG_FILE}`);
|
|
27
|
-
root = path_1.default.join(root, '..');
|
|
28
|
-
count += 1;
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
root,
|
|
32
|
-
modules: path_1.default.join(root, 'modules'),
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
exports.getBaseDir = getBaseDir;
|
|
36
|
-
const getGlobalConfig = (baseDir) => {
|
|
37
|
-
const data = (0, core_1.loadConfig)(path_1.default.join(baseDir.root, (0, exports.CONFIG_FILE)()), 'yaml');
|
|
38
|
-
const isExistsGlobal = data && typeof data === 'object' && data.global && typeof data.global === 'object';
|
|
39
|
-
try {
|
|
40
|
-
if (!isExistsGlobal)
|
|
41
|
-
throw new core_1.TsuError('en_US', 'array_error');
|
|
42
|
-
const lang = data.global.lang ? core_1.localeTypeSchema.parse(data.global.lang) : undefined;
|
|
43
|
-
const commandPrefix = data.global['command-prefix'] ? data.global['command-prefix'] : undefined;
|
|
44
|
-
return (0, core_1.globalConfigSchemaController)(lang, commandPrefix).parse(data);
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
if (!(err instanceof core_1.TsuError))
|
|
48
|
-
throw err;
|
|
49
|
-
// process.exit(1);
|
|
50
|
-
throw new core_1.CoreError(`kotori-bot global ${exports.CONFIG_FILE} format error: ${err.message}`);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
exports.getGlobalConfig = getGlobalConfig;
|
package/lib/modules.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Context } from '@kotori-bot/core';
|
|
2
|
-
declare module '@kotori-bot/core' {
|
|
3
|
-
interface Context {
|
|
4
|
-
readonly moduleAll?: () => void;
|
|
5
|
-
readonly watchFile?: () => void;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export declare class Modules extends Context {
|
|
9
|
-
private isDev;
|
|
10
|
-
private readonly moduleRootDir;
|
|
11
|
-
private getDirFiles;
|
|
12
|
-
private getModuleRootDir;
|
|
13
|
-
private getModuleList;
|
|
14
|
-
private moduleQuick;
|
|
15
|
-
readonly moduleAll: () => Promise<void>;
|
|
16
|
-
readonly watchFile: () => Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
export default Modules;
|
package/lib/modules.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Modules = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const core_1 = require("@kotori-bot/core");
|
|
10
|
-
const consts_1 = require("./consts");
|
|
11
|
-
class Modules extends core_1.Context {
|
|
12
|
-
isDev = this.options.env === 'dev';
|
|
13
|
-
moduleRootDir = [];
|
|
14
|
-
getDirFiles(rootDir) {
|
|
15
|
-
const files = fs_1.default.readdirSync(rootDir);
|
|
16
|
-
const list = [];
|
|
17
|
-
files.forEach(fileName => {
|
|
18
|
-
const file = path_1.default.join(rootDir, fileName);
|
|
19
|
-
if (fs_1.default.statSync(file).isDirectory()) {
|
|
20
|
-
list.push(...this.getDirFiles(file));
|
|
21
|
-
}
|
|
22
|
-
if (path_1.default.parse(file).ext !== (this.isDev ? consts_1.DEV_FILE : consts_1.BUILD_FILE))
|
|
23
|
-
return;
|
|
24
|
-
list.push(path_1.default.resolve(file));
|
|
25
|
-
});
|
|
26
|
-
return list;
|
|
27
|
-
}
|
|
28
|
-
getModuleRootDir() {
|
|
29
|
-
Object.assign(this.config.global.dirs, [this.baseDir.modules]).forEach(dir => {
|
|
30
|
-
if (fs_1.default.existsSync(dir) && fs_1.default.statSync(dir).isDirectory())
|
|
31
|
-
this.moduleRootDir.push(dir);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
getModuleList(rootDir) {
|
|
35
|
-
const files = fs_1.default.readdirSync(rootDir);
|
|
36
|
-
files.forEach(fileName => {
|
|
37
|
-
const dir = path_1.default.join(rootDir, fileName);
|
|
38
|
-
if (!fs_1.default.statSync(dir).isDirectory())
|
|
39
|
-
return;
|
|
40
|
-
if (rootDir !== this.baseDir.modules && fileName.startsWith(core_1.PLUGIN_PREFIX))
|
|
41
|
-
return;
|
|
42
|
-
const packagePath = path_1.default.join(dir, 'package.json');
|
|
43
|
-
let packageJson;
|
|
44
|
-
if (!fs_1.default.existsSync(packagePath))
|
|
45
|
-
return;
|
|
46
|
-
try {
|
|
47
|
-
packageJson = JSON.parse(fs_1.default.readFileSync(packagePath).toString());
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
throw new core_1.DevError(`illegal package.json ${packagePath}`);
|
|
51
|
-
}
|
|
52
|
-
const result = core_1.ModulePackageSchema.parseSafe(packageJson);
|
|
53
|
-
if (!result.value && rootDir === this.baseDir.modules) {
|
|
54
|
-
throw new core_1.DevError(`package.json format error ${packagePath}: ${result.error.message}`);
|
|
55
|
-
}
|
|
56
|
-
const mainPath = path_1.default.join(dir, this.isDev ? consts_1.DEV_IMPORT : packageJson.main);
|
|
57
|
-
if (!fs_1.default.existsSync(mainPath))
|
|
58
|
-
throw new core_1.DevError(`cannot find ${mainPath}`);
|
|
59
|
-
const codeDirs = path_1.default.join(dir, this.isDev ? consts_1.DEV_CODE_DIRS : path_1.default.dirname(packageJson.main));
|
|
60
|
-
this.moduleStack.push({
|
|
61
|
-
package: packageJson,
|
|
62
|
-
fileList: fs_1.default.statSync(codeDirs).isDirectory() ? this.getDirFiles(codeDirs) : [],
|
|
63
|
-
mainPath: path_1.default.resolve(mainPath),
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
moduleQuick(moduleData) {
|
|
68
|
-
return this.use(moduleData, this, this.config.plugin[(0, core_1.stringRightSplit)(moduleData.package.name, core_1.PLUGIN_PREFIX)] ?? {});
|
|
69
|
-
}
|
|
70
|
-
moduleAll = async () => {
|
|
71
|
-
this.getModuleRootDir();
|
|
72
|
-
this.moduleRootDir.forEach(dir => {
|
|
73
|
-
this.getModuleList(dir);
|
|
74
|
-
});
|
|
75
|
-
const array = this.moduleStack.filter(data => data.package.name.startsWith(core_1.OFFICIAL_MODULES_SCOPE));
|
|
76
|
-
array.push(...this.moduleStack.filter(data => !array.includes(data)));
|
|
77
|
-
array.forEach(moduleData => this.moduleQuick(moduleData));
|
|
78
|
-
};
|
|
79
|
-
watchFile = async () => {
|
|
80
|
-
this.moduleStack.forEach(moduleData => moduleData.fileList.forEach(file => fs_1.default.watchFile(file, () => this.dispose(moduleData) && this.moduleQuick(moduleData))));
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
exports.Modules = Modules;
|
|
84
|
-
exports.default = Modules;
|