Files
WPSBot/routers/callback.py
2025-10-29 17:23:24 +08:00

235 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Callback路由处理"""
import logging
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse
from core.models import CallbackRequest
from core.database import get_db
from utils.message import get_message_sender
from utils.parser import CommandParser
from utils.rate_limit import get_rate_limiter
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/callback")
async def callback_verify():
"""Callback可用性校验 - WPS会发送GET请求验证"""
logger.info("收到Callback验证请求")
return JSONResponse({"result": "ok"})
@router.post("/callback")
async def callback_receive(request: Request):
"""接收WPS Callback消息"""
try:
# 解析请求数据
data = await request.json()
logger.info(f"收到消息: chatid={data.get('chatid')}, creator={data.get('creator')}")
logger.info(f"消息内容: {data.get('content')}")
logger.info(f"完整callback数据: {data}")
# 验证请求
try:
callback_data = CallbackRequest(**data)
except Exception as e:
logger.error(f"请求数据验证失败: {e}")
return JSONResponse({"result": "ok"}) # 仍返回ok以避免重试
# 解析指令
parse_result = CommandParser.parse(callback_data.content)
if not parse_result:
# 不是有效指令,忽略
logger.debug("非有效指令,忽略")
return JSONResponse({"result": "ok"})
game_type, command = parse_result
logger.info(f"识别指令: game_type={game_type}, command={command}")
# 检查限流
rate_limiter = get_rate_limiter()
if not rate_limiter.is_allowed():
remaining = rate_limiter.get_remaining()
reset_time = int(rate_limiter.get_reset_time())
sender = get_message_sender()
await sender.send_text(
f"⚠️ 消息发送过于频繁,请等待 {reset_time} 秒后再试\n"
f"剩余配额: {remaining}"
)
return JSONResponse({"result": "ok"})
# 更新用户信息
db = get_db()
db.get_or_create_user(callback_data.creator)
# 处理指令
response_text = await handle_command(
game_type=game_type,
command=command,
chat_id=callback_data.chatid,
user_id=callback_data.creator
)
# 发送回复
if response_text:
sender = get_message_sender()
# 根据内容选择消息类型
if response_text.startswith('#'):
# Markdown格式
await sender.send_markdown(response_text)
else:
# 普通文本
await sender.send_text(response_text)
return JSONResponse({"result": "ok"})
except Exception as e:
logger.error(f"处理Callback异常: {e}", exc_info=True)
# 仍然返回ok避免WPS重试
return JSONResponse({"result": "ok"})
async def handle_command(game_type: str, command: str,
chat_id: int, user_id: int) -> str:
"""处理游戏指令
Args:
game_type: 游戏类型
command: 完整指令
chat_id: 会话ID
user_id: 用户ID
Returns:
回复文本
"""
try:
# 帮助指令
if game_type == 'help':
from games.base import get_help_message
return get_help_message()
# 统计指令
if game_type == 'stats':
from games.base import get_stats_message
return get_stats_message(user_id)
# 注册系统
if game_type == 'register':
return await handle_register_command(command, chat_id, user_id)
# 骰娘游戏
if game_type == 'dice':
from games.dice import DiceGame
game = DiceGame()
return await game.handle(command, chat_id, user_id)
# 石头剪刀布
if game_type == 'rps':
from games.rps import RPSGame
game = RPSGame()
return await game.handle(command, chat_id, user_id)
# 运势占卜
if game_type == 'fortune':
from games.fortune import FortuneGame
game = FortuneGame()
return await game.handle(command, chat_id, user_id)
# 猜数字
if game_type == 'guess':
from games.guess import GuessGame
game = GuessGame()
return await game.handle(command, chat_id, user_id)
# 问答游戏
if game_type == 'quiz':
from games.quiz import QuizGame
game = QuizGame()
return await game.handle(command, chat_id, user_id)
# 成语接龙
if game_type == 'idiom':
from games.idiom import IdiomGame
game = IdiomGame()
return await game.handle(command, chat_id, user_id)
# 五子棋
if game_type == 'gomoku':
from games.gomoku import GomokuGame
game = GomokuGame()
return await game.handle(command, chat_id, user_id)
# 积分系统
if game_type == 'points':
from games.points import PointsGame
game = PointsGame()
return await game.handle(command, chat_id, user_id)
# 炼金系统
if game_type == 'alchemy':
from games.alchemy import AlchemyGame
game = AlchemyGame()
return await game.handle(command, chat_id, user_id)
# 冒险系统
if game_type == 'adventure':
from games.adventure import AdventureGame
game = AdventureGame()
return await game.handle(command, chat_id, user_id)
# 积分赠送系统
if game_type == 'gift':
from games.gift import GiftGame
game = GiftGame()
return await game.handle(command, chat_id, user_id)
# 未知游戏类型
logger.warning(f"未知游戏类型: {game_type}")
return "❌ 未知的游戏类型"
except Exception as e:
logger.error(f"处理游戏指令异常: {e}", exc_info=True)
return f"❌ 处理指令时出错: {str(e)}"
async def handle_register_command(command: str, chat_id: int, user_id: int) -> str:
"""处理注册命令
Args:
command: 完整指令 ".register name"
chat_id: 会话ID
user_id: 用户ID
Returns:
注册结果消息
"""
try:
# 提取参数
_, args = CommandParser.extract_command_args(command)
args = args.strip()
# 验证参数
if not args:
return "❌ 请提供要注册的名称!\n\n正确格式:`.register <名称>`\n\n示例:\n`.register 张三`\n`.register 小明`"
if len(args) > 20:
return "❌ 名称过长最多支持20个字符。"
# 更新用户名称
db = get_db()
success = db.update_user_name(user_id, args)
if success:
return f"✅ 注册成功!\n\n**您的名称**{args}\n\n之后您可以使用这个名称参与各种游戏和功能。"
else:
return "❌ 注册失败!请稍后重试。"
except Exception as e:
logger.error(f"处理注册指令错误: {e}", exc_info=True)
return f"❌ 处理指令出错: {str(e)}"