feat: add web telegram bot restart button
This commit is contained in:
@@ -144,6 +144,12 @@ async def stop_tg_bot():
|
||||
from web.api import app as web_app
|
||||
|
||||
|
||||
async def restart_tg_bot_runtime():
|
||||
"""供 Web API 调用:只重启 TG Bot,不重启 Web。"""
|
||||
await stop_tg_bot()
|
||||
asyncio.create_task(start_tg_bot_safe())
|
||||
|
||||
|
||||
async def start_tg_bot_safe():
|
||||
"""启动 TG Bot;初始化阶段网络失败时压缩日志并自动重试。"""
|
||||
delay = 10
|
||||
@@ -168,6 +174,8 @@ async def lifespan(app):
|
||||
# 初始化数据库
|
||||
await init_db()
|
||||
# 启动 TG Bot
|
||||
import web.api as web_api
|
||||
web_api.set_restart_bot_callback(restart_tg_bot_runtime)
|
||||
task = asyncio.create_task(start_tg_bot_safe())
|
||||
|
||||
def log_task_result(t: asyncio.Task):
|
||||
|
||||
+16
@@ -26,6 +26,12 @@ _sse_queues: list[asyncio.Queue] = []
|
||||
_log_buffer: list[dict] = []
|
||||
MAX_LOG_BUFFER = 300
|
||||
MAX_LOG_MESSAGE_CHARS = 1200
|
||||
_restart_bot_callback = None
|
||||
|
||||
|
||||
def set_restart_bot_callback(callback):
|
||||
global _restart_bot_callback
|
||||
_restart_bot_callback = callback
|
||||
|
||||
|
||||
def compact_log_message(record: logging.LogRecord) -> str:
|
||||
@@ -154,6 +160,16 @@ async def api_logs(limit: int = Query(default=100, ge=1, le=300)):
|
||||
return JSONResponse(_log_buffer[-limit:])
|
||||
|
||||
|
||||
@app.post("/api/restart-bot")
|
||||
async def api_restart_bot():
|
||||
"""只重启 Telegram Bot,不重启 Web 服务。"""
|
||||
if not _restart_bot_callback:
|
||||
return JSONResponse({"ok": False, "error": "Bot 重启回调未就绪"}, status_code=503)
|
||||
logging.getLogger("spam_guard").warning("🔄 Web 管理端请求重启 TG Bot")
|
||||
asyncio.create_task(_restart_bot_callback())
|
||||
return JSONResponse({"ok": True, "message": "TG Bot 正在重启"})
|
||||
|
||||
|
||||
@app.post("/api/restart")
|
||||
async def api_restart():
|
||||
"""重启服务:返回响应后退出当前进程,由 Docker restart 策略拉起。"""
|
||||
|
||||
+25
-1
@@ -184,7 +184,8 @@
|
||||
<div class="status">
|
||||
<span class="sse-dot" :class="sseConnected ? 'on' : 'off'"></span>
|
||||
{{ sseConnected ? '实时连接' : '连接中...' }}
|
||||
<el-button size="mini" type="warning" plain :loading="restarting" @click="restartService">重启</el-button>
|
||||
<el-button size="mini" type="primary" plain :loading="restartingBot" @click="restartBot">重启Bot</el-button>
|
||||
<el-button size="mini" type="warning" plain :loading="restarting" @click="restartService">重启服务</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -296,6 +297,7 @@ new Vue({
|
||||
newMessage: '',
|
||||
sending: false,
|
||||
restarting: false,
|
||||
restartingBot: false,
|
||||
stats: { today_bans: 0, total_bans: 0, active_bans: 0 },
|
||||
}
|
||||
},
|
||||
@@ -377,6 +379,28 @@ new Vue({
|
||||
async loadStats() {
|
||||
try { this.stats = await (await fetch('/api/stats')).json() } catch (e) {}
|
||||
},
|
||||
async restartBot() {
|
||||
this.$confirm('确认只重启 Telegram Bot?Web 管理页不会重启。', '重启 TG Bot', {
|
||||
confirmButtonText: '确认重启',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
this.restartingBot = true
|
||||
try {
|
||||
const data = await (await fetch('/api/restart-bot', { method: 'POST' })).json()
|
||||
if (data.ok) {
|
||||
this.$message.success('✅ TG Bot 正在重启')
|
||||
setTimeout(() => { this.restartingBot = false; this.loadLogs() }, 5000)
|
||||
} else {
|
||||
this.$message.error(`❌ 重启失败: ${data.error || '未知错误'}`)
|
||||
this.restartingBot = false
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error('❌ 网络错误')
|
||||
this.restartingBot = false
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
async restartService() {
|
||||
this.$confirm('确认重启 TG Spam Guard 服务?重启期间 Web 和 Bot 会短暂不可用。', '重启服务', {
|
||||
confirmButtonText: '确认重启',
|
||||
|
||||
Reference in New Issue
Block a user