blockmine 1.6.3 → 1.13.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.
Files changed (33) hide show
  1. package/.husky/commit-msg +1 -0
  2. package/.husky/pre-commit +1 -0
  3. package/.versionrc.json +17 -0
  4. package/CHANGELOG.md +36 -0
  5. package/README.md +1 -1
  6. package/backend/package.json +1 -0
  7. package/backend/prisma/migrations/20250718181335_add_plugin_data_store/migration.sql +14 -0
  8. package/backend/prisma/schema.prisma +17 -2
  9. package/backend/src/api/routes/auth.js +140 -0
  10. package/backend/src/api/routes/bots.js +176 -0
  11. package/backend/src/api/routes/changelog.js +16 -0
  12. package/backend/src/api/routes/eventGraphs.js +11 -1
  13. package/backend/src/api/routes/plugins.js +11 -0
  14. package/backend/src/core/BotManager.js +92 -40
  15. package/backend/src/core/BotProcess.js +44 -24
  16. package/backend/src/core/EventGraphManager.js +29 -5
  17. package/backend/src/core/GraphExecutionEngine.js +54 -12
  18. package/backend/src/core/MessageQueue.js +10 -1
  19. package/backend/src/core/NodeRegistry.js +2 -1
  20. package/backend/src/core/PluginLoader.js +72 -8
  21. package/backend/src/core/PluginManager.js +19 -0
  22. package/backend/src/plugins/PluginStore.js +87 -0
  23. package/backend/src/real-time/socketHandler.js +11 -3
  24. package/backend/src/server.js +2 -0
  25. package/backend/temp_migration.sql +0 -0
  26. package/commitlint.config.js +3 -0
  27. package/frontend/dist/assets/index-CHwi1QN9.js +8331 -0
  28. package/frontend/dist/assets/index-DhU2u6V0.css +1 -0
  29. package/frontend/dist/index.html +2 -2
  30. package/frontend/package.json +6 -0
  31. package/package.json +20 -4
  32. package/frontend/dist/assets/index-CIDmlKtb.js +0 -8203
  33. package/frontend/dist/assets/index-DF3i-W3m.css +0 -1
@@ -1,8 +1,36 @@
1
1
 
2
2
  const path = require('path');
3
3
  const fs = require('fs/promises');
4
+ const { execSync } = require('child_process');
5
+ const fssync = require('fs');
6
+ const PluginStore = require('../plugins/PluginStore');
4
7
 
5
- async function initializePlugins(bot, installedPlugins = []) {
8
+ const projectRoot = path.resolve(__dirname, '..');
9
+
10
+ async function ensurePluginDependencies(pluginPath, pluginName) {
11
+ const packageJsonPath = path.join(pluginPath, 'package.json');
12
+ try {
13
+ if (fssync.existsSync(packageJsonPath)) {
14
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
15
+ if (packageJson.dependencies && Object.keys(packageJson.dependencies).length > 0) {
16
+ console.log(`[PluginLoader] У плагина ${pluginName} есть зависимости, устанавливаем их...`);
17
+ try {
18
+ execSync('npm install', {
19
+ cwd: pluginPath,
20
+ stdio: 'pipe'
21
+ });
22
+ console.log(`[PluginLoader] Зависимости для плагина ${pluginName} установлены`);
23
+ } catch (installError) {
24
+ console.error(`[PluginLoader] Ошибка установки зависимостей для ${pluginName}:`, installError.message);
25
+ }
26
+ }
27
+ }
28
+ } catch (error) {
29
+ console.error(`[PluginLoader] Ошибка чтения package.json для ${pluginName}:`, error.message);
30
+ }
31
+ }
32
+
33
+ async function initializePlugins(bot, installedPlugins = [], prisma) {
6
34
  if (!installedPlugins || installedPlugins.length === 0) return;
7
35
 
8
36
  const sendLog = bot.sendLog || console.log;
@@ -11,6 +39,8 @@ async function initializePlugins(bot, installedPlugins = []) {
11
39
  for (const plugin of installedPlugins) {
12
40
  if (plugin && plugin.path) {
13
41
  try {
42
+ await ensurePluginDependencies(plugin.path, plugin.name);
43
+
14
44
  const manifest = plugin.manifest ? JSON.parse(plugin.manifest) : {};
15
45
  const savedSettings = plugin.settings ? JSON.parse(plugin.settings) : {};
16
46
  const defaultSettings = {};
@@ -38,20 +68,54 @@ async function initializePlugins(bot, installedPlugins = []) {
38
68
  }
39
69
 
40
70
  const finalSettings = { ...defaultSettings, ...savedSettings };
71
+ const store = new PluginStore(prisma, bot.config.id, plugin.name);
41
72
 
42
73
  const mainFile = manifest.main || 'index.js';
43
74
  const entryPointPath = path.join(plugin.path, mainFile);
44
75
  const normalizedPath = entryPointPath.replace(/\\/g, '/');
45
76
 
46
77
  sendLog(`[PluginLoader] Загрузка: ${plugin.name} (v${plugin.version}) из ${normalizedPath}`);
47
- const pluginModule = require(normalizedPath);
48
78
 
49
- if (typeof pluginModule === 'function') {
50
- pluginModule(bot, { settings: finalSettings });
51
- } else if (pluginModule && typeof pluginModule.onLoad === 'function') {
52
- pluginModule.onLoad(bot, { settings: finalSettings });
53
- } else {
54
- sendLog(`[PluginLoader] [ERROR] ${plugin.name} не экспортирует функцию или объект с методом onLoad.`);
79
+ try {
80
+ const pluginModule = require(normalizedPath);
81
+
82
+ if (typeof pluginModule === 'function') {
83
+ pluginModule(bot, { settings: finalSettings, store });
84
+ } else if (pluginModule && typeof pluginModule.onLoad === 'function') {
85
+ pluginModule.onLoad(bot, { settings: finalSettings, store });
86
+ } else {
87
+ sendLog(`[PluginLoader] [ERROR] ${plugin.name} не экспортирует функцию или объект с методом onLoad.`);
88
+ }
89
+ } catch (error) {
90
+ if (error.message.includes('Cannot find module')) {
91
+ const moduleMatch = error.message.match(/Cannot find module '([^']+)'/);
92
+ if (moduleMatch) {
93
+ const missingModule = moduleMatch[1];
94
+ sendLog(`[PluginLoader] Попытка установки недостающего модуля ${missingModule} в папку плагина ${plugin.name}`);
95
+ try {
96
+ execSync(`npm install ${missingModule}`, {
97
+ cwd: plugin.path,
98
+ stdio: 'pipe'
99
+ });
100
+ sendLog(`[PluginLoader] Модуль ${missingModule} успешно установлен в папку плагина ${plugin.name}, повторная попытка загрузки`);
101
+
102
+ // Повторная попытка загрузки
103
+ const pluginModule = require(normalizedPath);
104
+ if (typeof pluginModule === 'function') {
105
+ pluginModule(bot, { settings: finalSettings, store });
106
+ } else if (pluginModule && typeof pluginModule.onLoad === 'function') {
107
+ pluginModule.onLoad(bot, { settings: finalSettings, store });
108
+ }
109
+ } catch (installError) {
110
+ sendLog(`[PluginLoader] Не удалось установить модуль ${missingModule} в папку плагина ${plugin.name}: ${installError.message}`);
111
+ throw error; // Пробрасываем оригинальную ошибку
112
+ }
113
+ } else {
114
+ throw error;
115
+ }
116
+ } else {
117
+ throw error;
118
+ }
55
119
  }
56
120
 
57
121
  } catch (error) {
@@ -277,6 +277,25 @@ class PluginManager {
277
277
 
278
278
  return await this.installFromGithub(botId, repoUrl, prisma, true);
279
279
  }
280
+
281
+ async clearPluginData(pluginId) {
282
+ const plugin = await prisma.installedPlugin.findUnique({ where: { id: pluginId } });
283
+ if (!plugin) {
284
+ throw new Error('Плагин не найден.');
285
+ }
286
+
287
+ console.log(`[PluginManager] Очистка данных для плагина ${plugin.name} (Bot ID: ${plugin.botId})`);
288
+
289
+ const { count } = await prisma.pluginDataStore.deleteMany({
290
+ where: {
291
+ pluginName: plugin.name,
292
+ botId: plugin.botId,
293
+ },
294
+ });
295
+
296
+ console.log(`[PluginManager] Удалено ${count} записей из хранилища.`);
297
+ return { count };
298
+ }
280
299
  }
281
300
 
282
301
  module.exports = PluginManager;
@@ -0,0 +1,87 @@
1
+ class PluginStore {
2
+ constructor(prisma, botId, pluginName) {
3
+ this.prisma = prisma;
4
+ this.botId = botId;
5
+ this.pluginName = pluginName;
6
+ }
7
+
8
+ async set(key, value) {
9
+ const jsonValue = JSON.stringify(value);
10
+ await this.prisma.pluginDataStore.upsert({
11
+ where: {
12
+ pluginName_botId_key: {
13
+ pluginName: this.pluginName,
14
+ botId: this.botId,
15
+ key: key
16
+ }
17
+ },
18
+ update: {
19
+ value: jsonValue
20
+ },
21
+ create: {
22
+ pluginName: this.pluginName,
23
+ botId: this.botId,
24
+ key: key,
25
+ value: jsonValue
26
+ }
27
+ });
28
+ }
29
+
30
+ async get(key) {
31
+ const data = await this.prisma.pluginDataStore.findUnique({
32
+ where: {
33
+ pluginName_botId_key: {
34
+ pluginName: this.pluginName,
35
+ botId: this.botId,
36
+ key: key
37
+ }
38
+ }
39
+ });
40
+ return data ? JSON.parse(data.value) : null;
41
+ }
42
+
43
+ async delete(key) {
44
+ try {
45
+ await this.prisma.pluginDataStore.delete({
46
+ where: {
47
+ pluginName_botId_key: {
48
+ pluginName: this.pluginName,
49
+ botId: this.botId,
50
+ key: key
51
+ }
52
+ }
53
+ });
54
+ return true;
55
+ } catch (error) {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ async has(key) {
61
+ const count = await this.prisma.pluginDataStore.count({
62
+ where: {
63
+ pluginName: this.pluginName,
64
+ botId: this.botId,
65
+ key: key
66
+ }
67
+ });
68
+ return count > 0;
69
+ }
70
+
71
+ async getAll() {
72
+ const allData = await this.prisma.pluginDataStore.findMany({
73
+ where: {
74
+ pluginName: this.pluginName,
75
+ botId: this.botId
76
+ }
77
+ });
78
+ const map = new Map();
79
+ for (const item of allData) {
80
+ map.set(item.key, JSON.parse(item.value));
81
+ }
82
+ return map;
83
+ }
84
+ }
85
+
86
+ module.exports = PluginStore;
87
+
@@ -1,6 +1,8 @@
1
1
  const { Server } = require('socket.io');
2
2
  const config = require('../config');
3
3
 
4
+ const { botManager } = require('../core/services');
5
+
4
6
  let io;
5
7
 
6
8
  function initializeSocket(httpServer) {
@@ -16,14 +18,20 @@ function initializeSocket(httpServer) {
16
18
  });
17
19
 
18
20
  io.on('connection', (socket) => {
19
- // console.log(`[Socket.IO] Пользователь подключен: ${socket.id}. Всего клиентов: ${io.engine.clientsCount}`);
20
21
 
21
22
  socket.on('disconnect', () => {
22
- // console.log(`[Socket.IO] Пользователь отключен: ${socket.id}. Всего клиентов: ${io.engine.clientsCount}`);
23
+ botManager.handleSocketDisconnect(socket);
24
+ });
25
+
26
+ socket.on('plugin:ui:subscribe', ({ botId, pluginName }) => {
27
+ botManager.subscribeToPluginUi(botId, pluginName, socket);
28
+ });
29
+
30
+ socket.on('plugin:ui:unsubscribe', ({ botId, pluginName }) => {
31
+ botManager.unsubscribeFromPluginUi(botId, pluginName, socket);
23
32
  });
24
33
  });
25
34
 
26
- // console.log('Socket.IO инициализирован с динамическим CORS.');
27
35
  return io;
28
36
  }
29
37
 
@@ -19,6 +19,7 @@ const searchRoutes = require('./api/routes/search');
19
19
  const eventGraphsRouter = require('./api/routes/eventGraphs');
20
20
  const TaskScheduler = require('./core/TaskScheduler');
21
21
  const panelRoutes = require('./api/routes/panel');
22
+ const changelogRoutes = require('./api/routes/changelog');
22
23
 
23
24
  const app = express();
24
25
  const server = http.createServer(app);
@@ -59,6 +60,7 @@ app.use('/api/servers', serverRoutes);
59
60
  app.use('/api/permissions', permissionsRoutes);
60
61
  app.use('/api/search', searchRoutes);
61
62
  app.use('/api/panel', panelRoutes);
63
+ app.use('/api/changelog', changelogRoutes);
62
64
 
63
65
  app.use(express.static(frontendPath));
64
66
 
Binary file
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ extends: ['@commitlint/config-conventional']
3
+ };