blockmine 1.5.7 → 1.5.9
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/README.md +2 -3
- package/backend/src/api/routes/bots.js +18 -11
- package/backend/src/core/BotManager.js +707 -714
- package/backend/src/core/BotProcess.js +5 -0
- package/backend/src/core/EventGraphManager.js +3 -0
- package/backend/src/core/GraphExecutionEngine.js +18 -9
- package/backend/src/core/NodeRegistry.js +14 -0
- package/backend/src/core/TaskScheduler.js +8 -3
- package/backend/src/lib/prisma.js +5 -0
- package/backend/src/real-time/socketHandler.js +9 -11
- package/backend/src/server.js +25 -20
- package/frontend/dist/assets/{index-BRG5IJlS.js → index-Cb7r5FoV.js} +1650 -1650
- package/frontend/dist/assets/index-OIucIMTn.css +1 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend/dist/assets/index-CxAe5KlR.css +0 -1
|
@@ -160,6 +160,7 @@ process.on('message', async (message) => {
|
|
|
160
160
|
version: config.server.version,
|
|
161
161
|
auth: 'offline',
|
|
162
162
|
hideErrors: false,
|
|
163
|
+
chat: 'enabled',
|
|
163
164
|
};
|
|
164
165
|
|
|
165
166
|
if (config.proxyHost && config.proxyPort) {
|
|
@@ -484,6 +485,10 @@ process.on('message', async (message) => {
|
|
|
484
485
|
}
|
|
485
486
|
});
|
|
486
487
|
|
|
488
|
+
bot.on('death', () => {
|
|
489
|
+
sendEvent('botDied', { user: { username: bot.username } });
|
|
490
|
+
});
|
|
491
|
+
|
|
487
492
|
bot.on('kicked', (reason) => {
|
|
488
493
|
let reasonText;
|
|
489
494
|
try { reasonText = JSON.parse(reason).text || reason; } catch (e) { reasonText = reason; }
|
|
@@ -536,18 +536,27 @@ class GraphExecutionEngine {
|
|
|
536
536
|
}
|
|
537
537
|
|
|
538
538
|
case 'string:contains': {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
539
|
+
if (pinId === 'result') {
|
|
540
|
+
const haystack = String(await this.resolvePinValue(node, 'haystack', ''));
|
|
541
|
+
const needle = String(await this.resolvePinValue(node, 'needle', ''));
|
|
542
|
+
const caseSensitive = await this.resolvePinValue(node, 'case_sensitive', false);
|
|
543
|
+
|
|
544
|
+
if (caseSensitive) {
|
|
545
|
+
return haystack.includes(needle);
|
|
546
|
+
} else {
|
|
547
|
+
return haystack.toLowerCase().includes(needle.toLowerCase());
|
|
548
|
+
}
|
|
549
|
+
}
|
|
543
550
|
break;
|
|
544
551
|
}
|
|
545
552
|
case 'string:matches': {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
553
|
+
if (pinId === 'result') {
|
|
554
|
+
const str = String(await this.resolvePinValue(node, 'string', ''));
|
|
555
|
+
const regexStr = String(await this.resolvePinValue(node, 'regex', ''));
|
|
556
|
+
try {
|
|
557
|
+
result = new RegExp(regexStr).test(str);
|
|
558
|
+
} catch (e) { result = false; }
|
|
559
|
+
}
|
|
551
560
|
break;
|
|
552
561
|
}
|
|
553
562
|
case 'data:string_literal':
|
|
@@ -876,6 +876,20 @@ class NodeRegistry {
|
|
|
876
876
|
}
|
|
877
877
|
});
|
|
878
878
|
|
|
879
|
+
this.registerNodeType({
|
|
880
|
+
type: 'event:botDied',
|
|
881
|
+
label: '💀 Бот умер',
|
|
882
|
+
category: 'События',
|
|
883
|
+
description: 'Срабатывает, когда бот умирает.',
|
|
884
|
+
graphType: event,
|
|
885
|
+
pins: {
|
|
886
|
+
inputs: [],
|
|
887
|
+
outputs: [
|
|
888
|
+
{ id: 'exec', name: 'Выполнить', type: 'Exec' },
|
|
889
|
+
]
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
|
|
879
893
|
console.log(`NodeRegistry: Registered ${this.nodes.size} base nodes`);
|
|
880
894
|
}
|
|
881
895
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
const cron = require('node-cron');
|
|
2
|
-
const
|
|
2
|
+
const prisma = require('../lib/prisma');
|
|
3
3
|
const BotManager = require('./BotManager');
|
|
4
4
|
|
|
5
|
-
const prisma = new PrismaClient();
|
|
6
|
-
|
|
7
5
|
class TaskScheduler {
|
|
8
6
|
constructor() {
|
|
9
7
|
this.scheduledJobs = new Map();
|
|
@@ -112,6 +110,13 @@ class TaskScheduler {
|
|
|
112
110
|
this.scheduleTask(updatedTask);
|
|
113
111
|
}
|
|
114
112
|
}
|
|
113
|
+
|
|
114
|
+
shutdown() {
|
|
115
|
+
console.log('[TaskScheduler] Остановка всех запланированных задач...');
|
|
116
|
+
this.scheduledJobs.forEach(job => job.stop());
|
|
117
|
+
this.scheduledJobs.clear();
|
|
118
|
+
console.log('[TaskScheduler] Все задачи остановлены.');
|
|
119
|
+
}
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
module.exports = new TaskScheduler();
|
|
@@ -5,27 +5,25 @@ let io;
|
|
|
5
5
|
|
|
6
6
|
function initializeSocket(httpServer) {
|
|
7
7
|
const corsOptions = {
|
|
8
|
-
|
|
8
|
+
origin: true,
|
|
9
|
+
methods: ["GET", "POST"],
|
|
10
|
+
credentials: true
|
|
9
11
|
};
|
|
10
12
|
|
|
11
|
-
if (config.server.allowExternalAccess) {
|
|
12
|
-
corsOptions.origin = "*";
|
|
13
|
-
} else {
|
|
14
|
-
corsOptions.origin = "http://localhost:5173";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
13
|
io = new Server(httpServer, {
|
|
18
|
-
cors: corsOptions
|
|
14
|
+
cors: corsOptions,
|
|
15
|
+
transports: ['websocket', 'polling']
|
|
19
16
|
});
|
|
20
17
|
|
|
21
18
|
io.on('connection', (socket) => {
|
|
22
|
-
console.log(
|
|
19
|
+
// console.log(`[Socket.IO] Пользователь подключен: ${socket.id}. Всего клиентов: ${io.engine.clientsCount}`);
|
|
20
|
+
|
|
23
21
|
socket.on('disconnect', () => {
|
|
24
|
-
console.log(
|
|
22
|
+
// console.log(`[Socket.IO] Пользователь отключен: ${socket.id}. Всего клиентов: ${io.engine.clientsCount}`);
|
|
25
23
|
});
|
|
26
24
|
});
|
|
27
25
|
|
|
28
|
-
console.log('Socket.IO инициализирован с CORS
|
|
26
|
+
// console.log('Socket.IO инициализирован с динамическим CORS.');
|
|
29
27
|
return io;
|
|
30
28
|
}
|
|
31
29
|
|
package/backend/src/server.js
CHANGED
|
@@ -3,7 +3,7 @@ const http = require('http');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const os = require('os');
|
|
6
|
-
const
|
|
6
|
+
const prisma = require('./lib/prisma');
|
|
7
7
|
|
|
8
8
|
const config = require('./config');
|
|
9
9
|
const { initializeSocket } = require('./real-time/socketHandler');
|
|
@@ -57,6 +57,7 @@ app.use('/api/bots', botRoutes);
|
|
|
57
57
|
app.use('/api/plugins', pluginRoutes);
|
|
58
58
|
app.use('/api/servers', serverRoutes);
|
|
59
59
|
app.use('/api/permissions', permissionsRoutes);
|
|
60
|
+
app.use('/api/search', searchRoutes);
|
|
60
61
|
app.use('/api/panel', panelRoutes);
|
|
61
62
|
|
|
62
63
|
app.use(express.static(frontendPath));
|
|
@@ -75,9 +76,7 @@ app.get(/^(?!\/api).*/, (req, res) => {
|
|
|
75
76
|
});
|
|
76
77
|
|
|
77
78
|
async function runStartupMigrations() {
|
|
78
|
-
const prisma = new PrismaClient();
|
|
79
79
|
try {
|
|
80
|
-
// 1. Migrate legacy '*' permission for Admin role
|
|
81
80
|
const adminRole = await prisma.panelRole.findUnique({ where: { name: 'Admin' } });
|
|
82
81
|
if (adminRole) {
|
|
83
82
|
const permissions = JSON.parse(adminRole.permissions);
|
|
@@ -93,7 +92,6 @@ async function runStartupMigrations() {
|
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
// 2. Ensure root user (ID 1) has all permissions
|
|
97
95
|
const rootUser = await prisma.panelUser.findUnique({ where: { id: 1 }, include: { role: true } });
|
|
98
96
|
if (rootUser && rootUser.role) {
|
|
99
97
|
const allPermissions = ALL_PERMISSIONS.map(p => p.id).filter(id => id !== '*');
|
|
@@ -109,8 +107,6 @@ async function runStartupMigrations() {
|
|
|
109
107
|
}
|
|
110
108
|
} catch (error) {
|
|
111
109
|
console.error('[Migration] Ошибка во время миграции прав:', error);
|
|
112
|
-
} finally {
|
|
113
|
-
await prisma.$disconnect();
|
|
114
110
|
}
|
|
115
111
|
}
|
|
116
112
|
|
|
@@ -145,26 +141,35 @@ async function startServer() {
|
|
|
145
141
|
});
|
|
146
142
|
}
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
|
|
145
|
+
const gracefulShutdown = async (signal) => {
|
|
146
|
+
console.log(`[Shutdown] Получен сигнал ${signal}. Начинаем корректное завершение...`);
|
|
147
|
+
|
|
148
|
+
TaskScheduler.shutdown();
|
|
149
|
+
|
|
151
150
|
const botIds = Array.from(botManager.bots.keys());
|
|
152
151
|
if (botIds.length > 0) {
|
|
153
152
|
console.log(`[Shutdown] Остановка ${botIds.length} активных ботов...`);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
153
|
+
await Promise.all(botIds.map(botId => botManager.stopBot(botId)));
|
|
154
|
+
console.log('[Shutdown] Все боты остановлены.');
|
|
157
155
|
}
|
|
158
156
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
const io = require('./real-time/socketHandler').getIO();
|
|
158
|
+
if (io) {
|
|
159
|
+
io.close(async () => {
|
|
160
|
+
console.log('[Shutdown] WebSocket сервер закрыт.');
|
|
161
|
+
|
|
162
|
+
await new Promise(resolve => server.close(resolve));
|
|
163
|
+
console.log('[Shutdown] HTTP сервер закрыт.');
|
|
164
|
+
|
|
165
|
+
const prisma = require('./lib/prisma');
|
|
166
|
+
await prisma.$disconnect();
|
|
167
|
+
console.log('[Shutdown] Соединение с БД закрыто.');
|
|
163
168
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
169
|
+
console.log('[Shutdown] Корректное завершение выполнено.');
|
|
170
|
+
process.exit(0);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
168
173
|
};
|
|
169
174
|
|
|
170
175
|
process.on('SIGUSR2', () => gracefulShutdown('SIGUSR2 (nodemon)'));
|