vipsphi commited on
Commit
f252513
·
verified ·
1 Parent(s): caa9e56

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +399 -399
server.js CHANGED
@@ -1,399 +1,399 @@
1
- const { app: electronApp, session } = require("electron");
2
-
3
- // Global Proxy Auth Handler
4
- electronApp.on("login", (event, webContents, details, authInfo, callback) => {
5
- if (authInfo.isProxy) {
6
- const ses = webContents.session;
7
- if (ses.proxyCredentials) {
8
- logger.debug(`[Main] Providing credentials for proxy via app.on('login')`);
9
- event.preventDefault();
10
- callback(ses.proxyCredentials.username, ses.proxyCredentials.password);
11
- }
12
- }
13
- });
14
-
15
- const express = require("express");
16
- const bodyParser = require("body-parser");
17
- const cors = require("cors");
18
- const sqlite3 = require("sqlite3");
19
- const { v4: uuidv4 } = require("uuid");
20
- const path = require("path");
21
- const RecaptchaSolver = require("./solver");
22
- const http = require("http");
23
- const { Server } = require("socket.io");
24
- const logger = require("./logger");
25
-
26
- const PORT = 3000;
27
- const app = express();
28
- const server = http.createServer(app);
29
- const io = new Server(server, {
30
- cors: { origin: "*" },
31
- });
32
-
33
- const db = new sqlite3.Database("./database.sqlite");
34
-
35
- // --- INIT DB ---
36
- db.serialize(() => {
37
- // Thêm cột role để phân quyền (admin/user)
38
- db.run(`CREATE TABLE IF NOT EXISTS users (
39
- id INTEGER PRIMARY KEY AUTOINCREMENT,
40
- username TEXT UNIQUE,
41
- password TEXT,
42
- api_key TEXT,
43
- credits INTEGER DEFAULT 0,
44
- role TEXT DEFAULT 'user',
45
- hwid TEXT
46
- )`);
47
- db.run("ALTER TABLE users ADD COLUMN hwid TEXT", (err) => {
48
- if (err) {
49
- if (!err.message.includes("duplicate column name")) {
50
- console.error("Migration error (hwid):", err.message);
51
- }
52
- }
53
- });
54
- db.run("UPDATE users SET role = 'admin' WHERE username = 'admin'");
55
-
56
- // Bảng lưu lịch sử nạp tiền chờ duyệt
57
- db.run(`CREATE TABLE IF NOT EXISTS transactions (
58
- id INTEGER PRIMARY KEY AUTOINCREMENT,
59
- user_id INTEGER,
60
- username TEXT,
61
- amount INTEGER,
62
- method TEXT,
63
- status TEXT DEFAULT 'pending', -- pending, approved, rejected
64
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP
65
- )`);
66
-
67
- // Bảng log lịch sử sử dụng
68
- db.run(`CREATE TABLE IF NOT EXISTS usage_logs (
69
- id INTEGER PRIMARY KEY AUTOINCREMENT,
70
- user_id INTEGER,
71
- action TEXT,
72
- details TEXT,
73
- timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
74
- )`);
75
- });
76
-
77
- app.use(cors());
78
- app.use(bodyParser.json());
79
- app.use(express.static(path.join(__dirname, "public")));
80
-
81
- // --- MIDDLEWARE CHECK ADMIN ---
82
- const requireAdmin = (req, res, next) => {
83
- const apiKey = req.headers["x-api-key"];
84
- db.get("SELECT role FROM users WHERE api_key = ?", [apiKey], (err, row) => {
85
- if (row && row.role === "admin") next();
86
- else res.status(403).json({ error: "Bạn không phải Admin!" });
87
- });
88
- };
89
-
90
- // --- AUTH ---
91
- app.post("/api/register", (req, res) => {
92
- const { username, password, hwid } = req.body;
93
- const apiKey = uuidv4();
94
-
95
- // Kiểm tra xem HWID này đã được cộng tiền lần nào chưa
96
- db.get("SELECT id FROM users WHERE hwid = ?", [hwid], (err, row) => {
97
- const initialCredits = row ? 0 : 100; // Nếu đã tồn tại HWID thì 0, mới thì 10
98
- const message = row
99
- ? "Đăng ký thành công! (Máy này đã nhận bonus trước đó nên không được cộng thêm)"
100
- : "Đăng ký thành công! Bạn nhận được +100 Credits bonus.";
101
-
102
- const stmt = db.prepare(
103
- "INSERT INTO users (username, password, api_key, credits, role, hwid) VALUES (?, ?, ?, ?, 'user', ?)"
104
- );
105
- stmt.run(username, password, apiKey, initialCredits, hwid, function (err) {
106
- if (err) return res.status(400).json({ error: "User đã tồn tại" });
107
- res.json({ success: true, message: message });
108
- io.emit("admin:new-user");
109
- });
110
- stmt.finalize();
111
- });
112
- });
113
-
114
- app.post("/api/login", (req, res) => {
115
- const { username, password } = req.body;
116
- db.get(
117
- "SELECT * FROM users WHERE username = ? AND password = ?",
118
- [username, password],
119
- (err, row) => {
120
- if (!row) return res.status(401).json({ error: "Sai thông tin" });
121
- res.json({ success: true, user: row });
122
- }
123
- );
124
- });
125
-
126
- app.get("/api/me", (req, res) => {
127
- const apiKey = req.headers["x-api-key"];
128
- db.get(
129
- "SELECT username, credits, api_key, role FROM users WHERE api_key = ?",
130
- [apiKey],
131
- (err, row) => {
132
- if (row) res.json(row);
133
- else res.status(401).json({ error: "Key lỗi" });
134
- }
135
- );
136
- });
137
-
138
- // --- HISTORY API ---
139
- app.get("/api/history/usage", (req, res) => {
140
- const apiKey = req.headers["x-api-key"];
141
- db.get("SELECT id FROM users WHERE api_key = ?", [apiKey], (err, user) => {
142
- if (!user) return res.status(401).json({ error: "Auth failed" });
143
- db.all(
144
- "SELECT * FROM usage_logs WHERE user_id = ? ORDER BY id DESC LIMIT 50",
145
- [user.id],
146
- (err, rows) => {
147
- res.json(rows);
148
- }
149
- );
150
- });
151
- });
152
-
153
- app.get("/api/history/transactions", (req, res) => {
154
- const apiKey = req.headers["x-api-key"];
155
- db.get("SELECT id FROM users WHERE api_key = ?", [apiKey], (err, user) => {
156
- if (!user) return res.status(401).json({ error: "Auth failed" });
157
- db.all(
158
- "SELECT * FROM transactions WHERE user_id = ? ORDER BY id DESC",
159
- [user.id],
160
- (err, rows) => {
161
- res.json(rows);
162
- }
163
- );
164
- });
165
- });
166
-
167
- // --- USER: TẠO YÊU CẦU NẠP TIỀN ---
168
- app.post("/api/deposit", (req, res) => {
169
- const apiKey = req.headers["x-api-key"];
170
- const { amount, method } = req.body; // amount tính bằng USD (1, 5, 10)
171
-
172
- db.get(
173
- "SELECT id, username FROM users WHERE api_key = ?",
174
- [apiKey],
175
- (err, user) => {
176
- if (!user) return res.status(401).json({ error: "User không tồn tại" });
177
-
178
- const stmt = db.prepare(
179
- "INSERT INTO transactions (user_id, username, amount, method) VALUES (?, ?, ?, ?)"
180
- );
181
- stmt.run(user.id, user.username, amount, method, function (err) {
182
- if (err) return res.status(500).json({ error: "Lỗi tạo giao dịch" });
183
- res.json({
184
- success: true,
185
- message: "Đã gửi yêu cầu! Vui lòng đợi Admin duyệt.",
186
- });
187
- io.emit("admin:new-transaction"); // Notify admin
188
- });
189
- stmt.finalize();
190
- }
191
- );
192
- });
193
-
194
- // --- ADMIN API ---
195
-
196
- // 1. Lấy danh sách user
197
- app.get("/api/admin/users", requireAdmin, (req, res) => {
198
- db.all(
199
- "SELECT id, username, credits, role, api_key FROM users",
200
- [],
201
- (err, rows) => {
202
- res.json(rows);
203
- }
204
- );
205
- });
206
-
207
- // 2. Lấy danh sách giao dịch nạp tiền
208
- app.get("/api/admin/transactions", requireAdmin, (req, res) => {
209
- db.all("SELECT * FROM transactions ORDER BY id DESC", [], (err, rows) => {
210
- res.json(rows);
211
- });
212
- });
213
-
214
- // 3. Duyệt hoặc Từ chối nạp tiền
215
- app.post("/api/admin/approve", requireAdmin, (req, res) => {
216
- const { transId, action } = req.body; // action: 'approve' | 'reject'
217
-
218
- db.get("SELECT * FROM transactions WHERE id = ?", [transId], (err, trans) => {
219
- if (!trans || trans.status !== "pending")
220
- return res.status(400).json({ error: "Giao dịch không hợp lệ" });
221
-
222
- if (action === "reject") {
223
- db.run("UPDATE transactions SET status = 'rejected' WHERE id = ?", [
224
- transId,
225
- ]);
226
- io.emit("transaction-updated");
227
- return res.json({ success: true, message: "Đã từ chối giao dịch" });
228
- }
229
-
230
- if (action === "approve") {
231
- const creditsToAdd = trans.amount * 1000; // $1 = 1000 credits
232
- db.serialize(() => {
233
- db.run("UPDATE transactions SET status = 'approved' WHERE id = ?", [
234
- transId,
235
- ]);
236
- db.run("UPDATE users SET credits = credits + ? WHERE id = ?", [
237
- creditsToAdd,
238
- trans.user_id,
239
- ]);
240
- });
241
- return res.json({
242
- success: true,
243
- message: `Đã duyệt! Cộng ${creditsToAdd} credits cho ${trans.username}`,
244
- });
245
- io.emit("transaction-updated");
246
- // Notify specific user to update credits (client filters by checking if it's their update)
247
- io.emit("user:credit-update");
248
- }
249
- });
250
- });
251
-
252
- // 5. Xóa user
253
- app.post("/api/admin/delete-user", requireAdmin, (req, res) => {
254
- const { userId } = req.body;
255
- db.run("DELETE FROM users WHERE id = ?", [userId], function (err) {
256
- if (err) return res.status(500).json({ error: "Lỗi xóa user" });
257
- res.json({ success: true, message: "Đã xóa người dùng thành công." });
258
- io.emit("admin:user-deleted"); // Notify admin to refresh list
259
- });
260
- });
261
-
262
- // 4. Cộng/Trừ tiền thủ công cho user
263
- app.post("/api/admin/update-credits", requireAdmin, (req, res) => {
264
- const { userId, amount } = req.body; // amount có thể là số âm để trừ
265
- db.run(
266
- "UPDATE users SET credits = credits + ? WHERE id = ?",
267
- [amount, userId],
268
- function (err) {
269
- if (err) return res.status(500).json({ error: "Lỗi database" });
270
- res.json({ success: true, message: "Đã cập nhật số dư user." });
271
- io.emit("user:credit-update");
272
- }
273
- );
274
- });
275
-
276
- // --- CAPTCHA SOLVE QUEUE ---
277
- const solveQueue = [];
278
- let activeSolves = 0;
279
- const MAX_CONCURRENT_SOLVES = 3; // Tăng lên 3 vì đã tối ưu logging
280
-
281
- async function processQueue() {
282
- if (solveQueue.length === 0 || activeSolves >= MAX_CONCURRENT_SOLVES) {
283
- logger.updateStats(activeSolves, solveQueue.length);
284
- return;
285
- }
286
-
287
- activeSolves++;
288
- const { req, res, user, targetUrl, targetKey, action, proxy } = solveQueue.shift();
289
-
290
- logger.debug(`Processing request for ${user.username}. Active: ${activeSolves}/${MAX_CONCURRENT_SOLVES}`);
291
- logger.updateStats(activeSolves, solveQueue.length);
292
-
293
- const solver = new RecaptchaSolver();
294
- try {
295
- const token = await solver.getRecaptchaToken(
296
- targetUrl,
297
- targetKey,
298
- action || "homepage",
299
- proxy
300
- );
301
-
302
- if (token && !token.startsWith("ERROR")) {
303
- db.run("UPDATE users SET credits = credits - 1 WHERE id = ?", [user.id]);
304
- db.run(
305
- "INSERT INTO usage_logs (user_id, action, details) VALUES (?, ?, ?)",
306
- [user.id, "SOLVE_CAPTCHA", targetUrl]
307
- );
308
-
309
- res.json({ success: true, token: token });
310
- io.emit("user:credit-update");
311
- logger.debug(`Success for ${user.username}`);
312
- } else {
313
- res.status(500).json({ success: false, error: token });
314
- logger.warn(`Solver returned error for ${user.username}: ${token}`);
315
- }
316
- } catch (e) {
317
- res.status(500).json({ success: false, error: e.message });
318
- logger.error(`Catch error for ${user.username}: ${e.message}`);
319
- } finally {
320
- activeSolves--;
321
- logger.updateStats(activeSolves, solveQueue.length);
322
- processQueue();
323
- }
324
- }
325
-
326
- // --- API GIẢI CAPTCHA ---
327
- app.post("/api/solve", async (req, res) => {
328
- const { action, proxy } = req.body;
329
- const targetUrl = "https://labs.google";
330
- const targetKey = "6LdsFiUsAAAAAIjVDZcuLhaHiDn5nnHVXVRQGeMV";
331
- const apiKey = req.headers["x-api-key"];
332
-
333
- if (!apiKey) return res.status(401).json({ error: "Thiếu API Key" });
334
-
335
- db.get(
336
- "SELECT * FROM users WHERE api_key = ?",
337
- [apiKey],
338
- async (err, user) => {
339
- if (!user) return res.status(403).json({ error: "API Key không hợp lệ" });
340
- if (user.credits < 1) return res.status(402).json({ error: "Hết tiền, nạp thêm đi!" });
341
-
342
- solveQueue.push({ req, res, user, targetUrl, targetKey, action, proxy });
343
- logger.updateStats(activeSolves, solveQueue.length);
344
- processQueue();
345
- }
346
- );
347
- });
348
-
349
- const https = require("https");
350
- const fs = require("fs");
351
-
352
- electronApp.on("window-all-closed", (e) => e.preventDefault());
353
- electronApp.whenReady().then(() => {
354
- // 1. Start Default Port 3000
355
- server.listen(PORT, () =>
356
- console.log(`Server running at: http://localhost:${PORT}`)
357
- );
358
-
359
- // 2. Start HTTP Port 80
360
- try {
361
- const httpServer = http.createServer(app);
362
- io.attach(httpServer);
363
- httpServer.listen(80, () => console.log("HTTP Server running on port 80"));
364
- httpServer.on("error", (e) =>
365
- console.error("Error on Port 80:", e.message)
366
- );
367
- } catch (e) {
368
- console.error("Could not start HTTP server on port 80");
369
- }
370
-
371
- // 3. Start HTTPS Port 443
372
- const certPath = path.join(__dirname, "cert.pem");
373
- const keyPath = path.join(__dirname, "key.pem");
374
-
375
- if (fs.existsSync(certPath) && fs.existsSync(keyPath)) {
376
- try {
377
- const httpsServer = https.createServer(
378
- {
379
- key: fs.readFileSync(keyPath),
380
- cert: fs.readFileSync(certPath),
381
- },
382
- app
383
- );
384
- io.attach(httpsServer);
385
- httpsServer.listen(443, () =>
386
- console.log("HTTPS Server running on port 443")
387
- );
388
- httpsServer.on("error", (e) =>
389
- console.error("Error on Port 443:", e.message)
390
- );
391
- } catch (e) {
392
- console.error("Could not start HTTPS server on port 443");
393
- }
394
- } else {
395
- console.log(
396
- "No SSL certificates found (cert.pem, key.pem). Skipping HTTPS (443)."
397
- );
398
- }
399
- });
 
1
+ const { app: electronApp, session } = require("electron");
2
+
3
+ // Global Proxy Auth Handler
4
+ electronApp.on("login", (event, webContents, details, authInfo, callback) => {
5
+ if (authInfo.isProxy) {
6
+ const ses = webContents.session;
7
+ if (ses.proxyCredentials) {
8
+ logger.debug(`[Main] Providing credentials for proxy via app.on('login')`);
9
+ event.preventDefault();
10
+ callback(ses.proxyCredentials.username, ses.proxyCredentials.password);
11
+ }
12
+ }
13
+ });
14
+
15
+ const express = require("express");
16
+ const bodyParser = require("body-parser");
17
+ const cors = require("cors");
18
+ const sqlite3 = require("sqlite3");
19
+ const { v4: uuidv4 } = require("uuid");
20
+ const path = require("path");
21
+ const RecaptchaSolver = require("./solver");
22
+ const http = require("http");
23
+ const { Server } = require("socket.io");
24
+ const logger = require("./logger");
25
+
26
+ const PORT = 7860;
27
+ const app = express();
28
+ const server = http.createServer(app);
29
+ const io = new Server(server, {
30
+ cors: { origin: "*" },
31
+ });
32
+
33
+ const db = new sqlite3.Database("./database.sqlite");
34
+
35
+ // --- INIT DB ---
36
+ db.serialize(() => {
37
+ // Thêm cột role để phân quyền (admin/user)
38
+ db.run(`CREATE TABLE IF NOT EXISTS users (
39
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
40
+ username TEXT UNIQUE,
41
+ password TEXT,
42
+ api_key TEXT,
43
+ credits INTEGER DEFAULT 0,
44
+ role TEXT DEFAULT 'user',
45
+ hwid TEXT
46
+ )`);
47
+ db.run("ALTER TABLE users ADD COLUMN hwid TEXT", (err) => {
48
+ if (err) {
49
+ if (!err.message.includes("duplicate column name")) {
50
+ console.error("Migration error (hwid):", err.message);
51
+ }
52
+ }
53
+ });
54
+ db.run("UPDATE users SET role = 'admin' WHERE username = 'admin'");
55
+
56
+ // Bảng lưu lịch sử nạp tiền chờ duyệt
57
+ db.run(`CREATE TABLE IF NOT EXISTS transactions (
58
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
59
+ user_id INTEGER,
60
+ username TEXT,
61
+ amount INTEGER,
62
+ method TEXT,
63
+ status TEXT DEFAULT 'pending', -- pending, approved, rejected
64
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
65
+ )`);
66
+
67
+ // Bảng log lịch sử sử dụng
68
+ db.run(`CREATE TABLE IF NOT EXISTS usage_logs (
69
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
70
+ user_id INTEGER,
71
+ action TEXT,
72
+ details TEXT,
73
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
74
+ )`);
75
+ });
76
+
77
+ app.use(cors());
78
+ app.use(bodyParser.json());
79
+ app.use(express.static(path.join(__dirname, "public")));
80
+
81
+ // --- MIDDLEWARE CHECK ADMIN ---
82
+ const requireAdmin = (req, res, next) => {
83
+ const apiKey = req.headers["x-api-key"];
84
+ db.get("SELECT role FROM users WHERE api_key = ?", [apiKey], (err, row) => {
85
+ if (row && row.role === "admin") next();
86
+ else res.status(403).json({ error: "Bạn không phải Admin!" });
87
+ });
88
+ };
89
+
90
+ // --- AUTH ---
91
+ app.post("/api/register", (req, res) => {
92
+ const { username, password, hwid } = req.body;
93
+ const apiKey = uuidv4();
94
+
95
+ // Kiểm tra xem HWID này đã được cộng tiền lần nào chưa
96
+ db.get("SELECT id FROM users WHERE hwid = ?", [hwid], (err, row) => {
97
+ const initialCredits = row ? 0 : 100; // Nếu đã tồn tại HWID thì 0, mới thì 10
98
+ const message = row
99
+ ? "Đăng ký thành công! (Máy này đã nhận bonus trước đó nên không được cộng thêm)"
100
+ : "Đăng ký thành công! Bạn nhận được +100 Credits bonus.";
101
+
102
+ const stmt = db.prepare(
103
+ "INSERT INTO users (username, password, api_key, credits, role, hwid) VALUES (?, ?, ?, ?, 'user', ?)"
104
+ );
105
+ stmt.run(username, password, apiKey, initialCredits, hwid, function (err) {
106
+ if (err) return res.status(400).json({ error: "User đã tồn tại" });
107
+ res.json({ success: true, message: message });
108
+ io.emit("admin:new-user");
109
+ });
110
+ stmt.finalize();
111
+ });
112
+ });
113
+
114
+ app.post("/api/login", (req, res) => {
115
+ const { username, password } = req.body;
116
+ db.get(
117
+ "SELECT * FROM users WHERE username = ? AND password = ?",
118
+ [username, password],
119
+ (err, row) => {
120
+ if (!row) return res.status(401).json({ error: "Sai thông tin" });
121
+ res.json({ success: true, user: row });
122
+ }
123
+ );
124
+ });
125
+
126
+ app.get("/api/me", (req, res) => {
127
+ const apiKey = req.headers["x-api-key"];
128
+ db.get(
129
+ "SELECT username, credits, api_key, role FROM users WHERE api_key = ?",
130
+ [apiKey],
131
+ (err, row) => {
132
+ if (row) res.json(row);
133
+ else res.status(401).json({ error: "Key lỗi" });
134
+ }
135
+ );
136
+ });
137
+
138
+ // --- HISTORY API ---
139
+ app.get("/api/history/usage", (req, res) => {
140
+ const apiKey = req.headers["x-api-key"];
141
+ db.get("SELECT id FROM users WHERE api_key = ?", [apiKey], (err, user) => {
142
+ if (!user) return res.status(401).json({ error: "Auth failed" });
143
+ db.all(
144
+ "SELECT * FROM usage_logs WHERE user_id = ? ORDER BY id DESC LIMIT 50",
145
+ [user.id],
146
+ (err, rows) => {
147
+ res.json(rows);
148
+ }
149
+ );
150
+ });
151
+ });
152
+
153
+ app.get("/api/history/transactions", (req, res) => {
154
+ const apiKey = req.headers["x-api-key"];
155
+ db.get("SELECT id FROM users WHERE api_key = ?", [apiKey], (err, user) => {
156
+ if (!user) return res.status(401).json({ error: "Auth failed" });
157
+ db.all(
158
+ "SELECT * FROM transactions WHERE user_id = ? ORDER BY id DESC",
159
+ [user.id],
160
+ (err, rows) => {
161
+ res.json(rows);
162
+ }
163
+ );
164
+ });
165
+ });
166
+
167
+ // --- USER: TẠO YÊU CẦU NẠP TIỀN ---
168
+ app.post("/api/deposit", (req, res) => {
169
+ const apiKey = req.headers["x-api-key"];
170
+ const { amount, method } = req.body; // amount tính bằng USD (1, 5, 10)
171
+
172
+ db.get(
173
+ "SELECT id, username FROM users WHERE api_key = ?",
174
+ [apiKey],
175
+ (err, user) => {
176
+ if (!user) return res.status(401).json({ error: "User không tồn tại" });
177
+
178
+ const stmt = db.prepare(
179
+ "INSERT INTO transactions (user_id, username, amount, method) VALUES (?, ?, ?, ?)"
180
+ );
181
+ stmt.run(user.id, user.username, amount, method, function (err) {
182
+ if (err) return res.status(500).json({ error: "Lỗi tạo giao dịch" });
183
+ res.json({
184
+ success: true,
185
+ message: "Đã gửi yêu cầu! Vui lòng đợi Admin duyệt.",
186
+ });
187
+ io.emit("admin:new-transaction"); // Notify admin
188
+ });
189
+ stmt.finalize();
190
+ }
191
+ );
192
+ });
193
+
194
+ // --- ADMIN API ---
195
+
196
+ // 1. Lấy danh sách user
197
+ app.get("/api/admin/users", requireAdmin, (req, res) => {
198
+ db.all(
199
+ "SELECT id, username, credits, role, api_key FROM users",
200
+ [],
201
+ (err, rows) => {
202
+ res.json(rows);
203
+ }
204
+ );
205
+ });
206
+
207
+ // 2. Lấy danh sách giao dịch nạp tiền
208
+ app.get("/api/admin/transactions", requireAdmin, (req, res) => {
209
+ db.all("SELECT * FROM transactions ORDER BY id DESC", [], (err, rows) => {
210
+ res.json(rows);
211
+ });
212
+ });
213
+
214
+ // 3. Duyệt hoặc Từ chối nạp tiền
215
+ app.post("/api/admin/approve", requireAdmin, (req, res) => {
216
+ const { transId, action } = req.body; // action: 'approve' | 'reject'
217
+
218
+ db.get("SELECT * FROM transactions WHERE id = ?", [transId], (err, trans) => {
219
+ if (!trans || trans.status !== "pending")
220
+ return res.status(400).json({ error: "Giao dịch không hợp lệ" });
221
+
222
+ if (action === "reject") {
223
+ db.run("UPDATE transactions SET status = 'rejected' WHERE id = ?", [
224
+ transId,
225
+ ]);
226
+ io.emit("transaction-updated");
227
+ return res.json({ success: true, message: "Đã từ chối giao dịch" });
228
+ }
229
+
230
+ if (action === "approve") {
231
+ const creditsToAdd = trans.amount * 1000; // $1 = 1000 credits
232
+ db.serialize(() => {
233
+ db.run("UPDATE transactions SET status = 'approved' WHERE id = ?", [
234
+ transId,
235
+ ]);
236
+ db.run("UPDATE users SET credits = credits + ? WHERE id = ?", [
237
+ creditsToAdd,
238
+ trans.user_id,
239
+ ]);
240
+ });
241
+ return res.json({
242
+ success: true,
243
+ message: `Đã duyệt! Cộng ${creditsToAdd} credits cho ${trans.username}`,
244
+ });
245
+ io.emit("transaction-updated");
246
+ // Notify specific user to update credits (client filters by checking if it's their update)
247
+ io.emit("user:credit-update");
248
+ }
249
+ });
250
+ });
251
+
252
+ // 5. Xóa user
253
+ app.post("/api/admin/delete-user", requireAdmin, (req, res) => {
254
+ const { userId } = req.body;
255
+ db.run("DELETE FROM users WHERE id = ?", [userId], function (err) {
256
+ if (err) return res.status(500).json({ error: "Lỗi xóa user" });
257
+ res.json({ success: true, message: "Đã xóa người dùng thành công." });
258
+ io.emit("admin:user-deleted"); // Notify admin to refresh list
259
+ });
260
+ });
261
+
262
+ // 4. Cộng/Trừ tiền thủ công cho user
263
+ app.post("/api/admin/update-credits", requireAdmin, (req, res) => {
264
+ const { userId, amount } = req.body; // amount có thể là số âm để trừ
265
+ db.run(
266
+ "UPDATE users SET credits = credits + ? WHERE id = ?",
267
+ [amount, userId],
268
+ function (err) {
269
+ if (err) return res.status(500).json({ error: "Lỗi database" });
270
+ res.json({ success: true, message: "Đã cập nhật số dư user." });
271
+ io.emit("user:credit-update");
272
+ }
273
+ );
274
+ });
275
+
276
+ // --- CAPTCHA SOLVE QUEUE ---
277
+ const solveQueue = [];
278
+ let activeSolves = 0;
279
+ const MAX_CONCURRENT_SOLVES = 3; // Tăng lên 3 vì đã tối ưu logging
280
+
281
+ async function processQueue() {
282
+ if (solveQueue.length === 0 || activeSolves >= MAX_CONCURRENT_SOLVES) {
283
+ logger.updateStats(activeSolves, solveQueue.length);
284
+ return;
285
+ }
286
+
287
+ activeSolves++;
288
+ const { req, res, user, targetUrl, targetKey, action, proxy } = solveQueue.shift();
289
+
290
+ logger.debug(`Processing request for ${user.username}. Active: ${activeSolves}/${MAX_CONCURRENT_SOLVES}`);
291
+ logger.updateStats(activeSolves, solveQueue.length);
292
+
293
+ const solver = new RecaptchaSolver();
294
+ try {
295
+ const token = await solver.getRecaptchaToken(
296
+ targetUrl,
297
+ targetKey,
298
+ action || "homepage",
299
+ proxy
300
+ );
301
+
302
+ if (token && !token.startsWith("ERROR")) {
303
+ db.run("UPDATE users SET credits = credits - 1 WHERE id = ?", [user.id]);
304
+ db.run(
305
+ "INSERT INTO usage_logs (user_id, action, details) VALUES (?, ?, ?)",
306
+ [user.id, "SOLVE_CAPTCHA", targetUrl]
307
+ );
308
+
309
+ res.json({ success: true, token: token });
310
+ io.emit("user:credit-update");
311
+ logger.debug(`Success for ${user.username}`);
312
+ } else {
313
+ res.status(500).json({ success: false, error: token });
314
+ logger.warn(`Solver returned error for ${user.username}: ${token}`);
315
+ }
316
+ } catch (e) {
317
+ res.status(500).json({ success: false, error: e.message });
318
+ logger.error(`Catch error for ${user.username}: ${e.message}`);
319
+ } finally {
320
+ activeSolves--;
321
+ logger.updateStats(activeSolves, solveQueue.length);
322
+ processQueue();
323
+ }
324
+ }
325
+
326
+ // --- API GIẢI CAPTCHA ---
327
+ app.post("/api/solve", async (req, res) => {
328
+ const { action, proxy } = req.body;
329
+ const targetUrl = "https://labs.google";
330
+ const targetKey = "6LdsFiUsAAAAAIjVDZcuLhaHiDn5nnHVXVRQGeMV";
331
+ const apiKey = req.headers["x-api-key"];
332
+
333
+ if (!apiKey) return res.status(401).json({ error: "Thiếu API Key" });
334
+
335
+ db.get(
336
+ "SELECT * FROM users WHERE api_key = ?",
337
+ [apiKey],
338
+ async (err, user) => {
339
+ if (!user) return res.status(403).json({ error: "API Key không hợp lệ" });
340
+ if (user.credits < 1) return res.status(402).json({ error: "Hết tiền, nạp thêm đi!" });
341
+
342
+ solveQueue.push({ req, res, user, targetUrl, targetKey, action, proxy });
343
+ logger.updateStats(activeSolves, solveQueue.length);
344
+ processQueue();
345
+ }
346
+ );
347
+ });
348
+
349
+ const https = require("https");
350
+ const fs = require("fs");
351
+
352
+ electronApp.on("window-all-closed", (e) => e.preventDefault());
353
+ electronApp.whenReady().then(() => {
354
+ // 1. Start Default Port 3000
355
+ server.listen(PORT, () =>
356
+ console.log(`Server running at: http://localhost:${PORT}`)
357
+ );
358
+
359
+ // 2. Start HTTP Port 80
360
+ try {
361
+ const httpServer = http.createServer(app);
362
+ io.attach(httpServer);
363
+ httpServer.listen(80, () => console.log("HTTP Server running on port 80"));
364
+ httpServer.on("error", (e) =>
365
+ console.error("Error on Port 80:", e.message)
366
+ );
367
+ } catch (e) {
368
+ console.error("Could not start HTTP server on port 80");
369
+ }
370
+
371
+ // 3. Start HTTPS Port 443
372
+ const certPath = path.join(__dirname, "cert.pem");
373
+ const keyPath = path.join(__dirname, "key.pem");
374
+
375
+ if (fs.existsSync(certPath) && fs.existsSync(keyPath)) {
376
+ try {
377
+ const httpsServer = https.createServer(
378
+ {
379
+ key: fs.readFileSync(keyPath),
380
+ cert: fs.readFileSync(certPath),
381
+ },
382
+ app
383
+ );
384
+ io.attach(httpsServer);
385
+ httpsServer.listen(443, () =>
386
+ console.log("HTTPS Server running on port 443")
387
+ );
388
+ httpsServer.on("error", (e) =>
389
+ console.error("Error on Port 443:", e.message)
390
+ );
391
+ } catch (e) {
392
+ console.error("Could not start HTTPS server on port 443");
393
+ }
394
+ } else {
395
+ console.log(
396
+ "No SSL certificates found (cert.pem, key.pem). Skipping HTTPS (443)."
397
+ );
398
+ }
399
+ });