- 增加了通过外部 HTTP API 向 QQ 群组发送消息的核心功能。 - 实现了对长文本消息的图片渲染,以避免被认定为垃圾信息。 - 支持在消息中提及特定的 QQ 用户。 - 创建了用于 API 令牌和图片渲染设置的配置选项。 - 开发了一个测试脚本以验证 API 功能。 - 对现有代码进行了重构,以提高组织性和可维护性。
762 lines
32 KiB
Python
762 lines
32 KiB
Python
import os
|
||
from nonebot import on_command, on_startswith
|
||
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent, Message
|
||
from nonebot.adapters.onebot.v11.message import MessageSegment
|
||
from nonebot.typing import T_State
|
||
from nonebot.rule import Rule
|
||
from pathlib import Path
|
||
|
||
from .config import Config
|
||
from .gacha import GachaSystem
|
||
from .utils import format_user_mention, get_image_path
|
||
from .api_utils import process_ssr_sp_reward, process_achievement_reward
|
||
from . import web_api
|
||
|
||
# 创建Config实例
|
||
config = Config()
|
||
|
||
# 允许的群聊ID和用户ID
|
||
ALLOWED_GROUP_ID = config.ALLOWED_GROUP_ID
|
||
ALLOWED_USER_ID = config.ALLOWED_USER_ID
|
||
GACHA_COMMANDS = config.GACHA_COMMANDS
|
||
STATS_COMMANDS = config.STATS_COMMANDS
|
||
DAILY_STATS_COMMANDS = config.DAILY_STATS_COMMANDS
|
||
TRIPLE_GACHA_COMMANDS = config.TRIPLE_GACHA_COMMANDS
|
||
ACHIEVEMENT_COMMANDS = config.ACHIEVEMENT_COMMANDS
|
||
INTRO_COMMANDS = config.INTRO_COMMANDS
|
||
DAILY_LIMIT = config.DAILY_LIMIT
|
||
|
||
gacha_system = GachaSystem()
|
||
|
||
# 检查是否允许使用功能的规则
|
||
def check_permission() -> Rule:
|
||
async def _checker(event: MessageEvent) -> bool:
|
||
# 允许特定用户在任何场景下使用
|
||
if event.user_id == ALLOWED_USER_ID:
|
||
return True
|
||
|
||
# 在允许的群聊中任何人都可以使用
|
||
if isinstance(event, GroupMessageEvent) and event.group_id == ALLOWED_GROUP_ID:
|
||
return True
|
||
|
||
return False
|
||
|
||
return Rule(_checker)
|
||
|
||
# 注册抽卡命令,添加权限检查规则
|
||
gacha_matcher = on_command("抽卡", aliases=set(GACHA_COMMANDS), priority=10, rule=check_permission())
|
||
|
||
@gacha_matcher.handle()
|
||
async def handle_gacha(bot: Bot, event: MessageEvent, state: T_State):
|
||
user_id = str(event.user_id)
|
||
user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
|
||
|
||
# 执行抽卡
|
||
result = gacha_system.draw(user_id)
|
||
|
||
if not result["success"]:
|
||
await gacha_matcher.finish(format_user_mention(user_id, user_name) + " ❌ " + result["message"])
|
||
|
||
# 成功抽卡,格式化消息
|
||
rarity = result["rarity"]
|
||
name = result["name"]
|
||
image_url = result["image_url"]
|
||
draws_left = result["draws_left"]
|
||
unlocked_achievements = result.get("unlocked_achievements", [])
|
||
|
||
# 构建消息
|
||
msg = Message()
|
||
|
||
# 根据稀有度设置不同的消息样式
|
||
if rarity == "SSR":
|
||
msg.append(f"🌟✨ 恭喜 {format_user_mention(user_id, user_name)} ✨🌟\n")
|
||
msg.append(f"🎊 抽到了 SSR 式神:{name} 🎊\n")
|
||
msg.append(f"💫 真是太幸运了!💫")
|
||
elif rarity == "SP":
|
||
msg.append(f"🌈🎆 恭喜 {format_user_mention(user_id, user_name)} 🎆🌈\n")
|
||
msg.append(f"🎉 抽到了 SP 式神:{name} 🎉\n")
|
||
msg.append(f"🔥 这是传说中的SP!🔥")
|
||
elif rarity == "SR":
|
||
msg.append(f"⭐ 恭喜 {format_user_mention(user_id, user_name)} ⭐\n")
|
||
msg.append(f"✨ 抽到了 SR 式神:{name} ✨")
|
||
else: # R
|
||
msg.append(f"🍀 {format_user_mention(user_id, user_name)} 🍀\n")
|
||
msg.append(f"📜 抽到了 R 式神:{name}")
|
||
|
||
# 添加图片
|
||
if image_url and os.path.exists(image_url):
|
||
msg.append(MessageSegment.image(f"file:///{get_image_path(image_url)}"))
|
||
|
||
# 添加成就通知
|
||
if unlocked_achievements:
|
||
msg.append("\n\n🏆 恭喜解锁新成就!\n")
|
||
has_manual_rewards = False
|
||
|
||
for achievement_id in unlocked_achievements:
|
||
# 尝试自动发放成就奖励
|
||
auto_success, reward_msg = await process_achievement_reward(user_id, achievement_id)
|
||
|
||
# 检查是否是重复奖励
|
||
if "_repeat_" in achievement_id:
|
||
base_achievement_id = achievement_id.split("_repeat_")[0]
|
||
achievement_config = config.ACHIEVEMENTS.get(base_achievement_id)
|
||
if achievement_config:
|
||
achievement_name = achievement_config["name"]
|
||
# 使用重复奖励或默认为天卡
|
||
reward = achievement_config.get("repeat_reward", "天卡")
|
||
status = "✅ 已自动发放" if auto_success else "⚠️ 需手动领取"
|
||
msg.append(f"🎖️ {achievement_name} 重复奖励 (奖励:{reward}) {status}\n")
|
||
else:
|
||
msg.append(f"🎖️ {achievement_id}\n")
|
||
else:
|
||
achievement_config = config.ACHIEVEMENTS.get(achievement_id)
|
||
if achievement_config:
|
||
achievement_name = achievement_config["name"]
|
||
reward = achievement_config["reward"]
|
||
status = "✅ 已自动发放" if auto_success else "⚠️ 需手动领取"
|
||
msg.append(f"🎖️ {achievement_name} (奖励:{reward}) {status}\n")
|
||
else:
|
||
msg.append(f"🎖️ {achievement_id}\n")
|
||
|
||
# 记录是否有需要手动领取的奖励
|
||
if not auto_success:
|
||
has_manual_rewards = True
|
||
|
||
# 如果有未自动发放的奖励,提示联系管理员
|
||
if has_manual_rewards:
|
||
msg.append("💰 未自动发放的奖励请联系管理员\n")
|
||
|
||
# 添加成就进度提示
|
||
achievement_data = gacha_system.get_user_achievements(user_id)
|
||
if achievement_data["success"]:
|
||
progress = achievement_data["progress"]
|
||
consecutive_days = progress.get("consecutive_days", 0)
|
||
no_ssr_streak = progress.get("no_ssr_streak", 0)
|
||
|
||
msg.append("\n📈 成就进度:\n")
|
||
|
||
# 连续抽卡天数进度
|
||
if consecutive_days > 0:
|
||
if consecutive_days < 30:
|
||
msg.append(f"📅 勤勤恳恳Ⅰ:{consecutive_days}/30天 🎯\n")
|
||
elif consecutive_days < 60:
|
||
msg.append(f"📅 勤勤恳恳Ⅱ:{consecutive_days}/60天 🎯\n")
|
||
elif consecutive_days < 90:
|
||
msg.append(f"📅 勤勤恳恳Ⅲ:{consecutive_days}/90天 🎯\n")
|
||
elif consecutive_days < 120:
|
||
msg.append(f"📅 勤勤恳恳Ⅳ:{consecutive_days}/120天 ⭐\n")
|
||
elif consecutive_days < 150:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ:{consecutive_days}/150天 ⭐\n")
|
||
else:
|
||
next_reward_days = 30 - (consecutive_days % 30)
|
||
if next_reward_days == 30:
|
||
next_reward_days = 0
|
||
if next_reward_days > 0:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ (满级):{consecutive_days}天,距离下次奖励{next_reward_days}天 🎁\n")
|
||
else:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ (满级):{consecutive_days}天,可获得奖励!🎉\n")
|
||
|
||
# 无SSR/SP连击进度
|
||
if no_ssr_streak > 0:
|
||
if no_ssr_streak < 60:
|
||
msg.append(f"💔 非酋进度:{no_ssr_streak}/60次 😭\n")
|
||
elif no_ssr_streak < 120:
|
||
msg.append(f"💔 顶级非酋:{no_ssr_streak}/120次 😱\n")
|
||
elif no_ssr_streak < 180:
|
||
msg.append(f"💔 月见黑:{no_ssr_streak}/180次 🌙\n")
|
||
else:
|
||
msg.append(f"💔 已达月见黑级别:{no_ssr_streak}次 🌚\n")
|
||
|
||
# 添加剩余次数和概率信息
|
||
msg.append(f"\n📊 今日剩余抽卡次数:{draws_left}/{DAILY_LIMIT}\n")
|
||
msg.append(gacha_system.get_probability_text())
|
||
|
||
# 如果抽到了SSR或SP,处理奖励发放
|
||
if rarity in ["SSR", "SP"]:
|
||
# 尝试自动发放奖励
|
||
auto_success, reward_msg = await process_ssr_sp_reward(user_id)
|
||
msg.append(f"\n\n{reward_msg}")
|
||
|
||
# 通知管理员好友
|
||
admin_id = 2185330092
|
||
notify_msg = Message()
|
||
if auto_success:
|
||
notify_msg.append(f"用户 {user_name}({user_id}) 抽中了{rarity}稀有度式神: {name}! 已自动发放奖励!")
|
||
else:
|
||
notify_msg.append(f"用户 {user_name}({user_id}) 抽中了{rarity}稀有度式神: {name}! 需要手动发放奖励!")
|
||
await bot.send_private_msg(user_id=admin_id, message=notify_msg)
|
||
else:
|
||
msg.append(f"\n\n抽中SSR或SP时,可获得蛋定助手天卡一张哦~~")
|
||
|
||
await gacha_matcher.finish(msg)
|
||
|
||
async def notify_admin(bot: Bot, message: str):
|
||
"""通知管理员"""
|
||
admin_id = 2185330092
|
||
try:
|
||
await bot.send_private_msg(user_id=admin_id, message=message)
|
||
except Exception as e:
|
||
pass # 忽略通知失败的错误
|
||
|
||
# 注册查询命令,添加权限检查规则
|
||
stats_matcher = on_command("我的抽卡", aliases=set(STATS_COMMANDS), priority=5, rule=check_permission())
|
||
|
||
# 注册今日统计命令
|
||
daily_stats_matcher = on_command("今日抽卡", aliases=set(DAILY_STATS_COMMANDS), priority=5, rule=check_permission())
|
||
|
||
# 注册三连抽命令
|
||
triple_gacha_matcher = on_command("三连抽", aliases=set(TRIPLE_GACHA_COMMANDS), priority=5, rule=check_permission())
|
||
|
||
# 注册成就查询命令
|
||
achievement_matcher = on_command("查询成就", aliases=set(ACHIEVEMENT_COMMANDS), priority=5, rule=check_permission())
|
||
|
||
@stats_matcher.handle()
|
||
async def handle_stats(bot: Bot, event: MessageEvent, state: T_State):
|
||
user_id = str(event.user_id)
|
||
user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
|
||
|
||
# 获取用户统计
|
||
stats = gacha_system.get_user_stats(user_id)
|
||
|
||
if not stats["success"]:
|
||
await stats_matcher.finish(format_user_mention(user_id, user_name) + " " + stats["message"])
|
||
|
||
# 构建消息
|
||
msg = Message()
|
||
msg.append(f"📊 {format_user_mention(user_id, user_name)} 的抽卡统计:\n\n")
|
||
msg.append(f"🎲 总抽卡次数:{stats['total_draws']}次\n\n")
|
||
|
||
# 稀有度统计
|
||
msg.append("🎯 稀有度分布:\n")
|
||
msg.append(f"📜 R:{stats['R_count']}张 ({stats['R_count']/stats['total_draws']*100:.1f}%)\n")
|
||
msg.append(f"⭐ SR:{stats['SR_count']}张 ({stats['SR_count']/stats['total_draws']*100:.1f}%)\n")
|
||
msg.append(f"🌟 SSR:{stats['SSR_count']}张 ({stats['SSR_count']/stats['total_draws']*100:.1f}%)\n")
|
||
msg.append(f"🌈 SP:{stats['SP_count']}张 ({stats['SP_count']/stats['total_draws']*100:.1f}%)\n")
|
||
|
||
# 添加最近抽卡记录
|
||
if stats["recent_draws"]:
|
||
msg.append("\n🕐 最近抽卡记录:\n")
|
||
for draw in reversed(stats["recent_draws"]):
|
||
# 根据稀有度添加emoji
|
||
if draw['rarity'] == "SSR":
|
||
emoji = "🌟"
|
||
elif draw['rarity'] == "SP":
|
||
emoji = "🌈"
|
||
elif draw['rarity'] == "SR":
|
||
emoji = "⭐"
|
||
else:
|
||
emoji = "📜"
|
||
|
||
msg.append(f"{emoji} {draw['rarity']} - {draw['name']} ({draw['date']})\n")
|
||
|
||
await stats_matcher.finish(msg)
|
||
|
||
@triple_gacha_matcher.handle()
|
||
async def handle_triple_gacha(bot: Bot, event: MessageEvent, state: T_State):
|
||
"""处理三连抽命令"""
|
||
user_id = str(event.user_id)
|
||
user_name = event.sender.card or event.sender.nickname or "未知用户"
|
||
|
||
# 执行三连抽
|
||
result = gacha_system.triple_draw(user_id)
|
||
|
||
if not result["success"]:
|
||
await triple_gacha_matcher.finish(f"❌ {result['message']}")
|
||
|
||
# 构建三连抽结果消息
|
||
msg = Message()
|
||
msg.append(f"🎯 {format_user_mention(user_id, user_name)} 的三连抽结果:\n\n")
|
||
|
||
# 显示每次抽卡结果
|
||
for i, draw_result in enumerate(result["results"], 1):
|
||
rarity = draw_result["rarity"]
|
||
name = draw_result["name"]
|
||
|
||
# 根据稀有度添加emoji
|
||
if rarity == "SSR":
|
||
msg.append(f"🌟 第{i}抽:SSR - {name}\n")
|
||
elif rarity == "SP":
|
||
msg.append(f"🌈 第{i}抽:SP - {name}\n")
|
||
elif rarity == "SR":
|
||
msg.append(f"⭐ 第{i}抽:SR - {name}\n")
|
||
else: # R
|
||
msg.append(f"📜 第{i}抽:R - {name}\n")
|
||
|
||
# 统计结果
|
||
ssr_count = sum(1 for r in result["results"] if r["rarity"] in ["SSR", "SP"])
|
||
sr_count = sum(1 for r in result["results"] if r["rarity"] == "SR")
|
||
r_count = sum(1 for r in result["results"] if r["rarity"] == "R")
|
||
|
||
msg.append(f"\n📈 本次三连抽统计:\n")
|
||
if ssr_count > 0:
|
||
msg.append(f"🎊 SSR/SP:{ssr_count}张\n")
|
||
if sr_count > 0:
|
||
msg.append(f"✨ SR:{sr_count}张\n")
|
||
if r_count > 0:
|
||
msg.append(f"📜 R:{r_count}张\n")
|
||
|
||
# 添加成就通知
|
||
unlocked_achievements = result.get("unlocked_achievements", [])
|
||
if unlocked_achievements:
|
||
msg.append("\n🏆 恭喜解锁新成就!\n")
|
||
has_manual_rewards = False
|
||
|
||
for achievement_id in unlocked_achievements:
|
||
# 尝试自动发放成就奖励
|
||
auto_success, reward_msg = await process_achievement_reward(user_id, achievement_id)
|
||
|
||
# 检查是否是重复奖励
|
||
if "_repeat_" in achievement_id:
|
||
base_achievement_id = achievement_id.split("_repeat_")[0]
|
||
achievement_config = config.ACHIEVEMENTS.get(base_achievement_id)
|
||
if achievement_config:
|
||
achievement_name = achievement_config["name"]
|
||
# 使用重复奖励或默认为天卡
|
||
reward = achievement_config.get("repeat_reward", "天卡")
|
||
status = "✅ 已自动发放" if auto_success else "⚠️ 需手动领取"
|
||
msg.append(f"🎖️ {achievement_name} 重复奖励 (奖励:{reward}) {status}\n")
|
||
else:
|
||
msg.append(f"🎖️ {achievement_id}\n")
|
||
else:
|
||
achievement_config = config.ACHIEVEMENTS.get(achievement_id)
|
||
if achievement_config:
|
||
achievement_name = achievement_config["name"]
|
||
reward = achievement_config["reward"]
|
||
status = "✅ 已自动发放" if auto_success else "⚠️ 需手动领取"
|
||
msg.append(f"🎖️ {achievement_name} (奖励:{reward}) {status}\n")
|
||
else:
|
||
msg.append(f"🎖️ {achievement_id}\n")
|
||
|
||
# 记录是否有需要手动领取的奖励
|
||
if not auto_success:
|
||
has_manual_rewards = True
|
||
|
||
# 如果有未自动发放的奖励,提示联系管理员
|
||
if has_manual_rewards:
|
||
msg.append("💰 未自动发放的奖励请联系管理员\n")
|
||
|
||
# 添加成就进度提示
|
||
achievement_data = gacha_system.get_user_achievements(user_id)
|
||
if achievement_data["success"]:
|
||
progress = achievement_data["progress"]
|
||
consecutive_days = progress.get("consecutive_days", 0)
|
||
no_ssr_streak = progress.get("no_ssr_streak", 0)
|
||
|
||
msg.append("\n📈 成就进度:\n")
|
||
|
||
# 连续抽卡天数进度
|
||
if consecutive_days > 0:
|
||
if consecutive_days < 30:
|
||
msg.append(f"📅 勤勤恳恳Ⅰ:{consecutive_days}/30天 🎯\n")
|
||
elif consecutive_days < 60:
|
||
msg.append(f"📅 勤勤恳恳Ⅱ:{consecutive_days}/60天 🎯\n")
|
||
elif consecutive_days < 90:
|
||
msg.append(f"📅 勤勤恳恳Ⅲ:{consecutive_days}/90天 🎯\n")
|
||
elif consecutive_days < 120:
|
||
msg.append(f"📅 勤勤恳恳Ⅳ:{consecutive_days}/120天 ⭐\n")
|
||
elif consecutive_days < 150:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ:{consecutive_days}/150天 ⭐\n")
|
||
else:
|
||
next_reward_days = 30 - (consecutive_days % 30)
|
||
if next_reward_days == 30:
|
||
next_reward_days = 0
|
||
if next_reward_days > 0:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ (满级):{consecutive_days}天,距离下次奖励{next_reward_days}天 🎁\n")
|
||
else:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ (满级):{consecutive_days}天,可获得奖励!🎉\n")
|
||
|
||
# 无SSR/SP连击进度
|
||
if no_ssr_streak > 0:
|
||
if no_ssr_streak < 60:
|
||
msg.append(f"💔 非酋进度:{no_ssr_streak}/60次 😭\n")
|
||
elif no_ssr_streak < 120:
|
||
msg.append(f"💔 顶级非酋:{no_ssr_streak}/120次 😱\n")
|
||
elif no_ssr_streak < 180:
|
||
msg.append(f"💔 月见黑:{no_ssr_streak}/180次 🌙\n")
|
||
else:
|
||
msg.append(f"💔 已达月见黑级别:{no_ssr_streak}次 🌚\n")
|
||
|
||
# 添加剩余次数
|
||
draws_left = result["draws_left"]
|
||
msg.append(f"\n📊 今日剩余抽卡次数:{draws_left}/{DAILY_LIMIT}")
|
||
|
||
# 如果抽到SSR/SP,处理奖励发放
|
||
if ssr_count > 0:
|
||
# 为每张SSR/SP处理奖励
|
||
auto_success, reward_msg = await process_ssr_sp_reward(user_id, ssr_count)
|
||
|
||
msg.append(f"\n\n{reward_msg}")
|
||
|
||
# 通知管理员
|
||
admin_msg = f"🎉 用户 {user_name}({user_id}) 在三连抽中抽到了 {ssr_count} 张 SSR/SP!"
|
||
if auto_success:
|
||
admin_msg += f" 已自动发放 {ssr_count} 张奖励!"
|
||
else:
|
||
admin_msg += f" 需要手动发放 {ssr_count} 张奖励!"
|
||
await notify_admin(bot, admin_msg)
|
||
|
||
await triple_gacha_matcher.finish(msg)
|
||
|
||
@achievement_matcher.handle()
|
||
async def handle_achievement(bot: Bot, event: MessageEvent, state: T_State):
|
||
"""处理成就查询命令"""
|
||
user_id = str(event.user_id)
|
||
user_name = event.sender.card or event.sender.nickname or "未知用户"
|
||
|
||
# 获取用户成就信息
|
||
result = gacha_system.get_user_achievements(user_id)
|
||
|
||
if not result["success"]:
|
||
await achievement_matcher.finish(f"❌ {result['message']}")
|
||
|
||
# 构建成就消息
|
||
msg = Message()
|
||
msg.append(f"🏆 {format_user_mention(user_id, user_name)} 的成就信息:\n\n")
|
||
|
||
# 显示已解锁成就
|
||
unlocked = result["achievements"]
|
||
if unlocked:
|
||
msg.append("🎖️ 已解锁成就:\n")
|
||
for achievement in unlocked:
|
||
# 检查是否是重复奖励
|
||
if "_repeat_" in achievement:
|
||
base_achievement_id = achievement.split("_repeat_")[0]
|
||
achievement_config = config.ACHIEVEMENTS.get(base_achievement_id)
|
||
if achievement_config:
|
||
achievement_name = achievement_config["name"]
|
||
reward = achievement_config.get("repeat_reward", "天卡")
|
||
msg.append(f"✅ {achievement_name} 重复奖励 (奖励:{reward})\n")
|
||
else:
|
||
msg.append(f"✅ {achievement}\n")
|
||
else:
|
||
achievement_config = config.ACHIEVEMENTS.get(achievement)
|
||
if achievement_config:
|
||
achievement_name = achievement_config["name"]
|
||
reward = achievement_config["reward"]
|
||
msg.append(f"✅ {achievement_name} (奖励:{reward})\n")
|
||
else:
|
||
msg.append(f"✅ {achievement}\n")
|
||
msg.append("\n💰 获取奖励请联系管理员\n\n")
|
||
|
||
# 显示成就进度
|
||
progress = result["progress"]
|
||
msg.append("📊 成就进度:\n")
|
||
|
||
# 连续抽卡天数 - 勤勤恳恳系列成就
|
||
consecutive_days = progress.get("consecutive_days", 0)
|
||
if consecutive_days > 0:
|
||
# 判断当前应该显示哪个等级的进度
|
||
if consecutive_days < 30:
|
||
msg.append(f"📅 勤勤恳恳Ⅰ:{consecutive_days}/30 天 (奖励:天卡)\n")
|
||
elif consecutive_days < 60:
|
||
msg.append(f"📅 勤勤恳恳Ⅱ:{consecutive_days}/60 天 (奖励:天卡)\n")
|
||
elif consecutive_days < 90:
|
||
msg.append(f"📅 勤勤恳恳Ⅲ:{consecutive_days}/90 天 (奖励:天卡)\n")
|
||
elif consecutive_days < 120:
|
||
msg.append(f"📅 勤勤恳恳Ⅳ:{consecutive_days}/120 天 (奖励:周卡)\n")
|
||
elif consecutive_days < 150:
|
||
msg.append(f"📅 勤勤恳恳Ⅴ:{consecutive_days}/150 天 (奖励:周卡)\n")
|
||
else:
|
||
# 已达到最高等级,显示下次奖励进度
|
||
next_reward_days = 30 - (consecutive_days % 30)
|
||
if next_reward_days == 30:
|
||
next_reward_days = 0
|
||
msg.append(f"📅 勤勤恳恳Ⅴ (已满级):{consecutive_days} 天\n")
|
||
if next_reward_days > 0:
|
||
msg.append(f"🎁 距离下次奖励:{next_reward_days} 天 (奖励:天卡)\n")
|
||
else:
|
||
msg.append(f"🎁 可获得奖励!请联系管理员 (奖励:天卡)\n")
|
||
|
||
# 无SSR/SP连击数
|
||
no_ssr_streak = progress.get("no_ssr_streak", 0)
|
||
if no_ssr_streak > 0:
|
||
msg.append(f"💔 无SSR/SP连击:{no_ssr_streak} 次\n")
|
||
|
||
# 显示各个非酋成就的进度
|
||
if no_ssr_streak < 60:
|
||
msg.append(f" 🎯 非酋成就:{no_ssr_streak}/60 (奖励:天卡)\n")
|
||
elif no_ssr_streak < 120:
|
||
msg.append(f" 🎯 顶级非酋成就:{no_ssr_streak}/120 (奖励:周卡)\n")
|
||
elif no_ssr_streak < 180:
|
||
msg.append(f" 🎯 月见黑成就:{no_ssr_streak}/180 (奖励:月卡)\n")
|
||
else:
|
||
msg.append(f" 🌙 已达到月见黑级别!\n")
|
||
|
||
# 如果没有任何进度,显示提示
|
||
if consecutive_days == 0 and no_ssr_streak == 0:
|
||
msg.append("🌱 还没有任何成就进度,快去抽卡吧!")
|
||
|
||
await achievement_matcher.finish(msg)
|
||
|
||
# 注册查询抽卡指令,支持@用户查询功能
|
||
query_matcher = on_command("查询抽卡", aliases={"查询抽奖"}, priority=5, rule=check_permission())
|
||
|
||
@query_matcher.handle()
|
||
async def handle_query(bot: Bot, event: MessageEvent, state: T_State):
|
||
# 获取消息中的@用户
|
||
message = event.get_message()
|
||
at_segment = None
|
||
|
||
for segment in message:
|
||
if segment.type == "at":
|
||
at_segment = segment
|
||
break
|
||
|
||
# 确定查询的用户ID
|
||
if at_segment:
|
||
# 查询被@的用户
|
||
target_user_id = str(at_segment.data.get("qq", ""))
|
||
# 获取被@用户的信息
|
||
if isinstance(event, GroupMessageEvent):
|
||
try:
|
||
group_id = event.group_id
|
||
user_info = await bot.get_group_member_info(group_id=group_id, user_id=int(target_user_id))
|
||
target_user_name = user_info.get("card") or user_info.get("nickname", "用户")
|
||
except:
|
||
target_user_name = "用户"
|
||
else:
|
||
target_user_name = "用户"
|
||
else:
|
||
# 查询自己
|
||
target_user_id = str(event.user_id)
|
||
target_user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
|
||
|
||
# 获取用户统计
|
||
stats = gacha_system.get_user_stats(target_user_id)
|
||
|
||
# 构建响应消息
|
||
msg = Message()
|
||
|
||
# 如果查询的是他人
|
||
if target_user_id != str(event.user_id):
|
||
msg.append(format_user_mention(str(event.user_id), event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname))
|
||
msg.append(f" 查询了 ")
|
||
msg.append(format_user_mention(target_user_id, target_user_name))
|
||
msg.append(f" 的抽卡记录\n\n")
|
||
else:
|
||
msg.append(format_user_mention(target_user_id, target_user_name) + "\n")
|
||
|
||
if not stats["success"]:
|
||
msg.append(f"该用户还没有抽卡记录哦!")
|
||
await query_matcher.finish(msg)
|
||
|
||
# 构建统计信息
|
||
msg.append(f"总抽卡次数:{stats['total_draws']}\n")
|
||
msg.append(f"R卡数量:{stats['R_count']}\n")
|
||
msg.append(f"SR卡数量:{stats['SR_count']}\n")
|
||
msg.append(f"SSR卡数量:{stats['SSR_count']}\n")
|
||
msg.append(f"SP卡数量:{stats['SP_count']}\n")
|
||
|
||
# 计算每种稀有度的比例
|
||
if stats['total_draws'] > 0:
|
||
msg.append("\n稀有度比例:\n")
|
||
msg.append(f"R: {stats['R_count']/stats['total_draws']*100:.2f}%\n")
|
||
msg.append(f"SR: {stats['SR_count']/stats['total_draws']*100:.2f}%\n")
|
||
msg.append(f"SSR: {stats['SSR_count']/stats['total_draws']*100:.2f}%\n")
|
||
msg.append(f"SP: {stats['SP_count']/stats['total_draws']*100:.2f}%\n")
|
||
|
||
# 添加最近抽卡记录
|
||
if stats["recent_draws"]:
|
||
msg.append("\n最近5次抽卡记录:\n")
|
||
for draw in reversed(stats["recent_draws"]):
|
||
msg.append(f"{draw['date']}: {draw['rarity']} - {draw['name']}\n")
|
||
|
||
await query_matcher.finish(msg)
|
||
|
||
# 自定义排行榜权限检查(仅检查白名单,不检查抽卡次数)
|
||
def check_rank_permission() -> Rule:
|
||
async def _checker(event: MessageEvent) -> bool:
|
||
# 允许特定用户在任何场景下使用
|
||
if event.user_id == ALLOWED_USER_ID:
|
||
return True
|
||
|
||
# 在允许的群聊中任何人都可以使用
|
||
if isinstance(event, GroupMessageEvent) and event.group_id == ALLOWED_GROUP_ID:
|
||
return True
|
||
|
||
return False
|
||
|
||
return Rule(_checker)
|
||
|
||
|
||
rank_matcher = on_startswith(("抽卡排行","抽卡榜"), priority=1, rule=check_rank_permission())
|
||
|
||
@rank_matcher.handle()
|
||
async def handle_rank(bot: Bot, event: MessageEvent, state: T_State):
|
||
# 获取排行榜数据
|
||
rank_data = gacha_system.get_rank_list()
|
||
|
||
if not rank_data:
|
||
await rank_matcher.finish("暂无抽卡排行榜数据")
|
||
|
||
# 构建消息
|
||
msg = Message("✨┈┈┈┈┈ 抽卡排行榜 ┈┈┈┈┈✨\n")
|
||
msg.append("🏆 SSR/SP稀有度式神排行榜 🏆\n")
|
||
msg.append("┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈\n")
|
||
|
||
for i, (user_id, data) in enumerate(rank_data[:10], 1):
|
||
# 获取用户昵称
|
||
user_name = "未知用户"
|
||
try:
|
||
if isinstance(event, GroupMessageEvent):
|
||
# 群聊场景获取群名片或昵称
|
||
user_info = await bot.get_group_member_info(group_id=event.group_id, user_id=int(user_id))
|
||
user_name = user_info.get("card") or user_info.get("nickname", "未知用户")
|
||
else:
|
||
# 私聊场景获取昵称
|
||
user_info = await bot.get_stranger_info(user_id=int(user_id))
|
||
user_name = user_info.get("nickname", "未知用户")
|
||
except Exception as e:
|
||
# 如果获取失败,尝试从事件中获取发送者信息
|
||
if str(user_id) == str(event.user_id):
|
||
user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
|
||
|
||
# 美化输出格式
|
||
rank_icon = "🥇" if i == 1 else "🥈" if i == 2 else "🥉" if i == 3 else f"{i}."
|
||
ssr_icon = "🌟"
|
||
sp_icon = "💫"
|
||
total = data['SSR_count'] + data['SP_count']
|
||
|
||
msg.append(f"{rank_icon} {user_name}\n")
|
||
msg.append(f" {ssr_icon}SSR: {data['SSR_count']}次 {sp_icon}SP: {data['SP_count']}次\n")
|
||
msg.append(f" 🔮总计: {total}次\n")
|
||
msg.append("┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈\n")
|
||
|
||
await rank_matcher.finish(msg)
|
||
|
||
|
||
|
||
@daily_stats_matcher.handle()
|
||
async def handle_daily_stats(bot: Bot, event: MessageEvent, state: T_State):
|
||
"""处理今日抽卡统计命令"""
|
||
result = gacha_system.get_daily_stats()
|
||
|
||
if not result["success"]:
|
||
await daily_stats_matcher.finish(f"❌ {result['message']}")
|
||
|
||
stats = result["stats"]
|
||
date = result["date"]
|
||
|
||
# 构建统计消息
|
||
msg = Message()
|
||
msg.append(f"📊 今日抽卡统计 ({date})\n\n")
|
||
msg.append(f"👥 参与人数:{stats['total_users']}人\n")
|
||
msg.append(f"🎲 总抽卡次数:{stats['total_draws']}次\n\n")
|
||
|
||
# 稀有度分布
|
||
msg.append("🎯 稀有度分布:\n")
|
||
if stats['total_draws'] > 0:
|
||
msg.append(f"📜 R:{stats['rarity_stats']['R']}张 ({stats['rarity_stats']['R']/stats['total_draws']*100:.1f}%)\n")
|
||
msg.append(f"⭐ SR:{stats['rarity_stats']['SR']}张 ({stats['rarity_stats']['SR']/stats['total_draws']*100:.1f}%)\n")
|
||
msg.append(f"🌟 SSR:{stats['rarity_stats']['SSR']}张 ({stats['rarity_stats']['SSR']/stats['total_draws']*100:.1f}%)\n")
|
||
msg.append(f"🌈 SP:{stats['rarity_stats']['SP']}张 ({stats['rarity_stats']['SP']/stats['total_draws']*100:.1f}%)\n\n")
|
||
else:
|
||
msg.append("暂无数据\n\n")
|
||
|
||
# SSR/SP排行榜
|
||
if stats['top_users']:
|
||
msg.append("🏆 今日SSR/SP排行榜:\n")
|
||
for i, user_data in enumerate(stats['top_users'][:5], 1):
|
||
user_id = user_data['user_id']
|
||
ssr_count = user_data['ssr_count']
|
||
|
||
# 尝试获取用户昵称
|
||
try:
|
||
user_info = await bot.get_stranger_info(user_id=int(user_id))
|
||
user_name = user_info.get('nickname', f'用户{user_id}')
|
||
except:
|
||
user_name = f'用户{user_id}'
|
||
|
||
if i == 1:
|
||
msg.append(f"🥇 {user_name}:{ssr_count}张\n")
|
||
elif i == 2:
|
||
msg.append(f"🥈 {user_name}:{ssr_count}张\n")
|
||
elif i == 3:
|
||
msg.append(f"🥉 {user_name}:{ssr_count}张\n")
|
||
else:
|
||
msg.append(f"🏅 {user_name}:{ssr_count}张\n")
|
||
else:
|
||
msg.append("🏆 今日还没有人抽到SSR/SP哦~")
|
||
|
||
await daily_stats_matcher.finish(msg)
|
||
|
||
# 抽卡介绍命令
|
||
intro_matcher = on_command("抽卡介绍", aliases=set(INTRO_COMMANDS), priority=5, rule=check_permission())
|
||
|
||
@intro_matcher.handle()
|
||
async def handle_intro(bot: Bot, event: MessageEvent, state: T_State):
|
||
"""处理抽卡介绍命令"""
|
||
|
||
# 构建介绍消息
|
||
msg = "🎮 阴阳师抽卡系统介绍 🎮\n\n"
|
||
|
||
# 抽卡机制
|
||
msg += "📋 抽卡机制:\n"
|
||
msg += f"• 每日限制:{DAILY_LIMIT}次免费抽卡\n"
|
||
msg += "• 稀有度概率:\n"
|
||
for rarity, prob in config.RARITY_PROBABILITY.items():
|
||
msg += f" - {rarity}: {prob}%\n"
|
||
msg += "\n"
|
||
|
||
# 可用指令
|
||
msg += "🎯 可用指令:\n"
|
||
msg += f"• 抽卡:{', '.join(GACHA_COMMANDS[:3])}\n"
|
||
msg += f"• 三连抽:{', '.join(TRIPLE_GACHA_COMMANDS)}\n"
|
||
msg += f"• 个人统计:{', '.join(STATS_COMMANDS[:2])}\n"
|
||
msg += f"• 今日统计:{', '.join(DAILY_STATS_COMMANDS[:2])}\n"
|
||
msg += f"• 查询成就:{', '.join(ACHIEVEMENT_COMMANDS)}\n"
|
||
msg += "• 查询抽卡/查询抽奖:查询自己的或@他人的抽卡数据\n"
|
||
msg += "• 抽卡排行/抽卡榜:查看SSR/SP排行榜\n"
|
||
msg += "\n"
|
||
|
||
# 成就系统
|
||
msg += "🏆 成就系统:\n"
|
||
msg += "\n📅 勤勤恳恳系列(连续抽卡):\n"
|
||
consecutive_achievements = [
|
||
("勤勤恳恳Ⅰ", "30天", "天卡"),
|
||
("勤勤恳恳Ⅱ", "60天", "天卡"),
|
||
("勤勤恳恳Ⅲ", "90天", "天卡"),
|
||
("勤勤恳恳Ⅳ", "120天", "周卡"),
|
||
("勤勤恳恳Ⅴ", "150天", "周卡")
|
||
]
|
||
|
||
for name, days, reward in consecutive_achievements:
|
||
msg += f"• {name}:连续{days} → {reward} 💎\n"
|
||
msg += " ※ 达到最高等级后每30天可重复获得天卡奖励\n\n"
|
||
|
||
msg += "😭 非酋系列(无SSR/SP连击):\n"
|
||
no_ssr_achievements = [
|
||
("非酋", "60次", "天卡"),
|
||
("顶级非酋", "120次", "周卡"),
|
||
("月见黑", "180次", "月卡")
|
||
]
|
||
|
||
for name, count, reward in no_ssr_achievements:
|
||
msg += f"• {name}:连续{count}未中SSR/SP → {reward} 💎\n"
|
||
msg += "\n"
|
||
|
||
# 奖励说明
|
||
msg += "🎁 奖励说明:\n"
|
||
msg += "• 天卡:蛋定助手天卡奖励\n"
|
||
msg += "• 周卡:蛋定助手周卡奖励\n"
|
||
msg += "• 月卡:蛋定助手月卡奖励\n"
|
||
msg += "\n"
|
||
|
||
# 联系管理员
|
||
msg += "📞 重要提醒:\n"
|
||
msg += "🔸 所有奖励需要联系管理员获取 🔸\n"
|
||
msg += "请在获得成就后主动联系管理员领取奖励哦~ 😊\n\n"
|
||
|
||
# 祝福语
|
||
msg += "🍀 祝您抽卡愉快,欧气满满! ✨"
|
||
|
||
await intro_matcher.finish(msg)
|
||
|
||
# 导入 Web API 模块,使其路由能够注册到 NoneBot 的 FastAPI 应用
|
||
from . import web_api
|
||
|
||
# 注册 Web 路由
|
||
try:
|
||
web_api.register_web_routes()
|
||
except Exception as e:
|
||
print(f"❌ 注册 onmyoji_gacha Web 路由失败: {e}") |