blockmine 1.25.0 → 1.27.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.
Files changed (165) hide show
  1. package/CHANGELOG.md +46 -1
  2. package/backend/cli.js +1 -1
  3. package/backend/package.json +2 -2
  4. package/backend/prisma/migrations/20260328173000_add_plugin_source_ref/migration.sql +2 -0
  5. package/backend/prisma/migrations/migration_lock.toml +2 -2
  6. package/backend/prisma/schema.prisma +2 -0
  7. package/backend/src/api/routes/apiKeys.js +8 -0
  8. package/backend/src/api/routes/bots.js +258 -9
  9. package/backend/src/api/routes/eventGraphs.js +151 -1
  10. package/backend/src/api/routes/health.js +38 -0
  11. package/backend/src/api/routes/nodeRegistry.js +63 -0
  12. package/backend/src/api/routes/plugins.js +254 -29
  13. package/backend/src/container.js +11 -8
  14. package/backend/src/core/BotCommandLoader.js +161 -0
  15. package/backend/src/core/BotConnection.js +125 -0
  16. package/backend/src/core/BotEventHandlers.js +234 -0
  17. package/backend/src/core/BotIPCHandler.js +445 -0
  18. package/backend/src/core/BotManager.js +15 -7
  19. package/backend/src/core/BotProcess.js +75 -142
  20. package/backend/src/core/EventGraphManager.js +7 -3
  21. package/backend/src/core/GraphDebugHandler.js +229 -0
  22. package/backend/src/core/GraphDebugIPC.js +117 -0
  23. package/backend/src/core/GraphExecutionEngine.js +545 -978
  24. package/backend/src/core/GraphTraversal.js +80 -0
  25. package/backend/src/core/GraphValidation.js +73 -0
  26. package/backend/src/core/NodeDefinition.js +138 -0
  27. package/backend/src/core/NodeRegistry.js +153 -141
  28. package/backend/src/core/PluginManager.js +272 -31
  29. package/backend/src/core/RewindSignal.js +9 -0
  30. package/backend/src/core/config/ConfigValidator.js +72 -0
  31. package/backend/src/core/config/FeatureFlags.js +52 -0
  32. package/backend/src/core/config/__tests__/ConfigValidator.test.js +232 -0
  33. package/backend/src/core/domain/entities/Bot.js +39 -0
  34. package/backend/src/core/domain/entities/Command.js +41 -0
  35. package/backend/src/core/domain/entities/EventGraph.js +39 -0
  36. package/backend/src/core/domain/entities/Plugin.js +45 -0
  37. package/backend/src/core/domain/entities/User.js +40 -0
  38. package/backend/src/core/domain/services/DependencyResolver.js +168 -0
  39. package/backend/src/core/domain/services/GraphValidator.js +117 -0
  40. package/backend/src/core/domain/services/PermissionChecker.js +34 -0
  41. package/backend/src/core/domain/services/__tests__/DependencyResolver.test.js +126 -0
  42. package/backend/src/core/domain/valueObjects/BotConfig.js +27 -0
  43. package/backend/src/core/domain/valueObjects/DependencyGraph.js +86 -0
  44. package/backend/src/core/domain/valueObjects/PluginManifest.js +36 -0
  45. package/backend/src/core/errors/BaseError.js +29 -0
  46. package/backend/src/core/errors/ErrorHandler.js +81 -0
  47. package/backend/src/core/errors/__tests__/ErrorHandler.test.js +188 -0
  48. package/backend/src/core/errors/index.js +68 -0
  49. package/backend/src/core/infrastructure/BatchingUtility.js +66 -0
  50. package/backend/src/core/infrastructure/CircuitBreaker.js +103 -0
  51. package/backend/src/core/infrastructure/ConnectionPool.js +81 -0
  52. package/backend/src/core/infrastructure/RateLimiter.js +64 -0
  53. package/backend/src/core/infrastructure/__tests__/BatchingUtility.test.js +86 -0
  54. package/backend/src/core/infrastructure/__tests__/CircuitBreaker.test.js +156 -0
  55. package/backend/src/core/infrastructure/__tests__/ConnectionPool.test.js +146 -0
  56. package/backend/src/core/infrastructure/__tests__/RateLimiter.test.js +171 -0
  57. package/backend/src/core/ipc/botApiFactory.js +72 -0
  58. package/backend/src/core/ipc/ipcMessageTypes.js +115 -0
  59. package/backend/src/core/logging/AuditLogger.js +61 -0
  60. package/backend/src/core/logging/StructuredLogger.js +80 -0
  61. package/backend/src/core/logging/__tests__/StructuredLogger.test.js +213 -0
  62. package/backend/src/core/logging/index.js +7 -0
  63. package/backend/src/core/metrics/MetricsCollector.js +104 -0
  64. package/backend/src/core/metrics/__tests__/MetricsCollector.test.js +131 -0
  65. package/backend/src/core/node-registries/actionsNodes.js +191 -0
  66. package/backend/src/core/node-registries/arraysNodes.js +152 -0
  67. package/backend/src/core/node-registries/botNodes.js +48 -0
  68. package/backend/src/core/node-registries/containerNodes.js +141 -0
  69. package/backend/src/core/node-registries/dataNodes.js +284 -0
  70. package/backend/src/core/node-registries/debugNodes.js +23 -0
  71. package/backend/src/core/node-registries/eventsNodes.js +223 -0
  72. package/backend/src/core/node-registries/flowNodes.js +151 -0
  73. package/backend/src/core/node-registries/furnaceNodes.js +123 -0
  74. package/backend/src/core/node-registries/index.js +108 -0
  75. package/backend/src/core/node-registries/inventory.js +102 -106
  76. package/backend/src/core/node-registries/logicNodes.js +54 -0
  77. package/backend/src/core/node-registries/mathNodes.js +38 -0
  78. package/backend/src/core/node-registries/navigationNodes.js +109 -0
  79. package/backend/src/core/node-registries/objectsNodes.js +90 -0
  80. package/backend/src/core/node-registries/stringsNodes.js +165 -0
  81. package/backend/src/core/node-registries/timeNodes.js +105 -0
  82. package/backend/src/core/node-registries/typeNodes.js +22 -0
  83. package/backend/src/core/node-registries/usersNodes.js +126 -0
  84. package/backend/src/core/nodes/arrays/shuffle.js +14 -0
  85. package/backend/src/core/nodes/bot/get_name.js +8 -0
  86. package/backend/src/core/nodes/bot/stop_bot.js +5 -0
  87. package/backend/src/core/nodes/container/open.js +101 -111
  88. package/backend/src/core/nodes/data/store_read.js +26 -0
  89. package/backend/src/core/nodes/data/store_write.js +23 -0
  90. package/backend/src/core/nodes/event/call_event.js +31 -0
  91. package/backend/src/core/nodes/event/custom_event.js +8 -0
  92. package/backend/src/core/nodes/flow/timer.js +35 -0
  93. package/backend/src/core/nodes/inventory/drop.js +73 -65
  94. package/backend/src/core/nodes/inventory/equip.js +54 -45
  95. package/backend/src/core/nodes/inventory/select_slot.js +48 -46
  96. package/backend/src/core/nodes/navigation/follow.js +54 -51
  97. package/backend/src/core/nodes/navigation/go_to.js +41 -53
  98. package/backend/src/core/nodes/navigation/go_to_entity.js +65 -69
  99. package/backend/src/core/nodes/navigation/go_to_player.js +65 -70
  100. package/backend/src/core/nodes/navigation/stop.js +17 -26
  101. package/backend/src/core/nodes/users/add_to_group.js +24 -0
  102. package/backend/src/core/nodes/users/check_permission.js +26 -0
  103. package/backend/src/core/nodes/users/remove_from_group.js +24 -0
  104. package/backend/src/core/services/BotIPCMessageRouter.js +337 -0
  105. package/backend/src/core/services/BotLifecycleService.js +41 -632
  106. package/backend/src/core/services/CacheManager.js +83 -23
  107. package/backend/src/core/services/CrashRestartManager.js +42 -0
  108. package/backend/src/core/services/DebugSessionManager.js +114 -12
  109. package/backend/src/core/services/EventGraphService.js +69 -0
  110. package/backend/src/core/services/MinecraftBotManager.js +9 -1
  111. package/backend/src/core/services/PluginManagementService.js +84 -0
  112. package/backend/src/core/services/TestModeContext.js +65 -0
  113. package/backend/src/core/services/__tests__/CacheManager.test.js +168 -0
  114. package/backend/src/core/services.js +1 -11
  115. package/backend/src/core/validation/InputValidator.js +167 -0
  116. package/backend/src/core/validation/__tests__/InputValidator.test.js +296 -0
  117. package/backend/src/real-time/botApi/index.js +1 -1
  118. package/backend/src/real-time/socketHandler.js +26 -0
  119. package/backend/src/server.js +10 -5
  120. package/frontend/dist/assets/{browser-ponyfill-DN7pwmHT.js → browser-ponyfill-D8y0Ty7C.js} +1 -1
  121. package/frontend/dist/assets/index-CFJLS0dk.css +32 -0
  122. package/frontend/dist/assets/{index-LSy71uwm.js → index-D91UGNMG.js} +1880 -1881
  123. package/frontend/dist/index.html +2 -2
  124. package/frontend/dist/locales/en/bots.json +4 -1
  125. package/frontend/dist/locales/en/common.json +7 -1
  126. package/frontend/dist/locales/en/login.json +2 -0
  127. package/frontend/dist/locales/en/management.json +79 -1
  128. package/frontend/dist/locales/en/nodes.json +59 -4
  129. package/frontend/dist/locales/en/plugin-detail.json +24 -4
  130. package/frontend/dist/locales/en/plugins.json +226 -7
  131. package/frontend/dist/locales/en/setup.json +2 -0
  132. package/frontend/dist/locales/en/sidebar.json +171 -3
  133. package/frontend/dist/locales/en/visual-editor.json +230 -31
  134. package/frontend/dist/locales/ru/bots.json +4 -1
  135. package/frontend/dist/locales/ru/login.json +2 -0
  136. package/frontend/dist/locales/ru/management.json +79 -1
  137. package/frontend/dist/locales/ru/minecraft-viewer.json +3 -0
  138. package/frontend/dist/locales/ru/nodes.json +105 -51
  139. package/frontend/dist/locales/ru/plugins.json +103 -4
  140. package/frontend/dist/locales/ru/setup.json +2 -0
  141. package/frontend/dist/locales/ru/sidebar.json +171 -3
  142. package/frontend/dist/locales/ru/visual-editor.json +232 -33
  143. package/frontend/package.json +2 -0
  144. package/nul +12 -0
  145. package/package.json +3 -3
  146. package/scripts/postinstall.js +38 -0
  147. package/backend/package-lock.json +0 -6801
  148. package/backend/src/core/node-registries/actions.js +0 -202
  149. package/backend/src/core/node-registries/arrays.js +0 -155
  150. package/backend/src/core/node-registries/bot.js +0 -23
  151. package/backend/src/core/node-registries/container.js +0 -162
  152. package/backend/src/core/node-registries/data.js +0 -290
  153. package/backend/src/core/node-registries/debug.js +0 -26
  154. package/backend/src/core/node-registries/events.js +0 -201
  155. package/backend/src/core/node-registries/flow.js +0 -139
  156. package/backend/src/core/node-registries/furnace.js +0 -143
  157. package/backend/src/core/node-registries/logic.js +0 -62
  158. package/backend/src/core/node-registries/math.js +0 -42
  159. package/backend/src/core/node-registries/navigation.js +0 -111
  160. package/backend/src/core/node-registries/objects.js +0 -98
  161. package/backend/src/core/node-registries/strings.js +0 -187
  162. package/backend/src/core/node-registries/time.js +0 -113
  163. package/backend/src/core/node-registries/type.js +0 -25
  164. package/backend/src/core/node-registries/users.js +0 -79
  165. package/frontend/dist/assets/index-SfhKxI4-.css +0 -32
@@ -12,6 +12,8 @@ const Command = require('./system/Command');
12
12
  const { parseArguments } = require('./system/parseArguments');
13
13
  const GraphExecutionEngine = require('./GraphExecutionEngine');
14
14
  const NodeRegistry = require('./NodeRegistry');
15
+ const { createBotApi } = require('./ipc/botApiFactory');
16
+ const { MessageTypes, EventTypes } = require('./ipc/ipcMessageTypes');
15
17
 
16
18
  const UserService = require('./UserService');
17
19
  const PermissionManager = require('./ipc/PermissionManager.stub.js');
@@ -40,7 +42,7 @@ JSON.parse = function (text, reviver) {
40
42
 
41
43
  function sendLog(content) {
42
44
  if (process.send) {
43
- process.send({ type: 'log', content });
45
+ process.send({ type: MessageTypes.BOT.LOG, content });
44
46
  } else {
45
47
  console.log(`[ChildProcess Log] ${content}`);
46
48
  }
@@ -49,7 +51,6 @@ function sendLog(content) {
49
51
 
50
52
  function sendEvent(eventName, eventArgs) {
51
53
  if (process.send) {
52
- // Добавляем информацию о боте (позицию) во все события
53
54
  const enrichedArgs = {
54
55
  ...eventArgs,
55
56
  botEntity: bot && bot.entity ? {
@@ -58,7 +59,7 @@ function sendEvent(eventName, eventArgs) {
58
59
  pitch: bot.entity.pitch
59
60
  } : null
60
61
  };
61
- process.send({ type: 'event', eventType: eventName, args: enrichedArgs });
62
+ process.send({ type: MessageTypes.BOT.EVENT, eventType: eventName, args: enrichedArgs });
62
63
  }
63
64
  }
64
65
 
@@ -145,7 +146,7 @@ function handleIncomingCommand(type, username, message) {
145
146
 
146
147
  if (process.send) {
147
148
  process.send({
148
- type: 'validate_and_run_command',
149
+ type: MessageTypes.COMMAND.VALIDATE_AND_RUN,
149
150
  commandName: commandInstance.name,
150
151
  username,
151
152
  args: processedArgs,
@@ -159,17 +160,17 @@ function handleIncomingCommand(type, username, message) {
159
160
  }
160
161
 
161
162
  process.on('message', async (message) => {
162
- if (message.type === 'plugin:ui:start-updates') {
163
+ if (message.type === MessageTypes.PLUGIN.UI_START_UPDATES) {
163
164
  const { pluginName } = message;
164
165
  const state = pluginUiState.get(pluginName);
165
166
  if (state && process.send) {
166
167
  process.send({
167
- type: 'plugin:data',
168
+ type: MessageTypes.PLUGIN.UI_DATA,
168
169
  plugin: pluginName,
169
170
  payload: state
170
171
  });
171
172
  }
172
- } else if (message.type === 'user_action_response') {
173
+ } else if (message.type === MessageTypes.USER.ACTION_RESPONSE) {
173
174
  if (pendingRequests.has(message.requestId)) {
174
175
  const { resolve, reject } = pendingRequests.get(message.requestId);
175
176
  if (message.error) {
@@ -179,7 +180,7 @@ process.on('message', async (message) => {
179
180
  }
180
181
  pendingRequests.delete(message.requestId);
181
182
  }
182
- } else if (message.type === 'credentials_operation_response') {
183
+ } else if (message.type === MessageTypes.USER.CREDENTIALS_OPERATION_RESPONSE) {
183
184
  if (pendingRequests.has(message.requestId)) {
184
185
  const { resolve, reject } = pendingRequests.get(message.requestId);
185
186
  if (message.error) {
@@ -189,16 +190,16 @@ process.on('message', async (message) => {
189
190
  }
190
191
  pendingRequests.delete(message.requestId);
191
192
  }
192
- } else if (message.type === 'system:get_player_list') {
193
+ } else if (message.type === MessageTypes.SYSTEM.GET_PLAYER_LIST) {
193
194
  const playerList = bot ? Object.keys(bot.players) : [];
194
195
  if (process.send) {
195
196
  process.send({
196
- type: 'get_player_list_response',
197
+ type: MessageTypes.SYSTEM.GET_PLAYER_LIST_RESPONSE,
197
198
  requestId: message.requestId,
198
199
  payload: { players: playerList }
199
200
  });
200
201
  }
201
- } else if (message.type === 'system:get_nearby_entities') {
202
+ } else if (message.type === MessageTypes.SYSTEM.GET_NEARBY_ENTITIES) {
202
203
  const entities = [];
203
204
  if (bot && bot.entities) {
204
205
  const centerPos = message.payload?.position || bot.entity?.position;
@@ -225,12 +226,12 @@ process.on('message', async (message) => {
225
226
 
226
227
  if (process.send) {
227
228
  process.send({
228
- type: 'get_nearby_entities_response',
229
+ type: MessageTypes.SYSTEM.GET_NEARBY_ENTITIES_RESPONSE,
229
230
  requestId: message.requestId,
230
231
  payload: { entities }
231
232
  });
232
233
  }
233
- } else if (message.type === 'viewer:get_state') {
234
+ } else if (message.type === MessageTypes.VIEWER.GET_STATE) {
234
235
  if (bot && process.send) {
235
236
  let blocks = undefined;
236
237
 
@@ -297,12 +298,12 @@ process.on('message', async (message) => {
297
298
  };
298
299
 
299
300
  process.send({
300
- type: 'viewer:state_response',
301
+ type: MessageTypes.VIEWER.STATE_RESPONSE,
301
302
  requestId: message.requestId,
302
303
  payload: state
303
304
  });
304
305
  }
305
- } else if (message.type === 'viewer:control') {
306
+ } else if (message.type === MessageTypes.VIEWER.CONTROL) {
306
307
  const { command } = message;
307
308
  if (!bot) return;
308
309
 
@@ -367,58 +368,12 @@ process.on('message', async (message) => {
367
368
  } catch (error) {
368
369
  sendLog(`[Viewer] Control error: ${error.message}`);
369
370
  }
370
- } else if (message.type === 'execute_event_graph') {
371
- // Выполнение event графа в child process
371
+ } else if (message.type === MessageTypes.GRAPH.EXECUTE_EVENT_GRAPH) {
372
372
  const { botId, graph, eventType, eventArgs } = message;
373
373
 
374
374
  try {
375
-
376
375
  const playerList = bot ? Object.keys(bot.players) : [];
377
- const botApi = {
378
- sendMessage: (chatType, message, recipient) => {
379
- if (!bot || !bot.messageQueue) {
380
- sendLog('[EventGraph] Bot not ready');
381
- return;
382
- }
383
-
384
- bot.messageQueue.enqueue(chatType, message, recipient);
385
- },
386
- executeCommand: (command) => {
387
- if (!bot || !bot.messageQueue) {
388
- sendLog('[EventGraph] Bot not ready');
389
- return;
390
- }
391
- bot.messageQueue.enqueue('command', command);
392
- },
393
- lookAt: async (x, y, z) => {
394
- if (!bot) return;
395
- const target = new Vec3(x, y, z);
396
- await bot.lookAt(target);
397
- },
398
- navigate: async (x, y, z) => {
399
- if (!bot || !bot.pathfinder) return;
400
- const goal = new (require('mineflayer-pathfinder').goals.GoalBlock)(x, y, z);
401
- await bot.pathfinder.goto(goal);
402
- },
403
- attack: (entityId) => {
404
- if (!bot) return;
405
- const entity = bot.entities[entityId];
406
- if (entity) bot.attack(entity);
407
- },
408
- follow: (username) => {
409
- if (!bot || !bot.pathfinder) return;
410
- const player = bot.players[username];
411
- if (player && player.entity) {
412
- const goal = new (require('mineflayer-pathfinder').goals.GoalFollow)(player.entity, 3);
413
- bot.pathfinder.setGoal(goal, true);
414
- }
415
- },
416
- stopFollow: () => {
417
- if (bot && bot.pathfinder) {
418
- bot.pathfinder.setGoal(null);
419
- }
420
- }
421
- };
376
+ const botApi = createBotApi(bot, { enableLogging: true });
422
377
 
423
378
  const context = {
424
379
  bot: bot, // Полный mineflayer bot
@@ -446,7 +401,7 @@ process.on('message', async (message) => {
446
401
  sendLog(`[EventGraph] Error executing ${eventType} graph: ${error.message}`);
447
402
  sendLog(`[EventGraph] Stack: ${error.stack}`);
448
403
  }
449
- } else if (message.type === 'start') {
404
+ } else if (message.type === MessageTypes.BOT.START) {
450
405
  const config = message.config;
451
406
  sendLog(`[System] Получена команда на запуск бота ${config.username}...`);
452
407
  try {
@@ -524,7 +479,7 @@ process.on('message', async (message) => {
524
479
  if (type === 'websocket') {
525
480
  if (process.send) {
526
481
  process.send({
527
- type: 'send_websocket_message',
482
+ type: MessageTypes.WEBSOCKET.SEND_MESSAGE,
528
483
  payload: {
529
484
  botId: bot.config.id,
530
485
  message: message,
@@ -633,7 +588,7 @@ process.on('message', async (message) => {
633
588
 
634
589
  if (process.send) {
635
590
  process.send({
636
- type: 'register_command',
591
+ type: MessageTypes.COMMAND.REGISTER,
637
592
  commandConfig: {
638
593
  name: command.name,
639
594
  description: command.description,
@@ -664,7 +619,7 @@ process.on('message', async (message) => {
664
619
 
665
620
  if (process.send) {
666
621
  process.send({
667
- type: 'request_user_action',
622
+ type: MessageTypes.USER.REQUEST_ACTION,
668
623
  requestId,
669
624
  payload: {
670
625
  targetUsername: username,
@@ -791,7 +746,7 @@ process.on('message', async (message) => {
791
746
 
792
747
  if (process.send) {
793
748
  process.send({
794
- type: 'plugin:data',
749
+ type: MessageTypes.PLUGIN.UI_DATA,
795
750
  plugin: pluginName,
796
751
  payload: newState
797
752
  });
@@ -806,7 +761,7 @@ process.on('message', async (message) => {
806
761
 
807
762
  if (process.send) {
808
763
  process.send({
809
- type: 'update_credentials',
764
+ type: MessageTypes.BOT.UPDATE_CREDENTIALS,
810
765
  requestId,
811
766
  payload: {
812
767
  botId: bot.config.id,
@@ -834,7 +789,7 @@ process.on('message', async (message) => {
834
789
 
835
790
  if (process.send) {
836
791
  process.send({
837
- type: 'restart_bot',
792
+ type: MessageTypes.BOT.RESTART,
838
793
  requestId,
839
794
  payload: {
840
795
  botId: bot.config.id
@@ -860,7 +815,7 @@ process.on('message', async (message) => {
860
815
 
861
816
  if (process.send) {
862
817
  process.send({
863
- type: 'change_credentials',
818
+ type: MessageTypes.BOT.CHANGE_CREDENTIALS,
864
819
  requestId,
865
820
  payload: {
866
821
  botId: bot.config.id,
@@ -892,7 +847,7 @@ process.on('message', async (message) => {
892
847
  const processApi = {
893
848
  appendLog: (botId, message) => {
894
849
  if (process.send) {
895
- process.send({ type: 'log', content: message });
850
+ process.send({ type: MessageTypes.BOT.LOG, content: message });
896
851
  }
897
852
  }
898
853
  };
@@ -990,7 +945,7 @@ process.on('message', async (message) => {
990
945
  if (process.send) {
991
946
  for (const cmd of bot.commands.values()) {
992
947
  process.send({
993
- type: 'register_command',
948
+ type: MessageTypes.COMMAND.REGISTER,
994
949
  commandConfig: {
995
950
  name: cmd.name,
996
951
  description: cmd.description,
@@ -1028,7 +983,7 @@ process.on('message', async (message) => {
1028
983
 
1029
984
  if (process.send && rawMessageText.trim()) {
1030
985
  process.send({
1031
- type: 'viewer:chat',
986
+ type: MessageTypes.VIEWER.CHAT,
1032
987
  payload: {
1033
988
  rawText: rawMessageText,
1034
989
  timestamp: Date.now()
@@ -1050,12 +1005,22 @@ process.on('message', async (message) => {
1050
1005
 
1051
1006
  bot.on('chat', (username, message) => {
1052
1007
  if (messageHandledByCustomParser) return;
1053
- handleIncomingCommand('chat', username, message);
1008
+ bot.events.emit('chat:message', {
1009
+ username,
1010
+ message,
1011
+ type: EventTypes.CHAT,
1012
+ raw: message
1013
+ });
1054
1014
  });
1055
1015
 
1056
1016
  bot.on('whisper', (username, message) => {
1057
1017
  if (messageHandledByCustomParser) return;
1058
- handleIncomingCommand('whisper', username, message);
1018
+ bot.events.emit('chat:message', {
1019
+ username,
1020
+ message,
1021
+ type: EventTypes.WHISPER,
1022
+ raw: message
1023
+ });
1059
1024
  });
1060
1025
 
1061
1026
  bot.on('userAction', async ({ action, target, ...data }) => {
@@ -1086,8 +1051,8 @@ process.on('message', async (message) => {
1086
1051
  }
1087
1052
  sendLog('[Event: login] Успешно залогинился!');
1088
1053
  if (process.send && !botReadySent) {
1089
- process.send({ type: 'bot_ready' });
1090
- process.send({ type: 'status', status: 'running' });
1054
+ process.send({ type: MessageTypes.BOT.READY });
1055
+ process.send({ type: MessageTypes.BOT.STATUS, status: 'running' });
1091
1056
  botReadySent = true;
1092
1057
  }
1093
1058
  });
@@ -1106,7 +1071,13 @@ process.on('message', async (message) => {
1106
1071
 
1107
1072
  bot.on('kicked', (reason) => {
1108
1073
  let reasonText;
1109
- try { reasonText = JSON.parse(reason).text || reason; } catch (e) { reasonText = reason; }
1074
+ if (typeof reason === 'string') {
1075
+ try { reasonText = JSON.parse(reason).text || reason; } catch (e) { reasonText = reason; }
1076
+ } else if (reason && typeof reason === 'object') {
1077
+ reasonText = reason.text || reason.message || reason.reason || JSON.stringify(reason);
1078
+ } else {
1079
+ reasonText = String(reason);
1080
+ }
1110
1081
  sendLog(`[Event: kicked] Меня кикнули. Причина: ${reasonText}.`);
1111
1082
  process.exit(0);
1112
1083
  });
@@ -1180,7 +1151,7 @@ process.on('message', async (message) => {
1180
1151
  // Отправка события для viewer
1181
1152
  if (process.send) {
1182
1153
  process.send({
1183
- type: 'viewer:spawn',
1154
+ type: MessageTypes.VIEWER.SPAWN,
1184
1155
  payload: {
1185
1156
  position: bot.entity?.position,
1186
1157
  yaw: bot.entity?.yaw,
@@ -1193,7 +1164,7 @@ process.on('message', async (message) => {
1193
1164
  bot.on('health', () => {
1194
1165
  if (process.send) {
1195
1166
  process.send({
1196
- type: 'viewer:health',
1167
+ type: MessageTypes.VIEWER.HEALTH,
1197
1168
  payload: {
1198
1169
  health: bot.health,
1199
1170
  food: bot.food
@@ -1205,7 +1176,7 @@ process.on('message', async (message) => {
1205
1176
  bot.on('move', () => {
1206
1177
  if (process.send) {
1207
1178
  process.send({
1208
- type: 'viewer:move',
1179
+ type: MessageTypes.VIEWER.MOVE,
1209
1180
  payload: {
1210
1181
  position: bot.entity?.position,
1211
1182
  yaw: bot.entity?.yaw,
@@ -1241,7 +1212,7 @@ process.on('message', async (message) => {
1241
1212
  sendLog(`[CRITICAL] Критическая ошибка при создании бота: ${err.stack}`);
1242
1213
  process.exit(1);
1243
1214
  }
1244
- } else if (message.type === 'config:reload') {
1215
+ } else if (message.type === MessageTypes.CONFIG.RELOAD) {
1245
1216
  sendLog('[System] Received config:reload command. Reloading configuration...');
1246
1217
  try {
1247
1218
  const newConfig = await fetchNewConfig(bot.config.id, prisma);
@@ -1258,7 +1229,7 @@ process.on('message', async (message) => {
1258
1229
  } catch (error) {
1259
1230
  sendLog(`[System] Error reloading configuration: ${error.message}`);
1260
1231
  }
1261
- } else if (message.type === 'stop') {
1232
+ } else if (message.type === MessageTypes.BOT.STOP) {
1262
1233
  if (connectionTimeout) {
1263
1234
  clearTimeout(connectionTimeout);
1264
1235
  connectionTimeout = null;
@@ -1266,12 +1237,12 @@ process.on('message', async (message) => {
1266
1237
  botReadySent = false;
1267
1238
  if (bot) bot.quit();
1268
1239
  else process.exit(0);
1269
- } else if (message.type === 'chat') {
1240
+ } else if (message.type === MessageTypes.CHAT.CHAT) {
1270
1241
  if (bot && bot.entity) {
1271
1242
  const { message: msg, chatType, username } = message.payload;
1272
1243
  bot.messageQueue.enqueue(chatType, msg, username);
1273
1244
  }
1274
- } else if (message.type === 'register_temp_command') {
1245
+ } else if (message.type === MessageTypes.COMMAND.REGISTER_TEMP) {
1275
1246
  // Регистрация временной команды из главного процесса
1276
1247
  const { commandData } = message;
1277
1248
 
@@ -1303,7 +1274,7 @@ process.on('message', async (message) => {
1303
1274
  } catch (error) {
1304
1275
  sendLog(`[BotProcess] Ошибка регистрации временной команды: ${error.message}`);
1305
1276
  }
1306
- } else if (message.type === 'unregister_temp_command') {
1277
+ } else if (message.type === MessageTypes.COMMAND.UNREGISTER_TEMP) {
1307
1278
  const { commandName, aliases } = message;
1308
1279
 
1309
1280
  try {
@@ -1321,7 +1292,7 @@ process.on('message', async (message) => {
1321
1292
  } catch (error) {
1322
1293
  sendLog(`[BotProcess] Ошибка удаления временной команды: ${error.message}`);
1323
1294
  }
1324
- } else if (message.type === 'execute_handler') {
1295
+ } else if (message.type === MessageTypes.GRAPH.EXECUTE_HANDLER) {
1325
1296
  const { commandName, username, args, typeChat } = message;
1326
1297
  const commandInstance = bot.commands.get(commandName);
1327
1298
  if (commandInstance) {
@@ -1344,7 +1315,7 @@ process.on('message', async (message) => {
1344
1315
  }
1345
1316
  })();
1346
1317
  }
1347
- } else if (message.type === 'execute_command_request') {
1318
+ } else if (message.type === MessageTypes.GRAPH.EXECUTE_COMMAND_REQUEST) {
1348
1319
  const { requestId, payload } = message;
1349
1320
  const { commandName, args, username, typeChat } = payload;
1350
1321
 
@@ -1368,7 +1339,7 @@ process.on('message', async (message) => {
1368
1339
  if (typeChat === 'websocket') {
1369
1340
  result = await commandInstance.handler(context);
1370
1341
  if (process.send) {
1371
- process.send({ type: 'execute_command_response', requestId, result });
1342
+ process.send({ type: MessageTypes.GRAPH.EXECUTE_COMMAND_RESPONSE, requestId, result });
1372
1343
  }
1373
1344
  } else {
1374
1345
  commandInstance.handler(context).catch(e => {
@@ -1397,7 +1368,7 @@ process.on('message', async (message) => {
1397
1368
  result = sendMessageCalled ? resultFromSendMessage : returnValue;
1398
1369
 
1399
1370
  if (process.send) {
1400
- process.send({ type: 'execute_command_response', requestId, result });
1371
+ process.send({ type: MessageTypes.GRAPH.EXECUTE_COMMAND_RESPONSE, requestId, result });
1401
1372
  }
1402
1373
  } finally {
1403
1374
  bot.sendMessage = originalSendMessage;
@@ -1412,15 +1383,15 @@ process.on('message', async (message) => {
1412
1383
 
1413
1384
  } catch (error) {
1414
1385
  if (process.send) {
1415
- process.send({ type: 'execute_command_response', requestId, error: error.message });
1386
+ process.send({ type: MessageTypes.GRAPH.EXECUTE_COMMAND_RESPONSE, requestId, error: error.message });
1416
1387
  }
1417
1388
  }
1418
1389
  })();
1419
- } else if (message.type === 'invalidate_user_cache') {
1390
+ } else if (message.type === MessageTypes.USER.INVALIDATE_USER_CACHE) {
1420
1391
  if (message.username && bot && bot.config) {
1421
1392
  UserService.clearCache(message.username, bot.config.id);
1422
1393
  }
1423
- } else if (message.type === 'invalidate_all_user_cache') {
1394
+ } else if (message.type === MessageTypes.USER.INVALIDATE_ALL_USER_CACHE) {
1424
1395
  if (bot && bot.config) {
1425
1396
  for (const [cacheKey, user] of UserService.cache.entries()) {
1426
1397
  if (cacheKey.startsWith(`${bot.config.id}:`)) {
@@ -1429,7 +1400,7 @@ process.on('message', async (message) => {
1429
1400
  }
1430
1401
  sendLog(`[BotProcess] Кэш пользователей очищен для бота ${bot.config.id}`);
1431
1402
  }
1432
- } else if (message.type === 'handle_permission_error') {
1403
+ } else if (message.type === MessageTypes.COMMAND.HANDLE_PERMISSION_ERROR) {
1433
1404
  const { commandName, username, typeChat } = message;
1434
1405
  const commandInstance = bot.commands.get(commandName);
1435
1406
  if (commandInstance) {
@@ -1439,7 +1410,7 @@ process.on('message', async (message) => {
1439
1410
  bot.api.sendMessage(typeChat, `У вас нет прав для выполнения команды ${commandName}.`, username);
1440
1411
  }
1441
1412
  }
1442
- } else if (message.type === 'handle_wrong_chat') {
1413
+ } else if (message.type === MessageTypes.COMMAND.HANDLE_WRONG_CHAT) {
1443
1414
  const { commandName, username, typeChat } = message;
1444
1415
  const commandInstance = bot.commands.get(commandName);
1445
1416
  if (commandInstance) {
@@ -1449,7 +1420,7 @@ process.on('message', async (message) => {
1449
1420
  bot.api.sendMessage('private', `Команду ${commandName} нельзя использовать в этом типе чата - ${typeChat}.`, username);
1450
1421
  }
1451
1422
  }
1452
- } else if (message.type === 'handle_cooldown') {
1423
+ } else if (message.type === MessageTypes.COMMAND.HANDLE_COOLDOWN) {
1453
1424
  const { commandName, username, typeChat, timeLeft } = message;
1454
1425
  const commandInstance = bot.commands.get(commandName);
1455
1426
  if (commandInstance) {
@@ -1459,7 +1430,7 @@ process.on('message', async (message) => {
1459
1430
  bot.api.sendMessage(typeChat, `Команду ${commandName} можно будет использовать через ${timeLeft} сек.`, username);
1460
1431
  }
1461
1432
  }
1462
- } else if (message.type === 'handle_blacklist') {
1433
+ } else if (message.type === MessageTypes.COMMAND.HANDLE_BLACKLIST) {
1463
1434
  const { commandName, username, typeChat } = message;
1464
1435
  const commandInstance = bot.commands.get(commandName);
1465
1436
  if (commandInstance) {
@@ -1467,12 +1438,12 @@ process.on('message', async (message) => {
1467
1438
  commandInstance.onBlacklisted(bot, typeChat, { username });
1468
1439
  }
1469
1440
  }
1470
- } else if (message.type === 'send_message') {
1441
+ } else if (message.type === MessageTypes.CHAT.SEND_MESSAGE) {
1471
1442
  const { typeChat, message: msg, username } = message;
1472
1443
  if (bot && bot.api) {
1473
1444
  bot.api.sendMessage(typeChat, msg, username);
1474
1445
  }
1475
- } else if (message.type === 'action') {
1446
+ } else if (message.type === MessageTypes.CHAT.ACTION) {
1476
1447
  if (message.name === 'lookAt' && bot && message.payload.position) {
1477
1448
  const { x, y, z } = message.payload.position;
1478
1449
  if (typeof x === 'number' && typeof y === 'number' && typeof z === 'number') {
@@ -1481,7 +1452,7 @@ process.on('message', async (message) => {
1481
1452
  sendLog(`[BotProcess] Ошибка lookAt: получены невалидные координаты: ${JSON.stringify(message.payload.position)}`);
1482
1453
  }
1483
1454
  }
1484
- } else if (message.type === 'plugins:reload') {
1455
+ } else if (message.type === MessageTypes.PLUGINS.RELOAD) {
1485
1456
  sendLog('[System] Получена команда на перезагрузку плагинов...');
1486
1457
  const newConfig = await fetchNewConfig(bot.config.id, prisma);
1487
1458
  if (newConfig) {
@@ -1495,12 +1466,11 @@ process.on('message', async (message) => {
1495
1466
  } else {
1496
1467
  sendLog('[System] Не удалось получить новую конфигурацию для перезагрузки плагинов.');
1497
1468
  }
1498
- } else if (message.type === 'server_command') {
1469
+ } else if (message.type === MessageTypes.SERVER.COMMAND) {
1499
1470
  if (bot && bot.messageQueue && message.payload && message.payload.command) {
1500
1471
  bot.messageQueue.enqueue('command', message.payload.command);
1501
1472
  }
1502
- } else if (message.type === 'execute_event_graph') {
1503
- // Выполнение event графа в child process
1473
+ } else if (message.type === MessageTypes.GRAPH.EXECUTE_EVENT_GRAPH) {
1504
1474
  const { graph, eventType, eventArgs } = message;
1505
1475
 
1506
1476
  try {
@@ -1515,44 +1485,7 @@ process.on('message', async (message) => {
1515
1485
  return;
1516
1486
  }
1517
1487
 
1518
- const botApi = {
1519
- sendMessage: (chatType, messageText, recipient) => {
1520
- if (!bot || !bot.messageQueue) return;
1521
- bot.messageQueue.enqueue(chatType, messageText, recipient);
1522
- },
1523
- executeCommand: (command) => {
1524
- if (!bot || !bot.messageQueue) return;
1525
- bot.messageQueue.enqueue('command', command);
1526
- },
1527
- lookAt: async (x, y, z) => {
1528
- if (!bot) return;
1529
- const target = new Vec3(x, y, z);
1530
- await bot.lookAt(target);
1531
- },
1532
- navigate: async (x, y, z) => {
1533
- if (!bot || !bot.pathfinder) return;
1534
- const goal = new (require('mineflayer-pathfinder').goals.GoalBlock)(x, y, z);
1535
- await bot.pathfinder.goto(goal);
1536
- },
1537
- attack: (entityId) => {
1538
- if (!bot) return;
1539
- const entity = bot.entities[entityId];
1540
- if (entity) bot.attack(entity);
1541
- },
1542
- follow: (username) => {
1543
- if (!bot || !bot.pathfinder) return;
1544
- const player = bot.players[username];
1545
- if (player && player.entity) {
1546
- const goal = new (require('mineflayer-pathfinder').goals.GoalFollow)(player.entity, 3);
1547
- bot.pathfinder.setGoal(goal, true);
1548
- }
1549
- },
1550
- stopFollow: () => {
1551
- if (bot && bot.pathfinder) {
1552
- bot.pathfinder.setGoal(null);
1553
- }
1554
- }
1555
- };
1488
+ const botApi = createBotApi(bot);
1556
1489
 
1557
1490
  const players = bot ? Object.keys(bot.players) : [];
1558
1491
 
@@ -7,14 +7,18 @@ const botHistoryStore = require('./BotHistoryStore');
7
7
  const prisma = prismaService.getClient();
8
8
 
9
9
  class EventGraphManager {
10
- constructor(botManager = null) {
11
- this.botManager = botManager;
10
+ constructor() {
11
+ this._botManager = null;
12
12
  this.activeGraphs = new Map();
13
13
  this.graphStates = new Map();
14
14
  }
15
15
 
16
+ get botManager() {
17
+ return this._botManager;
18
+ }
19
+
16
20
  setBotManager(botManager) {
17
- this.botManager = botManager;
21
+ this._botManager = botManager;
18
22
  }
19
23
 
20
24
  async loadGraphsForBot(botId) {