From ac1b0c86fd13745ecbddad47bb37d43e175b5927 Mon Sep 17 00:00:00 2001 From: ypsdf1 Date: Thu, 15 Oct 2026 14:08:49 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E5=8D=81=E4=B9=9D=E6=89=B9=EF=BC=9A?= =?UTF-8?q?=E5=B0=81=E7=A6=81=E5=85=AC=E7=A4=BA=E6=8C=89=E6=92=AD=E6=8A=A5?= =?UTF-8?q?=E8=B5=B7=E7=82=B9=E8=BF=87=E6=BB=A4(web=5Fplayer=5Fbans?= =?UTF-8?q?=E8=A1=A5created=5Ftime=E5=88=97=E5=B9=B6=E9=9A=8F=E6=8E=A8?= =?UTF-8?q?=E9=80=81=E5=85=A5=E5=BA=93=E3=80=81web=5Fban=5Fboard=5Fcfg?= =?UTF-8?q?=E5=AD=98ban=5Fcutoff=E3=80=81=E6=9F=A5=E8=AF=A2=E5=8A=A0create?= =?UTF-8?q?d=5Ftime>=3D=E8=B5=B7=E7=82=B9)=20+=20=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=E4=BA=BA=E6=9C=BA=E9=AA=8C=E8=AF=81=E7=BB=84=E4=BB=B6?= =?UTF-8?q?300px=E6=8C=89=E5=AE=B9=E5=99=A8=E5=AE=BD=E7=AD=89=E6=AF=94?= =?UTF-8?q?=E7=BC=A9=E6=94=BE=E5=AF=B9=E9=BD=90=E9=98=B2=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/sync.php | 35 +++++++++++++++++++++++++++++++++-- captcha_guard.php | 19 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/api/sync.php b/api/sync.php index 0866868..811adcd 100644 --- a/api/sync.php +++ b/api/sync.php @@ -5416,9 +5416,20 @@ function getBanBoard() { // 若路由到的那侧根本没有这张表(个别站点库未切分/表在另一侧)→ 显式换侧再查一次。 // 仅公示名字封禁(ban_type='name'),IP 封禁不公开(IP 属敏感信息) $now = time(); + // ★ 第十九批:只公示「播报起点」之后创建的封禁 —— 与游戏内播报同源(Java推送时下发), + // 插件上服务器之前的历史封禁不上公示;起点未下发(0)时不过滤,行为与旧版一致。 + try { $db->exec("ALTER TABLE web_player_bans ADD COLUMN created_time INTEGER DEFAULT 0"); } catch (Throwable $e) {} + $cutoff = 0; + try { + $cr = $db->query("SELECT start_cutoff FROM web_ban_board_cfg WHERE id = 1"); + if ($cr) { + $crow = $cr->fetchArray(SQLITE3_ASSOC); + if ($crow) $cutoff = (int) ($crow['start_cutoff'] ?? 0); + } + } catch (Throwable $e) { $cutoff = 0; } $sql = "SELECT target, ban_type, reason, expire_time, synced_at FROM web_player_bans - WHERE ban_type = 'name' + WHERE ban_type = 'name' AND created_time >= " . $cutoff . " ORDER BY synced_at DESC LIMIT " . $limit; @@ -5483,8 +5494,12 @@ function syncBans() { source TEXT DEFAULT '', expire_time INTEGER DEFAULT 0, synced_at INTEGER DEFAULT 0, + created_time INTEGER DEFAULT 0, PRIMARY KEY (target, ban_type) )"); + // ★ 第十九批:老库补列(CREATE TABLE IF NOT EXISTS 不会给老表补列)—— + // created_time = 封禁创建时间(毫秒),公示按它过滤插件上架前的历史封禁 + try { $db->exec("ALTER TABLE web_player_bans ADD COLUMN created_time INTEGER DEFAULT 0"); } catch (Throwable $e) {} $now = time(); // ★ 第十六批:保留旧 synced_at 作为「首见时间」,供封禁公示按时间从近到远排序 @@ -5498,7 +5513,7 @@ function syncBans() { } // 先清空旧数据再全量写入 $db->exec("DELETE FROM web_player_bans"); - $stmt = $db->prepare("INSERT OR REPLACE INTO web_player_bans (target, ban_type, reason, source, expire_time, synced_at) VALUES (:target, :type, :reason, :source, :expire, :now)"); + $stmt = $db->prepare("INSERT OR REPLACE INTO web_player_bans (target, ban_type, reason, source, expire_time, synced_at, created_time) VALUES (:target, :type, :reason, :source, :expire, :now, :created)"); foreach ($bans as $ban) { if (empty($ban['target'])) continue; $stmt->bindValue(':target', $ban['target'], SQLITE3_TEXT); @@ -5506,6 +5521,7 @@ function syncBans() { $stmt->bindValue(':reason', $ban['reason'] ?? '', SQLITE3_TEXT); $stmt->bindValue(':source', $ban['source'] ?? '', SQLITE3_TEXT); $stmt->bindValue(':expire', (int)($ban['expire'] ?? 0), SQLITE3_INTEGER); + $stmt->bindValue(':created', (int)($ban['created'] ?? 0), SQLITE3_INTEGER); $fk = $ban['target'] . "\x1f" . ($ban['type'] ?? 'name'); $stmt->bindValue(':now', (isset($firstSeen[$fk]) && $firstSeen[$fk] > 0) ? $firstSeen[$fk] : $now, SQLITE3_INTEGER); $stmt->execute(); @@ -5522,6 +5538,21 @@ function syncBans() { } } + // ★ 第十九批:接收 Java 端「播报起点」(与游戏内封禁播报同源), + // get_ban_board 用它过滤插件上服务器之前的历史封禁;Java 没传/传0 = 不过滤 + $cutoffRaw = getParam('ban_cutoff', ''); + if ($cutoffRaw !== null && $cutoffRaw !== '') { + $cutoff = (int) $cutoffRaw; + if ($cutoff < 0) $cutoff = 0; + try { + $db->exec("CREATE TABLE IF NOT EXISTS web_ban_board_cfg (id INTEGER PRIMARY KEY, start_cutoff INTEGER DEFAULT 0, updated_at INTEGER DEFAULT 0)"); + $cst = $db->prepare("INSERT OR REPLACE INTO web_ban_board_cfg (id, start_cutoff, updated_at) VALUES (1, :c, :t)"); + $cst->bindValue(':c', $cutoff, SQLITE3_INTEGER); + $cst->bindValue(':t', $now, SQLITE3_INTEGER); + $cst->execute(); + } catch (Throwable $e) {} + } + success(['count' => count($bans), 'ip_blacklist' => $ipCount]); } diff --git a/captcha_guard.php b/captcha_guard.php index ec84c24..89dee46 100644 --- a/captcha_guard.php +++ b/captcha_guard.php @@ -343,6 +343,7 @@ function cgWidgetHtml() { .cg-badge.bad{background:#da3633;color:#fff} .cg-badge.warn{background:#9e6a03;color:#fff} .cg-err{display:none;margin-top:8px;font-size:12.5px;color:#f85149} +#cgCfBox{width:100%} .cg-btn{width:100%;padding:11px 14px;font-size:14px;font-weight:600;border:none;border-radius:6px; background:#21262d;color:#e6edf3;cursor:not-allowed} .cg-btn:enabled{background:#238636;color:#fff;cursor:pointer} @@ -375,6 +376,19 @@ function cgWidgetHtml() { function loadScript(src,ok,failFn){var s=document.createElement('script');s.src=src;s.async=true; s.onload=ok;s.onerror=failFn;document.head.appendChild(s);} + // ★ 第十九批:Turnstile 挂件固定 300px 宽,容器(如管理后台登录卡)比它窄时右侧溢出边框 —— + // 按容器宽度整体等比缩放(原点左上),视觉与 .cg-box 边框对齐;容器够宽则还原不缩放 + function fitCf(){ + var box=el('cgCfBox'); if(!box) return; + var w=box.clientWidth||0; + if(!w) return; + if(w>=300){ box.style.transform=''; box.style.marginBottom=''; return; } + var s=w/300; + box.style.transformOrigin='top left'; + box.style.transform='scale('+s+')'; + box.style.marginBottom=(65*s-65)+'px'; + } + function initCf(){ el('cgCfBox').style.display='block'; // ★ 关键:本页必须自己拉起 Turnstile SDK(测试页是