Files
tg-spam-guard/handlers/knowledge.py
T
2026-07-06 19:26:00 +08:00

83 lines
2.7 KiB
Python

"""知识库问答 handler"""
import asyncio
import logging
from telegram import Update
from telegram.ext import CommandHandler, ContextTypes, filters
import config
logger = logging.getLogger("spam_guard")
def split_answer(text: str, max_len: int = 3500, max_parts: int = 3) -> list[str]:
"""Telegram 单条消息长度有限,长回答按段发送,不再硬截断。"""
if len(text) <= max_len:
return [text]
parts = []
rest = text
while rest and len(parts) < max_parts:
if len(rest) <= max_len:
parts.append(rest)
break
cut = rest.rfind("\n\n", 0, max_len)
if cut < max_len // 2:
cut = rest.rfind("\n", 0, max_len)
if cut < max_len // 2:
cut = max_len
parts.append(rest[:cut].strip())
rest = rest[cut:].strip()
if rest and parts:
parts[-1] += "\n\n...(回答较长,后续内容已省略;可以追问具体部分)"
return parts
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(
"❓ 用法: /ask <你的问题>\n"
"例如: /ask 怎么安装收割机\n"
f"文档地址: {config.SITE_URL}"
)
asyncio.create_task(auto_delete(update.message))
asyncio.create_task(auto_delete(reply))
return
logger.info(f"📩 用户提问: [{update.message.from_user.username}] {query}")
searching_msg = await update.message.reply_text("🔍 正在搜索知识库并整理详细答案...")
asyncio.create_task(auto_delete(update.message))
asyncio.create_task(auto_delete(searching_msg, seconds=8))
try:
from services.knowledge_base import ask_knowledge_base
answer = await ask_knowledge_base(query)
replies = []
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)
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}")
asyncio.create_task(auto_delete(reply))
async def auto_delete(message, seconds=60):
try:
await asyncio.sleep(seconds)
await message.delete()
except Exception:
pass
def register_knowledge(app):
app.add_handler(CommandHandler("ask", cmd_ask, filters.ChatType.GROUPS))