fix(settings): Telegram 检测/测试闭环与 8 项告警开关恢复

检测与测试前自动持久化 Token/Chat ID;getUpdates 清除 Webhook 并返回具体 API 错误;恢复 NOTIFY 分项开关与免密 reveal。
This commit is contained in:
Nexus Agent
2026-06-07 19:45:07 +08:00
parent 2e911dcca7
commit 540a7fce05
7 changed files with 480 additions and 105 deletions
+52 -14
View File
@@ -291,14 +291,11 @@ async def get_setting(key: str, admin: Admin = Depends(get_current_admin), db: A
@router.post("/api-key/reveal", response_model=dict)
async def reveal_api_key(
payload: ApiKeyRevealRequest,
request: Request,
admin: Admin = Depends(get_current_admin),
db: AsyncSession = Depends(get_db),
):
"""Reveal global API_KEY after re-entering account password."""
await _verify_reauth(db, admin, payload.current_password)
"""Reveal global API_KEY for authenticated admin (JWT required)."""
repo = SettingRepositoryImpl(db)
value = await repo.get("api_key")
if value is None:
@@ -903,13 +900,34 @@ async def alert_stats(
# ── Telegram Test + Chat ID Detection ──
async def _telegram_clear_webhook_if_set(client, base_url: str) -> None:
"""Remove active webhook so getUpdates can receive messages."""
wh_resp = await client.get(f"{base_url}/getWebhookInfo")
if wh_resp.status_code != 200:
raise HTTPException(status_code=502, detail=f"Telegram getWebhookInfo 返回 {wh_resp.status_code}")
wh_data = wh_resp.json()
if not wh_data.get("ok"):
desc = wh_data.get("description") or "getWebhookInfo 失败"
raise HTTPException(status_code=502, detail=f"Telegram API: {desc}")
if wh_data.get("result", {}).get("url"):
del_resp = await client.post(
f"{base_url}/deleteWebhook",
params={"drop_pending_updates": "false"},
)
del_data = del_resp.json()
if not del_data.get("ok"):
desc = del_data.get("description") or "deleteWebhook 失败"
raise HTTPException(status_code=502, detail=f"无法清除 Webhook: {desc}")
@router.post("/telegram/test", response_model=dict)
async def telegram_test_send(
admin: Admin = Depends(get_current_admin),
):
"""Send a test Telegram message to verify Bot Token + Chat ID configuration."""
from server.infrastructure.telegram import send_telegram
import httpx
from server.config import settings as _settings
from server.infrastructure.telegram import TELEGRAM_API_BASE
if not _settings.TELEGRAM_BOT_TOKEN:
raise HTTPException(status_code=400, detail="TELEGRAM_BOT_TOKEN 未配置")
@@ -918,26 +936,41 @@ async def telegram_test_send(
from datetime import datetime, timezone
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
ok = await send_telegram(
message = (
f"✅ <b>Nexus 测试消息</b>\n"
f"Bot 配置正确,告警通知已就绪\n"
f"时间: {now}"
)
if ok:
try:
async with httpx.AsyncClient(timeout=10.0) as client:
resp = await client.post(
f"{TELEGRAM_API_BASE}/bot{_settings.TELEGRAM_BOT_TOKEN}/sendMessage",
json={
"chat_id": _settings.TELEGRAM_CHAT_ID,
"text": message,
"parse_mode": "HTML",
},
)
data = resp.json()
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=502, detail=f"请求失败: {e}") from e
if resp.status_code == 200 and data.get("ok"):
return {"success": True}
raise HTTPException(status_code=502, detail="Telegram API 返回错误,请检查 Bot Token 和 Chat ID")
desc = data.get("description") or f"HTTP {resp.status_code}"
raise HTTPException(status_code=502, detail=f"Telegram API: {desc}")
@router.post("/telegram/reveal-token", response_model=dict)
async def reveal_telegram_token(
payload: ApiKeyRevealRequest,
request: Request,
admin: Admin = Depends(get_current_admin),
db: AsyncSession = Depends(get_db),
):
"""Reveal Telegram Bot Token after re-entering account password."""
await _verify_reauth(db, admin, payload.current_password)
"""Reveal Telegram Bot Token for authenticated admin (JWT required)."""
repo = SettingRepositoryImpl(db)
value = await repo.get("telegram_bot_token")
if value is None:
@@ -973,13 +1006,18 @@ async def telegram_get_chats(
try:
async with httpx.AsyncClient(timeout=10.0) as client:
base_url = f"{TELEGRAM_API_BASE}/bot{token}"
await _telegram_clear_webhook_if_set(client, base_url)
resp = await client.get(
f"{TELEGRAM_API_BASE}/bot{token}/getUpdates",
params={"limit": 50, "allowed_updates": ["message", "channel_post"]},
f"{base_url}/getUpdates",
params={"limit": 50},
)
if resp.status_code != 200:
raise HTTPException(status_code=502, detail=f"Telegram API 返回 {resp.status_code}")
data = resp.json()
if not data.get("ok"):
desc = data.get("description") or "getUpdates 失败"
raise HTTPException(status_code=502, detail=f"Telegram API: {desc}")
except HTTPException:
raise
except Exception as e: