fix: use host network and restore web chat records

This commit is contained in:
ngfchl
2026-07-06 19:44:23 +08:00
parent 251b926b6f
commit 04781f144c
7 changed files with 329 additions and 40 deletions
+15 -4
View File
@@ -34,11 +34,22 @@ def split_answer(text: str, max_len: int = 3500, max_parts: int = 3) -> list[str
return parts
async def safe_send(update: Update, context: ContextTypes.DEFAULT_TYPE, text: str):
"""优先回复原消息;若原消息已被自动删除,退回普通 send_message。"""
chat_id = update.effective_chat.id
try:
return await update.message.reply_text(text)
except Exception as e:
if "Message to be replied not found" not in str(e):
logger.warning(f"reply_text 失败,改用 send_message: {e}")
return await context.bot.send_message(chat_id=chat_id, text=text)
async def cmd_ask(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""向知识库提问"""
query = " ".join(context.args) if context.args else ""
if not query:
reply = await update.message.reply_text(
reply = await safe_send(update, context,
"❓ 用法: /ask <你的问题>\n"
"例如: /ask 怎么安装收割机\n"
f"文档地址: {config.SITE_URL}"
@@ -48,7 +59,7 @@ async def cmd_ask(update: Update, context: ContextTypes.DEFAULT_TYPE):
return
logger.info(f"📩 用户提问: [{update.message.from_user.username}] {query}")
searching_msg = await update.message.reply_text("🔍 正在搜索知识库并整理详细答案...")
searching_msg = await safe_send(update, context, "🔍 正在搜索知识库并整理详细答案...")
asyncio.create_task(auto_delete(update.message))
asyncio.create_task(auto_delete(searching_msg, seconds=8))
@@ -60,13 +71,13 @@ async def cmd_ask(update: Update, context: ContextTypes.DEFAULT_TYPE):
parts = split_answer(answer)
for i, part in enumerate(parts, 1):
prefix = f"📚 回答 {i}/{len(parts)}\n\n" if len(parts) > 1 else ""
reply = await update.message.reply_text(prefix + part)
reply = await safe_send(update, context, prefix + part)
replies.append(reply)
for reply in replies:
asyncio.create_task(auto_delete(reply, seconds=180))
except Exception as e:
logger.error(f"❌ 回答失败: {e}")
reply = await update.message.reply_text(f"❌ 回答失败: {e}")
reply = await safe_send(update, context, f"❌ 回答失败: {e}")
asyncio.create_task(auto_delete(reply))
+40 -3
View File
@@ -9,6 +9,7 @@ from telegram.ext import ContextTypes, MessageHandler, filters
import config
from db.models import Message, Ban, Action
from services.spam_detector import detect
from web.api import broadcast_sse, json_safe
logger = logging.getLogger("spam_guard")
@@ -48,8 +49,8 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
logger.warning(f"⚡ 防刷屏: @{username} ({user.id}) {len(_flood_cache[user.id])}条/{config.RATE_LIMIT_WINDOW}s")
return
# 记录消息
await Message.create(
# 记录消息并推送到 Web 管理页
message_record = await Message.create(
msg_id=msg.message_id,
chat_id=update.effective_chat.id,
user_id=user.id,
@@ -57,12 +58,36 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
first_name=first_name,
text=text[:500],
)
await broadcast_sse("chat", json_safe({
"id": message_record.id,
"msg_id": msg.message_id,
"chat_id": update.effective_chat.id,
"user_id": user.id,
"username": username,
"first_name": first_name,
"text": text[:500],
"time": message_record.created_at,
"spam": False,
}))
# === 垃圾检测 ===
is_spam, reason = await detect(text, username, first_name)
if is_spam:
logger.warning(f"🚨 垃圾消息 [{username}]: {reason}")
await message_record.update_from_dict({"is_spam": True, "spam_reason": reason}).save()
await broadcast_sse("spam", json_safe({
"id": message_record.id,
"msg_id": msg.message_id,
"chat_id": update.effective_chat.id,
"user_id": user.id,
"username": username,
"first_name": first_name,
"text": text[:500],
"time": message_record.created_at,
"spam": True,
"reason": reason,
}))
# 删消息
try:
@@ -86,8 +111,20 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
"duration_minutes": config.BAN_DURATION_MINUTES,
"unban_at": unban_at,
}
await Ban.create(**ban_record)
ban = await Ban.create(**ban_record)
await Action.create(action="BAN", user_id=user.id, username=username, details={"reason": reason})
await broadcast_sse("ban", json_safe({
"id": ban.id,
"user_id": user.id,
"username": username,
"first_name": first_name,
"reason": reason,
"method": "auto",
"duration_minutes": config.BAN_DURATION_MINUTES,
"auto_unban": True,
"unban_at": unban_at,
"time": ban.created_at,
}))
logger.info(f"🔨 已封禁 [{username}] {config.BAN_DURATION_MINUTES} 分钟")
except Exception as e:
logger.error(f"❌ 封禁失败: {e}")