300 lines
10 KiB
Python
300 lines
10 KiB
Python
"""
|
||
消息格式化模块 - 抽卡、成就、统计等所有用户可见输出
|
||
|
||
提供所有用户可见消息的格式化函数,包括:
|
||
- 抽卡结果消息
|
||
- 三连抽结果消息
|
||
- 成就通知消息
|
||
- 统计查询消息
|
||
- 排行榜消息
|
||
- 每日统计消息
|
||
|
||
所有函数返回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
|