blockmine 1.4.4 → 1.4.7

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.
@@ -24,6 +24,26 @@ const WARNING_COOLDOWN = 10 * 1000;
24
24
  const STATS_SERVER_URL = 'http://185.65.200.184:3000';
25
25
  let instanceId = null;
26
26
  const DATA_DIR = path.join(os.homedir(), '.blockmine');
27
+ const INSTANCE_ID_PATH = path.join(DATA_DIR, '.instance_id');
28
+
29
+ function getInstanceId() {
30
+ if (instanceId) return instanceId;
31
+ try {
32
+ if (fs.existsSync(INSTANCE_ID_PATH)) {
33
+ instanceId = fs.readFileSync(INSTANCE_ID_PATH, 'utf-8');
34
+ } else {
35
+ instanceId = uuidv4();
36
+ if (!fs.existsSync(DATA_DIR)) {
37
+ fs.mkdirSync(DATA_DIR, { recursive: true });
38
+ }
39
+ fs.writeFileSync(INSTANCE_ID_PATH, instanceId, 'utf-8');
40
+ }
41
+ } catch (error) {
42
+ console.error('[Telemetry] Ошибка при загрузке/создании Instance ID:', error);
43
+ return null;
44
+ }
45
+ return instanceId;
46
+ }
27
47
 
28
48
 
29
49
  class BotManager {
@@ -33,6 +53,8 @@ class BotManager {
33
53
  this.resourceUsage = new Map();
34
54
  this.botConfigs = new Map();
35
55
 
56
+ getInstanceId();
57
+
36
58
  setInterval(() => this.updateAllResourceUsage(), 5000);
37
59
  if (config.telemetry?.enabled) {
38
60
  setInterval(() => this.sendHeartbeat(), 5 * 60 * 1000);
@@ -74,6 +96,17 @@ class BotManager {
74
96
  }
75
97
  }
76
98
 
99
+ reloadBotConfigInRealTime(botId) {
100
+ this.invalidateConfigCache(botId);
101
+ const child = this.bots.get(botId);
102
+ if (child && !child.killed) {
103
+ child.send({ type: 'config:reload' });
104
+ console.log(`[BotManager] Sent config:reload to bot process ${botId}`);
105
+
106
+ getIO().emit('bot:config_reloaded', { botId });
107
+ }
108
+ }
109
+
77
110
  triggerHeartbeat() {
78
111
  if (!config.telemetry?.enabled) return;
79
112
  if (this.heartbeatDebounceTimer) {
@@ -538,6 +571,18 @@ class BotManager {
538
571
  }
539
572
  return { success: true };
540
573
  }
574
+
575
+ reloadBotConfigInRealTime(botId) {
576
+ this.invalidateConfigCache(botId);
577
+ const child = this.bots.get(botId);
578
+ if (child && !child.killed) {
579
+ child.send({ type: 'config:reload' });
580
+ console.log(`[BotManager] Sent config:reload to bot process ${botId}`);
581
+
582
+ const { getIO } = require('../real-time/socketHandler');
583
+ getIO().emit('bot:config_reloaded', { botId });
584
+ }
585
+ }
541
586
  }
542
587
 
543
588
  module.exports = new BotManager();
@@ -22,6 +22,29 @@ function sendLog(content) {
22
22
  }
23
23
  }
24
24
 
25
+ async function fetchNewConfig(botId) {
26
+ try {
27
+ const botData = await prisma.bot.findUnique({
28
+ where: { id: botId },
29
+ include: {
30
+ server: true,
31
+ installedPlugins: {
32
+ where: { isEnabled: true }
33
+ },
34
+ }
35
+ });
36
+
37
+ if (!botData) return null;
38
+
39
+ const commands = await prisma.command.findMany({ where: { botId } });
40
+
41
+ return { ...botData, commands };
42
+ } catch (error) {
43
+ sendLog(`[fetchNewConfig] Error: ${error.message}`);
44
+ return null;
45
+ }
46
+ }
47
+
25
48
  function handleIncomingCommand(type, username, message) {
26
49
  if (!message.startsWith(bot.config.prefix || '@')) return;
27
50
 
@@ -51,7 +74,7 @@ function handleIncomingCommand(type, username, message) {
51
74
  if (argDef.type === 'number') {
52
75
  const numValue = parseFloat(value);
53
76
  if (isNaN(numValue)) {
54
- bot.api.sendMessage(type, `Ошибка: Аргумент "${argDef.description}" должен быть числом.`, username);
77
+ bot.api.sendMessage(type, `Ошибка: Аргумент \"${argDef.description}\" должен быть числом.`, username);
55
78
  return;
56
79
  }
57
80
  value = numValue;
@@ -181,7 +204,7 @@ process.on('message', async (message) => {
181
204
  }
182
205
  });
183
206
  }
184
- sendLog(`[API] Команда "${commandInstance.name}" от плагина "${commandInstance.owner}" зарегистрирована в процессе.`);
207
+ sendLog(`[API] Команда \"${commandInstance.name}\" от плагина \"${commandInstance.owner}\" зарегистрирована в процессе.`);
185
208
  },
186
209
  performUserAction: (username, action, data = {}) => {
187
210
  return new Promise((resolve, reject) => {
@@ -283,6 +306,26 @@ process.on('message', async (message) => {
283
306
  sendLog(`[CRITICAL] Критическая ошибка при создании бота: ${err.stack}`);
284
307
  process.exit(1);
285
308
  }
309
+ } else if (message.type === 'config:reload') {
310
+ sendLog('[System] Received config:reload command. Reloading configuration...');
311
+ try {
312
+ const newConfig = await fetchNewConfig(bot.config.id);
313
+ if (newConfig) {
314
+ bot.config = { ...bot.config, ...newConfig };
315
+
316
+ const newCommands = await loadCommands();
317
+ const newPlugins = bot.config.plugins;
318
+
319
+ bot.commands = newCommands;
320
+ await initializePlugins(bot, newPlugins, true);
321
+
322
+ sendLog('[System] Bot configuration and plugins reloaded successfully.');
323
+ } else {
324
+ sendLog('[System] Failed to fetch new configuration.');
325
+ }
326
+ } catch (error) {
327
+ sendLog(`[System] Error reloading configuration: ${error.message}`);
328
+ }
286
329
  } else if (message.type === 'stop') {
287
330
  if (bot) bot.quit();
288
331
  else process.exit(0);
@@ -340,4 +383,4 @@ process.on('unhandledRejection', (reason, promise) => {
340
383
  sendLog(errorMsg);
341
384
  console.error(errorMsg, promise);
342
385
  process.exit(1);
343
- });
386
+ });
@@ -1,24 +1,30 @@
1
-
2
1
  const crypto = require('crypto');
3
2
  const config = require('../../config');
4
-
5
3
  const ALGORITHM = 'aes-256-gcm';
6
4
  const IV_LENGTH = 16;
7
- const AUTH_TAG_LENGTH = 16;
8
- const KEY = Buffer.from(config.security.encryptionKey, 'hex');
5
+
6
+
7
+ function getEncryptionKey() {
8
+ const key = config.security.encryptionKey;
9
+ if (!key || key.length !== 64) {
10
+ throw new Error('[Crypto] Ключ шифрования не настроен или имеет неверную длину в config.json');
11
+ }
12
+ return Buffer.from(key, 'hex');
13
+ }
14
+
9
15
 
10
16
  function encrypt(text) {
11
17
  if (!text) return null;
12
18
  try {
19
+ const key = getEncryptionKey();
13
20
  const iv = crypto.randomBytes(IV_LENGTH);
14
- const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);
21
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
15
22
  const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
16
23
  const authTag = cipher.getAuthTag();
17
24
 
18
25
  return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted.toString('hex')}`;
19
26
  } catch (error) {
20
- console.error('[Crypto] Ошибка шифрования:', error);
21
- return null;
27
+ throw new Error(`[Crypto] Ошибка шифрования: ${error.message}`);
22
28
  }
23
29
  }
24
30
 
@@ -27,22 +33,21 @@ function decrypt(hash) {
27
33
  try {
28
34
  const parts = hash.split(':');
29
35
  if (parts.length !== 3) {
30
- console.error('[Crypto] Неверный формат зашифрованных данных. Возвращаем как есть.');
31
- return hash;
36
+ return hash;
32
37
  }
33
38
 
39
+ const key = getEncryptionKey();
34
40
  const iv = Buffer.from(parts[0], 'hex');
35
41
  const authTag = Buffer.from(parts[1], 'hex');
36
42
  const encrypted = Buffer.from(parts[2], 'hex');
37
43
 
38
- const decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv);
44
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
39
45
  decipher.setAuthTag(authTag);
40
46
 
41
47
  const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
42
48
  return decrypted.toString('utf8');
43
49
  } catch (error) {
44
- console.error('[Crypto] Ошибка дешифрования. Возможно, ключ был изменен или данные повреждены.', error);
45
- return null;
50
+ throw new Error(`[Crypto] Ошибка дешифрования. Возможно, ключ был изменен или данные повреждены. ${error.message}`);
46
51
  }
47
52
  }
48
53
 
@@ -12,6 +12,7 @@ const serverRoutes = require('./api/routes/servers');
12
12
  const permissionsRoutes = require('./api/routes/permissions');
13
13
  const taskRoutes = require('./api/routes/tasks');
14
14
  const authRoutes = require('./api/routes/auth');
15
+ const searchRoutes = require('./api/routes/search');
15
16
  const BotManager = require('./core/BotManager');
16
17
  const TaskScheduler = require('./core/TaskScheduler');
17
18
  const panelRoutes = require('./api/routes/panel');
@@ -51,6 +52,7 @@ app.use('/api/bots', botRoutes);
51
52
  app.use('/api/plugins', pluginRoutes);
52
53
  app.use('/api/servers', serverRoutes);
53
54
  app.use('/api/permissions', permissionsRoutes);
55
+ app.use('/api/search', searchRoutes);
54
56
  app.use('/api/panel', panelRoutes);
55
57
 
56
58
  app.use(express.static(frontendPath));