blockmine 1.6.3 → 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.
@@ -1085,4 +1085,180 @@ router.put('/:botId/event-graphs/:graphId', authorize('management:edit'), async
1085
1085
  router.post('/:botId/visual-editor/save', authorize('management:edit'), async (req, res) => {
1086
1086
  });
1087
1087
 
1088
+ router.get('/:botId/ui-extensions', authorize('plugin:list'), async (req, res) => {
1089
+ try {
1090
+ const botId = parseInt(req.params.botId, 10);
1091
+ const enabledPlugins = await prisma.installedPlugin.findMany({
1092
+ where: { botId: botId, isEnabled: true }
1093
+ });
1094
+
1095
+ const extensions = [];
1096
+ for (const plugin of enabledPlugins) {
1097
+ if (plugin.manifest) {
1098
+ try {
1099
+ const manifest = JSON.parse(plugin.manifest);
1100
+ if (manifest.uiExtensions && Array.isArray(manifest.uiExtensions)) {
1101
+ manifest.uiExtensions.forEach(ext => {
1102
+ extensions.push({
1103
+ pluginName: plugin.name,
1104
+ ...ext
1105
+ });
1106
+ });
1107
+ }
1108
+ } catch (e) {
1109
+ console.error(`Ошибка парсинга манифеста для плагина ${plugin.name}:`, e);
1110
+ }
1111
+ }
1112
+ }
1113
+ res.json(extensions);
1114
+ } catch (error) {
1115
+ res.status(500).json({ error: 'Не удалось получить расширения интерфейса' });
1116
+ }
1117
+ });
1118
+
1119
+ router.get('/:botId/plugins/:pluginName/ui-content/:path', authorize('plugin:list'), async (req, res) => {
1120
+ const { botId, pluginName, path: uiPath } = req.params;
1121
+ const numericBotId = parseInt(botId, 10);
1122
+
1123
+ try {
1124
+ const plugin = await prisma.installedPlugin.findFirst({
1125
+ where: { botId: numericBotId, name: pluginName, isEnabled: true }
1126
+ });
1127
+
1128
+ if (!plugin) {
1129
+ return res.status(404).json({ error: `Активный плагин "${pluginName}" не найден для этого бота.` });
1130
+ }
1131
+
1132
+ const manifest = plugin.manifest ? JSON.parse(plugin.manifest) : {};
1133
+ const savedSettings = plugin.settings ? JSON.parse(plugin.settings) : {};
1134
+ const defaultSettings = {};
1135
+
1136
+ if (manifest.settings) {
1137
+ for (const key in manifest.settings) {
1138
+ const config = manifest.settings[key];
1139
+ if (config.type === 'json_file' && config.defaultPath) {
1140
+ const configFilePath = path.join(plugin.path, config.defaultPath);
1141
+ try {
1142
+ const fileContent = await fs.readFile(configFilePath, 'utf-8');
1143
+ defaultSettings[key] = JSON.parse(fileContent);
1144
+ } catch (e) { defaultSettings[key] = {}; }
1145
+ } else {
1146
+ try { defaultSettings[key] = JSON.parse(config.default || 'null'); }
1147
+ catch { defaultSettings[key] = config.default; }
1148
+ }
1149
+ }
1150
+ }
1151
+ const finalSettings = { ...defaultSettings, ...savedSettings };
1152
+
1153
+ const mainFilePath = manifest.main || 'index.js';
1154
+ const pluginEntryPoint = path.join(plugin.path, mainFilePath);
1155
+
1156
+ delete require.cache[require.resolve(pluginEntryPoint)];
1157
+ const pluginModule = require(pluginEntryPoint);
1158
+
1159
+ if (typeof pluginModule.getUiPageContent !== 'function') {
1160
+ return res.status(501).json({ error: `Плагин "${pluginName}" не предоставляет кастомный UI контент.` });
1161
+ }
1162
+
1163
+ const botProcess = botManager.bots.get(numericBotId);
1164
+ const botApi = botProcess ? botProcess.api : null;
1165
+
1166
+ const content = await pluginModule.getUiPageContent({
1167
+ path: uiPath,
1168
+ bot: botApi,
1169
+ botId: numericBotId,
1170
+ settings: finalSettings
1171
+ });
1172
+
1173
+ if (content === null) {
1174
+ return res.status(404).json({ error: `Для пути "${uiPath}" не найдено содержимого в плагине "${pluginName}".` });
1175
+ }
1176
+
1177
+ res.json(content);
1178
+
1179
+ } catch (error) {
1180
+ console.error(`[UI Content] Ошибка при получении контента для плагина "${pluginName}":`, error);
1181
+ res.status(500).json({ error: error.message || 'Внутренняя ошибка сервера.' });
1182
+ }
1183
+ });
1184
+
1185
+
1186
+ router.post('/:botId/plugins/:pluginName/action', authorize('plugin:list'), async (req, res) => {
1187
+ const { botId, pluginName } = req.params;
1188
+ const { actionName, payload } = req.body;
1189
+ const numericBotId = parseInt(botId, 10);
1190
+
1191
+ if (!actionName) {
1192
+ return res.status(400).json({ error: 'Необходимо указать "actionName".' });
1193
+ }
1194
+
1195
+ try {
1196
+ const botProcess = botManager.bots.get(numericBotId);
1197
+
1198
+ if (!botProcess) {
1199
+ return res.status(404).json({ error: 'Бот не найден или не запущен.' });
1200
+ }
1201
+
1202
+ const plugin = await prisma.installedPlugin.findFirst({
1203
+ where: { botId: numericBotId, name: pluginName, isEnabled: true }
1204
+ });
1205
+
1206
+ if (!plugin) {
1207
+ return res.status(404).json({ error: `Активный плагин с таким именем "${pluginName}" не найден.` });
1208
+ }
1209
+
1210
+ const manifest = plugin.manifest ? JSON.parse(plugin.manifest) : {};
1211
+ const savedSettings = plugin.settings ? JSON.parse(plugin.settings) : {};
1212
+ const defaultSettings = {};
1213
+
1214
+ if (manifest.settings) {
1215
+ for (const key in manifest.settings) {
1216
+ const config = manifest.settings[key];
1217
+ if (config.type === 'json_file' && config.defaultPath) {
1218
+ const configFilePath = path.join(plugin.path, config.defaultPath);
1219
+ try {
1220
+ const fileContent = await fs.readFile(configFilePath, 'utf-8');
1221
+ defaultSettings[key] = JSON.parse(fileContent);
1222
+ } catch (e) {
1223
+ console.error(`[Action] Не удалось прочитать defaultPath для ${pluginName}: ${e.message}`);
1224
+ defaultSettings[key] = {};
1225
+ }
1226
+ } else {
1227
+ try {
1228
+ defaultSettings[key] = JSON.parse(config.default || 'null');
1229
+ } catch {
1230
+ defaultSettings[key] = config.default;
1231
+ }
1232
+ }
1233
+ }
1234
+ }
1235
+ const finalSettings = { ...defaultSettings, ...savedSettings };
1236
+
1237
+ const mainFilePath = manifest.main || 'index.js';
1238
+ const pluginPath = path.join(plugin.path, mainFilePath);
1239
+
1240
+ delete require.cache[require.resolve(pluginPath)];
1241
+ const pluginModule = require(pluginPath);
1242
+
1243
+ if (typeof pluginModule.handleAction !== 'function') {
1244
+ return res.status(501).json({ error: `Плагин "${pluginName}" не поддерживает обработку действий.` });
1245
+ }
1246
+
1247
+ const result = await pluginModule.handleAction({
1248
+ botProcess: botProcess,
1249
+ botId: numericBotId,
1250
+ action: actionName,
1251
+ payload: payload,
1252
+ settings: finalSettings
1253
+ });
1254
+
1255
+ res.json({ success: true, message: 'Действие выполнено.', result: result || null });
1256
+
1257
+ } catch (error) {
1258
+ console.error(`Ошибка выполнения действия "${actionName}" для плагина "${pluginName}":`, error);
1259
+ res.status(500).json({ error: error.message || 'Внутренняя ошибка сервера.' });
1260
+ }
1261
+ });
1262
+
1263
+
1088
1264
  module.exports = router;
@@ -0,0 +1,16 @@
1
+ const express = require('express');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const router = express.Router();
5
+
6
+ router.get('/', async (req, res) => {
7
+ try {
8
+ const file = path.resolve(__dirname, '../../../../CHANGELOG.md');
9
+ const data = await fs.promises.readFile(file, 'utf8');
10
+ res.type('text/markdown').send(data);
11
+ } catch (e) {
12
+ res.status(500).json({ error: 'changelog_not_found' });
13
+ }
14
+ });
15
+
16
+ module.exports = router;
@@ -121,7 +121,17 @@ router.put('/:graphId',
121
121
 
122
122
  const parsedGraph = JSON.parse(graphJson);
123
123
  const eventNodes = parsedGraph.nodes.filter(node => node.type.startsWith('event:'));
124
- const eventTypes = eventNodes.map(node => node.type.split(':')[1]);
124
+ const eventTypes = [...new Set(eventNodes.map(node => node.type.split(':')[1]))];
125
+
126
+ const existingGraph = await prisma.eventGraph.findUnique({
127
+ where: { id: parseInt(graphId) },
128
+ include: { triggers: true }
129
+ });
130
+
131
+ const existingEventTypes = existingGraph?.triggers?.map(t => t.eventType) || [];
132
+
133
+ const eventTypesToDelete = existingEventTypes.filter(et => !eventTypes.includes(et));
134
+ const eventTypesToCreate = eventTypes.filter(et => !existingEventTypes.includes(et));
125
135
 
126
136
  dataToUpdate.triggers = {
127
137
  deleteMany: {},
@@ -53,6 +53,17 @@ router.post('/update/:pluginId', authenticate, authorize('plugin:update'), async
53
53
  }
54
54
  });
55
55
 
56
+ router.post('/:id/clear-data', authenticate, authorize('plugin:settings:edit'), async (req, res) => {
57
+ try {
58
+ const pluginId = parseInt(req.params.id);
59
+ await pluginManager.clearPluginData(pluginId);
60
+ res.status(200).json({ message: 'Данные плагина успешно очищены.' });
61
+ } catch (error) {
62
+ console.error(`[API Error] /plugins/:id/clear-data:`, error);
63
+ res.status(500).json({ error: error.message || 'Не удалось очистить данные плагина.' });
64
+ }
65
+ });
66
+
56
67
  router.get('/catalog/:name', async (req, res) => {
57
68
  try {
58
69
  const pluginName = req.params.name;
@@ -1,6 +1,5 @@
1
1
  const { fork } = require('child_process');
2
2
  const path = require('path');
3
- const { getIO } = require('../real-time/socketHandler');
4
3
  const prisma = require('../lib/prisma');
5
4
  const pidusage = require('pidusage');
6
5
  const DependencyService = require('./DependencyService');
@@ -12,8 +11,6 @@ const crypto = require('crypto');
12
11
  const { decrypt } = require('./utils/crypto');
13
12
  const EventGraphManager = require('./EventGraphManager');
14
13
  const nodeRegistry = require('./NodeRegistry');
15
- const GraphExecutionEngine = require('./GraphExecutionEngine');
16
-
17
14
  const UserService = require('./UserService');
18
15
 
19
16
  const cooldowns = new Map();
@@ -53,8 +50,8 @@ class BotManager {
53
50
  this.nodeRegistry = nodeRegistry;
54
51
  this.pendingPlayerListRequests = new Map();
55
52
  this.playerListCache = new Map();
56
- this.graphEngine = new GraphExecutionEngine(this.nodeRegistry, this);
57
53
  this.eventGraphManager = null;
54
+ this.uiSubscriptions = new Map();
58
55
 
59
56
  getInstanceId();
60
57
  setInterval(() => this.updateAllResourceUsage(), 5000);
@@ -69,6 +66,55 @@ class BotManager {
69
66
  }
70
67
  }
71
68
 
69
+ subscribeToPluginUi(botId, pluginName, socket) {
70
+ if (!this.uiSubscriptions.has(botId)) {
71
+ this.uiSubscriptions.set(botId, new Map());
72
+ }
73
+ const botSubscriptions = this.uiSubscriptions.get(botId);
74
+
75
+ if (!botSubscriptions.has(pluginName)) {
76
+ botSubscriptions.set(pluginName, new Set());
77
+ }
78
+ const pluginSubscribers = botSubscriptions.get(pluginName);
79
+
80
+ pluginSubscribers.add(socket);
81
+ console.log(`[UI Sub] Сокет ${socket.id} подписался на ${pluginName} для бота ${botId}. Всего подписчиков: ${pluginSubscribers.size}`);
82
+
83
+ const botProcess = this.bots.get(botId);
84
+ if (botProcess && !botProcess.killed) {
85
+ botProcess.send({ type: 'plugin:ui:start-updates', pluginName });
86
+ }
87
+ }
88
+
89
+ unsubscribeFromPluginUi(botId, pluginName, socket) {
90
+ const botSubscriptions = this.uiSubscriptions.get(botId);
91
+ if (!botSubscriptions) return;
92
+
93
+ const pluginSubscribers = botSubscriptions.get(pluginName);
94
+ if (!pluginSubscribers) return;
95
+
96
+ pluginSubscribers.delete(socket);
97
+ console.log(`[UI Sub] Сокет ${socket.id} отписался от ${pluginName} для бота ${botId}. Осталось: ${pluginSubscribers.size}`);
98
+
99
+ if (pluginSubscribers.size === 0) {
100
+ const botProcess = this.bots.get(botId);
101
+ if (botProcess && !botProcess.killed) {
102
+ botProcess.send({ type: 'plugin:ui:stop-updates', pluginName });
103
+ }
104
+ botSubscriptions.delete(pluginName);
105
+ }
106
+ }
107
+
108
+ handleSocketDisconnect(socket) {
109
+ this.uiSubscriptions.forEach((botSubscriptions, botId) => {
110
+ botSubscriptions.forEach((pluginSubscribers, pluginName) => {
111
+ if (pluginSubscribers.has(socket)) {
112
+ this.unsubscribeFromPluginUi(botId, pluginName, socket);
113
+ }
114
+ });
115
+ });
116
+ }
117
+
72
118
  async loadConfigForBot(botId) {
73
119
  console.log(`[BotManager] Caching configuration for bot ID ${botId}...`);
74
120
  try {
@@ -108,6 +154,7 @@ class BotManager {
108
154
  }
109
155
 
110
156
  reloadBotConfigInRealTime(botId) {
157
+ const { getIO } = require('../real-time/socketHandler');
111
158
  this.invalidateConfigCache(botId);
112
159
  const child = this.bots.get(botId);
113
160
  if (child && !child.killed) {
@@ -214,6 +261,7 @@ class BotManager {
214
261
  }
215
262
 
216
263
  async updateAllResourceUsage() {
264
+ const { getIO } = require('../real-time/socketHandler');
217
265
  if (this.bots.size === 0) {
218
266
  if (this.resourceUsage.size > 0) {
219
267
  this.resourceUsage.clear();
@@ -270,12 +318,13 @@ class BotManager {
270
318
  }
271
319
 
272
320
  emitStatusUpdate(botId, status, message = null) {
273
- // console.log(`[BotManager] Отправка статуса для бота ${botId}: status=${status}, message=${message || 'null'}`);
321
+ const { getIO } = require('../real-time/socketHandler');
274
322
  if (message) this.appendLog(botId, `[SYSTEM] ${message}`);
275
323
  getIO().emit('bot:status', { botId, status, message });
276
324
  }
277
325
 
278
326
  appendLog(botId, logContent) {
327
+ const { getIO } = require('../real-time/socketHandler');
279
328
  const logEntry = {
280
329
  id: Date.now() + Math.random(),
281
330
  content: logContent,
@@ -333,6 +382,17 @@ class BotManager {
333
382
 
334
383
  child.botConfig = botConfig;
335
384
 
385
+ child.api = {
386
+ sendMessage: (type, message, username) => {
387
+ if (!child.killed) {
388
+ child.send({ type: 'chat', payload: { message, chatType: type, username } });
389
+ }
390
+ },
391
+ sendLog: (message) => {
392
+ this.appendLog(botConfig.id, message);
393
+ }
394
+ };
395
+
336
396
  child.on('message', async (message) => {
337
397
  const botId = botConfig.id;
338
398
  try {
@@ -342,6 +402,21 @@ class BotManager {
342
402
  this.eventGraphManager.handleEvent(botId, message.eventType, message.args);
343
403
  }
344
404
  break;
405
+ case 'plugin:data': {
406
+ const { plugin: pluginName, payload } = message;
407
+ const botSubscriptions = this.uiSubscriptions.get(botId);
408
+ if (!botSubscriptions) break;
409
+
410
+ const pluginSubscribers = botSubscriptions.get(pluginName);
411
+ if (pluginSubscribers && pluginSubscribers.size > 0) {
412
+ pluginSubscribers.forEach(socket => {
413
+ socket.emit('plugin:ui:dataUpdate', payload);
414
+ });
415
+ }
416
+ break;
417
+ }
418
+ case 'plugin:stopped':
419
+ break;
345
420
  case 'log':
346
421
  this.appendLog(botId, message.content);
347
422
  break;
@@ -444,6 +519,7 @@ class BotManager {
444
519
  await this.eventGraphManager.loadGraphsForBot(botConfig.id);
445
520
 
446
521
  this.triggerHeartbeat();
522
+ const { getIO } = require('../real-time/socketHandler');
447
523
  getIO().emit('bot:status', { botId: botConfig.id, status: 'starting' });
448
524
  return child;
449
525
  }
@@ -505,41 +581,17 @@ class BotManager {
505
581
  cooldowns.set(cooldownKey, now);
506
582
  }
507
583
 
508
- if (dbCommand.isVisual) {
509
- const graph = dbCommand.graphJson;
510
- if (graph) {
511
- const players = await this.getPlayerList(botId);
512
- console.log('[BotManager] Received player list for graph:', players);
513
-
514
- const botAPI = {
515
- sendMessage: (type, message, recipient) => {
516
- this.sendMessageToBot(botId, message, type, recipient);
517
- },
518
- executeCommand: (command) => {
519
- this.sendServerCommandToBot(botId, command);
520
- },
521
- };
522
-
523
- const graphContext = {
524
- bot: botAPI,
525
- botId: botId,
526
- user,
527
- args,
528
- typeChat,
529
- players,
530
- };
531
-
532
- try {
533
- const resultContext = await this.graphEngine.execute(graph, graphContext, 'command');
534
- } catch (e) {
535
- console.error(`[BotManager] Ошибка выполнения визуальной команды '${commandName}':`, e);
536
- this.sendMessageToBot(botId, 'Произошла внутренняя ошибка при выполнении команды.', 'private', username);
537
- }
538
- }
539
- } else {
540
- child.send({ type: 'execute_handler', commandName: dbCommand.name, username, args, typeChat });
584
+ if (this.eventGraphManager) {
585
+ this.eventGraphManager.handleEvent(botId, 'command', {
586
+ commandName: dbCommand.name,
587
+ user: { username },
588
+ args,
589
+ typeChat
590
+ });
541
591
  }
542
592
 
593
+ child.send({ type: 'execute_handler', commandName: dbCommand.name, username, args, typeChat });
594
+
543
595
  } catch (error) {
544
596
  console.error(`[BotManager] Command validation error for botId: ${botId}`, {
545
597
  command: commandName, user: username, error: error.message, stack: error.stack
@@ -685,7 +737,7 @@ class BotManager {
685
737
  sendMessageToBot(botId, message, chatType = 'command', username = null) {
686
738
  const child = this.bots.get(botId);
687
739
  if (child) {
688
- child.send({ type: 'chat', payload: { message, chatType, username } });
740
+ child.api.sendMessage(chatType, message, username);
689
741
  return { success: true };
690
742
  }
691
743
  return { success: false, message: 'Бот не найден или не запущен' };
@@ -786,4 +838,4 @@ class BotManager {
786
838
  }
787
839
  }
788
840
 
789
- module.exports = new BotManager();
841
+ module.exports = new BotManager();
@@ -16,6 +16,8 @@ const UserService = require('./UserService');
16
16
  const PermissionManager = require('./ipc/PermissionManager.stub.js');
17
17
 
18
18
  let bot = null;
19
+ const prisma = new PrismaClient();
20
+ const pluginUiState = new Map();
19
21
  const pendingRequests = new Map();
20
22
  const entityMoveThrottles = new Map();
21
23
 
@@ -34,8 +36,7 @@ function sendEvent(eventName, eventArgs) {
34
36
  }
35
37
  }
36
38
 
37
- async function fetchNewConfig(botId) {
38
- const prisma = new PrismaClient();
39
+ async function fetchNewConfig(botId, prisma) {
39
40
  try {
40
41
  const botData = await prisma.bot.findUnique({
41
42
  where: { id: botId },
@@ -55,8 +56,6 @@ async function fetchNewConfig(botId) {
55
56
  } catch (error) {
56
57
  sendLog(`[fetchNewConfig] Error: ${error.message}`);
57
58
  return null;
58
- } finally {
59
- await prisma.$disconnect();
60
59
  }
61
60
  }
62
61
 
@@ -129,7 +128,17 @@ function handleIncomingCommand(type, username, message) {
129
128
  }
130
129
 
131
130
  process.on('message', async (message) => {
132
- if (message.type === 'user_action_response') {
131
+ if (message.type === 'plugin:ui:start-updates') {
132
+ const { pluginName } = message;
133
+ const state = pluginUiState.get(pluginName);
134
+ if (state && process.send) {
135
+ process.send({
136
+ type: 'plugin:data',
137
+ plugin: pluginName,
138
+ payload: state
139
+ });
140
+ }
141
+ } else if (message.type === 'user_action_response') {
133
142
  if (pendingRequests.has(message.requestId)) {
134
143
  const { resolve, reject } = pendingRequests.get(message.requestId);
135
144
  if (message.error) {
@@ -193,6 +202,8 @@ process.on('message', async (message) => {
193
202
 
194
203
  bot = mineflayer.createBot(botOptions);
195
204
 
205
+ bot.pluginUiState = pluginUiState;
206
+
196
207
  let isReady = false;
197
208
 
198
209
  bot.events = new EventEmitter();
@@ -214,8 +225,7 @@ process.on('message', async (message) => {
214
225
  registerGroup: (groupConfig) => PermissionManager.registerGroup(bot.config.id, groupConfig),
215
226
  addPermissionsToGroup: (groupName, permissionNames) => PermissionManager.addPermissionsToGroup(bot.config.id, groupName, permissionNames),
216
227
  installedPlugins: installedPluginNames,
217
- registerCommand: async (command) => { // похуй. пляшем
218
- const prisma = new PrismaClient();
228
+ registerCommand: async (command) => {
219
229
  try {
220
230
  let permissionId = null;
221
231
  if (command.permissions) {
@@ -231,7 +241,7 @@ process.on('message', async (message) => {
231
241
  if (permission) {
232
242
  permissionId = permission.id;
233
243
  } else {
234
- sendLog(`[API] Внимание: право "${command.permissions}" не найдено для команды "${command.name}". Команда будет создана без привязанного права.`);
244
+ sendLog(`[API] Внимание: право \"${command.permissions}\" не найдено для команды \"${command.name}\". Команда будет создана без привязанного права.`);
235
245
  }
236
246
  }
237
247
 
@@ -281,7 +291,7 @@ process.on('message', async (message) => {
281
291
  }
282
292
  });
283
293
  }
284
- sendLog(`[API] Команда "${command.name}" от плагина "${command.owner}" зарегистрирована в процессе.`);
294
+ sendLog(`[API] Команда \"${command.name}\" от плагина \"${command.owner}\" зарегистрирована в процессе.`);
285
295
 
286
296
  if (!bot.commands) bot.commands = new Map();
287
297
  bot.commands.set(command.name, command);
@@ -292,8 +302,6 @@ process.on('message', async (message) => {
292
302
  }
293
303
  } catch (error) {
294
304
  sendLog(`[API] Ошибка при регистрации команды: ${error.message}`);
295
- } finally {
296
- await prisma.$disconnect();
297
305
  }
298
306
  },
299
307
  performUserAction: (username, action, data = {}) => {
@@ -331,6 +339,20 @@ process.on('message', async (message) => {
331
339
  if (bot && position) {
332
340
  bot.lookAt(position);
333
341
  }
342
+ },
343
+ sendUiUpdate: (pluginName, stateUpdate) => {
344
+ const currentState = pluginUiState.get(pluginName) || {};
345
+ const newState = { ...currentState, ...stateUpdate };
346
+ pluginUiState.set(pluginName, newState);
347
+
348
+
349
+ if (process.send) {
350
+ process.send({
351
+ type: 'plugin:data',
352
+ plugin: pluginName,
353
+ payload: newState
354
+ });
355
+ }
334
356
  }
335
357
  };
336
358
 
@@ -346,9 +368,7 @@ process.on('message', async (message) => {
346
368
 
347
369
  bot.commands = await loadCommands();
348
370
 
349
- const prisma = new PrismaClient();
350
371
  const dbCommands = await prisma.command.findMany({ where: { botId: config.id } });
351
- await prisma.$disconnect();
352
372
 
353
373
  for (const dbCommand of dbCommands) {
354
374
  if (!dbCommand.isEnabled) {
@@ -406,7 +426,7 @@ process.on('message', async (message) => {
406
426
  }
407
427
  }
408
428
 
409
- await initializePlugins(bot, config.plugins);
429
+ await initializePlugins(bot, config.plugins, prisma);
410
430
  sendLog('[System] Все системы инициализированы.');
411
431
 
412
432
  let messageHandledByCustomParser = false;
@@ -540,13 +560,13 @@ process.on('message', async (message) => {
540
560
  } else if (message.type === 'config:reload') {
541
561
  sendLog('[System] Received config:reload command. Reloading configuration...');
542
562
  try {
543
- const newConfig = await fetchNewConfig(bot.config.id);
563
+ const newConfig = await fetchNewConfig(bot.config.id, prisma);
544
564
  if (newConfig) {
545
565
  bot.config = { ...bot.config, ...newConfig };
546
566
  const newCommands = await loadCommands();
547
567
  const newPlugins = bot.config.plugins;
548
568
  bot.commands = newCommands;
549
- await initializePlugins(bot, newPlugins, true);
569
+ await initializePlugins(bot, newPlugins, prisma);
550
570
  sendLog('[System] Bot configuration and plugins reloaded successfully.');
551
571
  } else {
552
572
  sendLog('[System] Failed to fetch new configuration.');
@@ -610,14 +630,14 @@ process.on('message', async (message) => {
610
630
  }
611
631
  } else if (message.type === 'plugins:reload') {
612
632
  sendLog('[System] Получена команда на перезагрузку плагинов...');
613
- const newConfig = await fetchNewConfig(bot.config.id);
614
- if (newConfig) {
615
- bot.config.plugins = newConfig.installedPlugins;
616
- bot.commands.clear();
617
- await loadCommands(bot, newConfig.commands);
618
- await initializePlugins(bot, newConfig.installedPlugins);
619
- sendLog('[System] Плагины успешно перезагружены.');
620
- } else {
633
+ const newConfig = await fetchNewConfig(bot.config.id, prisma);
634
+ if (newConfig) {
635
+ bot.config.plugins = newConfig.installedPlugins;
636
+ bot.commands.clear();
637
+ await loadCommands(bot, newConfig.commands);
638
+ await initializePlugins(bot, newConfig.installedPlugins, prisma);
639
+ sendLog('[System] Плагины успешно перезагружены.');
640
+ } else {
621
641
  sendLog('[System] Не удалось получить новую конфигурацию для перезагрузки плагинов.');
622
642
  }
623
643
  } else if (message.type === 'server_command') {