refactor: onmyoji gacha plugin overhaul (gacha-refactor)
This commit is contained in:
299
danding_bot/plugins/onmyoji_gacha/formatters.py
Normal file
299
danding_bot/plugins/onmyoji_gacha/formatters.py
Normal file
@@ -0,0 +1,299 @@
|
||||
"""
|
||||
消息格式化模块 - 抽卡、成就、统计等所有用户可见输出
|
||||
|
||||
提供所有用户可见消息的格式化函数,包括:
|
||||
- 抽卡结果消息
|
||||
- 三连抽结果消息
|
||||
- 成就通知消息
|
||||
- 统计查询消息
|
||||
- 排行榜消息
|
||||
- 每日统计消息
|
||||
|
||||
所有函数返回NoneBot的Message对象,可直接用于matcher.send()。
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Any, Optional, Tuple
|
||||
from nonebot.adapters.onebot.v11 import Message, MessageSegment
|
||||
from .utils import format_user_mention, get_image_path
|
||||
import os
|
||||
|
||||
|
||||
# 稀有度显示配置(单一数据源,消除重复模式)
|
||||
RARITY_DISPLAY = {
|
||||
"SSR": {"congrats": ("🌟✨", "✨🌟"), "card": "🎊", "desc": "SSR", "tail": "💫"},
|
||||
"SP": {"congrats": ("🌈🎆", "🎆🌈"), "card": "🎉", "desc": "SP", "tail": "🔥"},
|
||||
"SR": {"congrats": ("⭐", "⭐"), "card": "✨", "desc": "SR", "tail": ""},
|
||||
"R": {"congrats": ("🍀", "🍀"), "card": "📜", "desc": "R", "tail": ""},
|
||||
}
|
||||
|
||||
def format_gacha_result(rarity: str, name: str, user_id: str, user_name: str, image_url: str) -> Message:
|
||||
"""
|
||||
格式化单次抽卡结果消息。
|
||||
|
||||
Args:
|
||||
rarity: 稀有度 (SSR/SP/SR/R)
|
||||
name: 式神名称
|
||||
user_id: QQ号
|
||||
user_name: 用户昵称
|
||||
image_url: 图片路径
|
||||
|
||||
Returns:
|
||||
Message: 包含文本和图片的消息对象
|
||||
"""
|
||||
if not rarity or not name:
|
||||
return Message("[抽卡] 数据不完整")
|
||||
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)}"))
|
||||
return msg
|
||||
|
||||
|
||||
def format_triple_gacha_result(results: List[Tuple[str, str, str]], user_id: str, user_name: str) -> Message:
|
||||
"""
|
||||
格式化三连抽结果消息。
|
||||
|
||||
Args:
|
||||
results: 三连抽结果列表,每个元素为(稀有度, 式神名, 图片路径)
|
||||
user_id: QQ号
|
||||
user_name: 用户昵称
|
||||
|
||||
Returns:
|
||||
Message: 包含三连抽结果的消息对象
|
||||
"""
|
||||
msg = Message()
|
||||
msg.append(f"🎯 {format_user_mention(user_id, user_name)} 的三连抽结果:\n\n")
|
||||
|
||||
for i, (rarity, name, image_path) in enumerate(results, 1):
|
||||
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")
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def format_achievement_notify(
|
||||
achievements_data: List[Dict[str, Any]],
|
||||
user_id: str,
|
||||
) -> Message:
|
||||
"""
|
||||
格式化成就解锁通知消息。
|
||||
|
||||
纯格式化函数,不执行任何业务逻辑(奖励发放等)。
|
||||
调用方负责解析成就数据和处理奖励。
|
||||
|
||||
Args:
|
||||
achievements_data: 已解析的成就数据列表,每项含 name/reward/claimed/reward_msg 等字段
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
Message: 格式化的成就通知消息
|
||||
|
||||
Note:
|
||||
纯函数,无副作用,无外部调用。
|
||||
"""
|
||||
if not achievements_data:
|
||||
return Message()
|
||||
msg = Message()
|
||||
|
||||
if achievements_data:
|
||||
msg.append("\n\n🏆 恭喜解锁新成就!\n")
|
||||
|
||||
for ach in achievements_data:
|
||||
name = ach.get("name", "未知成就")
|
||||
reward = ach.get("reward", 0)
|
||||
reward_msg = ach.get("reward_msg", "")
|
||||
claimed = ach.get("claimed", False)
|
||||
|
||||
if claimed and reward_msg:
|
||||
msg.append(f"🎖️ {name} 重复奖励 (奖励:{reward}) {reward_msg}\n")
|
||||
else:
|
||||
msg.append(f"🎖️ {name}\n")
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def format_achievement_progress(
|
||||
consecutive_days: int,
|
||||
no_ssr_streak: int,
|
||||
user_id: str
|
||||
) -> Message:
|
||||
"""
|
||||
格式化成就进度消息。
|
||||
|
||||
Args:
|
||||
consecutive_days: 连续抽卡天数
|
||||
no_ssr_streak: 连续未出SSR/SP次数
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
Message: 包含成就进度的消息对象
|
||||
"""
|
||||
from .gacha import get_achievement_definition
|
||||
|
||||
msg = Message()
|
||||
msg.append(f"🎯 成就进度:\n")
|
||||
|
||||
# 勤勤恳恳成就进度
|
||||
achievement = get_achievement_definition("勤勤恳恳Ⅰ")
|
||||
if achievement:
|
||||
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 = 150 + ((consecutive_days - 150) // 30 + 1) * 30
|
||||
if next_reward <= 365:
|
||||
msg.append(f"📅 勤勤恳恳Ⅴ (满级):{consecutive_days}天,距离下次奖励{next_reward}天 🎯\n")
|
||||
else:
|
||||
msg.append(f"📅 勤勤恳恳Ⅴ (满级):{consecutive_days}天,可获得奖励!🎉\n")
|
||||
|
||||
# 非酋成就进度
|
||||
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")
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def format_user_stats(stats: Dict[str, Any], user_id: str, user_name: str) -> Message:
|
||||
"""
|
||||
格式化用户抽卡统计消息。
|
||||
|
||||
Args:
|
||||
stats: 用户统计数据字典
|
||||
user_id: 用户ID
|
||||
user_name: 用户昵称
|
||||
|
||||
Returns:
|
||||
Message: 包含统计信息的消息对象
|
||||
"""
|
||||
msg = Message()
|
||||
msg.append(f"📊 {format_user_mention(user_id, user_name)} 的抽卡统计:\n")
|
||||
msg.append(f"🎲 总抽卡次数:{stats['total_draws']}次\n")
|
||||
|
||||
total = stats['total_draws']
|
||||
if total > 0:
|
||||
msg.append(f"\n稀有度分布:\n")
|
||||
msg.append(f"📜 R:{stats.get('R_count',0)}张 ({stats.get('R_count',0)/total*100:.1f}%)\n")
|
||||
msg.append(f"⭐ SR:{stats.get('SR_count',0)}张 ({stats.get('SR_count',0)/total*100:.1f}%)\n")
|
||||
msg.append(f"✨ SSR:{stats.get('SSR_count',0)}张 ({stats.get('SSR_count',0)/total*100:.1f}%)\n")
|
||||
msg.append(f"🌈 SP:{stats.get('SP_count',0)}张 ({stats.get('SP_count',0)/total*100:.1f}%)")
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def format_user_detail_stats(
|
||||
stats: Dict[str, Any],
|
||||
user_id: str,
|
||||
user_name: str,
|
||||
recent_draws: List[Dict[str, Any]]
|
||||
) -> Message:
|
||||
"""
|
||||
格式化用户详细抽卡统计消息。
|
||||
|
||||
Args:
|
||||
stats: 用户统计数据字典
|
||||
user_id: 用户ID
|
||||
user_name: 用户昵称
|
||||
recent_draws: 最近抽卡记录列表
|
||||
|
||||
Returns:
|
||||
Message: 包含详细统计信息的消息对象
|
||||
"""
|
||||
msg = Message()
|
||||
msg.append(f"{format_user_mention(user_id, user_name)} 的抽卡统计:\n")
|
||||
msg.append(f"总抽卡次数:{stats['total_draws']}次\n")
|
||||
|
||||
total = stats['total_draws']
|
||||
if total > 0:
|
||||
msg.append(f"R:{stats.get('R_count',0)}张 ({stats.get('R_count',0)/total*100:.1f}%)\n")
|
||||
msg.append(f"SR:{stats.get('SR_count',0)}张 ({stats.get('SR_count',0)/total*100:.1f}%)\n")
|
||||
msg.append(f"SSR:{stats.get('SSR_count',0)}张 ({stats.get('SSR_count',0)/total*100:.1f}%)\n")
|
||||
msg.append(f"SP:{stats.get('SP_count',0)}张 ({stats.get('SP_count',0)/total*100:.1f}%)")
|
||||
|
||||
if recent_draws:
|
||||
msg.append(f"\n最近{len(recent_draws)}次抽卡:\n")
|
||||
for draw in recent_draws:
|
||||
msg.append(f"• {draw}\n")
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def format_rank_list(rank_data: List[Dict[str, Any]], page: int, total_pages: int) -> Message:
|
||||
"""
|
||||
格式化抽卡排行榜消息。
|
||||
|
||||
Args:
|
||||
rank_data: 排行榜数据列表
|
||||
page: 当前页码
|
||||
total_pages: 总页数
|
||||
|
||||
Returns:
|
||||
Message: 包含排行榜的消息对象
|
||||
"""
|
||||
msg = Message()
|
||||
msg.append(f"🏆 抽卡排行榜 (第{page}页/共{total_pages}页)\n\n")
|
||||
|
||||
for idx, entry in enumerate(rank_data, 1):
|
||||
msg.append(f"{idx}. {entry.get('user_name', '未知')} - {entry.get('total_draws', 0)}次\n")
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
def format_daily_stats(daily_stats: Dict[str, Any]) -> Message:
|
||||
"""
|
||||
格式化今日抽卡统计消息。
|
||||
|
||||
Args:
|
||||
daily_stats: 今日统计数据字典
|
||||
|
||||
Returns:
|
||||
Message: 包含今日统计的消息对象
|
||||
"""
|
||||
msg = Message()
|
||||
msg.append(f"📅 今日抽卡统计\n")
|
||||
msg.append(f"总抽卡次数:{daily_stats.get('today_total',0)}次\n")
|
||||
|
||||
msg.append(f"\n稀有度分布:\n")
|
||||
msg.append(f"R:{daily_stats.get('R_count',0)}张\n")
|
||||
msg.append(f"SR:{daily_stats.get('SR_count',0)}张\n")
|
||||
msg.append(f"SSR:{daily_stats.get('SSR_count',0)}张\n")
|
||||
msg.append(f"SP:{daily_stats.get('SP_count',0)}张\n")
|
||||
|
||||
top = daily_stats.get("top_users", [])
|
||||
if top:
|
||||
msg.append("\n今日TOP5:\n")
|
||||
for idx, u in enumerate(top[:5], 1):
|
||||
msg.append(f"{idx}. {u.get('user_name','未知')} - {u.get('draws',0)}次\n")
|
||||
|
||||
return msg
|
||||
Reference in New Issue
Block a user