feat(bot): use runtime api for bot data

This commit is contained in:
2026-06-20 18:20:40 +08:00
parent f67f3ca1d6
commit 8d26c46323
16 changed files with 1803 additions and 1491 deletions

View File

@@ -1,7 +1,7 @@
import os
import logging
import random
from nonebot import on_command, on_startswith
import os
import logging
import random
from nonebot import get_driver, 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
@@ -29,12 +29,22 @@ ACHIEVEMENT_COMMANDS = config.ACHIEVEMENT_COMMANDS
INTRO_COMMANDS = config.INTRO_COMMANDS
DAILY_LIMIT = config.DAILY_LIMIT
gacha_system = GachaSystem()
logger = logging.getLogger(__name__)
gacha_system = GachaSystem()
logger = logging.getLogger(__name__)
SIGN_IN_MIN_POINTS = 1
SIGN_IN_MAX_POINTS = 100
SIGN_IN_SOURCE = "gacha_sign"
SIGN_IN_REASON = "抽卡签到"
SIGN_IN_REASON = "抽卡签到"
@get_driver().on_startup
async def load_gacha_shikigami_data() -> None:
"""启动时从 xapi 拉取式神基础数据缓存。"""
try:
await gacha_system.data_manager.refresh_shikigami_data()
except Exception:
logger.exception("启动拉取抽卡式神缓存失败")
# 检查是否允许使用功能的规则
def check_permission() -> Rule:
@@ -52,14 +62,11 @@ def check_permission() -> Rule:
return Rule(_checker)
async def try_handle_daily_sign_in(matcher, user_id: str, user_name: str) -> None:
"""处理抽卡成功后的每日签到,不影响主流程"""
try:
if gacha_system.data_manager.has_signed_in_today(user_id):
return
points = random.randint(SIGN_IN_MIN_POINTS, SIGN_IN_MAX_POINTS)
success, new_balance = await points_api.add_points(
async def try_handle_daily_sign_in(matcher, user_id: str, user_name: str) -> None:
"""处理抽卡成功后的每日签到,不影响主流程"""
try:
points = random.randint(SIGN_IN_MIN_POINTS, SIGN_IN_MAX_POINTS)
success, new_balance = await points_api.add_points(
user_id,
points,
SIGN_IN_SOURCE,
@@ -69,13 +76,23 @@ async def try_handle_daily_sign_in(matcher, user_id: str, user_name: str) -> Non
logger.error("抽卡签到积分发放失败 user_id=%s points=%s", user_id, points)
return
if not gacha_system.data_manager.record_sign_in(user_id, points):
logger.warning("抽卡签到落库冲突,积分已发放但签到记录重复 user_id=%s", user_id)
return
await matcher.send(format_sign_in_message(user_id, user_name, points, new_balance))
except Exception:
logger.exception("处理抽卡签到失败 user_id=%s", user_id)
if not await gacha_system.data_manager.record_sign_in(user_id, points):
logger.warning("抽卡签到落库冲突,积分已发放但签到记录重复 user_id=%s", user_id)
return
await matcher.send(format_sign_in_message(user_id, user_name, points, new_balance))
except Exception:
logger.exception("处理抽卡签到失败 user_id=%s", user_id)
async def claim_achievement_after_reward(user_id: str, achievement_id: str, reward_success: bool) -> None:
"""成就奖励发放成功后标记 xapi reward_claimed。"""
if not reward_success:
return
claimed = await gacha_system.data_manager.claim_achievement_reward(user_id, achievement_id)
if not claimed:
logger.warning("成就奖励已发放但 claim 标记失败 user_id=%s achievement_id=%s", user_id, achievement_id)
# 注册抽卡命令,添加权限检查规则
gacha_matcher = on_command("抽卡", aliases=set(GACHA_COMMANDS), priority=10, rule=check_permission())
@@ -86,7 +103,7 @@ async def handle_gacha(bot: Bot, event: MessageEvent, state: T_State):
user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
# 执行抽卡
result = gacha_system.draw(user_id)
result = await gacha_system.draw(user_id)
if not result["success"]:
await gacha_matcher.finish(format_user_mention(user_id, user_name) + "" + result["message"])
@@ -127,8 +144,9 @@ async def handle_gacha(bot: Bot, event: MessageEvent, state: T_State):
has_manual_rewards = False
for achievement_id in unlocked_achievements:
# 尝试自动发放成就奖励
auto_success, reward_msg = await process_achievement_reward(user_id, achievement_id)
# 尝试自动发放成就奖励
auto_success, reward_msg = await process_achievement_reward(user_id, achievement_id)
await claim_achievement_after_reward(user_id, achievement_id, auto_success)
# 检查是否是重复奖励
if "_repeat_" in achievement_id:
@@ -161,7 +179,7 @@ async def handle_gacha(bot: Bot, event: MessageEvent, state: T_State):
msg.append("💰 未自动发放的奖励请联系管理员\n")
# 添加成就进度提示
achievement_data = gacha_system.get_user_achievements(user_id)
achievement_data = await gacha_system.get_user_achievements(user_id)
if achievement_data["success"]:
progress = achievement_data["progress"]
consecutive_days = progress.get("consecutive_days", 0)
@@ -226,13 +244,13 @@ async def handle_gacha(bot: Bot, event: MessageEvent, state: T_State):
await try_handle_daily_sign_in(gacha_matcher, user_id, user_name)
return
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 # 忽略通知失败的错误
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:
logger.debug("通知管理员失败: %s", e)
# 注册查询命令,添加权限检查规则
stats_matcher = on_command("我的抽卡", aliases=set(STATS_COMMANDS), priority=5, rule=check_permission())
@@ -252,7 +270,7 @@ async def handle_stats(bot: Bot, event: MessageEvent, state: T_State):
user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
# 获取用户统计
stats = gacha_system.get_user_stats(user_id)
stats = await gacha_system.get_user_stats(user_id)
if not stats["success"]:
await stats_matcher.finish(format_user_mention(user_id, user_name) + " " + stats["message"])
@@ -294,7 +312,7 @@ async def handle_triple_gacha(bot: Bot, event: MessageEvent, state: T_State):
user_name = event.sender.card or event.sender.nickname or "未知用户"
# 执行三连抽
result = gacha_system.triple_draw(user_id)
result = await gacha_system.triple_draw(user_id)
if not result["success"]:
await triple_gacha_matcher.finish(f"{result['message']}")
@@ -338,8 +356,9 @@ async def handle_triple_gacha(bot: Bot, event: MessageEvent, state: T_State):
has_manual_rewards = False
for achievement_id in unlocked_achievements:
# 尝试自动发放成就奖励
auto_success, reward_msg = await process_achievement_reward(user_id, achievement_id)
# 尝试自动发放成就奖励
auto_success, reward_msg = await process_achievement_reward(user_id, achievement_id)
await claim_achievement_after_reward(user_id, achievement_id, auto_success)
# 检查是否是重复奖励
if "_repeat_" in achievement_id:
@@ -372,7 +391,7 @@ async def handle_triple_gacha(bot: Bot, event: MessageEvent, state: T_State):
msg.append("💰 未自动发放的奖励请联系管理员\n")
# 添加成就进度提示
achievement_data = gacha_system.get_user_achievements(user_id)
achievement_data = await gacha_system.get_user_achievements(user_id)
if achievement_data["success"]:
progress = achievement_data["progress"]
consecutive_days = progress.get("consecutive_days", 0)
@@ -442,7 +461,7 @@ async def handle_achievement(bot: Bot, event: MessageEvent, state: T_State):
user_name = event.sender.card or event.sender.nickname or "未知用户"
# 获取用户成就信息
result = gacha_system.get_user_achievements(user_id)
result = await gacha_system.get_user_achievements(user_id)
if not result["success"]:
await achievement_matcher.finish(f"{result['message']}")
@@ -561,7 +580,7 @@ async def handle_query(bot: Bot, event: MessageEvent, state: T_State):
target_user_name = event.sender.card if isinstance(event, GroupMessageEvent) else event.sender.nickname
# 获取用户统计
stats = gacha_system.get_user_stats(target_user_id)
stats = await gacha_system.get_user_stats(target_user_id)
# 构建响应消息
msg = Message()
@@ -623,7 +642,7 @@ rank_matcher = on_startswith(("抽卡排行","抽卡榜"), priority=1, rule=chec
@rank_matcher.handle()
async def handle_rank(bot: Bot, event: MessageEvent, state: T_State):
# 获取排行榜数据
rank_data = gacha_system.get_rank_list()
rank_data = await gacha_system.get_rank_list()
if not rank_data:
await rank_matcher.finish("暂无抽卡排行榜数据")
@@ -668,7 +687,7 @@ async def handle_rank(bot: Bot, event: MessageEvent, state: T_State):
@daily_stats_matcher.handle()
async def handle_daily_stats(bot: Bot, event: MessageEvent, state: T_State):
"""处理今日抽卡统计命令"""
result = gacha_system.get_daily_stats()
result = await gacha_system.get_daily_stats()
if not result["success"]:
await daily_stats_matcher.finish(f"{result['message']}")