blockmine 1.22.0 → 1.23.0
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/.claude/settings.json +5 -1
- package/.claude/settings.local.json +10 -1
- package/CHANGELOG.md +27 -3
- package/CLAUDE.md +284 -0
- package/README.md +302 -152
- package/backend/package-lock.json +681 -9
- package/backend/package.json +8 -0
- package/backend/prisma/migrations/20251116111851_add_execution_trace/migration.sql +22 -0
- package/backend/prisma/migrations/20251120154914_add_panel_api_keys/migration.sql +21 -0
- package/backend/prisma/migrations/20251121110241_add_proxy_table/migration.sql +45 -0
- package/backend/prisma/migrations/migration_lock.toml +2 -2
- package/backend/prisma/schema.prisma +70 -1
- package/backend/src/__tests__/services/BotLifecycleService.test.js +9 -4
- package/backend/src/ai/plugin-assistant-system-prompt.md +788 -0
- package/backend/src/api/middleware/auth.js +27 -0
- package/backend/src/api/middleware/botAccess.js +7 -3
- package/backend/src/api/middleware/panelApiAuth.js +135 -0
- package/backend/src/api/routes/aiAssistant.js +995 -0
- package/backend/src/api/routes/auth.js +669 -633
- package/backend/src/api/routes/botCommands.js +107 -0
- package/backend/src/api/routes/botGroups.js +165 -0
- package/backend/src/api/routes/botHistory.js +108 -0
- package/backend/src/api/routes/botPermissions.js +99 -0
- package/backend/src/api/routes/botStatus.js +36 -0
- package/backend/src/api/routes/botUsers.js +162 -0
- package/backend/src/api/routes/bots.js +2451 -2402
- package/backend/src/api/routes/eventGraphs.js +4 -1
- package/backend/src/api/routes/logs.js +13 -3
- package/backend/src/api/routes/panel.js +66 -66
- package/backend/src/api/routes/panelApiKeys.js +179 -0
- package/backend/src/api/routes/pluginIde.js +1715 -135
- package/backend/src/api/routes/plugins.js +376 -219
- package/backend/src/api/routes/proxies.js +130 -0
- package/backend/src/api/routes/search.js +4 -0
- package/backend/src/api/routes/servers.js +20 -3
- package/backend/src/api/routes/settings.js +5 -0
- package/backend/src/api/routes/system.js +174 -174
- package/backend/src/api/routes/traces.js +131 -0
- package/backend/src/config/debug.config.js +36 -0
- package/backend/src/core/BotHistoryStore.js +180 -0
- package/backend/src/core/BotManager.js +14 -4
- package/backend/src/core/BotProcess.js +1517 -1092
- package/backend/src/core/EventGraphManager.js +37 -123
- package/backend/src/core/GraphExecutionEngine.js +977 -321
- package/backend/src/core/MessageQueue.js +12 -6
- package/backend/src/core/PluginLoader.js +99 -5
- package/backend/src/core/PluginManager.js +74 -13
- package/backend/src/core/TaskScheduler.js +1 -1
- package/backend/src/core/commands/whois.js +1 -1
- package/backend/src/core/node-registries/actions.js +70 -0
- package/backend/src/core/node-registries/arrays.js +18 -0
- package/backend/src/core/node-registries/data.js +1 -1
- package/backend/src/core/node-registries/events.js +14 -0
- package/backend/src/core/node-registries/logic.js +17 -0
- package/backend/src/core/node-registries/strings.js +34 -0
- package/backend/src/core/node-registries/type.js +25 -0
- package/backend/src/core/nodes/actions/bot_look_at.js +1 -1
- package/backend/src/core/nodes/actions/create_command.js +189 -0
- package/backend/src/core/nodes/actions/delete_command.js +92 -0
- package/backend/src/core/nodes/actions/update_command.js +133 -0
- package/backend/src/core/nodes/arrays/join.js +28 -0
- package/backend/src/core/nodes/data/cast.js +2 -1
- package/backend/src/core/nodes/logic/not.js +22 -0
- package/backend/src/core/nodes/strings/starts_with.js +1 -1
- package/backend/src/core/nodes/strings/to_lower.js +22 -0
- package/backend/src/core/nodes/strings/to_upper.js +22 -0
- package/backend/src/core/nodes/type/to_string.js +32 -0
- package/backend/src/core/services/BotLifecycleService.js +255 -16
- package/backend/src/core/services/CommandExecutionService.js +430 -351
- package/backend/src/core/services/DebugSessionManager.js +347 -0
- package/backend/src/core/services/GraphCollaborationManager.js +501 -0
- package/backend/src/core/services/MinecraftBotManager.js +259 -0
- package/backend/src/core/services/MinecraftViewerService.js +216 -0
- package/backend/src/core/services/TraceCollectorService.js +545 -0
- package/backend/src/core/system/RuntimeCommandRegistry.js +116 -0
- package/backend/src/core/system/Transport.js +0 -4
- package/backend/src/core/validation/nodeSchemas.js +6 -6
- package/backend/src/real-time/botApi/handlers/graphHandlers.js +2 -2
- package/backend/src/real-time/botApi/handlers/graphWebSocketHandlers.js +1 -1
- package/backend/src/real-time/botApi/utils.js +11 -0
- package/backend/src/real-time/panelNamespace.js +387 -0
- package/backend/src/real-time/presence.js +7 -2
- package/backend/src/real-time/socketHandler.js +395 -4
- package/backend/src/server.js +18 -0
- package/frontend/dist/assets/index-B1serztM.js +11210 -0
- package/frontend/dist/assets/index-t6K1u4OV.css +32 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/package-lock.json +9437 -0
- package/frontend/package.json +8 -0
- package/package.json +2 -2
- package/screen/console.png +0 -0
- package/screen/dashboard.png +0 -0
- package/screen/graph_collabe.png +0 -0
- package/screen/graph_live_debug.png +0 -0
- package/screen/management_command.png +0 -0
- package/screen/node_debug_trace.png +0 -0
- package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
- package/screen/websocket.png +0 -0
- package/screen//320/275/320/260/321/201/321/202/321/200/320/276/320/271/320/272/320/270_/320/276/321/202/320/264/320/265/320/273/321/214/320/275/321/213/321/205_/320/272/320/276/320/274/320/260/320/275/320/264_/320/272/320/260/320/266/320/264/321/203_/320/272/320/276/320/274/320/260/320/275/320/273/320/264/321/203_/320/274/320/276/320/266/320/275/320/276_/320/275/320/260/321/201/321/202/321/200/320/260/320/270/320/262/320/260/321/202/321/214.png +0 -0
- package/screen//320/277/320/273/320/260/320/275/320/270/321/200/320/276/320/262/321/211/320/270/320/272_/320/274/320/276/320/266/320/275/320/276_/320/267/320/260/320/264/320/260/320/262/320/260/321/202/321/214_/320/264/320/265/320/271/321/201/321/202/320/262/320/270/321/217_/320/277/320/276_/320/262/321/200/320/265/320/274/320/265/320/275/320/270.png +0 -0
- package/frontend/dist/assets/index-CfTo92bP.css +0 -1
- package/frontend/dist/assets/index-CiFD5X9Z.js +0 -8344
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const prismaService = require('../../PrismaService');
|
|
2
|
+
const prisma = prismaService.getClient();
|
|
3
|
+
const { getRuntimeCommandRegistry } = require('../../system/RuntimeCommandRegistry');
|
|
4
|
+
const Command = require('../../system/Command');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Создает новую команду (временную или постоянную)
|
|
8
|
+
* @param {object} node - Экземпляр узла из графа
|
|
9
|
+
* @param {object} context - Контекст выполнения графа
|
|
10
|
+
* @param {object} helpers - Вспомогательные функции движка
|
|
11
|
+
*/
|
|
12
|
+
async function execute(node, context, helpers) {
|
|
13
|
+
const { resolvePinValue, traverse, memo } = helpers;
|
|
14
|
+
const { botId, botManager } = context;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const name = await resolvePinValue(node, 'name');
|
|
18
|
+
const description = await resolvePinValue(node, 'description', '');
|
|
19
|
+
let aliases = await resolvePinValue(node, 'aliases', []);
|
|
20
|
+
const cooldown = await resolvePinValue(node, 'cooldown', 0);
|
|
21
|
+
let allowedChatTypes = await resolvePinValue(node, 'allowedChatTypes', ['chat', 'private']);
|
|
22
|
+
const permissionName = await resolvePinValue(node, 'permissionName', null);
|
|
23
|
+
const temporary = await resolvePinValue(node, 'temporary', false);
|
|
24
|
+
|
|
25
|
+
if (typeof aliases === 'string') {
|
|
26
|
+
try {
|
|
27
|
+
const normalizedString = aliases.replace(/'/g, '"');
|
|
28
|
+
aliases = JSON.parse(normalizedString);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.warn('[create_command] Не удалось распарсить aliases:', e);
|
|
31
|
+
aliases = [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof allowedChatTypes === 'string') {
|
|
36
|
+
try {
|
|
37
|
+
const normalizedString = allowedChatTypes.replace(/'/g, '"');
|
|
38
|
+
allowedChatTypes = JSON.parse(normalizedString);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.warn('[create_command] Не удалось распарсить allowedChatTypes:', e);
|
|
41
|
+
allowedChatTypes = ['chat', 'private'];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!name) {
|
|
46
|
+
console.error('[create_command] Имя команды обязательно');
|
|
47
|
+
memo.set(`${node.id}:success`, false);
|
|
48
|
+
memo.set(`${node.id}:commandId`, null);
|
|
49
|
+
await traverse(node, 'exec');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let commandId = null;
|
|
54
|
+
|
|
55
|
+
if (temporary) {
|
|
56
|
+
commandId = `temp_${Date.now()}`;
|
|
57
|
+
|
|
58
|
+
let permissionId = null;
|
|
59
|
+
|
|
60
|
+
if (permissionName) {
|
|
61
|
+
const permission = await prisma.permission.findFirst({
|
|
62
|
+
where: {
|
|
63
|
+
botId,
|
|
64
|
+
name: permissionName
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (permission) {
|
|
69
|
+
permissionId = permission.id;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const tempCommand = new Command({
|
|
74
|
+
name,
|
|
75
|
+
description: description || '',
|
|
76
|
+
aliases: Array.isArray(aliases) ? aliases : [],
|
|
77
|
+
cooldown: cooldown || 0,
|
|
78
|
+
allowedChatTypes: Array.isArray(allowedChatTypes) ? allowedChatTypes : ['chat', 'private'],
|
|
79
|
+
args: [],
|
|
80
|
+
owner: 'runtime',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
tempCommand.permissionId = permissionId;
|
|
84
|
+
tempCommand.isTemporary = true;
|
|
85
|
+
tempCommand.tempId = commandId;
|
|
86
|
+
tempCommand.isVisual = false;
|
|
87
|
+
|
|
88
|
+
tempCommand.handler = () => {
|
|
89
|
+
// Handler будет вызван через validate_and_run_command в BotProcess
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Регистрируем в runtime registry (для главного процесса)
|
|
93
|
+
const runtimeRegistry = getRuntimeCommandRegistry();
|
|
94
|
+
runtimeRegistry.register(botId, name, tempCommand);
|
|
95
|
+
|
|
96
|
+
// Также регистрируем алиасы в runtime registry
|
|
97
|
+
if (Array.isArray(aliases)) {
|
|
98
|
+
for (const alias of aliases) {
|
|
99
|
+
runtimeRegistry.register(botId, alias, tempCommand);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Отправляем IPC сообщение в child process для регистрации команды
|
|
104
|
+
if (botManager && botManager.processManager) {
|
|
105
|
+
botManager.processManager.sendMessage(botId, {
|
|
106
|
+
type: 'register_temp_command',
|
|
107
|
+
commandData: {
|
|
108
|
+
name,
|
|
109
|
+
description: description || '',
|
|
110
|
+
aliases: Array.isArray(aliases) ? aliases : [],
|
|
111
|
+
cooldown: cooldown || 0,
|
|
112
|
+
allowedChatTypes: Array.isArray(allowedChatTypes) ? allowedChatTypes : ['chat', 'private'],
|
|
113
|
+
permissionId,
|
|
114
|
+
tempId: commandId,
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log(`[create_command] Временная команда "${name}" создана с ID ${commandId}`);
|
|
120
|
+
} else {
|
|
121
|
+
const existingCommand = await prisma.command.findFirst({
|
|
122
|
+
where: { botId, name }
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (existingCommand) {
|
|
126
|
+
console.error(`[create_command] Команда "${name}" уже существует`);
|
|
127
|
+
memo.set(`${node.id}:success`, false);
|
|
128
|
+
memo.set(`${node.id}:commandId`, null);
|
|
129
|
+
await traverse(node, 'exec');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let permissionId = null;
|
|
134
|
+
if (permissionName) {
|
|
135
|
+
const permission = await prisma.permission.findFirst({
|
|
136
|
+
where: {
|
|
137
|
+
botId,
|
|
138
|
+
name: permissionName
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (permission) {
|
|
143
|
+
permissionId = permission.id;
|
|
144
|
+
} else {
|
|
145
|
+
console.warn(`[create_command] Право "${permissionName}" не найдено, команда будет создана без права`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const newCommand = await prisma.command.create({
|
|
150
|
+
data: {
|
|
151
|
+
botId,
|
|
152
|
+
name,
|
|
153
|
+
description: description || '',
|
|
154
|
+
aliases: JSON.stringify(Array.isArray(aliases) ? aliases : []),
|
|
155
|
+
permissionId: permissionId || null,
|
|
156
|
+
cooldown: cooldown || 0,
|
|
157
|
+
allowedChatTypes: JSON.stringify(Array.isArray(allowedChatTypes) ? allowedChatTypes : ['chat', 'private']),
|
|
158
|
+
isVisual: true,
|
|
159
|
+
argumentsJson: '[]',
|
|
160
|
+
graphJson: JSON.stringify({
|
|
161
|
+
nodes: [],
|
|
162
|
+
edges: []
|
|
163
|
+
}),
|
|
164
|
+
pluginOwnerId: null
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
commandId = newCommand.id;
|
|
169
|
+
console.log(`[create_command] Постоянная команда "${name}" создана с ID ${commandId}`);
|
|
170
|
+
|
|
171
|
+
if (botManager && botManager.reloadBotConfigInRealTime) {
|
|
172
|
+
botManager.reloadBotConfigInRealTime(botId);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
memo.set(`${node.id}:commandId`, commandId);
|
|
177
|
+
memo.set(`${node.id}:success`, true);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error('[create_command] Ошибка создания команды:', error);
|
|
180
|
+
memo.set(`${node.id}:success`, false);
|
|
181
|
+
memo.set(`${node.id}:commandId`, null);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
await traverse(node, 'exec');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = {
|
|
188
|
+
execute,
|
|
189
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const prismaService = require('../../PrismaService');
|
|
2
|
+
const prisma = prismaService.getClient();
|
|
3
|
+
const { getRuntimeCommandRegistry } = require('../../system/RuntimeCommandRegistry');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Удаляет существующую команду
|
|
7
|
+
* @param {object} node - Экземпляр узла из графа
|
|
8
|
+
* @param {object} context - Контекст выполнения графа
|
|
9
|
+
* @param {object} helpers - Вспомогательные функции движка
|
|
10
|
+
*/
|
|
11
|
+
async function execute(node, context, helpers) {
|
|
12
|
+
const { resolvePinValue, traverse, memo } = helpers;
|
|
13
|
+
const { botId, botManager } = context;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const commandName = await resolvePinValue(node, 'commandName');
|
|
17
|
+
|
|
18
|
+
if (!commandName) {
|
|
19
|
+
console.error('[delete_command] Имя команды обязательно');
|
|
20
|
+
memo.set(`${node.id}:success`, false);
|
|
21
|
+
await traverse(node, 'exec');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const runtimeRegistry = getRuntimeCommandRegistry();
|
|
26
|
+
|
|
27
|
+
if (runtimeRegistry.has(botId, commandName)) {
|
|
28
|
+
const tempCommand = runtimeRegistry.get(botId, commandName);
|
|
29
|
+
const aliases = tempCommand && tempCommand.aliases ? tempCommand.aliases : [];
|
|
30
|
+
|
|
31
|
+
runtimeRegistry.unregister(botId, commandName);
|
|
32
|
+
|
|
33
|
+
if (Array.isArray(aliases)) {
|
|
34
|
+
for (const alias of aliases) {
|
|
35
|
+
runtimeRegistry.unregister(botId, alias);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (botManager && botManager.processManager) {
|
|
40
|
+
botManager.processManager.sendMessage(botId, {
|
|
41
|
+
type: 'unregister_temp_command',
|
|
42
|
+
commandName,
|
|
43
|
+
aliases
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(`[delete_command] Временная команда "${commandName}" успешно удалена`);
|
|
48
|
+
memo.set(`${node.id}:success`, true);
|
|
49
|
+
await traverse(node, 'exec');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const existingCommand = await prisma.command.findFirst({
|
|
54
|
+
where: { name: commandName, botId }
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (!existingCommand) {
|
|
58
|
+
console.error(`[delete_command] Команда "${commandName}" не найдена`);
|
|
59
|
+
memo.set(`${node.id}:success`, false);
|
|
60
|
+
await traverse(node, 'exec');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!existingCommand.isVisual) {
|
|
65
|
+
console.error(`[delete_command] Команда "${commandName}" является системной и не может быть удалена`);
|
|
66
|
+
memo.set(`${node.id}:success`, false);
|
|
67
|
+
await traverse(node, 'exec');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
await prisma.command.delete({
|
|
72
|
+
where: { id: existingCommand.id }
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log(`[delete_command] Команда "${commandName}" успешно удалена`);
|
|
76
|
+
|
|
77
|
+
if (botManager && botManager.reloadBotConfigInRealTime) {
|
|
78
|
+
botManager.reloadBotConfigInRealTime(botId);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
memo.set(`${node.id}:success`, true);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('[delete_command] Ошибка удаления команды:', error);
|
|
84
|
+
memo.set(`${node.id}:success`, false);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await traverse(node, 'exec');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = {
|
|
91
|
+
execute,
|
|
92
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const prismaService = require('../../PrismaService');
|
|
2
|
+
const prisma = prismaService.getClient();
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Обновляет существующую команду
|
|
6
|
+
* @param {object} node - Экземпляр узла из графа
|
|
7
|
+
* @param {object} context - Контекст выполнения графа
|
|
8
|
+
* @param {object} helpers - Вспомогательные функции движка
|
|
9
|
+
*/
|
|
10
|
+
async function execute(node, context, helpers) {
|
|
11
|
+
const { resolvePinValue, traverse, memo } = helpers;
|
|
12
|
+
const { botId, botManager } = context;
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const commandName = await resolvePinValue(node, 'commandName');
|
|
16
|
+
const newName = await resolvePinValue(node, 'newName', null);
|
|
17
|
+
const description = await resolvePinValue(node, 'description', null);
|
|
18
|
+
let aliases = await resolvePinValue(node, 'aliases', null);
|
|
19
|
+
const cooldown = await resolvePinValue(node, 'cooldown', null);
|
|
20
|
+
let allowedChatTypes = await resolvePinValue(node, 'allowedChatTypes', null);
|
|
21
|
+
const permissionName = await resolvePinValue(node, 'permissionName', null);
|
|
22
|
+
|
|
23
|
+
if (aliases !== null && typeof aliases === 'string') {
|
|
24
|
+
try {
|
|
25
|
+
const normalizedString = aliases.replace(/'/g, '"');
|
|
26
|
+
aliases = JSON.parse(normalizedString);
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.warn('[update_command] Не удалось распарсить aliases:', e);
|
|
29
|
+
aliases = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (allowedChatTypes !== null && typeof allowedChatTypes === 'string') {
|
|
34
|
+
try {
|
|
35
|
+
const normalizedString = allowedChatTypes.replace(/'/g, '"');
|
|
36
|
+
allowedChatTypes = JSON.parse(normalizedString);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
console.warn('[update_command] Не удалось распарсить allowedChatTypes:', e);
|
|
39
|
+
allowedChatTypes = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!commandName) {
|
|
44
|
+
console.error('[update_command] Имя команды обязательно');
|
|
45
|
+
memo.set(`${node.id}:success`, false);
|
|
46
|
+
await traverse(node, 'exec');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const existingCommand = await prisma.command.findFirst({
|
|
51
|
+
where: { name: commandName, botId }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!existingCommand) {
|
|
55
|
+
console.error(`[update_command] Команда "${commandName}" не найдена`);
|
|
56
|
+
memo.set(`${node.id}:success`, false);
|
|
57
|
+
await traverse(node, 'exec');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (newName && newName !== existingCommand.name) {
|
|
62
|
+
const duplicateCommand = await prisma.command.findFirst({
|
|
63
|
+
where: {
|
|
64
|
+
botId,
|
|
65
|
+
name: newName,
|
|
66
|
+
id: { not: existingCommand.id }
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (duplicateCommand) {
|
|
71
|
+
console.error(`[update_command] Команда с именем "${newName}" уже существует`);
|
|
72
|
+
memo.set(`${node.id}:success`, false);
|
|
73
|
+
await traverse(node, 'exec');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const updateData = {};
|
|
79
|
+
|
|
80
|
+
if (newName !== null) updateData.name = newName;
|
|
81
|
+
if (description !== null) updateData.description = description;
|
|
82
|
+
if (aliases !== null) {
|
|
83
|
+
updateData.aliases = JSON.stringify(Array.isArray(aliases) ? aliases : []);
|
|
84
|
+
}
|
|
85
|
+
if (cooldown !== null) updateData.cooldown = cooldown;
|
|
86
|
+
if (allowedChatTypes !== null) {
|
|
87
|
+
updateData.allowedChatTypes = JSON.stringify(
|
|
88
|
+
Array.isArray(allowedChatTypes) ? allowedChatTypes : ['chat', 'private']
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (permissionName !== null) {
|
|
93
|
+
if (permissionName === '') {
|
|
94
|
+
updateData.permissionId = null;
|
|
95
|
+
} else {
|
|
96
|
+
const permission = await prisma.permission.findFirst({
|
|
97
|
+
where: {
|
|
98
|
+
botId,
|
|
99
|
+
name: permissionName
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (permission) {
|
|
104
|
+
updateData.permissionId = permission.id;
|
|
105
|
+
} else {
|
|
106
|
+
console.warn(`[update_command] Право "${permissionName}" не найдено, поле не будет обновлено`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await prisma.command.update({
|
|
112
|
+
where: { id: existingCommand.id },
|
|
113
|
+
data: updateData
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
console.log(`[update_command] Команда "${commandName}" успешно обновлена`);
|
|
117
|
+
|
|
118
|
+
if (botManager && botManager.reloadBotConfigInRealTime) {
|
|
119
|
+
botManager.reloadBotConfigInRealTime(botId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
memo.set(`${node.id}:success`, true);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error('[update_command] Ошибка обновления команды:', error);
|
|
125
|
+
memo.set(`${node.id}:success`, false);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await traverse(node, 'exec');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
execute,
|
|
133
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} node - Экземпляр узла из графа.
|
|
3
|
+
* @param {string} pinId - Идентификатор выходного пина.
|
|
4
|
+
* @param {object} context - Контекст выполнения графа.
|
|
5
|
+
* @param {object} helpers - Вспомогательные функции движка.
|
|
6
|
+
* @param {function} helpers.resolvePinValue - Функция для получения значения с входного пина.
|
|
7
|
+
* @returns {Promise<any>} - Вычисленное значение для выходного пина.
|
|
8
|
+
*/
|
|
9
|
+
async function evaluate(node, pinId, context, helpers) {
|
|
10
|
+
const { resolvePinValue } = helpers;
|
|
11
|
+
|
|
12
|
+
if (pinId === 'result') {
|
|
13
|
+
const array = await resolvePinValue(node, 'array', []);
|
|
14
|
+
const separator = String(await resolvePinValue(node, 'separator', ', '));
|
|
15
|
+
|
|
16
|
+
if (!Array.isArray(array)) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return array.join(separator);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
evaluate,
|
|
28
|
+
};
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
async function evaluate(node, pinId, context, helpers) {
|
|
10
10
|
const { resolvePinValue } = helpers;
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
// Поддерживаем оба варианта: 'result' (новая версия) и 'value' (старая версия для обратной совместимости)
|
|
13
|
+
if (pinId === 'result' || pinId === 'value') {
|
|
13
14
|
const value = await resolvePinValue(node, 'value');
|
|
14
15
|
const targetType = node.data?.targetType || 'String';
|
|
15
16
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} node - Экземпляр узла из графа.
|
|
3
|
+
* @param {string} pinId - Идентификатор выходного пина, значение которого нужно вычислить.
|
|
4
|
+
* @param {object} context - Контекст выполнения графа.
|
|
5
|
+
* @param {object} helpers - Вспомогательные функции движка.
|
|
6
|
+
* @param {function} helpers.resolvePinValue - Функция для получения значения с входного пина.
|
|
7
|
+
* @returns {Promise<any>} - Вычисленное значение для выходного пина.
|
|
8
|
+
*/
|
|
9
|
+
async function evaluate(node, pinId, context, helpers) {
|
|
10
|
+
const { resolvePinValue } = helpers;
|
|
11
|
+
|
|
12
|
+
if (pinId === 'result') {
|
|
13
|
+
const value = await resolvePinValue(node, 'value', false);
|
|
14
|
+
return !value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = {
|
|
21
|
+
evaluate,
|
|
22
|
+
};
|
|
@@ -23,7 +23,7 @@ async function evaluate(node, pinId, context, helpers) {
|
|
|
23
23
|
const { resolvePinValue } = helpers;
|
|
24
24
|
|
|
25
25
|
if (pinId === 'result') {
|
|
26
|
-
const str = String(await resolvePinValue(node, '
|
|
26
|
+
const str = String(await resolvePinValue(node, 'text', ''));
|
|
27
27
|
const prefix = String(await resolvePinValue(node, 'prefix', ''));
|
|
28
28
|
const caseSensitive = await resolvePinValue(node, 'case_sensitive', false);
|
|
29
29
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} node - Экземпляр узла из графа.
|
|
3
|
+
* @param {string} pinId - Идентификатор выходного пина.
|
|
4
|
+
* @param {object} context - Контекст выполнения графа.
|
|
5
|
+
* @param {object} helpers - Вспомогательные функции движка.
|
|
6
|
+
* @param {function} helpers.resolvePinValue - Функция для получения значения с входного пина.
|
|
7
|
+
* @returns {Promise<any>} - Вычисленное значение для выходного пина.
|
|
8
|
+
*/
|
|
9
|
+
async function evaluate(node, pinId, context, helpers) {
|
|
10
|
+
const { resolvePinValue } = helpers;
|
|
11
|
+
|
|
12
|
+
if (pinId === 'result') {
|
|
13
|
+
const text = String(await resolvePinValue(node, 'text', ''));
|
|
14
|
+
return text.toLowerCase();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = {
|
|
21
|
+
evaluate,
|
|
22
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} node - Экземпляр узла из графа.
|
|
3
|
+
* @param {string} pinId - Идентификатор выходного пина.
|
|
4
|
+
* @param {object} context - Контекст выполнения графа.
|
|
5
|
+
* @param {object} helpers - Вспомогательные функции движка.
|
|
6
|
+
* @param {function} helpers.resolvePinValue - Функция для получения значения с входного пина.
|
|
7
|
+
* @returns {Promise<any>} - Вычисленное значение для выходного пина.
|
|
8
|
+
*/
|
|
9
|
+
async function evaluate(node, pinId, context, helpers) {
|
|
10
|
+
const { resolvePinValue } = helpers;
|
|
11
|
+
|
|
12
|
+
if (pinId === 'result') {
|
|
13
|
+
const text = String(await resolvePinValue(node, 'text', ''));
|
|
14
|
+
return text.toUpperCase();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = {
|
|
21
|
+
evaluate,
|
|
22
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object} node - Экземпляр узла из графа.
|
|
3
|
+
* @param {string} pinId - Идентификатор выходного пина.
|
|
4
|
+
* @param {object} context - Контекст выполнения графа.
|
|
5
|
+
* @param {object} helpers - Вспомогательные функции движка.
|
|
6
|
+
* @param {function} helpers.resolvePinValue - Функция для получения значения с входного пина.
|
|
7
|
+
* @returns {Promise<any>} - Вычисленное значение для выходного пина.
|
|
8
|
+
*/
|
|
9
|
+
async function evaluate(node, pinId, context, helpers) {
|
|
10
|
+
const { resolvePinValue } = helpers;
|
|
11
|
+
|
|
12
|
+
if (pinId === 'result') {
|
|
13
|
+
const value = await resolvePinValue(node, 'value', '');
|
|
14
|
+
|
|
15
|
+
// Преобразуем в строку
|
|
16
|
+
if (value === null || value === undefined) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof value === 'object') {
|
|
21
|
+
return JSON.stringify(value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return String(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
evaluate,
|
|
32
|
+
};
|