2025-10-29 11:32:43 +08:00
|
|
|
|
"""积分系统游戏模块"""
|
|
|
|
|
|
import random
|
|
|
|
|
|
import logging
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
from games.base import BaseGame
|
|
|
|
|
|
from utils.parser import CommandParser
|
|
|
|
|
|
from core.database import get_db
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PointsGame(BaseGame):
|
|
|
|
|
|
"""积分系统游戏"""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
"""初始化游戏"""
|
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
self.db = get_db()
|
|
|
|
|
|
|
|
|
|
|
|
async def handle(self, command: str, chat_id: int, user_id: int) -> str:
|
|
|
|
|
|
"""处理积分相关指令
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
command: 指令,如 ".points", ".checkin", ".leaderboard"
|
|
|
|
|
|
chat_id: 会话ID
|
|
|
|
|
|
user_id: 用户ID
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
回复消息
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 提取参数
|
|
|
|
|
|
_, args = CommandParser.extract_command_args(command)
|
|
|
|
|
|
args = args.strip().lower()
|
|
|
|
|
|
|
|
|
|
|
|
# 积分排行榜
|
2025-10-29 15:07:49 +08:00
|
|
|
|
if args in ['leaderboard', '排行榜', '排行']:
|
2025-10-29 11:32:43 +08:00
|
|
|
|
return self._get_leaderboard()
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-10-29 15:07:49 +08:00
|
|
|
|
# 默认:每日签到
|
2025-10-29 11:32:43 +08:00
|
|
|
|
else:
|
2025-10-29 15:07:49 +08:00
|
|
|
|
return self._daily_checkin(user_id)
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"处理积分指令错误: {e}", exc_info=True)
|
|
|
|
|
|
return f"❌ 处理指令出错: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
def _daily_checkin(self, user_id: int) -> str:
|
|
|
|
|
|
"""每日签到
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
user_id: 用户ID
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
签到结果消息
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 固定签到积分
|
2025-10-29 12:56:57 +08:00
|
|
|
|
checkin_points = 100
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
# 检查是否已签到
|
|
|
|
|
|
today = datetime.now().strftime('%Y-%m-%d')
|
|
|
|
|
|
if self.db.check_daily_checkin(user_id, today):
|
2025-10-29 15:07:49 +08:00
|
|
|
|
return self._get_user_points(user_id)
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
# 执行签到
|
2025-10-29 11:51:15 +08:00
|
|
|
|
try:
|
|
|
|
|
|
result = self.db.daily_checkin(user_id, checkin_points)
|
|
|
|
|
|
if result:
|
|
|
|
|
|
# 获取用户积分信息
|
|
|
|
|
|
points_info = self.db.get_user_points(user_id)
|
|
|
|
|
|
|
|
|
|
|
|
text = f"## ✅ 签到成功!\n\n"
|
|
|
|
|
|
text += f"**获得积分**:+{checkin_points} 分\n\n"
|
2025-10-29 12:29:18 +08:00
|
|
|
|
text += f"**当前积分**:{points_info['points']} 分\n\n"
|
2025-10-29 11:51:15 +08:00
|
|
|
|
text += f"📅 签到日期:{today}\n\n"
|
|
|
|
|
|
text += "💡 提示:每天签到可获得固定积分奖励!"
|
|
|
|
|
|
|
|
|
|
|
|
return text
|
|
|
|
|
|
else:
|
|
|
|
|
|
return "❌ 签到失败,请稍后重试"
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"签到过程中发生错误: {e}", exc_info=True)
|
|
|
|
|
|
return f"❌ 签到过程中发生错误: {str(e)}"
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
def _get_user_points(self, user_id: int) -> str:
|
|
|
|
|
|
"""获取用户积分信息
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
user_id: 用户ID
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
积分信息消息
|
|
|
|
|
|
"""
|
|
|
|
|
|
points_info = self.db.get_user_points(user_id)
|
|
|
|
|
|
|
|
|
|
|
|
text = f"## 💎 个人积分\n\n"
|
2025-10-29 12:29:18 +08:00
|
|
|
|
text += f"**当前积分**:{points_info['points']} 分\n\n"
|
2025-10-29 11:32:43 +08:00
|
|
|
|
text += "---\n\n"
|
|
|
|
|
|
text += "💡 提示:\n"
|
2025-10-29 15:07:49 +08:00
|
|
|
|
text += "• 每日签到可获得 100 积分\n"
|
2025-10-29 11:32:43 +08:00
|
|
|
|
text += "• 查看运势可获得随机积分\n"
|
2025-10-29 12:29:18 +08:00
|
|
|
|
text += "• 使用 `.points leaderboard` 查看排行榜"
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _get_leaderboard(self, limit: int = 10) -> str:
|
|
|
|
|
|
"""获取积分排行榜
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
limit: 限制数量
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
排行榜消息
|
|
|
|
|
|
"""
|
|
|
|
|
|
leaderboard = self.db.get_points_leaderboard(limit)
|
|
|
|
|
|
|
|
|
|
|
|
if not leaderboard:
|
|
|
|
|
|
return "📊 暂无排行榜数据"
|
|
|
|
|
|
|
|
|
|
|
|
text = f"## 🏆 积分排行榜(前 {len(leaderboard)} 名)\n\n"
|
|
|
|
|
|
|
|
|
|
|
|
medals = ["🥇", "🥈", "🥉"] + ["🏅"] * (limit - 3)
|
|
|
|
|
|
|
|
|
|
|
|
for i, user in enumerate(leaderboard):
|
|
|
|
|
|
rank = i + 1
|
|
|
|
|
|
medal = medals[i] if i < len(medals) else "🏅"
|
2025-10-31 11:07:41 +08:00
|
|
|
|
username = self.db.get_user_display_name(user['user_id'])
|
2025-10-29 12:29:18 +08:00
|
|
|
|
points = user.get('points', 0)
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
text += f"{medal} **第 {rank} 名** {username}\n"
|
2025-10-29 12:29:18 +08:00
|
|
|
|
text += f" 积分:{points} 分\n\n"
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
text += "---\n\n"
|
|
|
|
|
|
text += "💡 提示:使用 `.points` 查看个人积分"
|
|
|
|
|
|
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
|
|
|
def add_fortune_points(self, user_id: int) -> int:
|
|
|
|
|
|
"""为运势游戏添加随机积分奖励
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
user_id: 用户ID
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
获得的积分数量
|
|
|
|
|
|
"""
|
2025-10-29 12:56:57 +08:00
|
|
|
|
# 随机积分范围:50-200分
|
|
|
|
|
|
points = random.randint(50, 200)
|
2025-10-29 11:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
if self.db.add_points(user_id, points, "fortune", "运势奖励"):
|
|
|
|
|
|
logger.info(f"用户 {user_id} 通过运势获得 {points} 积分")
|
|
|
|
|
|
return points
|
|
|
|
|
|
else:
|
|
|
|
|
|
logger.error(f"用户 {user_id} 运势积分奖励失败")
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
def get_help(self) -> str:
|
|
|
|
|
|
"""获取帮助信息"""
|
|
|
|
|
|
return """## 💎 积分系统
|
|
|
|
|
|
|
|
|
|
|
|
### 基础用法
|
|
|
|
|
|
- `.points` - 查看个人积分
|
|
|
|
|
|
- `.checkin` - 每日签到
|
|
|
|
|
|
- `.points leaderboard` - 积分排行榜
|
|
|
|
|
|
|
|
|
|
|
|
### 积分获取方式
|
|
|
|
|
|
- **每日签到**:固定 10 积分
|
|
|
|
|
|
- **运势占卜**:随机 1-20 积分
|
|
|
|
|
|
- **游戏奖励**:根据游戏表现获得
|
|
|
|
|
|
|
|
|
|
|
|
### 示例
|
|
|
|
|
|
```
|
|
|
|
|
|
.points
|
|
|
|
|
|
.checkin
|
|
|
|
|
|
.points leaderboard
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 说明
|
|
|
|
|
|
- 每日签到只能进行一次
|
|
|
|
|
|
- 运势积分每次查看都有机会获得
|
2025-10-29 12:29:18 +08:00
|
|
|
|
- 积分系统已简化,不再保留历史记录
|
2025-10-29 11:32:43 +08:00
|
|
|
|
"""
|