Files
Mr.Xia 569801dd14 fix: 赛马插件P0-P2问题修复
- P0: room_store sqlite3→aiosqlite异步化
- P0: points_service统一异常处理+轻量重试
- P0: _send_to_scope加warning日志
- P1: 积分历史记录补充source/reason字段
- P1: 赛马结算写入赔率快照(odds_snapshot)
- P1: test_commands改为commands_mod间接引用(测试隔离)
- P2: 马名去重统一casefold()比较
2026-05-01 22:50:14 +08:00

87 lines
3.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
import logging
from typing import Tuple
from danding_bot.plugins.danding_points import points_api
from .config import Config
logger = logging.getLogger("horse_racing.points")
MAX_RETRIES = 3
RETRY_DELAY = 0.5
class PointsService:
def __init__(self, config: Config):
self.config = config
async def _call_with_retry(self, func, *args, retries=MAX_RETRIES):
"""Call API function with retry logic."""
last_exc = None
for attempt in range(retries):
try:
return await func(*args)
except Exception as e:
last_exc = e
logger.warning(
f"Points API call failed (attempt {attempt + 1}/{retries}): {e}"
)
if attempt < retries - 1:
await asyncio.sleep(RETRY_DELAY)
logger.error(f"Points API call failed after {retries} attempts: {last_exc}")
raise last_exc
async def spend_bet_points(
self, user_id: str, amount: int, reason: str = "赛马下注"
) -> Tuple[bool, int]:
"""Deduct points for betting with retry."""
try:
return await self._call_with_retry(
points_api.spend_points,
user_id, amount, "horse_race", reason
)
except Exception as e:
logger.error(f"spend_bet_points failed for user {user_id}: {e}")
return False, 0
async def refund_bet_points(
self, user_id: str, amount: int, reason: str = "取消报名退还"
) -> Tuple[bool, int]:
"""Refund bet points."""
return await points_api.add_points(user_id, amount, "horse_race", reason)
async def payout_winnings(
self, user_id: str, amount: int, odds: float
) -> Tuple[bool, int]:
"""Payout bet winnings."""
payout = int(amount * odds)
reason = f"下注获胜 ×{odds:.2f}"
return await points_api.add_points(user_id, payout, "horse_race", reason)
async def reward_participant(self, user_id: str) -> Tuple[bool, int]:
"""Reward race participant."""
return await points_api.add_points(
user_id,
self.config.PARTICIPANT_REWARD,
"horse_race",
"参赛奖励",
)
async def reward_champion(self, user_id: str) -> Tuple[bool, int]:
"""Reward race champion."""
return await points_api.add_points(
user_id,
self.config.CHAMPION_REWARD,
"horse_race",
"冠军奖励",
)
async def set_points(
self, user_id: str, amount: int, reason: str = "测试设置积分"
) -> Tuple[bool, int]:
"""Set user points (for testing)."""
return await points_api.set_points(user_id, amount, "horse_race", reason)
async def get_balance(self, user_id: str) -> int:
"""Get user balance."""
return await points_api.get_balance(user_id)