Files
Nexus/server/infrastructure/telegram/__init__.py
T
Your Name c9a99f4fb3 fix: 全项目文档对齐 + 代码清理
代码修复:
- web/agent/agent.py: datetime.utcnow() → datetime.now(timezone.utc)
- requirements.txt: 移除 paramiko==3.5.0 (已无活跃引用)
- 删除 server/infrastructure/ssh/pool.py (DEPRECATED, 无引用)

连接池三层对齐 (config.py/.env.example/session.py):
- DB_POOL_SIZE 100→160, DB_MAX_OVERFLOW 100→120
- 基于 MySQL max_connections=400, install.php 公式

文档修复 (21项):
- P0: 硬编码域名/IP替换为配置变量占位符
- P1: 10个过时设计文档加归档标注 (引用旧文件结构)
- P2: step-3-webssh报告 paramiko引用修正
- 6份审查报告连接池参数勘误 100/100→160/120
- ECC安全报告 EC5 datetime.utcnow 标记已修复
- docs/README.md 文档索引重写
- docs/memory/mem_nexus_overview.md 移除硬编码凭证
- docs/project/tech-stack-inventory.md paramiko标记已移除

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:19:56 +08:00

112 lines
3.6 KiB
Python

"""Nexus — Telegram Bot Notification Module
Sends alerts/recovery/system messages via Telegram Bot API.
"""
import logging
import httpx
from datetime import datetime, timezone
from server.config import settings
logger = logging.getLogger("nexus.telegram")
# Bot API base URL
TELEGRAM_API_BASE = "https://api.telegram.org"
# Reusable httpx client — avoids TCP connection churn during alert storms
_http_client: httpx.AsyncClient | None = None
async def _get_client() -> httpx.AsyncClient:
global _http_client
if _http_client is None or _http_client.is_closed:
_http_client = httpx.AsyncClient(timeout=10.0)
return _http_client
async def close_client():
"""Close the shared httpx client — call during app shutdown"""
global _http_client
if _http_client and not _http_client.is_closed:
await _http_client.aclose()
_http_client = None
async def send_telegram(message: str) -> bool:
"""Send a Telegram message via Bot API.
Returns True if sent successfully, False if skipped or failed.
Silently skips if TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID is not configured.
"""
if not settings.TELEGRAM_BOT_TOKEN or not settings.TELEGRAM_CHAT_ID:
return False # Not configured — silent skip
try:
client = await _get_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",
},
)
if resp.status_code == 200:
logger.info(f"Telegram sent: {message[:50]}...")
return True
else:
logger.error(f"Telegram API error: {resp.status_code} {resp.text[:100]}")
return False
except Exception as e:
logger.error(f"Telegram send failed: {e}")
return False
async def send_telegram_alert(server_name: str, alert_type: str, value: float) -> bool:
"""Send server alert notification"""
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
return await send_telegram(
f"🔴 <b>告警</b>\n"
f"服务器 <b>{server_name}</b> {alert_type} 使用率 <b>{value:.1f}%</b>\n"
f"时间: {now}"
)
async def send_telegram_recovery(server_name: str, metric: str, value: float) -> bool:
"""Send server recovery notification"""
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
return await send_telegram(
f"🟢 <b>恢复</b>\n"
f"服务器 <b>{server_name}</b> {metric} 已恢复正常 ({value:.1f}%)\n"
f"时间: {now}"
)
async def send_telegram_system_alert(message: str) -> bool:
"""Send system-level alert (Python crash, Redis disconnect, etc.)"""
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
return await send_telegram(
f"⚠️ <b>系统告警</b>\n"
f"{message}\n"
f"时间: {now}"
)
async def send_telegram_restart_success() -> bool:
"""Notify that Python backend has successfully restarted"""
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
return await send_telegram(
f"🟢 <b>Nexus后端已恢复</b>\n"
f"Python服务自动重启成功\n"
f"时间: {now}"
)
async def send_telegram_restart_failed() -> bool:
"""Notify that Python backend restart failed — needs human intervention"""
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
return await send_telegram(
f"🔴 <b>Nexus后端重启失败!</b>\n"
f"请人工介入检查\n"
f"时间: {now}"
)