fix(onmyoji_gacha): 避免重复签到发放积分
This commit is contained in:
@@ -8,12 +8,13 @@ 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_sign_in_message, format_user_mention, get_image_path
|
||||
from .api_utils import process_ssr_sp_reward, process_achievement_reward
|
||||
from . import web_api
|
||||
from danding_bot.plugins.danding_points import points_api
|
||||
from .config import Config
|
||||
from .gacha import GachaSystem
|
||||
from .utils import format_sign_in_message, format_user_mention, get_image_path
|
||||
from .sign_in import award_daily_sign_in_points
|
||||
from .api_utils import process_ssr_sp_reward, process_achievement_reward
|
||||
from . import web_api
|
||||
from danding_bot.plugins.danding_points import points_api
|
||||
|
||||
# 创建Config实例
|
||||
config = Config()
|
||||
@@ -66,18 +67,19 @@ async def try_handle_daily_sign_in(matcher, user_id: str, user_name: str) -> Non
|
||||
"""处理抽卡成功后的每日签到,不影响主流程"""
|
||||
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,
|
||||
SIGN_IN_REASON,
|
||||
)
|
||||
if not success:
|
||||
logger.error("抽卡签到积分发放失败 user_id=%s points=%s", user_id, points)
|
||||
return
|
||||
|
||||
if not await gacha_system.data_manager.record_sign_in(user_id, points):
|
||||
logger.warning("抽卡签到落库冲突,积分已发放但签到记录重复 user_id=%s", user_id)
|
||||
success, new_balance, status = await award_daily_sign_in_points(
|
||||
data_manager=gacha_system.data_manager,
|
||||
points_api=points_api,
|
||||
user_id=user_id,
|
||||
points=points,
|
||||
source=SIGN_IN_SOURCE,
|
||||
reason=SIGN_IN_REASON,
|
||||
)
|
||||
if not success:
|
||||
if status == "points_failed":
|
||||
logger.error("抽卡签到记录成功但积分发放失败 user_id=%s points=%s", user_id, points)
|
||||
else:
|
||||
logger.info("抽卡签到未发放积分 user_id=%s status=%s", user_id, status)
|
||||
return
|
||||
|
||||
await matcher.send(format_sign_in_message(user_id, user_name, points, new_balance))
|
||||
|
||||
40
danding_bot/plugins/onmyoji_gacha/sign_in.py
Normal file
40
danding_bot/plugins/onmyoji_gacha/sign_in.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""抽卡签到积分编排。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Protocol
|
||||
|
||||
|
||||
class GachaSignInRecorder(Protocol):
|
||||
async def record_sign_in(self, user_id: str, points_awarded: int) -> bool:
|
||||
"""记录抽卡签到,首次签到返回 True。"""
|
||||
|
||||
|
||||
class PointsAwarder(Protocol):
|
||||
async def add_points(self, user_id: str, amount: int, source: str, reason: str) -> tuple[bool, int]:
|
||||
"""发放积分,返回是否成功与新余额。"""
|
||||
|
||||
|
||||
async def award_daily_sign_in_points(
|
||||
*,
|
||||
data_manager: GachaSignInRecorder,
|
||||
points_api: PointsAwarder,
|
||||
user_id: str,
|
||||
points: int,
|
||||
source: str,
|
||||
reason: str,
|
||||
) -> tuple[bool, int, str]:
|
||||
"""先记录签到再发放积分,避免重复签到时重复发积分。
|
||||
|
||||
`/bot/gacha/sign-in` 负责判断当天是否已经签到;只有它确认首次签到后,
|
||||
nonebot 才调用 `/bot/points/add` 发积分。
|
||||
"""
|
||||
|
||||
signed = await data_manager.record_sign_in(user_id, points)
|
||||
if not signed:
|
||||
return False, 0, "signed_already_or_failed"
|
||||
|
||||
success, new_balance = await points_api.add_points(user_id, points, source, reason)
|
||||
if not success:
|
||||
return False, new_balance, "points_failed"
|
||||
return True, new_balance, "awarded"
|
||||
Reference in New Issue
Block a user