blockmine 1.6.2 → 1.12.1
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/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.versionrc.json +17 -0
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/backend/package.json +1 -0
- package/backend/prisma/migrations/20250718181335_add_plugin_data_store/migration.sql +14 -0
- package/backend/prisma/schema.prisma +201 -204
- package/backend/src/api/routes/bots.js +176 -0
- package/backend/src/api/routes/changelog.js +16 -0
- package/backend/src/api/routes/eventGraphs.js +11 -1
- package/backend/src/api/routes/plugins.js +11 -0
- package/backend/src/core/BotManager.js +92 -40
- package/backend/src/core/BotProcess.js +44 -24
- package/backend/src/core/EventGraphManager.js +29 -5
- package/backend/src/core/GraphExecutionEngine.js +54 -12
- package/backend/src/core/MessageQueue.js +10 -1
- package/backend/src/core/NodeRegistry.js +2 -1
- package/backend/src/core/PluginLoader.js +72 -8
- package/backend/src/core/PluginManager.js +19 -0
- package/backend/src/plugins/PluginStore.js +87 -0
- package/backend/src/real-time/socketHandler.js +11 -3
- package/backend/src/server.js +2 -0
- package/backend/temp_migration.sql +0 -0
- package/commitlint.config.js +3 -0
- package/frontend/dist/assets/index-BzDKhCKk.js +8330 -0
- package/frontend/dist/assets/index-DhU2u6V0.css +1 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/package.json +6 -0
- package/package.json +20 -4
- package/frontend/dist/assets/index-BHk5N684.css +0 -1
- package/frontend/dist/assets/index-CmhNg8XO.js +0 -8203
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
const { PrismaClient } = require('@prisma/client');
|
|
2
|
+
const GraphExecutionEngine = require('./GraphExecutionEngine');
|
|
3
|
+
const nodeRegistry = require('./NodeRegistry');
|
|
2
4
|
|
|
3
5
|
const prisma = new PrismaClient();
|
|
4
6
|
|
|
5
7
|
class EventGraphManager {
|
|
6
8
|
constructor(botManager) {
|
|
7
9
|
this.botManager = botManager;
|
|
8
|
-
this.graphEngine = botManager
|
|
10
|
+
this.graphEngine = new GraphExecutionEngine(nodeRegistry, botManager);
|
|
9
11
|
this.activeGraphs = new Map();
|
|
10
|
-
// Хранилище для состояний (переменных) каждого графа
|
|
11
12
|
this.graphStates = new Map();
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -26,7 +27,6 @@ class EventGraphManager {
|
|
|
26
27
|
const parsedGraph = JSON.parse(graph.graphJson);
|
|
27
28
|
if (!parsedGraph.nodes) continue;
|
|
28
29
|
|
|
29
|
-
// Инициализация начального состояния переменных для этого графа
|
|
30
30
|
const initialState = {};
|
|
31
31
|
if (graph.variables) {
|
|
32
32
|
try {
|
|
@@ -56,6 +56,7 @@ class EventGraphManager {
|
|
|
56
56
|
name: graph.name,
|
|
57
57
|
nodes: parsedGraph.nodes,
|
|
58
58
|
connections: parsedGraph.connections,
|
|
59
|
+
variables: parsedGraph.variables || [],
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
62
|
} catch (e) {
|
|
@@ -69,7 +70,6 @@ class EventGraphManager {
|
|
|
69
70
|
|
|
70
71
|
unloadGraphsForBot(botId) {
|
|
71
72
|
this.activeGraphs.delete(botId);
|
|
72
|
-
// Также очищаем состояния при выгрузке
|
|
73
73
|
for (const key of this.graphStates.keys()) {
|
|
74
74
|
if (key.startsWith(`${botId}-`)) {
|
|
75
75
|
this.graphStates.delete(key);
|
|
@@ -120,7 +120,25 @@ class EventGraphManager {
|
|
|
120
120
|
initialContext.botId = botId;
|
|
121
121
|
initialContext.players = players;
|
|
122
122
|
initialContext.botState = eventArgs.botState || {};
|
|
123
|
-
|
|
123
|
+
|
|
124
|
+
const savedVariables = { ...(this.graphStates.get(stateKey) || {}) };
|
|
125
|
+
|
|
126
|
+
if (graph.variables && Array.isArray(graph.variables)) {
|
|
127
|
+
for (const v of graph.variables) {
|
|
128
|
+
if (!savedVariables.hasOwnProperty(v.name)) {
|
|
129
|
+
let val;
|
|
130
|
+
switch (v.type) {
|
|
131
|
+
case 'number': val = Number(v.value) || 0; break;
|
|
132
|
+
case 'boolean': val = v.value === 'true'; break;
|
|
133
|
+
case 'array': try { val = Array.isArray(JSON.parse(v.value)) ? JSON.parse(v.value) : []; } catch { val = []; } break;
|
|
134
|
+
default: val = v.value;
|
|
135
|
+
}
|
|
136
|
+
savedVariables[v.name] = val;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
initialContext.variables = savedVariables;
|
|
124
142
|
|
|
125
143
|
try {
|
|
126
144
|
const finalContext = await this.graphEngine.execute(graph, initialContext, eventType);
|
|
@@ -162,6 +180,12 @@ class EventGraphManager {
|
|
|
162
180
|
case 'entityGone':
|
|
163
181
|
context.entity = args.entity;
|
|
164
182
|
break;
|
|
183
|
+
case 'command':
|
|
184
|
+
context.command_name = args.commandName;
|
|
185
|
+
context.user = args.user;
|
|
186
|
+
context.args = args.args;
|
|
187
|
+
context.chat_type = args.typeChat;
|
|
188
|
+
break;
|
|
165
189
|
}
|
|
166
190
|
return context;
|
|
167
191
|
}
|
|
@@ -219,6 +219,34 @@ class GraphExecutionEngine {
|
|
|
219
219
|
await this.traverse(node, 'completed');
|
|
220
220
|
break;
|
|
221
221
|
}
|
|
222
|
+
case 'flow:while': {
|
|
223
|
+
let iteration = 0;
|
|
224
|
+
const maxIterations = 1000;
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
while (iteration < maxIterations) {
|
|
228
|
+
const condition = await this.resolvePinValue(node, 'condition', false);
|
|
229
|
+
if (!condition) break;
|
|
230
|
+
|
|
231
|
+
this.memo.set(`${node.id}:iteration`, iteration);
|
|
232
|
+
this.clearLoopBodyMemo(node);
|
|
233
|
+
await this.traverse(node, 'loop_body');
|
|
234
|
+
iteration++;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (iteration >= maxIterations) {
|
|
238
|
+
console.warn(`[GraphExecutionEngine] Цикл while достиг максимального количества итераций (${maxIterations})`);
|
|
239
|
+
}
|
|
240
|
+
} catch (e) {
|
|
241
|
+
if (e instanceof BreakLoopSignal) {
|
|
242
|
+
} else {
|
|
243
|
+
throw e;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
await this.traverse(node, 'completed');
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
222
250
|
case 'flow:sequence': {
|
|
223
251
|
const pinCount = node.data?.pinCount || 2;
|
|
224
252
|
for (let i = 0; i < pinCount; i++) {
|
|
@@ -375,7 +403,7 @@ class GraphExecutionEngine {
|
|
|
375
403
|
case 'event:command':
|
|
376
404
|
if (pinId === 'args') result = this.context.args || {};
|
|
377
405
|
else if (pinId === 'user') result = this.context.user || {};
|
|
378
|
-
else if (pinId === 'chat_type') result = this.context.typeChat || '
|
|
406
|
+
else if (pinId === 'chat_type') result = this.context.typeChat || 'chat';
|
|
379
407
|
else result = this.context[pinId];
|
|
380
408
|
break;
|
|
381
409
|
case 'event:chat':
|
|
@@ -399,8 +427,13 @@ class GraphExecutionEngine {
|
|
|
399
427
|
break;
|
|
400
428
|
|
|
401
429
|
case 'data:get_variable':
|
|
402
|
-
const varName = node.data?.variableName || '';
|
|
403
|
-
|
|
430
|
+
const varName = node.data?.variableName || node.data?.selectedVariable || '';
|
|
431
|
+
if (!varName) {
|
|
432
|
+
console.warn('[GraphExecutionEngine] data:get_variable: не указано имя переменной', node.data);
|
|
433
|
+
result = null;
|
|
434
|
+
} else {
|
|
435
|
+
result = this.context.variables.hasOwnProperty(varName) ? this.context.variables[varName] : null;
|
|
436
|
+
}
|
|
404
437
|
break;
|
|
405
438
|
|
|
406
439
|
|
|
@@ -471,17 +504,13 @@ class GraphExecutionEngine {
|
|
|
471
504
|
case 'logic:operation': {
|
|
472
505
|
const op = node.data?.operation || 'AND';
|
|
473
506
|
const inputs = [];
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (inputs.length === 0) {
|
|
480
|
-
inputs.push(await this.resolvePinValue(node, 'a', false));
|
|
481
|
-
inputs.push(await this.resolvePinValue(node, 'b', false));
|
|
507
|
+
const pinCount = node.data?.pinCount || 2;
|
|
508
|
+
|
|
509
|
+
for (let i = 0; i < pinCount; i++) {
|
|
510
|
+
const value = await this.resolvePinValue(node, `pin_${i}`, false);
|
|
511
|
+
inputs.push(value);
|
|
482
512
|
}
|
|
483
513
|
|
|
484
|
-
|
|
485
514
|
switch (op) {
|
|
486
515
|
case 'AND': result = inputs.every(Boolean); break;
|
|
487
516
|
case 'OR': result = inputs.some(Boolean); break;
|
|
@@ -738,6 +767,12 @@ class GraphExecutionEngine {
|
|
|
738
767
|
}
|
|
739
768
|
break;
|
|
740
769
|
}
|
|
770
|
+
case 'flow:while': {
|
|
771
|
+
if (pinId === 'iteration') {
|
|
772
|
+
result = this.memo.get(`${node.id}:iteration`);
|
|
773
|
+
}
|
|
774
|
+
break;
|
|
775
|
+
}
|
|
741
776
|
|
|
742
777
|
case 'string:equals': {
|
|
743
778
|
const strA = String(await this.resolvePinValue(node, 'a', ''));
|
|
@@ -798,6 +833,13 @@ class GraphExecutionEngine {
|
|
|
798
833
|
|
|
799
834
|
return false;
|
|
800
835
|
}
|
|
836
|
+
|
|
837
|
+
hasConnection(node, pinId) {
|
|
838
|
+
if (!this.activeGraph || !this.activeGraph.connections) return false;
|
|
839
|
+
return this.activeGraph.connections.some(conn =>
|
|
840
|
+
conn.targetNodeId === node.id && conn.targetPinId === pinId
|
|
841
|
+
);
|
|
842
|
+
}
|
|
801
843
|
}
|
|
802
844
|
|
|
803
845
|
module.exports = GraphExecutionEngine;
|
|
@@ -33,7 +33,16 @@ class MessageQueue {
|
|
|
33
33
|
enqueue(chatType, message, username = null) {
|
|
34
34
|
const typeConfig = this.chatTypes[chatType];
|
|
35
35
|
if (!typeConfig) return;
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
if (Array.isArray(message)) {
|
|
38
|
+
for (const msg of message) {
|
|
39
|
+
if (typeof msg === 'string' && msg.trim().length > 0) {
|
|
40
|
+
this._enqueue({ type: 'simple', chatType, ...typeConfig, message: msg, username });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else if (typeof message === 'string') {
|
|
44
|
+
this._enqueue({ type: 'simple', chatType, ...typeConfig, message, username });
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
enqueueAndWait(command, patterns, timeout) {
|
|
@@ -102,11 +102,12 @@ class NodeRegistry {
|
|
|
102
102
|
label: '▶️ При выполнении команды',
|
|
103
103
|
category: 'События',
|
|
104
104
|
description: 'Стартовая точка для графа команды.',
|
|
105
|
-
graphType:
|
|
105
|
+
graphType: 'all',
|
|
106
106
|
pins: {
|
|
107
107
|
inputs: [],
|
|
108
108
|
outputs: [
|
|
109
109
|
{ id: 'exec', name: 'Выполнить', type: 'Exec' },
|
|
110
|
+
{ id: 'command_name', name: 'Имя команды', type: 'String' },
|
|
110
111
|
{ id: 'user', name: 'Пользователь', type: 'User' },
|
|
111
112
|
{ id: 'args', name: 'Аргументы', type: 'Object' },
|
|
112
113
|
{ id: 'chat_type', name: 'Тип чата', type: 'String' }
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs/promises');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
const fssync = require('fs');
|
|
6
|
+
const PluginStore = require('../plugins/PluginStore');
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
9
|
+
|
|
10
|
+
async function ensurePluginDependencies(pluginPath, pluginName) {
|
|
11
|
+
const packageJsonPath = path.join(pluginPath, 'package.json');
|
|
12
|
+
try {
|
|
13
|
+
if (fssync.existsSync(packageJsonPath)) {
|
|
14
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
15
|
+
if (packageJson.dependencies && Object.keys(packageJson.dependencies).length > 0) {
|
|
16
|
+
console.log(`[PluginLoader] У плагина ${pluginName} есть зависимости, устанавливаем их...`);
|
|
17
|
+
try {
|
|
18
|
+
execSync('npm install', {
|
|
19
|
+
cwd: pluginPath,
|
|
20
|
+
stdio: 'pipe'
|
|
21
|
+
});
|
|
22
|
+
console.log(`[PluginLoader] Зависимости для плагина ${pluginName} установлены`);
|
|
23
|
+
} catch (installError) {
|
|
24
|
+
console.error(`[PluginLoader] Ошибка установки зависимостей для ${pluginName}:`, installError.message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`[PluginLoader] Ошибка чтения package.json для ${pluginName}:`, error.message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function initializePlugins(bot, installedPlugins = [], prisma) {
|
|
6
34
|
if (!installedPlugins || installedPlugins.length === 0) return;
|
|
7
35
|
|
|
8
36
|
const sendLog = bot.sendLog || console.log;
|
|
@@ -11,6 +39,8 @@ async function initializePlugins(bot, installedPlugins = []) {
|
|
|
11
39
|
for (const plugin of installedPlugins) {
|
|
12
40
|
if (plugin && plugin.path) {
|
|
13
41
|
try {
|
|
42
|
+
await ensurePluginDependencies(plugin.path, plugin.name);
|
|
43
|
+
|
|
14
44
|
const manifest = plugin.manifest ? JSON.parse(plugin.manifest) : {};
|
|
15
45
|
const savedSettings = plugin.settings ? JSON.parse(plugin.settings) : {};
|
|
16
46
|
const defaultSettings = {};
|
|
@@ -38,20 +68,54 @@ async function initializePlugins(bot, installedPlugins = []) {
|
|
|
38
68
|
}
|
|
39
69
|
|
|
40
70
|
const finalSettings = { ...defaultSettings, ...savedSettings };
|
|
71
|
+
const store = new PluginStore(prisma, bot.config.id, plugin.name);
|
|
41
72
|
|
|
42
73
|
const mainFile = manifest.main || 'index.js';
|
|
43
74
|
const entryPointPath = path.join(plugin.path, mainFile);
|
|
44
75
|
const normalizedPath = entryPointPath.replace(/\\/g, '/');
|
|
45
76
|
|
|
46
77
|
sendLog(`[PluginLoader] Загрузка: ${plugin.name} (v${plugin.version}) из ${normalizedPath}`);
|
|
47
|
-
const pluginModule = require(normalizedPath);
|
|
48
78
|
|
|
49
|
-
|
|
50
|
-
pluginModule
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
79
|
+
try {
|
|
80
|
+
const pluginModule = require(normalizedPath);
|
|
81
|
+
|
|
82
|
+
if (typeof pluginModule === 'function') {
|
|
83
|
+
pluginModule(bot, { settings: finalSettings, store });
|
|
84
|
+
} else if (pluginModule && typeof pluginModule.onLoad === 'function') {
|
|
85
|
+
pluginModule.onLoad(bot, { settings: finalSettings, store });
|
|
86
|
+
} else {
|
|
87
|
+
sendLog(`[PluginLoader] [ERROR] ${plugin.name} не экспортирует функцию или объект с методом onLoad.`);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error.message.includes('Cannot find module')) {
|
|
91
|
+
const moduleMatch = error.message.match(/Cannot find module '([^']+)'/);
|
|
92
|
+
if (moduleMatch) {
|
|
93
|
+
const missingModule = moduleMatch[1];
|
|
94
|
+
sendLog(`[PluginLoader] Попытка установки недостающего модуля ${missingModule} в папку плагина ${plugin.name}`);
|
|
95
|
+
try {
|
|
96
|
+
execSync(`npm install ${missingModule}`, {
|
|
97
|
+
cwd: plugin.path,
|
|
98
|
+
stdio: 'pipe'
|
|
99
|
+
});
|
|
100
|
+
sendLog(`[PluginLoader] Модуль ${missingModule} успешно установлен в папку плагина ${plugin.name}, повторная попытка загрузки`);
|
|
101
|
+
|
|
102
|
+
// Повторная попытка загрузки
|
|
103
|
+
const pluginModule = require(normalizedPath);
|
|
104
|
+
if (typeof pluginModule === 'function') {
|
|
105
|
+
pluginModule(bot, { settings: finalSettings, store });
|
|
106
|
+
} else if (pluginModule && typeof pluginModule.onLoad === 'function') {
|
|
107
|
+
pluginModule.onLoad(bot, { settings: finalSettings, store });
|
|
108
|
+
}
|
|
109
|
+
} catch (installError) {
|
|
110
|
+
sendLog(`[PluginLoader] Не удалось установить модуль ${missingModule} в папку плагина ${plugin.name}: ${installError.message}`);
|
|
111
|
+
throw error; // Пробрасываем оригинальную ошибку
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
55
119
|
}
|
|
56
120
|
|
|
57
121
|
} catch (error) {
|
|
@@ -277,6 +277,25 @@ class PluginManager {
|
|
|
277
277
|
|
|
278
278
|
return await this.installFromGithub(botId, repoUrl, prisma, true);
|
|
279
279
|
}
|
|
280
|
+
|
|
281
|
+
async clearPluginData(pluginId) {
|
|
282
|
+
const plugin = await prisma.installedPlugin.findUnique({ where: { id: pluginId } });
|
|
283
|
+
if (!plugin) {
|
|
284
|
+
throw new Error('Плагин не найден.');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
console.log(`[PluginManager] Очистка данных для плагина ${plugin.name} (Bot ID: ${plugin.botId})`);
|
|
288
|
+
|
|
289
|
+
const { count } = await prisma.pluginDataStore.deleteMany({
|
|
290
|
+
where: {
|
|
291
|
+
pluginName: plugin.name,
|
|
292
|
+
botId: plugin.botId,
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
console.log(`[PluginManager] Удалено ${count} записей из хранилища.`);
|
|
297
|
+
return { count };
|
|
298
|
+
}
|
|
280
299
|
}
|
|
281
300
|
|
|
282
301
|
module.exports = PluginManager;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
class PluginStore {
|
|
2
|
+
constructor(prisma, botId, pluginName) {
|
|
3
|
+
this.prisma = prisma;
|
|
4
|
+
this.botId = botId;
|
|
5
|
+
this.pluginName = pluginName;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async set(key, value) {
|
|
9
|
+
const jsonValue = JSON.stringify(value);
|
|
10
|
+
await this.prisma.pluginDataStore.upsert({
|
|
11
|
+
where: {
|
|
12
|
+
pluginName_botId_key: {
|
|
13
|
+
pluginName: this.pluginName,
|
|
14
|
+
botId: this.botId,
|
|
15
|
+
key: key
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
update: {
|
|
19
|
+
value: jsonValue
|
|
20
|
+
},
|
|
21
|
+
create: {
|
|
22
|
+
pluginName: this.pluginName,
|
|
23
|
+
botId: this.botId,
|
|
24
|
+
key: key,
|
|
25
|
+
value: jsonValue
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async get(key) {
|
|
31
|
+
const data = await this.prisma.pluginDataStore.findUnique({
|
|
32
|
+
where: {
|
|
33
|
+
pluginName_botId_key: {
|
|
34
|
+
pluginName: this.pluginName,
|
|
35
|
+
botId: this.botId,
|
|
36
|
+
key: key
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return data ? JSON.parse(data.value) : null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async delete(key) {
|
|
44
|
+
try {
|
|
45
|
+
await this.prisma.pluginDataStore.delete({
|
|
46
|
+
where: {
|
|
47
|
+
pluginName_botId_key: {
|
|
48
|
+
pluginName: this.pluginName,
|
|
49
|
+
botId: this.botId,
|
|
50
|
+
key: key
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return true;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async has(key) {
|
|
61
|
+
const count = await this.prisma.pluginDataStore.count({
|
|
62
|
+
where: {
|
|
63
|
+
pluginName: this.pluginName,
|
|
64
|
+
botId: this.botId,
|
|
65
|
+
key: key
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return count > 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async getAll() {
|
|
72
|
+
const allData = await this.prisma.pluginDataStore.findMany({
|
|
73
|
+
where: {
|
|
74
|
+
pluginName: this.pluginName,
|
|
75
|
+
botId: this.botId
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const map = new Map();
|
|
79
|
+
for (const item of allData) {
|
|
80
|
+
map.set(item.key, JSON.parse(item.value));
|
|
81
|
+
}
|
|
82
|
+
return map;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = PluginStore;
|
|
87
|
+
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const { Server } = require('socket.io');
|
|
2
2
|
const config = require('../config');
|
|
3
3
|
|
|
4
|
+
const { botManager } = require('../core/services');
|
|
5
|
+
|
|
4
6
|
let io;
|
|
5
7
|
|
|
6
8
|
function initializeSocket(httpServer) {
|
|
@@ -16,14 +18,20 @@ function initializeSocket(httpServer) {
|
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
io.on('connection', (socket) => {
|
|
19
|
-
// console.log(`[Socket.IO] Пользователь подключен: ${socket.id}. Всего клиентов: ${io.engine.clientsCount}`);
|
|
20
21
|
|
|
21
22
|
socket.on('disconnect', () => {
|
|
22
|
-
|
|
23
|
+
botManager.handleSocketDisconnect(socket);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
socket.on('plugin:ui:subscribe', ({ botId, pluginName }) => {
|
|
27
|
+
botManager.subscribeToPluginUi(botId, pluginName, socket);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
socket.on('plugin:ui:unsubscribe', ({ botId, pluginName }) => {
|
|
31
|
+
botManager.unsubscribeFromPluginUi(botId, pluginName, socket);
|
|
23
32
|
});
|
|
24
33
|
});
|
|
25
34
|
|
|
26
|
-
// console.log('Socket.IO инициализирован с динамическим CORS.');
|
|
27
35
|
return io;
|
|
28
36
|
}
|
|
29
37
|
|
package/backend/src/server.js
CHANGED
|
@@ -19,6 +19,7 @@ const searchRoutes = require('./api/routes/search');
|
|
|
19
19
|
const eventGraphsRouter = require('./api/routes/eventGraphs');
|
|
20
20
|
const TaskScheduler = require('./core/TaskScheduler');
|
|
21
21
|
const panelRoutes = require('./api/routes/panel');
|
|
22
|
+
const changelogRoutes = require('./api/routes/changelog');
|
|
22
23
|
|
|
23
24
|
const app = express();
|
|
24
25
|
const server = http.createServer(app);
|
|
@@ -59,6 +60,7 @@ app.use('/api/servers', serverRoutes);
|
|
|
59
60
|
app.use('/api/permissions', permissionsRoutes);
|
|
60
61
|
app.use('/api/search', searchRoutes);
|
|
61
62
|
app.use('/api/panel', panelRoutes);
|
|
63
|
+
app.use('/api/changelog', changelogRoutes);
|
|
62
64
|
|
|
63
65
|
app.use(express.static(frontendPath));
|
|
64
66
|
|
|
Binary file
|