blockmine 1.4.6 → 1.4.8
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/backend/package.json +1 -2
- package/backend/src/api/routes/bots.js +32 -9
- package/backend/src/api/routes/search.js +55 -0
- package/backend/src/core/BotManager.js +24 -1
- package/backend/src/core/BotProcess.js +46 -3
- package/backend/src/server.js +2 -0
- package/frontend/dist/assets/index-CLCxr_rh.js +8179 -0
- package/frontend/dist/assets/index-Dk9CeSuD.css +1 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/package.json +1 -0
- package/image/1.png +0 -0
- package/image/2.png +0 -0
- package/image/3.png +0 -0
- package/package.json +3 -2
- package/frontend/dist/assets/index-BKT73TwN.css +0 -1
- package/frontend/dist/assets/index-eIaThNXb.js +0 -8179
package/backend/package.json
CHANGED
|
@@ -518,13 +518,36 @@ router.get('/:botId/management-data', authorize('management:view'), async (req,
|
|
|
518
518
|
};
|
|
519
519
|
})
|
|
520
520
|
|
|
521
|
-
const
|
|
521
|
+
const page = parseInt(req.query.page) || 1;
|
|
522
|
+
const pageSize = parseInt(req.query.pageSize) || 100;
|
|
523
|
+
|
|
524
|
+
const userSkip = (page - 1) * pageSize;
|
|
525
|
+
|
|
526
|
+
const [groups, users, allPermissions, usersCount] = await Promise.all([
|
|
522
527
|
prisma.group.findMany({ where: { botId }, include: { permissions: { include: { permission: true } } }, orderBy: { name: 'asc' } }),
|
|
523
|
-
prisma.user.findMany({
|
|
524
|
-
|
|
528
|
+
prisma.user.findMany({
|
|
529
|
+
where: { botId },
|
|
530
|
+
include: { groups: { include: { group: true } } },
|
|
531
|
+
orderBy: { username: 'asc' },
|
|
532
|
+
take: pageSize,
|
|
533
|
+
skip: userSkip,
|
|
534
|
+
}),
|
|
535
|
+
prisma.permission.findMany({ where: { botId }, orderBy: { name: 'asc' } }),
|
|
536
|
+
prisma.user.count({ where: { botId } })
|
|
525
537
|
]);
|
|
526
538
|
|
|
527
|
-
res.json({
|
|
539
|
+
res.json({
|
|
540
|
+
groups,
|
|
541
|
+
permissions: allPermissions,
|
|
542
|
+
users: {
|
|
543
|
+
items: users,
|
|
544
|
+
total: usersCount,
|
|
545
|
+
page,
|
|
546
|
+
pageSize,
|
|
547
|
+
totalPages: Math.ceil(usersCount / pageSize),
|
|
548
|
+
},
|
|
549
|
+
commands: finalCommands
|
|
550
|
+
});
|
|
528
551
|
|
|
529
552
|
} catch (error) {
|
|
530
553
|
console.error(`[API Error] /management-data for bot ${req.params.botId}:`, error);
|
|
@@ -558,7 +581,7 @@ router.put('/:botId/commands/:commandId', authorize('management:edit'), async (r
|
|
|
558
581
|
data: dataToUpdate,
|
|
559
582
|
});
|
|
560
583
|
|
|
561
|
-
BotManager.
|
|
584
|
+
BotManager.reloadBotConfigInRealTime(botId);
|
|
562
585
|
|
|
563
586
|
res.json(updatedCommand);
|
|
564
587
|
} catch (error) {
|
|
@@ -582,7 +605,7 @@ router.post('/:botId/groups', authorize('management:edit'), async (req, res) =>
|
|
|
582
605
|
}
|
|
583
606
|
});
|
|
584
607
|
|
|
585
|
-
BotManager.
|
|
608
|
+
BotManager.reloadBotConfigInRealTime(botId);
|
|
586
609
|
|
|
587
610
|
|
|
588
611
|
res.status(201).json(newGroup);
|
|
@@ -618,7 +641,7 @@ router.put('/:botId/groups/:groupId', authorize('management:edit'), async (req,
|
|
|
618
641
|
BotManager.invalidateUserCache(botId, user.username);
|
|
619
642
|
}
|
|
620
643
|
|
|
621
|
-
BotManager.
|
|
644
|
+
BotManager.reloadBotConfigInRealTime(botId);
|
|
622
645
|
|
|
623
646
|
res.status(200).send();
|
|
624
647
|
} catch (error) {
|
|
@@ -636,7 +659,7 @@ router.delete('/:botId/groups/:groupId', authorize('management:edit'), async (re
|
|
|
636
659
|
return res.status(403).json({ error: `Нельзя удалить группу с источником "${group.owner}".` });
|
|
637
660
|
}
|
|
638
661
|
await prisma.group.delete({ where: { id: groupId } });
|
|
639
|
-
BotManager.
|
|
662
|
+
BotManager.reloadBotConfigInRealTime(botId);
|
|
640
663
|
|
|
641
664
|
|
|
642
665
|
res.status(204).send();
|
|
@@ -652,7 +675,7 @@ router.post('/:botId/permissions', authorize('management:edit'), async (req, res
|
|
|
652
675
|
data: { name, description, botId, owner: 'admin' }
|
|
653
676
|
});
|
|
654
677
|
|
|
655
|
-
BotManager.
|
|
678
|
+
BotManager.reloadBotConfigInRealTime(botId);
|
|
656
679
|
|
|
657
680
|
res.status(201).json(newPermission);
|
|
658
681
|
} catch (error) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const { PrismaClient } = require('@prisma/client');
|
|
4
|
+
const prisma = new PrismaClient();
|
|
5
|
+
|
|
6
|
+
router.get('/', async (req, res) => {
|
|
7
|
+
const { query } = req.query;
|
|
8
|
+
|
|
9
|
+
if (!query) {
|
|
10
|
+
return res.status(400).json({ error: 'Query parameter is required' });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const bots = await prisma.bot.findMany({
|
|
15
|
+
where: {
|
|
16
|
+
OR: [
|
|
17
|
+
{ username: { contains: query } },
|
|
18
|
+
{
|
|
19
|
+
AND: [
|
|
20
|
+
{ note: { not: null } },
|
|
21
|
+
{ note: { contains: query } }
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const users = await prisma.user.findMany({
|
|
29
|
+
where: {
|
|
30
|
+
username: {
|
|
31
|
+
contains: query,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const plugins = await prisma.installedPlugin.findMany({
|
|
37
|
+
where: {
|
|
38
|
+
name: {
|
|
39
|
+
contains: query,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
res.json({
|
|
45
|
+
bots,
|
|
46
|
+
users,
|
|
47
|
+
plugins,
|
|
48
|
+
});
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Search error:', error);
|
|
51
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
module.exports = router;
|
|
@@ -96,6 +96,17 @@ class BotManager {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
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
|
+
|
|
99
110
|
triggerHeartbeat() {
|
|
100
111
|
if (!config.telemetry?.enabled) return;
|
|
101
112
|
if (this.heartbeatDebounceTimer) {
|
|
@@ -284,7 +295,7 @@ class BotManager {
|
|
|
284
295
|
|
|
285
296
|
appendLog(botId, log) {
|
|
286
297
|
const currentLogs = this.logCache.get(botId) || [];
|
|
287
|
-
const newLogs = [
|
|
298
|
+
const newLogs = [...currentLogs.slice(-499), log];
|
|
288
299
|
this.logCache.set(botId, newLogs);
|
|
289
300
|
getIO().emit('bot:log', { botId, log });
|
|
290
301
|
}
|
|
@@ -560,6 +571,18 @@ class BotManager {
|
|
|
560
571
|
}
|
|
561
572
|
return { success: true };
|
|
562
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
|
+
}
|
|
563
586
|
}
|
|
564
587
|
|
|
565
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
|
+
});
|
package/backend/src/server.js
CHANGED
|
@@ -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));
|