blockmine 1.4.3 → 1.4.6
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/cli.js +1 -1
- package/backend/prisma/migrations/20250614085849_add_bot_note/migration.sql +126 -126
- package/backend/prisma/migrations/20250614153037_add_plugin_installed_date/migration.sql +27 -27
- package/backend/prisma/migrations/20250615232848_add_scheduled_tasks/migration.sql +13 -13
- package/backend/prisma/migrations/20250617133815_add_panel_users_and_roles/migration.sql +26 -26
- package/backend/prisma/migrations/migration_lock.toml +2 -2
- package/backend/src/api/middleware/auth.js +24 -16
- package/backend/src/core/BotManager.js +62 -25
- package/backend/src/core/BotProcess.js +45 -17
- package/backend/src/core/utils/crypto.js +17 -12
- package/package.json +1 -1
package/backend/cli.js
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "Server" (
|
|
3
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
4
|
-
"name" TEXT NOT NULL,
|
|
5
|
-
"host" TEXT NOT NULL,
|
|
6
|
-
"port" INTEGER NOT NULL DEFAULT 25565,
|
|
7
|
-
"version" TEXT NOT NULL
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
-- CreateTable
|
|
11
|
-
CREATE TABLE "Bot" (
|
|
12
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
13
|
-
"username" TEXT NOT NULL,
|
|
14
|
-
"password" TEXT,
|
|
15
|
-
"prefix" TEXT DEFAULT '@',
|
|
16
|
-
"note" TEXT,
|
|
17
|
-
"serverId" INTEGER NOT NULL,
|
|
18
|
-
"proxyHost" TEXT,
|
|
19
|
-
"proxyPort" INTEGER,
|
|
20
|
-
"proxyUsername" TEXT,
|
|
21
|
-
"proxyPassword" TEXT,
|
|
22
|
-
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
23
|
-
"updatedAt" DATETIME NOT NULL,
|
|
24
|
-
CONSTRAINT "Bot_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "Server" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
-- CreateTable
|
|
28
|
-
CREATE TABLE "InstalledPlugin" (
|
|
29
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
30
|
-
"botId" INTEGER NOT NULL,
|
|
31
|
-
"name" TEXT NOT NULL,
|
|
32
|
-
"version" TEXT NOT NULL,
|
|
33
|
-
"description" TEXT,
|
|
34
|
-
"sourceType" TEXT NOT NULL,
|
|
35
|
-
"sourceUri" TEXT,
|
|
36
|
-
"path" TEXT NOT NULL,
|
|
37
|
-
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
38
|
-
"manifest" TEXT,
|
|
39
|
-
"settings" TEXT DEFAULT '{}',
|
|
40
|
-
CONSTRAINT "InstalledPlugin_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
-- CreateTable
|
|
44
|
-
CREATE TABLE "Command" (
|
|
45
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
46
|
-
"botId" INTEGER NOT NULL,
|
|
47
|
-
"name" TEXT NOT NULL,
|
|
48
|
-
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
49
|
-
"cooldown" INTEGER NOT NULL DEFAULT 0,
|
|
50
|
-
"aliases" TEXT NOT NULL DEFAULT '[]',
|
|
51
|
-
"description" TEXT,
|
|
52
|
-
"owner" TEXT,
|
|
53
|
-
"permissionId" INTEGER,
|
|
54
|
-
"allowedChatTypes" TEXT NOT NULL DEFAULT '["chat", "private"]',
|
|
55
|
-
CONSTRAINT "Command_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
56
|
-
CONSTRAINT "Command_permissionId_fkey" FOREIGN KEY ("permissionId") REFERENCES "Permission" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
-- CreateTable
|
|
60
|
-
CREATE TABLE "User" (
|
|
61
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
62
|
-
"username" TEXT NOT NULL,
|
|
63
|
-
"isBlacklisted" BOOLEAN NOT NULL DEFAULT false,
|
|
64
|
-
"botId" INTEGER NOT NULL,
|
|
65
|
-
CONSTRAINT "User_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
-- CreateTable
|
|
69
|
-
CREATE TABLE "Group" (
|
|
70
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
71
|
-
"name" TEXT NOT NULL,
|
|
72
|
-
"owner" TEXT NOT NULL DEFAULT 'system',
|
|
73
|
-
"botId" INTEGER NOT NULL,
|
|
74
|
-
CONSTRAINT "Group_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
-- CreateTable
|
|
78
|
-
CREATE TABLE "Permission" (
|
|
79
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
80
|
-
"name" TEXT NOT NULL,
|
|
81
|
-
"description" TEXT,
|
|
82
|
-
"owner" TEXT NOT NULL DEFAULT 'system',
|
|
83
|
-
"botId" INTEGER NOT NULL,
|
|
84
|
-
CONSTRAINT "Permission_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
-- CreateTable
|
|
88
|
-
CREATE TABLE "UserGroup" (
|
|
89
|
-
"userId" INTEGER NOT NULL,
|
|
90
|
-
"groupId" INTEGER NOT NULL,
|
|
91
|
-
|
|
92
|
-
PRIMARY KEY ("userId", "groupId"),
|
|
93
|
-
CONSTRAINT "UserGroup_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
94
|
-
CONSTRAINT "UserGroup_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "Group" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
-- CreateTable
|
|
98
|
-
CREATE TABLE "GroupPermission" (
|
|
99
|
-
"groupId" INTEGER NOT NULL,
|
|
100
|
-
"permissionId" INTEGER NOT NULL,
|
|
101
|
-
|
|
102
|
-
PRIMARY KEY ("groupId", "permissionId"),
|
|
103
|
-
CONSTRAINT "GroupPermission_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "Group" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
104
|
-
CONSTRAINT "GroupPermission_permissionId_fkey" FOREIGN KEY ("permissionId") REFERENCES "Permission" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
-- CreateIndex
|
|
108
|
-
CREATE UNIQUE INDEX "Server_name_key" ON "Server"("name");
|
|
109
|
-
|
|
110
|
-
-- CreateIndex
|
|
111
|
-
CREATE UNIQUE INDEX "Bot_username_key" ON "Bot"("username");
|
|
112
|
-
|
|
113
|
-
-- CreateIndex
|
|
114
|
-
CREATE UNIQUE INDEX "InstalledPlugin_botId_name_key" ON "InstalledPlugin"("botId", "name");
|
|
115
|
-
|
|
116
|
-
-- CreateIndex
|
|
117
|
-
CREATE UNIQUE INDEX "Command_botId_name_key" ON "Command"("botId", "name");
|
|
118
|
-
|
|
119
|
-
-- CreateIndex
|
|
120
|
-
CREATE UNIQUE INDEX "User_botId_username_key" ON "User"("botId", "username");
|
|
121
|
-
|
|
122
|
-
-- CreateIndex
|
|
123
|
-
CREATE UNIQUE INDEX "Group_botId_name_key" ON "Group"("botId", "name");
|
|
124
|
-
|
|
125
|
-
-- CreateIndex
|
|
126
|
-
CREATE UNIQUE INDEX "Permission_botId_name_key" ON "Permission"("botId", "name");
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "Server" (
|
|
3
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
4
|
+
"name" TEXT NOT NULL,
|
|
5
|
+
"host" TEXT NOT NULL,
|
|
6
|
+
"port" INTEGER NOT NULL DEFAULT 25565,
|
|
7
|
+
"version" TEXT NOT NULL
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
-- CreateTable
|
|
11
|
+
CREATE TABLE "Bot" (
|
|
12
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
13
|
+
"username" TEXT NOT NULL,
|
|
14
|
+
"password" TEXT,
|
|
15
|
+
"prefix" TEXT DEFAULT '@',
|
|
16
|
+
"note" TEXT,
|
|
17
|
+
"serverId" INTEGER NOT NULL,
|
|
18
|
+
"proxyHost" TEXT,
|
|
19
|
+
"proxyPort" INTEGER,
|
|
20
|
+
"proxyUsername" TEXT,
|
|
21
|
+
"proxyPassword" TEXT,
|
|
22
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
23
|
+
"updatedAt" DATETIME NOT NULL,
|
|
24
|
+
CONSTRAINT "Bot_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "Server" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
-- CreateTable
|
|
28
|
+
CREATE TABLE "InstalledPlugin" (
|
|
29
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
30
|
+
"botId" INTEGER NOT NULL,
|
|
31
|
+
"name" TEXT NOT NULL,
|
|
32
|
+
"version" TEXT NOT NULL,
|
|
33
|
+
"description" TEXT,
|
|
34
|
+
"sourceType" TEXT NOT NULL,
|
|
35
|
+
"sourceUri" TEXT,
|
|
36
|
+
"path" TEXT NOT NULL,
|
|
37
|
+
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
38
|
+
"manifest" TEXT,
|
|
39
|
+
"settings" TEXT DEFAULT '{}',
|
|
40
|
+
CONSTRAINT "InstalledPlugin_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
-- CreateTable
|
|
44
|
+
CREATE TABLE "Command" (
|
|
45
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
46
|
+
"botId" INTEGER NOT NULL,
|
|
47
|
+
"name" TEXT NOT NULL,
|
|
48
|
+
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
49
|
+
"cooldown" INTEGER NOT NULL DEFAULT 0,
|
|
50
|
+
"aliases" TEXT NOT NULL DEFAULT '[]',
|
|
51
|
+
"description" TEXT,
|
|
52
|
+
"owner" TEXT,
|
|
53
|
+
"permissionId" INTEGER,
|
|
54
|
+
"allowedChatTypes" TEXT NOT NULL DEFAULT '["chat", "private"]',
|
|
55
|
+
CONSTRAINT "Command_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
56
|
+
CONSTRAINT "Command_permissionId_fkey" FOREIGN KEY ("permissionId") REFERENCES "Permission" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
-- CreateTable
|
|
60
|
+
CREATE TABLE "User" (
|
|
61
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
62
|
+
"username" TEXT NOT NULL,
|
|
63
|
+
"isBlacklisted" BOOLEAN NOT NULL DEFAULT false,
|
|
64
|
+
"botId" INTEGER NOT NULL,
|
|
65
|
+
CONSTRAINT "User_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
-- CreateTable
|
|
69
|
+
CREATE TABLE "Group" (
|
|
70
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
71
|
+
"name" TEXT NOT NULL,
|
|
72
|
+
"owner" TEXT NOT NULL DEFAULT 'system',
|
|
73
|
+
"botId" INTEGER NOT NULL,
|
|
74
|
+
CONSTRAINT "Group_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
-- CreateTable
|
|
78
|
+
CREATE TABLE "Permission" (
|
|
79
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
80
|
+
"name" TEXT NOT NULL,
|
|
81
|
+
"description" TEXT,
|
|
82
|
+
"owner" TEXT NOT NULL DEFAULT 'system',
|
|
83
|
+
"botId" INTEGER NOT NULL,
|
|
84
|
+
CONSTRAINT "Permission_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
-- CreateTable
|
|
88
|
+
CREATE TABLE "UserGroup" (
|
|
89
|
+
"userId" INTEGER NOT NULL,
|
|
90
|
+
"groupId" INTEGER NOT NULL,
|
|
91
|
+
|
|
92
|
+
PRIMARY KEY ("userId", "groupId"),
|
|
93
|
+
CONSTRAINT "UserGroup_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
94
|
+
CONSTRAINT "UserGroup_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "Group" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
-- CreateTable
|
|
98
|
+
CREATE TABLE "GroupPermission" (
|
|
99
|
+
"groupId" INTEGER NOT NULL,
|
|
100
|
+
"permissionId" INTEGER NOT NULL,
|
|
101
|
+
|
|
102
|
+
PRIMARY KEY ("groupId", "permissionId"),
|
|
103
|
+
CONSTRAINT "GroupPermission_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "Group" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
104
|
+
CONSTRAINT "GroupPermission_permissionId_fkey" FOREIGN KEY ("permissionId") REFERENCES "Permission" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
-- CreateIndex
|
|
108
|
+
CREATE UNIQUE INDEX "Server_name_key" ON "Server"("name");
|
|
109
|
+
|
|
110
|
+
-- CreateIndex
|
|
111
|
+
CREATE UNIQUE INDEX "Bot_username_key" ON "Bot"("username");
|
|
112
|
+
|
|
113
|
+
-- CreateIndex
|
|
114
|
+
CREATE UNIQUE INDEX "InstalledPlugin_botId_name_key" ON "InstalledPlugin"("botId", "name");
|
|
115
|
+
|
|
116
|
+
-- CreateIndex
|
|
117
|
+
CREATE UNIQUE INDEX "Command_botId_name_key" ON "Command"("botId", "name");
|
|
118
|
+
|
|
119
|
+
-- CreateIndex
|
|
120
|
+
CREATE UNIQUE INDEX "User_botId_username_key" ON "User"("botId", "username");
|
|
121
|
+
|
|
122
|
+
-- CreateIndex
|
|
123
|
+
CREATE UNIQUE INDEX "Group_botId_name_key" ON "Group"("botId", "name");
|
|
124
|
+
|
|
125
|
+
-- CreateIndex
|
|
126
|
+
CREATE UNIQUE INDEX "Permission_botId_name_key" ON "Permission"("botId", "name");
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
-- AlterTable
|
|
2
|
-
ALTER TABLE "Bot" ADD COLUMN "owners" TEXT DEFAULT '';
|
|
3
|
-
|
|
4
|
-
-- RedefineTables
|
|
5
|
-
PRAGMA defer_foreign_keys=ON;
|
|
6
|
-
PRAGMA foreign_keys=OFF;
|
|
7
|
-
CREATE TABLE "new_InstalledPlugin" (
|
|
8
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
9
|
-
"botId" INTEGER NOT NULL,
|
|
10
|
-
"name" TEXT NOT NULL,
|
|
11
|
-
"version" TEXT NOT NULL,
|
|
12
|
-
"description" TEXT,
|
|
13
|
-
"sourceType" TEXT NOT NULL,
|
|
14
|
-
"sourceUri" TEXT,
|
|
15
|
-
"path" TEXT NOT NULL,
|
|
16
|
-
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
17
|
-
"manifest" TEXT,
|
|
18
|
-
"settings" TEXT DEFAULT '{}',
|
|
19
|
-
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
20
|
-
CONSTRAINT "InstalledPlugin_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
21
|
-
);
|
|
22
|
-
INSERT INTO "new_InstalledPlugin" ("botId", "description", "id", "isEnabled", "manifest", "name", "path", "settings", "sourceType", "sourceUri", "version") SELECT "botId", "description", "id", "isEnabled", "manifest", "name", "path", "settings", "sourceType", "sourceUri", "version" FROM "InstalledPlugin";
|
|
23
|
-
DROP TABLE "InstalledPlugin";
|
|
24
|
-
ALTER TABLE "new_InstalledPlugin" RENAME TO "InstalledPlugin";
|
|
25
|
-
CREATE UNIQUE INDEX "InstalledPlugin_botId_name_key" ON "InstalledPlugin"("botId", "name");
|
|
26
|
-
PRAGMA foreign_keys=ON;
|
|
27
|
-
PRAGMA defer_foreign_keys=OFF;
|
|
1
|
+
-- AlterTable
|
|
2
|
+
ALTER TABLE "Bot" ADD COLUMN "owners" TEXT DEFAULT '';
|
|
3
|
+
|
|
4
|
+
-- RedefineTables
|
|
5
|
+
PRAGMA defer_foreign_keys=ON;
|
|
6
|
+
PRAGMA foreign_keys=OFF;
|
|
7
|
+
CREATE TABLE "new_InstalledPlugin" (
|
|
8
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
"botId" INTEGER NOT NULL,
|
|
10
|
+
"name" TEXT NOT NULL,
|
|
11
|
+
"version" TEXT NOT NULL,
|
|
12
|
+
"description" TEXT,
|
|
13
|
+
"sourceType" TEXT NOT NULL,
|
|
14
|
+
"sourceUri" TEXT,
|
|
15
|
+
"path" TEXT NOT NULL,
|
|
16
|
+
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
17
|
+
"manifest" TEXT,
|
|
18
|
+
"settings" TEXT DEFAULT '{}',
|
|
19
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
20
|
+
CONSTRAINT "InstalledPlugin_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
21
|
+
);
|
|
22
|
+
INSERT INTO "new_InstalledPlugin" ("botId", "description", "id", "isEnabled", "manifest", "name", "path", "settings", "sourceType", "sourceUri", "version") SELECT "botId", "description", "id", "isEnabled", "manifest", "name", "path", "settings", "sourceType", "sourceUri", "version" FROM "InstalledPlugin";
|
|
23
|
+
DROP TABLE "InstalledPlugin";
|
|
24
|
+
ALTER TABLE "new_InstalledPlugin" RENAME TO "InstalledPlugin";
|
|
25
|
+
CREATE UNIQUE INDEX "InstalledPlugin_botId_name_key" ON "InstalledPlugin"("botId", "name");
|
|
26
|
+
PRAGMA foreign_keys=ON;
|
|
27
|
+
PRAGMA defer_foreign_keys=OFF;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "ScheduledTask" (
|
|
3
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
4
|
-
"name" TEXT NOT NULL,
|
|
5
|
-
"cronPattern" TEXT NOT NULL,
|
|
6
|
-
"action" TEXT NOT NULL,
|
|
7
|
-
"targetBotIds" TEXT NOT NULL,
|
|
8
|
-
"payload" TEXT DEFAULT '{}',
|
|
9
|
-
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
10
|
-
"lastRun" DATETIME,
|
|
11
|
-
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
-
"updatedAt" DATETIME NOT NULL
|
|
13
|
-
);
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "ScheduledTask" (
|
|
3
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
4
|
+
"name" TEXT NOT NULL,
|
|
5
|
+
"cronPattern" TEXT NOT NULL,
|
|
6
|
+
"action" TEXT NOT NULL,
|
|
7
|
+
"targetBotIds" TEXT NOT NULL,
|
|
8
|
+
"payload" TEXT DEFAULT '{}',
|
|
9
|
+
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
|
10
|
+
"lastRun" DATETIME,
|
|
11
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
+
"updatedAt" DATETIME NOT NULL
|
|
13
|
+
);
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
-- CreateTable
|
|
2
|
-
CREATE TABLE "PanelUser" (
|
|
3
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
4
|
-
"uuid" TEXT NOT NULL,
|
|
5
|
-
"username" TEXT NOT NULL,
|
|
6
|
-
"passwordHash" TEXT NOT NULL,
|
|
7
|
-
"roleId" INTEGER NOT NULL,
|
|
8
|
-
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
9
|
-
CONSTRAINT "PanelUser_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "PanelRole" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
10
|
-
);
|
|
11
|
-
|
|
12
|
-
-- CreateTable
|
|
13
|
-
CREATE TABLE "PanelRole" (
|
|
14
|
-
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
15
|
-
"name" TEXT NOT NULL,
|
|
16
|
-
"permissions" TEXT NOT NULL DEFAULT '[]'
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
-- CreateIndex
|
|
20
|
-
CREATE UNIQUE INDEX "PanelUser_uuid_key" ON "PanelUser"("uuid");
|
|
21
|
-
|
|
22
|
-
-- CreateIndex
|
|
23
|
-
CREATE UNIQUE INDEX "PanelUser_username_key" ON "PanelUser"("username");
|
|
24
|
-
|
|
25
|
-
-- CreateIndex
|
|
26
|
-
CREATE UNIQUE INDEX "PanelRole_name_key" ON "PanelRole"("name");
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "PanelUser" (
|
|
3
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
4
|
+
"uuid" TEXT NOT NULL,
|
|
5
|
+
"username" TEXT NOT NULL,
|
|
6
|
+
"passwordHash" TEXT NOT NULL,
|
|
7
|
+
"roleId" INTEGER NOT NULL,
|
|
8
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
9
|
+
CONSTRAINT "PanelUser_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "PanelRole" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
-- CreateTable
|
|
13
|
+
CREATE TABLE "PanelRole" (
|
|
14
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
15
|
+
"name" TEXT NOT NULL,
|
|
16
|
+
"permissions" TEXT NOT NULL DEFAULT '[]'
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
-- CreateIndex
|
|
20
|
+
CREATE UNIQUE INDEX "PanelUser_uuid_key" ON "PanelUser"("uuid");
|
|
21
|
+
|
|
22
|
+
-- CreateIndex
|
|
23
|
+
CREATE UNIQUE INDEX "PanelUser_username_key" ON "PanelUser"("username");
|
|
24
|
+
|
|
25
|
+
-- CreateIndex
|
|
26
|
+
CREATE UNIQUE INDEX "PanelRole_name_key" ON "PanelRole"("name");
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
# Please do not edit this file manually
|
|
2
|
-
# It should be added in your version-control system (i.e. Git)
|
|
1
|
+
# Please do not edit this file manually
|
|
2
|
+
# It should be added in your version-control system (i.e. Git)
|
|
3
3
|
provider = "sqlite"
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
1
|
const jwt = require('jsonwebtoken');
|
|
3
2
|
const config = require('../../config');
|
|
4
3
|
|
|
5
4
|
const JWT_SECRET = config.security.jwtSecret;
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
6
|
+
const tokenCache = new Map();
|
|
7
|
+
const CACHE_TTL = 5 * 60 * 1000;
|
|
8
|
+
|
|
9
|
+
|
|
12
10
|
function authenticate(req, res, next) {
|
|
13
11
|
const authHeader = req.header('Authorization');
|
|
14
|
-
|
|
15
12
|
if (!authHeader) {
|
|
16
13
|
return res.status(401).json({ error: 'Нет токена, доступ запрещен' });
|
|
17
14
|
}
|
|
@@ -23,28 +20,39 @@ function authenticate(req, res, next) {
|
|
|
23
20
|
|
|
24
21
|
const token = tokenParts[1];
|
|
25
22
|
|
|
23
|
+
if (tokenCache.has(token)) {
|
|
24
|
+
const cached = tokenCache.get(token);
|
|
25
|
+
if (Date.now() < cached.expires) {
|
|
26
|
+
req.user = cached.payload;
|
|
27
|
+
return next();
|
|
28
|
+
} else {
|
|
29
|
+
tokenCache.delete(token);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
26
33
|
try {
|
|
27
|
-
const decoded = jwt.verify(token, JWT_SECRET);
|
|
34
|
+
const decoded = jwt.verify(token, JWT_SECRET, { algorithms: ['HS256'] });
|
|
28
35
|
req.user = decoded;
|
|
36
|
+
|
|
37
|
+
tokenCache.set(token, {
|
|
38
|
+
payload: decoded,
|
|
39
|
+
expires: Date.now() + CACHE_TTL
|
|
40
|
+
});
|
|
41
|
+
|
|
29
42
|
next();
|
|
30
43
|
} catch (err) {
|
|
31
44
|
res.status(401).json({ error: 'Невалидный токен' });
|
|
32
45
|
}
|
|
33
46
|
}
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
* Middleware-фабрика для проверки прав доступа.
|
|
37
|
-
* @param {string} requiredPermission - Право, необходимое для доступа к роуту (например, 'bot:delete').
|
|
38
|
-
* @returns {function} - Express middleware.
|
|
39
|
-
*/
|
|
48
|
+
|
|
40
49
|
function authorize(requiredPermission) {
|
|
41
50
|
return (req, res, next) => {
|
|
42
|
-
if (!req.user || !req.user.permissions) {
|
|
43
|
-
return res.status(403).json({ error: 'Ошибка прав доступа: пользователь не
|
|
51
|
+
if (!req.user || !Array.isArray(req.user.permissions)) {
|
|
52
|
+
return res.status(403).json({ error: 'Ошибка прав доступа: пользователь не аутентифицирован или формат прав некорректен.' });
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
const userPermissions = req.user.permissions;
|
|
47
|
-
|
|
48
56
|
if (userPermissions.includes('*') || userPermissions.includes(requiredPermission)) {
|
|
49
57
|
next();
|
|
50
58
|
} else {
|
|
@@ -5,7 +5,6 @@ const { PrismaClient } = require('@prisma/client');
|
|
|
5
5
|
const pidusage = require('pidusage');
|
|
6
6
|
const DependencyService = require('./DependencyService');
|
|
7
7
|
const config = require('../config');
|
|
8
|
-
|
|
9
8
|
const fs = require('fs');
|
|
10
9
|
const os = require('os');
|
|
11
10
|
const { v4: uuidv4 } = require('uuid');
|
|
@@ -25,6 +24,26 @@ const WARNING_COOLDOWN = 10 * 1000;
|
|
|
25
24
|
const STATS_SERVER_URL = 'http://185.65.200.184:3000';
|
|
26
25
|
let instanceId = null;
|
|
27
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
|
+
}
|
|
28
47
|
|
|
29
48
|
|
|
30
49
|
class BotManager {
|
|
@@ -34,9 +53,9 @@ class BotManager {
|
|
|
34
53
|
this.resourceUsage = new Map();
|
|
35
54
|
this.botConfigs = new Map();
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
getInstanceId();
|
|
39
57
|
|
|
58
|
+
setInterval(() => this.updateAllResourceUsage(), 5000);
|
|
40
59
|
if (config.telemetry?.enabled) {
|
|
41
60
|
setInterval(() => this.sendHeartbeat(), 5 * 60 * 1000);
|
|
42
61
|
}
|
|
@@ -49,13 +68,11 @@ class BotManager {
|
|
|
49
68
|
prisma.command.findMany({ where: { botId } }),
|
|
50
69
|
prisma.permission.findMany({ where: { botId } }),
|
|
51
70
|
]);
|
|
52
|
-
|
|
53
71
|
const config = {
|
|
54
72
|
commands: new Map(commands.map(cmd => [cmd.name, cmd])),
|
|
55
73
|
permissionsById: new Map(permissions.map(p => [p.id, p])),
|
|
56
74
|
commandAliases: new Map()
|
|
57
75
|
};
|
|
58
|
-
|
|
59
76
|
for (const cmd of commands) {
|
|
60
77
|
const aliases = JSON.parse(cmd.aliases || '[]');
|
|
61
78
|
for (const alias of aliases) {
|
|
@@ -81,7 +98,6 @@ class BotManager {
|
|
|
81
98
|
|
|
82
99
|
triggerHeartbeat() {
|
|
83
100
|
if (!config.telemetry?.enabled) return;
|
|
84
|
-
|
|
85
101
|
if (this.heartbeatDebounceTimer) {
|
|
86
102
|
clearTimeout(this.heartbeatDebounceTimer);
|
|
87
103
|
}
|
|
@@ -105,7 +121,6 @@ class BotManager {
|
|
|
105
121
|
|
|
106
122
|
async sendHeartbeat() {
|
|
107
123
|
if (!config.telemetry?.enabled) return;
|
|
108
|
-
|
|
109
124
|
if (!instanceId) return;
|
|
110
125
|
|
|
111
126
|
try {
|
|
@@ -131,7 +146,6 @@ class BotManager {
|
|
|
131
146
|
return;
|
|
132
147
|
}
|
|
133
148
|
const { challenge, difficulty, prefix } = await challengeRes.json();
|
|
134
|
-
|
|
135
149
|
let nonce = 0;
|
|
136
150
|
let hash = '';
|
|
137
151
|
do {
|
|
@@ -150,7 +164,6 @@ class BotManager {
|
|
|
150
164
|
nonce: nonce
|
|
151
165
|
})
|
|
152
166
|
});
|
|
153
|
-
|
|
154
167
|
} catch (error) {
|
|
155
168
|
console.error(`[Telemetry] Не удалось отправить heartbeat: ${error.message}`);
|
|
156
169
|
}
|
|
@@ -170,7 +183,6 @@ class BotManager {
|
|
|
170
183
|
"User": ["user.say"],
|
|
171
184
|
"Admin": ["admin.*", "admin.cooldown.bypass", "user.cooldown.bypass", "user.*"]
|
|
172
185
|
};
|
|
173
|
-
|
|
174
186
|
console.log(`[Permission Sync] Синхронизация системных прав для бота ID ${botId}...`);
|
|
175
187
|
|
|
176
188
|
for (const perm of systemPermissions) {
|
|
@@ -218,7 +230,6 @@ class BotManager {
|
|
|
218
230
|
|
|
219
231
|
const pids = Array.from(this.bots.values()).map(child => child.pid).filter(Boolean);
|
|
220
232
|
if (pids.length === 0) return;
|
|
221
|
-
|
|
222
233
|
try {
|
|
223
234
|
const stats = await pidusage(pids);
|
|
224
235
|
const usageData = [];
|
|
@@ -237,7 +248,6 @@ class BotManager {
|
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
250
|
getIO().emit('bots:usage', usageData);
|
|
240
|
-
|
|
241
251
|
} catch (error) {
|
|
242
252
|
}
|
|
243
253
|
}
|
|
@@ -291,18 +301,15 @@ class BotManager {
|
|
|
291
301
|
|
|
292
302
|
await this._syncSystemPermissions(botConfig.id);
|
|
293
303
|
await this.loadConfigForBot(botConfig.id);
|
|
294
|
-
|
|
295
304
|
this.logCache.set(botConfig.id, []);
|
|
296
305
|
this.emitStatusUpdate(botConfig.id, 'starting', '');
|
|
297
306
|
|
|
298
307
|
const allPluginsForBot = await prisma.installedPlugin.findMany({
|
|
299
308
|
where: { botId: botConfig.id },
|
|
300
309
|
});
|
|
301
|
-
|
|
302
310
|
const enabledPlugins = allPluginsForBot.filter(p => p.isEnabled);
|
|
303
311
|
|
|
304
312
|
const { sortedPlugins, pluginInfo, hasCriticalIssues } = DependencyService.resolveDependencies(enabledPlugins, allPluginsForBot);
|
|
305
|
-
|
|
306
313
|
if (hasCriticalIssues) {
|
|
307
314
|
this.appendLog(botConfig.id, '[DependencyManager] Обнаружены критические проблемы с зависимостями:');
|
|
308
315
|
for (const plugin of Object.values(pluginInfo)) {
|
|
@@ -328,20 +335,16 @@ class BotManager {
|
|
|
328
335
|
}
|
|
329
336
|
|
|
330
337
|
const fullBotConfig = { ...decryptedConfig, plugins: sortedPlugins };
|
|
331
|
-
|
|
332
338
|
const botProcessPath = path.resolve(__dirname, 'BotProcess.js');
|
|
333
339
|
const child = fork(botProcessPath, [], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
|
|
334
340
|
|
|
335
341
|
child.botConfig = botConfig;
|
|
336
|
-
|
|
337
342
|
child.on('error', (err) => {
|
|
338
343
|
this.appendLog(botConfig.id, `[PROCESS FATAL] КРИТИЧЕСКАЯ ОШИБКА ПРОЦЕССА: ${err.stack}`);
|
|
339
344
|
});
|
|
340
|
-
|
|
341
345
|
child.stderr.on('data', (data) => {
|
|
342
346
|
this.appendLog(botConfig.id, `[STDERR] ${data.toString()}`);
|
|
343
347
|
});
|
|
344
|
-
|
|
345
348
|
child.on('message', async (message) => {
|
|
346
349
|
if (message.type === 'log') {
|
|
347
350
|
this.appendLog(botConfig.id, message.content);
|
|
@@ -351,9 +354,48 @@ class BotManager {
|
|
|
351
354
|
await this.handleCommandValidation(botConfig, message);
|
|
352
355
|
} else if (message.type === 'register_command') {
|
|
353
356
|
await this.handleCommandRegistration(botConfig.id, message.commandConfig);
|
|
357
|
+
} else if (message.type === 'request_user_action') {
|
|
358
|
+
const { requestId, payload } = message;
|
|
359
|
+
const { targetUsername, action, data } = payload;
|
|
360
|
+
const botId = botConfig.id;
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
const targetUser = await RealUserService.getUser(targetUsername, botId);
|
|
364
|
+
let replyPayload = {};
|
|
365
|
+
|
|
366
|
+
switch (action) {
|
|
367
|
+
case 'toggle_blacklist': {
|
|
368
|
+
const isCurrentlyBlacklisted = targetUser.isBlacklisted;
|
|
369
|
+
await targetUser.setBlacklist(!isCurrentlyBlacklisted);
|
|
370
|
+
replyPayload.newStatus = !isCurrentlyBlacklisted;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
case 'toggle_group': {
|
|
375
|
+
if (!data.groupName) throw new Error('Название группы не указано.');
|
|
376
|
+
const hasGroup = targetUser.hasGroup(data.groupName);
|
|
377
|
+
if (hasGroup) {
|
|
378
|
+
await targetUser.removeGroup(data.groupName);
|
|
379
|
+
replyPayload.actionTaken = 'removed';
|
|
380
|
+
} else {
|
|
381
|
+
await targetUser.addGroup(data.groupName);
|
|
382
|
+
replyPayload.actionTaken = 'added';
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
default:
|
|
388
|
+
throw new Error(`Неизвестное действие: ${action}`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
child.send({ type: 'user_action_response', requestId, payload: replyPayload });
|
|
392
|
+
|
|
393
|
+
} catch (error) {
|
|
394
|
+
console.error(`[BotManager] Ошибка выполнения действия '${action}' для пользователя '${targetUsername}':`, error);
|
|
395
|
+
child.send({ type: 'user_action_response', requestId, error: error.message });
|
|
396
|
+
}
|
|
354
397
|
}
|
|
355
398
|
});
|
|
356
|
-
|
|
357
399
|
child.on('exit', (code, signal) => {
|
|
358
400
|
const botId = botConfig.id;
|
|
359
401
|
this.bots.delete(botId);
|
|
@@ -362,7 +404,6 @@ class BotManager {
|
|
|
362
404
|
this.emitStatusUpdate(botId, 'stopped', `Процесс завершился с кодом ${code} (сигнал: ${signal || 'none'}).`);
|
|
363
405
|
this.updateAllResourceUsage();
|
|
364
406
|
});
|
|
365
|
-
|
|
366
407
|
this.bots.set(botConfig.id, child);
|
|
367
408
|
child.send({ type: 'start', config: fullBotConfig });
|
|
368
409
|
|
|
@@ -433,7 +474,6 @@ class BotManager {
|
|
|
433
474
|
}
|
|
434
475
|
|
|
435
476
|
child.send({ type: 'execute_handler', commandName: dbCommand.name, username, args, typeChat });
|
|
436
|
-
|
|
437
477
|
} catch (error) {
|
|
438
478
|
console.error(`[BotManager] Command validation error for botId: ${botId}`, {
|
|
439
479
|
command: commandName,
|
|
@@ -477,18 +517,15 @@ class BotManager {
|
|
|
477
517
|
allowedChatTypes: JSON.stringify(commandConfig.allowedChatTypes || []),
|
|
478
518
|
cooldown: commandConfig.cooldown || 0,
|
|
479
519
|
};
|
|
480
|
-
|
|
481
520
|
const updateData = {
|
|
482
521
|
description: commandConfig.description,
|
|
483
522
|
owner: commandConfig.owner,
|
|
484
523
|
};
|
|
485
|
-
|
|
486
524
|
await prisma.command.upsert({
|
|
487
525
|
where: { botId_name: { botId, name: commandConfig.name } },
|
|
488
526
|
update: updateData,
|
|
489
527
|
create: createData,
|
|
490
528
|
});
|
|
491
|
-
|
|
492
529
|
this.invalidateConfigCache(botId);
|
|
493
530
|
|
|
494
531
|
} catch (error) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
1
|
const mineflayer = require('mineflayer');
|
|
3
2
|
const { SocksClient } = require('socks');
|
|
4
3
|
const EventEmitter = require('events');
|
|
4
|
+
const { v4: uuidv4 } = require('uuid');
|
|
5
5
|
const { loadCommands } = require('./system/CommandRegistry');
|
|
6
6
|
const { initializePlugins } = require('./PluginLoader');
|
|
7
7
|
const MessageQueue = require('./MessageQueue');
|
|
@@ -12,6 +12,7 @@ const UserService = require('./ipc/UserService.stub.js');
|
|
|
12
12
|
const PermissionManager = require('./ipc/PermissionManager.stub.js');
|
|
13
13
|
|
|
14
14
|
let bot = null;
|
|
15
|
+
const pendingRequests = new Map();
|
|
15
16
|
|
|
16
17
|
function sendLog(content) {
|
|
17
18
|
if (process.send) {
|
|
@@ -29,8 +30,8 @@ function handleIncomingCommand(type, username, message) {
|
|
|
29
30
|
const commandName = commandParts.shift().toLowerCase();
|
|
30
31
|
const restOfMessage = commandParts.join(' ');
|
|
31
32
|
|
|
32
|
-
const commandInstance = bot.commands.get(commandName) ||
|
|
33
|
-
|
|
33
|
+
const commandInstance = bot.commands.get(commandName) ||
|
|
34
|
+
Array.from(bot.commands.values()).find(cmd => cmd.aliases.includes(commandName));
|
|
34
35
|
|
|
35
36
|
if (!commandInstance) return;
|
|
36
37
|
|
|
@@ -90,7 +91,17 @@ function handleIncomingCommand(type, username, message) {
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
process.on('message', async (message) => {
|
|
93
|
-
if (message.type === '
|
|
94
|
+
if (message.type === 'user_action_response') {
|
|
95
|
+
if (pendingRequests.has(message.requestId)) {
|
|
96
|
+
const { resolve, reject } = pendingRequests.get(message.requestId);
|
|
97
|
+
if (message.error) {
|
|
98
|
+
reject(new Error(message.error));
|
|
99
|
+
} else {
|
|
100
|
+
resolve(message.payload);
|
|
101
|
+
}
|
|
102
|
+
pendingRequests.delete(message.requestId);
|
|
103
|
+
}
|
|
104
|
+
} else if (message.type === 'start') {
|
|
94
105
|
const config = message.config;
|
|
95
106
|
sendLog(`[System] Получена команда на запуск бота ${config.username}...`);
|
|
96
107
|
try {
|
|
@@ -130,18 +141,17 @@ process.on('message', async (message) => {
|
|
|
130
141
|
}
|
|
131
142
|
} else {
|
|
132
143
|
sendLog(`[System] Прокси не настроен, используется прямое подключение.`);
|
|
133
|
-
|
|
144
|
+
}
|
|
134
145
|
|
|
135
146
|
bot = mineflayer.createBot(botOptions);
|
|
136
147
|
|
|
137
148
|
bot.events = new EventEmitter();
|
|
138
|
-
bot.events.setMaxListeners(30);
|
|
149
|
+
bot.events.setMaxListeners(30);
|
|
139
150
|
bot.config = config;
|
|
140
151
|
bot.sendLog = sendLog;
|
|
141
152
|
bot.messageQueue = new MessageQueue(bot);
|
|
142
153
|
|
|
143
154
|
const installedPluginNames = config.plugins.map(p => p.name);
|
|
144
|
-
|
|
145
155
|
bot.api = {
|
|
146
156
|
Command: Command,
|
|
147
157
|
events: bot.events,
|
|
@@ -172,17 +182,43 @@ process.on('message', async (message) => {
|
|
|
172
182
|
});
|
|
173
183
|
}
|
|
174
184
|
sendLog(`[API] Команда "${commandInstance.name}" от плагина "${commandInstance.owner}" зарегистрирована в процессе.`);
|
|
185
|
+
},
|
|
186
|
+
performUserAction: (username, action, data = {}) => {
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
const requestId = uuidv4();
|
|
189
|
+
pendingRequests.set(requestId, { resolve, reject });
|
|
190
|
+
|
|
191
|
+
if (process.send) {
|
|
192
|
+
process.send({
|
|
193
|
+
type: 'request_user_action',
|
|
194
|
+
requestId,
|
|
195
|
+
payload: {
|
|
196
|
+
targetUsername: username,
|
|
197
|
+
action,
|
|
198
|
+
data
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
} else {
|
|
202
|
+
reject(new Error('IPC channel is not available.'));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
setTimeout(() => {
|
|
206
|
+
if (pendingRequests.has(requestId)) {
|
|
207
|
+
reject(new Error('Request to main process timed out.'));
|
|
208
|
+
pendingRequests.delete(requestId);
|
|
209
|
+
}
|
|
210
|
+
}, 5000);
|
|
211
|
+
});
|
|
175
212
|
}
|
|
176
213
|
};
|
|
177
214
|
|
|
178
215
|
bot.commands = await loadCommands();
|
|
179
|
-
|
|
180
216
|
if (process.send) {
|
|
181
217
|
for (const cmd of bot.commands.values()) {
|
|
182
218
|
process.send({
|
|
183
219
|
type: 'register_command',
|
|
184
220
|
commandConfig: {
|
|
185
|
-
|
|
221
|
+
name: cmd.name,
|
|
186
222
|
description: cmd.description,
|
|
187
223
|
aliases: cmd.aliases,
|
|
188
224
|
owner: cmd.owner,
|
|
@@ -207,7 +243,6 @@ process.on('message', async (message) => {
|
|
|
207
243
|
handleIncomingCommand(type, username, message);
|
|
208
244
|
}
|
|
209
245
|
});
|
|
210
|
-
|
|
211
246
|
bot.on('message', (jsonMsg) => {
|
|
212
247
|
const ansiMessage = jsonMsg.toAnsi();
|
|
213
248
|
if (ansiMessage.trim()) {
|
|
@@ -218,39 +253,32 @@ process.on('message', async (message) => {
|
|
|
218
253
|
const rawMessageText = jsonMsg.toString();
|
|
219
254
|
bot.events.emit('core:raw_message', rawMessageText, jsonMsg);
|
|
220
255
|
});
|
|
221
|
-
|
|
222
256
|
bot.on('chat', (username, message) => {
|
|
223
257
|
if (messageHandledByCustomParser) {
|
|
224
258
|
return;
|
|
225
259
|
}
|
|
226
260
|
handleIncomingCommand('chat', username, message);
|
|
227
261
|
});
|
|
228
|
-
|
|
229
262
|
bot.on('login', () => {
|
|
230
263
|
sendLog('[Event: login] Успешно залогинился!');
|
|
231
264
|
if (process.send) {
|
|
232
265
|
process.send({ type: 'status', status: 'running' });
|
|
233
266
|
}
|
|
234
267
|
});
|
|
235
|
-
|
|
236
268
|
bot.on('spawn', () => {
|
|
237
269
|
sendLog('[Event: spawn] Бот заспавнился в мире. Полностью готов к работе!');
|
|
238
270
|
});
|
|
239
|
-
|
|
240
271
|
bot.on('kicked', (reason) => {
|
|
241
272
|
let reasonText;
|
|
242
273
|
try { reasonText = JSON.parse(reason).text || reason; } catch (e) { reasonText = reason; }
|
|
243
274
|
sendLog(`[Event: kicked] Меня кикнули. Причина: ${reasonText}.`);
|
|
244
275
|
process.exit(0);
|
|
245
276
|
});
|
|
246
|
-
|
|
247
277
|
bot.on('error', (err) => sendLog(`[Event: error] Произошла ошибка: ${err.stack || err.message}`));
|
|
248
|
-
|
|
249
278
|
bot.on('end', (reason) => {
|
|
250
279
|
sendLog(`[Event: end] Отключен от сервера. Причина: ${reason}`);
|
|
251
280
|
process.exit(0);
|
|
252
281
|
});
|
|
253
|
-
|
|
254
282
|
} catch (err) {
|
|
255
283
|
sendLog(`[CRITICAL] Критическая ошибка при создании бота: ${err.stack}`);
|
|
256
284
|
process.exit(1);
|
|
@@ -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
|
-
|
|
8
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
45
|
-
return null;
|
|
50
|
+
throw new Error(`[Crypto] Ошибка дешифрования. Возможно, ключ был изменен или данные повреждены. ${error.message}`);
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
|