仰望星辰工作室

better-staridc-MNBT

better-staridc-MNBT/ admin/api/node.php 29.1 KB · 668 行 原始文件
Z zfhsh first commit 1 天前
1<?php
2$mnbt_admin_node_actions = [
3 'listnode',
4 'addnode',
5 'delnode',
6 'setnodestatus',
7 'nodeconfig',
8 'nodeping',
9 'nodeforbiddenscan',
10 'listnodetask',
11 'listforbiddenscan',
12 'listforbiddenmatch',
13 'nodestats',
14 'get_global_keywords',
15 'clearoldscans',
16 'savescancfg',
17 'nodeloglist',
18 'nodelogcontent',
19 'nodelogclear',
20 'nodeloglevel',
21 'nodelogstats',
22 'reset_sitestats',
23];
24if (!in_array($egn, $mnbt_admin_node_actions, true)) return;
25require_once ROOT . 'MPHX/node.function.php';
26mnbt_node_ensure_tables($DB);
27
28function mnbt_admin_node_exit($success, $msg, $extra = []) {
29 $data = array_merge([
30 'success' => (bool)$success,
31 'code' => $success ? 1 : 0,
32 'msg' => $msg,
33 ], $extra);
34 exit(json_encode($data, JSON_UNESCAPED_UNICODE));
35}
36
37function mnbt_admin_node_sort($sort, $allowed, $default) {
38 $sort = preg_replace('/[^a-zA-Z0-9_]/', '', (string)$sort);
39 return isset($allowed[$sort]) ? $allowed[$sort] : $allowed[$default];
40}
41
42function mnbt_admin_node_order($order) {
43 return strtoupper((string)$order) === 'DESC' ? 'DESC' : 'ASC';
44}
45
46function mnbt_admin_node_row($DB, $id) {
47 return $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `id`=? LIMIT 1", [(int)$id]);
48}
49
50function mnbt_admin_node_site_url() {
51 $url = trim((string)($_POST['mnbt_url'] ?? ''));
52 return $url === '' ? mnbt_node_default_base_url() : rtrim($url, '/');
53}
54
55function mnbt_admin_node_keywords($text) {
56 $text = str_replace(["\r\n", "\r", ";", "\xEF\xBC\x9B", "\xEF\xBC\x8C"], "\n", (string)$text);
57 $parts = preg_split('/[\n,]+/', $text);
58 $keywords = [];
59 foreach ($parts as $part) {
60 $part = trim($part);
61 if ($part !== '' && !in_array($part, $keywords, true)) $keywords[] = $part;
62 }
63 return $keywords;
64}
65
66function mnbt_admin_node_log($user, $title, $content, $DB) {
67 if (function_exists('logjl')) logjl($user, $title, $content, '操作成功', $DB);
68}
69
70if($egn=='listnode') {
71 $limit = max(1, min(100, (int)($_POST['limit'] ?? 10)));
72 $page = max(1, (int)($_POST['page'] ?? 1));
73 $offset = ($page - 1) * $limit;
74 $sortMap = [
75 'id' => 'n.id',
76 'node_id' => 'n.node_id',
77 'node_name' => 'n.node_name',
78 'bt_id' => 'n.bt_id',
79 'status' => 'n.status',
80 'enabled' => 'n.enabled',
81 'ip' => 'n.ip',
82 'version' => 'n.version',
83 'last_heartbeat' => 'n.last_heartbeat',
84 'created_at' => 'n.created_at',
85 'updated_at' => 'n.updated_at',
86 ];
87 $sort = mnbt_admin_node_sort($_POST['sort'] ?? 'id', $sortMap, 'id');
88 $order = mnbt_admin_node_order($_POST['sortOrder'] ?? 'DESC');
89 $keyword = trim((string)($_POST['keyword'] ?? ''));
90 $status = trim((string)($_POST['status'] ?? ''));
91 $where = 'WHERE 1';
92 $params = [];
93 if ($keyword !== '') {
94 $where .= " AND (n.node_id LIKE ? OR n.node_name LIKE ? OR n.ip LIKE ? OR b.btdh LIKE ? OR b.btip LIKE ?)";
95 $like = '%' . $keyword . '%';
96 array_push($params, $like, $like, $like, $like, $like);
97 }
98 if ($status === 'enabled') {
99 $where .= " AND n.enabled='true'";
100 } elseif ($status === 'disabled') {
101 $where .= " AND n.enabled='false'";
102 }
103 $total = $DB->count_prepare("SELECT count(*) FROM `MN_node` n LEFT JOIN `MN_bt` b ON n.bt_id=b.id {$where}", $params);
104 $rows = $DB->get_all_prepare("SELECT n.*, b.btdh, b.btip FROM `MN_node` n LEFT JOIN `MN_bt` b ON n.bt_id=b.id {$where} ORDER BY {$sort} {$order} LIMIT {$offset},{$limit}", $params);
105 if (!is_array($rows)) $rows = [];
106 foreach ($rows as &$row) {
107 $row['display_status'] = mnbt_node_effective_status($row);
108 $row['capabilities_text'] = implode(', ', mnbt_node_normalize_json($row['capabilities'] ?? '[]'));
109 }
110 unset($row);
111 exit(json_encode(['total' => (int)$total, 'rows' => $rows], JSON_UNESCAPED_UNICODE));
112}
113
114if($egn=='addnode') {
115 $btId = (int)($_POST['bt_id'] ?? 0);
116 if ($btId <= 0) mnbt_admin_node_exit(false, '请选择要绑定的宝塔服务器');
117 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [$btId]);
118 if (!$bt) mnbt_admin_node_exit(false, '宝塔服务器不存在');
119 $nodeName = trim((string)($_POST['node_name'] ?? ''));
120 if ($nodeName === '') $nodeName = (string)($bt['btdh'] ?? ('node-' . $btId));
121 $nodeId = trim((string)($_POST['node_id'] ?? ''));
122 if ($nodeId !== '' && !preg_match('/^[a-zA-Z0-9_.:-]{1,64}$/', $nodeId)) {
123 mnbt_admin_node_exit(false, '节点ID只能包含字母、数字、点、横线、下划线和冒号,最长64位');
124 }
125 if ($nodeId !== '' && $DB->get_row_prepare("SELECT id FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId])) {
126 mnbt_admin_node_exit(false, '节点ID已存在,请更换或直接复制原节点配置');
127 }
128 $registered = mnbt_node_register($DB, $btId, $nodeName, $nodeId);
129 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$registered['node_id']]);
130 $config = mnbt_node_admin_config($conf, $node, mnbt_admin_node_site_url(), (int)($_POST['interval_seconds'] ?? 10));
131 mnbt_admin_node_log($user, '节点管理', '新增节点 '.$registered['node_id'], $DB);
132 mnbt_admin_node_exit(true, '新增节点成功', [
133 'id' => (int)($node['id'] ?? 0),
134 'node_id' => $registered['node_id'],
135 'config' => $config,
136 'config_json' => json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
137 ]);
138}
139
140if($egn=='delnode') {
141 $id = (int)($_POST['id'] ?? 0);
142 $node = mnbt_admin_node_row($DB, $id);
143 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
144 $nodeId = $node['node_id'];
145 $DB->query_prepare("DELETE FROM `MN_node_task` WHERE `node_id`=?", [$nodeId]);
146 $DB->query_prepare("DELETE FROM `MN_node_nonce` WHERE `node_id`=?", [$nodeId]);
147 $DB->query_prepare("DELETE FROM `MN_forbidden_scan` WHERE `node_id`=?", [$nodeId]);
148 $DB->query_prepare("DELETE FROM `MN_forbidden_match` WHERE `node_id`=?", [$nodeId]);
149 $ok = $DB->query_prepare("DELETE FROM `MN_node` WHERE `id`=? LIMIT 1", [$id]);
150 if ($ok && $DB->affected() > 0) {
151 mnbt_admin_node_log($user, '节点管理', '删除节点 '.$nodeId, $DB);
152 mnbt_admin_node_exit(true, '删除成功');
153 }
154 mnbt_admin_node_exit(false, '删除失败'.$DB->error());
155}
156
157if($egn=='setnodestatus') {
158 $id = (int)($_POST['id'] ?? 0);
159 $node = mnbt_admin_node_row($DB, $id);
160 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
161 $enabled = (($_POST['enabled'] ?? 'true') === 'true') ? 'true' : 'false';
162 $status = $enabled === 'true' ? 'offline' : 'disabled';
163 $ok = $DB->query_prepare("UPDATE `MN_node` SET `enabled`=?, `status`=?, `updated_at`=? WHERE `id`=?", [$enabled, $status, date('Y-m-d H:i:s'), $id]);
164 if ($ok && $DB->affected() > 0) {
165 mnbt_admin_node_log($user, '节点管理', ($enabled === 'true' ? '启用节点 ' : '停用节点 ').$node['node_id'], $DB);
166 mnbt_admin_node_exit(true, $enabled === 'true' ? '启用成功' : '停用成功');
167 }
168 mnbt_admin_node_exit(false, '操作失败'.$DB->error());
169}
170
171if($egn=='nodeconfig') {
172 $id = (int)($_POST['id'] ?? 0);
173 $node = mnbt_admin_node_row($DB, $id);
174 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
175 $config = mnbt_node_admin_config($conf, $node, mnbt_admin_node_site_url(), (int)($_POST['interval_seconds'] ?? 10));
176 mnbt_admin_node_exit(true, '获取成功', [
177 'config' => $config,
178 'config_json' => json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
179 ]);
180}
181
182if($egn=='nodeping') {
183 $id = (int)($_POST['id'] ?? 0);
184 $node = mnbt_admin_node_row($DB, $id);
185 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
186 if (($node['enabled'] ?? 'true') !== 'true') mnbt_admin_node_exit(false, '节点已停用,不能下发任务');
187 $taskId = mnbt_node_create_task($DB, $node['node_id'], 'ping', [
188 'created_by' => 'admin',
189 'created_at' => date('Y-m-d H:i:s'),
190 ]);
191 mnbt_admin_node_log($user, '节点管理', '下发Ping任务 '.$taskId, $DB);
192 mnbt_admin_node_exit(true, 'Ping任务已下发', ['task_id' => $taskId]);
193}
194
195if($egn=='nodeforbiddenscan') {
196 $id = (int)($_POST['id'] ?? 0);
197 $node = mnbt_admin_node_row($DB, $id);
198 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
199 if (($node['enabled'] ?? 'true') !== 'true') mnbt_admin_node_exit(false, '节点已停用,不能下发任务');
200 $root = trim((string)($_POST['root'] ?? ''));
201 if ($root === '') mnbt_admin_node_exit(false, '请填写扫描目录');
202 $keywords = mnbt_admin_node_keywords($_POST['keywords'] ?? '');
203 if (empty($keywords)) mnbt_admin_node_exit(false, '请填写违禁词');
204 $site = trim((string)($_POST['site'] ?? ''));
205 $maxFileSizeMb = max(1, min(50, (int)($_POST['max_file_size_mb'] ?? 5)));
206 $maxMatches = max(1, min(5000, (int)($_POST['max_matches'] ?? 1000)));
207 $taskId = mnbt_node_create_task($DB, $node['node_id'], 'forbidden_scan', [
208 'site' => $site,
209 'root' => $root,
210 'keywords' => $keywords,
211 'max_file_size' => $maxFileSizeMb * 1024 * 1024,
212 'max_matches' => $maxMatches,
213 'scan_changed_only' => false,
214 'scan_mode' => 'full',
215 ]);
216 mnbt_admin_node_log($user, '节点管理', '下发违禁词扫描任务 '.$taskId, $DB);
217 mnbt_admin_node_exit(true, '违禁词扫描任务已下发', ['task_id' => $taskId]);
218}
219
220if($egn=='listnodetask') {
221 $limit = max(1, min(100, (int)($_POST['limit'] ?? 10)));
222 $page = max(1, (int)($_POST['page'] ?? 1));
223 $offset = ($page - 1) * $limit;
224 $sortMap = [
225 'id' => 'id',
226 'task_id' => 'task_id',
227 'node_id' => 'node_id',
228 'action' => 'action',
229 'status' => 'status',
230 'created_at' => 'created_at',
231 'updated_at' => 'updated_at',
232 'finished_at' => 'finished_at',
233 ];
234 $sort = mnbt_admin_node_sort($_POST['sort'] ?? 'id', $sortMap, 'id');
235 $order = mnbt_admin_node_order($_POST['sortOrder'] ?? 'DESC');
236 $where = 'WHERE 1';
237 $params = [];
238
239 // 节点筛选
240 $id = (int)($_POST['node_pk'] ?? 0);
241 if ($id > 0) {
242 $node = mnbt_admin_node_row($DB, $id);
243 if ($node) {
244 $where .= ' AND `node_id`=?';
245 $params[] = $node['node_id'];
246 }
247 }
248
249 // 状态筛选
250 $status = trim((string)($_POST['status'] ?? ''));
251 if ($status === 'pending' || $status === 'running' || $status === 'success' || $status === 'failed') {
252 $where .= ' AND `status`=?';
253 $params[] = $status;
254 }
255
256 // 任务类型筛选
257 $action = trim((string)($_POST['action'] ?? ''));
258 if ($action === 'ping' || $action === 'forbidden_scan') {
259 $where .= ' AND `action`=?';
260 $params[] = $action;
261 }
262
263 $total = $DB->count_prepare("SELECT count(*) FROM `MN_node_task` {$where}", $params);
264 $rows = $DB->get_all_prepare("SELECT * FROM `MN_node_task` {$where} ORDER BY {$sort} {$order} LIMIT {$offset},{$limit}", $params);
265 if (!is_array($rows)) $rows = [];
266 foreach ($rows as &$row) {
267 $payload = mnbt_node_normalize_json($row['payload'] ?? '');
268 $result = mnbt_node_normalize_json($row['result'] ?? '');
269 $row['payload_text'] = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
270 $row['result_text'] = json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
271 }
272 unset($row);
273 exit(json_encode(['total' => (int)$total, 'rows' => $rows], JSON_UNESCAPED_UNICODE));
274}
275
276if($egn=='listforbiddenscan') {
277 $limit = max(1, min(100, (int)($_POST['limit'] ?? 10)));
278 $page = max(1, (int)($_POST['page'] ?? 1));
279 $offset = ($page - 1) * $limit;
280 $sortMap = [
281 'id' => 'id',
282 'task_id' => 'task_id',
283 'node_id' => 'node_id',
284 'site' => 'site',
285 'status' => 'status',
286 'matches_count' => 'matches_count',
287 'created_at' => 'created_at',
288 'updated_at' => 'updated_at',
289 ];
290 $sort = mnbt_admin_node_sort($_POST['sort'] ?? 'id', $sortMap, 'id');
291 $order = mnbt_admin_node_order($_POST['sortOrder'] ?? 'DESC');
292 $where = 'WHERE 1';
293 $params = [];
294
295 // 节点筛选
296 $id = (int)($_POST['node_pk'] ?? 0);
297 if ($id > 0) {
298 $node = mnbt_admin_node_row($DB, $id);
299 if ($node) {
300 $where .= ' AND `node_id`=?';
301 $params[] = $node['node_id'];
302 }
303 }
304
305 // 时间筛选
306 $timeFilter = trim((string)($_POST['time_filter'] ?? ''));
307 if ($timeFilter === 'today') {
308 $where .= ' AND DATE(created_at)=?';
309 $params[] = date('Y-m-d');
310 } elseif ($timeFilter === 'yesterday') {
311 $where .= ' AND DATE(created_at)=?';
312 $params[] = date('Y-m-d', strtotime('-1 day'));
313 } elseif ($timeFilter === 'week') {
314 $where .= ' AND created_at >= ?';
315 $params[] = date('Y-m-d', strtotime('-7 days'));
316 } elseif ($timeFilter === 'month') {
317 $where .= ' AND created_at >= ?';
318 $params[] = date('Y-m-d', strtotime('-30 days'));
319 }
320
321 // 状态筛选
322 $statusFilter = trim((string)($_POST['status_filter'] ?? ''));
323 if ($statusFilter === 'success') {
324 $where .= ' AND `status`=?';
325 $params[] = 'success';
326 } elseif ($statusFilter === 'failed') {
327 $where .= ' AND `status`=?';
328 $params[] = 'failed';
329 } elseif ($statusFilter === 'has_matches') {
330 $where .= ' AND matches_count > 0';
331 }
332
333 $total = $DB->count_prepare("SELECT count(*) FROM `MN_forbidden_scan` {$where}", $params);
334 $rows = $DB->get_all_prepare("SELECT * FROM `MN_forbidden_scan` {$where} ORDER BY {$sort} {$order} LIMIT {$offset},{$limit}", $params);
335 if (!is_array($rows)) $rows = [];
336 exit(json_encode(['total' => (int)$total, 'rows' => $rows], JSON_UNESCAPED_UNICODE));
337}
338
339if($egn=='listforbiddenmatch') {
340 $limit = max(1, min(100, (int)($_POST['limit'] ?? 10)));
341 $page = max(1, (int)($_POST['page'] ?? 1));
342 $offset = ($page - 1) * $limit;
343 $taskId = trim((string)($_POST['task_id'] ?? ''));
344 $where = 'WHERE 1';
345 $params = [];
346 if ($taskId !== '') {
347 $where .= ' AND `task_id`=?';
348 $params[] = $taskId;
349 }
350 $total = $DB->count_prepare("SELECT count(*) FROM `MN_forbidden_match` {$where}", $params);
351 $rows = $DB->get_all_prepare("SELECT * FROM `MN_forbidden_match` {$where} ORDER BY id DESC LIMIT {$offset},{$limit}", $params);
352 if (!is_array($rows)) $rows = [];
353 exit(json_encode(['total' => (int)$total, 'rows' => $rows], JSON_UNESCAPED_UNICODE));
354}
355
356// 获取统计数据
357if($egn=='nodestats') {
358 $now = date('Y-m-d');
359 $yesterday = date('Y-m-d', strtotime('-1 day'));
360
361 // 节点统计
362 $totalNodes = $DB->count_prepare("SELECT COUNT(*) FROM `MN_node`", []);
363 $onlineNodes = 0;
364 $offlineNodes = 0;
365 $nodes = $DB->get_all_prepare("SELECT * FROM `MN_node`", []);
366 if (is_array($nodes)) {
367 foreach ($nodes as $node) {
368 $status = mnbt_node_effective_status($node);
369 if ($status === 'online') $onlineNodes++;
370 else $offlineNodes++;
371 }
372 }
373
374 // 今日命中统计
375 $todayMatches = $DB->count_prepare("SELECT SUM(matches_count) FROM `MN_forbidden_scan` WHERE DATE(created_at)=?", [$now]) ?: 0;
376
377 // 待处理任务统计
378 $pendingTasks = $DB->count_prepare("SELECT COUNT(*) FROM `MN_node_task` WHERE `status`='pending'", []);
379
380 mnbt_admin_node_exit(true, 'ok', [
381 'data' => [
382 'total_nodes' => (int)$totalNodes,
383 'online' => (int)$onlineNodes,
384 'offline' => (int)$offlineNodes,
385 'today_matches' => (int)$todayMatches,
386 'pending_tasks' => (int)$pendingTasks,
387 ]
388 ]);
389}
390
391// 获取全局违禁词配置
392if($egn=='get_global_keywords') {
393 global $conf;
394 $content = $conf['wjsccnr'] ?? '';
395 $keywords = [];
396 if ($content) {
397 $lines = preg_split('/[\r\n]+/', $content);
398 foreach ($lines as $line) {
399 $line = trim($line);
400 if ($line && strpos($line, '#') !== 0) {
401 $keywords[] = $line;
402 }
403 }
404 }
405 mnbt_admin_node_exit(true, 'ok', [
406 'data' => implode("\n", $keywords)
407 ]);
408}
409
410// 清理旧扫描记录
411if($egn=='clearoldscans') {
412 $days = (int)($_POST['days'] ?? 7);
413 if ($days < 1) $days = 7;
414 if ($days > 365) $days = 365;
415 $cutoffDate = date('Y-m-d H:i:s', strtotime('-'.$days.' days'));
416
417 // 先查出要清理的 task_id,避免不同 MySQL 版本对子查询删除支持不一致
418 $oldScans = $DB->get_all_prepare("SELECT task_id FROM `MN_forbidden_scan` WHERE `created_at` < ?", [$cutoffDate]);
419 if (!is_array($oldScans) || count($oldScans) === 0) {
420 mnbt_admin_node_exit(true, $days.'天前没有可清理的扫描记录', [
421 'deleted_scans' => 0,
422 'deleted_matches' => 0,
423 'deleted_tasks' => 0,
424 ]);
425 }
426
427 $deletedScans = 0;
428 $deletedMatches = 0;
429 $deletedTasks = 0;
430 foreach ($oldScans as $scan) {
431 $taskId = (string)($scan['task_id'] ?? '');
432 if ($taskId === '') continue;
433
434 $matchCount = $DB->count_prepare("SELECT COUNT(*) FROM `MN_forbidden_match` WHERE `task_id`=?", [$taskId]);
435 $DB->query_prepare("DELETE FROM `MN_forbidden_match` WHERE `task_id`=?", [$taskId]);
436 $deletedMatches += (int)$matchCount;
437
438 $DB->query_prepare("DELETE FROM `MN_forbidden_scan` WHERE `task_id`=?", [$taskId]);
439 $deletedScans++;
440
441 // 同步清理对应的节点任务日志,避免任务列表里还显示旧扫描任务
442 $taskCount = $DB->count_prepare("SELECT COUNT(*) FROM `MN_node_task` WHERE `task_id`=? AND `action`='forbidden_scan'", [$taskId]);
443 $DB->query_prepare("DELETE FROM `MN_node_task` WHERE `task_id`=? AND `action`='forbidden_scan'", [$taskId]);
444 $deletedTasks += (int)$taskCount;
445 }
446
447 mnbt_admin_node_exit(true, '清理完成:扫描记录 '.$deletedScans.' 条,命中记录 '.$deletedMatches.' 条,任务记录 '.$deletedTasks.' 条', [
448 'deleted_scans' => $deletedScans,
449 'deleted_matches' => $deletedMatches,
450 'deleted_tasks' => $deletedTasks,
451 ]);
452}
453
454if($egn=='savescancfg') {
455 $skg = ($_POST['skg'] ?? 'false') === 'true' ? 'true' : 'false';
456 $snr = (string)($_POST['snr'] ?? '');
457 $sgbfx = ($_POST['sgbfx'] ?? 'true') === 'true' ? 'true' : 'false';
458 $sml = trim((string)($_POST['sml'] ?? '/www/wwwroot'));
459 $stqml = trim((string)($_POST['stqml'] ?? '.git,node_modules,vendor,runtime,cache,logs'));
460 $stqhz = trim((string)($_POST['stqhz'] ?? '.jpg,.png,.gif,.webp,.mp4,.zip,.rar,.7z,.pdf,.woff,.ttf'));
461 $sdzmax = max(1, (int)($_POST['sdzmax'] ?? 5)) * 1024 * 1024;
462 $sdhmax = max(1, (int)($_POST['sdhmax'] ?? 1000));
463 $sqzcskg = ($_POST['sqzcskg'] ?? 'true') === 'true' ? 'true' : 'false';
464 $sqzcs = trim((string)($_POST['sqzcs'] ?? '0 3 * * *'));
465
466 $currentKg = $conf['wjsckg'] ?? 'false';
467 $wasDisabled = ($currentKg !== 'true');
468 $isNowEnabled = ($skg === 'true');
469
470 if (function_exists('logjl')) logjl($user, '违禁词扫描设置', '对违禁词扫描设置进行了修改', '修改成功', $DB);
471
472 $sql = "UPDATE `MN_config` SET `wjsckg` = ?, `wjsccnr` = ?, `wjsckgqbfx` = ?, `wjscml` = ?, `wjstqml` = ?, `wjstqhz` = ?, `wjscdzmax` = ?, `wjscdhmax` = ?, `wjscqzcskg` = ?, `wjscqzcs` = ? WHERE `id` = 1";
473 if(!$DB->query_prepare($sql, [$skg, $snr, $sgbfx, $sml, $stqml, $stqhz, $sdzmax, $sdhmax, $sqzcskg, $sqzcs])) {
474 mnbt_admin_node_exit(false, '数据库操作失败请联系开发人员判断错误');
475 }
476
477 if($wasDisabled && $isNowEnabled) {
478 $keywords = [];
479 if($snr) {
480 $lines = preg_split('/[\r\n]+/', $snr);
481 foreach($lines as $line) {
482 $line = trim($line);
483 if($line && strpos($line, '#') !== 0) $keywords[] = $line;
484 }
485 }
486 if(!empty($keywords)) {
487 $nodes = $DB->get_all_prepare("SELECT * FROM `MN_node` WHERE `enabled`='true'", []);
488 if(!$nodes) $nodes = [];
489 $triggeredCount = 0;
490 foreach($nodes as $node) {
491 try {
492 mnbt_node_create_task($DB, $node['node_id'], 'forbidden_scan', [
493 'site' => '',
494 'root' => $sml,
495 'keywords' => $keywords,
496 'max_file_size' => $sdzmax,
497 'max_matches' => $sdhmax,
498 'scan_changed_only' => false,
499 'scan_mode' => 'full',
500 'auto_trigger' => true,
501 'trigger_reason' => '扫描开关已开启',
502 ]);
503 $triggeredCount++;
504 } catch(Exception $e) {}
505 }
506 if($triggeredCount > 0) {
507 mnbt_admin_node_exit(true, '修改成功,已向 '.$triggeredCount.' 个节点下发全量扫描任务');
508 }
509 }
510 }
511
512 mnbt_admin_node_exit(true, '修改成功');
513}
514
515if($egn=='nodeloglist') {
516 $nodeId = trim((string)($_POST['node_id'] ?? ''));
517 if ($nodeId === '') mnbt_admin_node_exit(false, '缺少节点ID');
518 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId]);
519 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
520 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [(int)($node['bt_id'] ?? 0)]);
521 if (!$bt) mnbt_admin_node_exit(false, '节点未绑定宝塔面板');
522 try {
523 $btApi = new bt_api($bt['panel'], $bt['btkey']);
524 $result = $btApi->pluginRequest('mnbt_connector', 'get_log_list', []);
525 if (!is_array($result) || !($result['status'] ?? false)) {
526 mnbt_admin_node_exit(false, '获取日志列表失败:' . ($result['msg'] ?? '未知错误'));
527 }
528 mnbt_admin_node_exit(true, '获取成功', ['data' => $result['data'] ?? [], 'total_count' => $result['total_count'] ?? 0]);
529 } catch(Exception $e) {
530 mnbt_admin_node_exit(false, '连接节点失败:' . $e->getMessage());
531 }
532}
533
534if($egn=='nodelogcontent') {
535 $nodeId = trim((string)($_POST['node_id'] ?? ''));
536 $logFile = trim((string)($_POST['log_file'] ?? ''));
537 $offset = max(0, (int)($_POST['offset'] ?? 0));
538 $limit = max(1000, min(500000, (int)($_POST['limit'] ?? 50000)));
539 $keyword = trim((string)($_POST['keyword'] ?? ''));
540 $level = trim((string)($_POST['level'] ?? ''));
541 if ($nodeId === '') mnbt_admin_node_exit(false, '缺少节点ID');
542 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId]);
543 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
544 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [(int)($node['bt_id'] ?? 0)]);
545 if (!$bt) mnbt_admin_node_exit(false, '节点未绑定宝塔面板');
546 try {
547 $btApi = new bt_api($bt['panel'], $bt['btkey']);
548 $result = $btApi->pluginRequest('mnbt_connector', 'get_log_content', [
549 'file' => $logFile,
550 'offset' => $offset,
551 'limit' => $limit,
552 'keyword' => $keyword,
553 'level' => $level,
554 ]);
555 if (!is_array($result) || !($result['status'] ?? false)) {
556 mnbt_admin_node_exit(false, '获取日志内容失败:' . ($result['msg'] ?? '未知错误'));
557 }
558 mnbt_admin_node_exit(true, '获取成功', [
559 'data' => $result['data'] ?? [],
560 'total_lines' => $result['total_lines'] ?? 0,
561 'file_size' => $result['file_size'] ?? 0,
562 'current_offset' => $result['current_offset'] ?? 0,
563 'has_more' => $result['has_more'] ?? false,
564 ]);
565 } catch(Exception $e) {
566 mnbt_admin_node_exit(false, '连接节点失败:' . $e->getMessage());
567 }
568}
569
570if($egn=='nodelogclear') {
571 $nodeId = trim((string)($_POST['node_id'] ?? ''));
572 $logFile = trim((string)($_POST['log_file'] ?? ''));
573 if ($nodeId === '') mnbt_admin_node_exit(false, '缺少节点ID');
574 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId]);
575 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
576 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [(int)($node['bt_id'] ?? 0)]);
577 if (!$bt) mnbt_admin_node_exit(false, '节点未绑定宝塔面板');
578 try {
579 $btApi = new bt_api($bt['panel'], $bt['btkey']);
580 $result = $btApi->pluginRequest('mnbt_connector', 'clear_log', ['file' => $logFile]);
581 if (!is_array($result) || !($result['status'] ?? false)) {
582 mnbt_admin_node_exit(false, '清空日志失败:' . ($result['msg'] ?? '未知错误'));
583 }
584 if (function_exists('logjl')) logjl($user, '节点日志', '清空节点 '.$nodeId.' 日志', '操作成功', $DB);
585 mnbt_admin_node_exit(true, $result['msg'] ?? '清空成功');
586 } catch(Exception $e) {
587 mnbt_admin_node_exit(false, '连接节点失败:' . $e->getMessage());
588 }
589}
590
591if($egn=='nodeloglevel') {
592 $nodeId = trim((string)($_POST['node_id'] ?? ''));
593 $level = trim((string)($_POST['level'] ?? ''));
594 if ($nodeId === '') mnbt_admin_node_exit(false, '缺少节点ID');
595 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId]);
596 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
597 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [(int)($node['bt_id'] ?? 0)]);
598 if (!$bt) mnbt_admin_node_exit(false, '节点未绑定宝塔面板');
599 try {
600 $btApi = new bt_api($bt['panel'], $bt['btkey']);
601 if ($level !== '') {
602 if (!in_array($level, ['DEBUG', 'INFO', 'WARNING', 'ERROR'], true)) {
603 mnbt_admin_node_exit(false, '无效的日志级别');
604 }
605 $result = $btApi->pluginRequest('mnbt_connector', 'set_log_level', ['level' => $level]);
606 if (!is_array($result) || !($result['status'] ?? false)) {
607 mnbt_admin_node_exit(false, '设置日志级别失败:' . ($result['msg'] ?? '未知错误'));
608 }
609 if (function_exists('logjl')) logjl($user, '节点日志', '设置节点 '.$nodeId.' 日志级别为 '.$level, '操作成功', $DB);
610 mnbt_admin_node_exit(true, $result['msg'] ?? '设置成功');
611 } else {
612 $result = $btApi->pluginRequest('mnbt_connector', 'get_log_level', []);
613 if (!is_array($result) || !($result['status'] ?? false)) {
614 mnbt_admin_node_exit(false, '获取日志级别失败:' . ($result['msg'] ?? '未知错误'));
615 }
616 mnbt_admin_node_exit(true, '获取成功', [
617 'level' => $result['level'] ?? 'INFO',
618 'available_levels' => $result['available_levels'] ?? [],
619 ]);
620 }
621 } catch(Exception $e) {
622 mnbt_admin_node_exit(false, '连接节点失败:' . $e->getMessage());
623 }
624}
625
626if($egn=='nodelogstats') {
627 $nodeId = trim((string)($_POST['node_id'] ?? ''));
628 $logFile = trim((string)($_POST['log_file'] ?? ''));
629 if ($nodeId === '') mnbt_admin_node_exit(false, '缺少节点ID');
630 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId]);
631 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
632 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [(int)($node['bt_id'] ?? 0)]);
633 if (!$bt) mnbt_admin_node_exit(false, '节点未绑定宝塔面板');
634 try {
635 $btApi = new bt_api($bt['panel'], $bt['btkey']);
636 $result = $btApi->pluginRequest('mnbt_connector', 'get_worker_log_stats', ['file' => $logFile]);
637 if (!is_array($result) || !($result['status'] ?? false)) {
638 mnbt_admin_node_exit(false, '获取日志统计失败:' . ($result['msg'] ?? '未知错误'));
639 }
640 mnbt_admin_node_exit(true, '获取成功', ['data' => $result['data'] ?? []]);
641 } catch(Exception $e) {
642 mnbt_admin_node_exit(false, '连接节点失败:' . $e->getMessage());
643 }
644}
645
646if($egn=='reset_sitestats') {
647 $nodeId = trim((string)($_POST['node_id'] ?? ''));
648 $site = trim((string)($_POST['site'] ?? ''));
649 if ($nodeId === '') mnbt_admin_node_exit(false, '缺少节点ID');
650 if ($site === '') mnbt_admin_node_exit(false, '缺少站点名称');
651 $node = $DB->get_row_prepare("SELECT * FROM `MN_node` WHERE `node_id`=? LIMIT 1", [$nodeId]);
652 if (!$node) mnbt_admin_node_exit(false, '节点不存在');
653 $bt = $DB->get_row_prepare("SELECT * FROM `MN_bt` WHERE `id`=? LIMIT 1", [(int)($node['bt_id'] ?? 0)]);
654 if (!$bt) mnbt_admin_node_exit(false, '节点未绑定宝塔面板');
655 try {
656 $btApi = new bt_api($bt['panel'], $bt['btkey']);
657 $result = $btApi->pluginRequest('mnbt_connector', 'reset_site_stats', ['site' => $site]);
658 if (!is_array($result) || !($result['status'] ?? false)) {
659 mnbt_admin_node_exit(false, '重置失败:' . ($result['msg'] ?? '未知错误'));
660 }
661 if (function_exists('logjl')) logjl($user, '节点统计', '重置节点 '.$nodeId.' 站点 '.$site.' 统计数据', '操作成功', $DB);
662 mnbt_admin_node_exit(true, $result['msg'] ?? '重置成功', ['deleted' => $result['deleted'] ?? []]);
663 } catch(Exception $e) {
664 mnbt_admin_node_exit(false, '连接节点失败:' . $e->getMessage());
665 }
666}
667
668return;