import asyncio from nonebot import on_command from nonebot.adapters.onebot.v11 import Bot, Event, GroupMessageEvent from .shared import ( room_store, race_engine, config, logger, get_scope, check_access, get_event_id, _send_to_scope, _build_race_image_message, _get_user_name, _get_horses_in_order, _format_horse_label, run_race_with_settlement, points_service, ) from ..models import RoomState, HorseState race_list_cmd = on_command("赛马列表", priority=5) @race_list_cmd.handle() async def handle_race_list(bot: Bot, event: Event): """显示当前房间所有报名马匹信息。""" if not await check_access(bot, event): await race_list_cmd.finish("无权限访问此功能") return scope = get_scope(event) room = room_store.get_room(scope) if not room or not room.horses: await race_list_cmd.finish("暂无报名马匹") return lines = ["🏇 当前报名马匹:"] for horse in _get_horses_in_order(room): owner_display = await _get_user_name(bot, scope, horse.owner_id) lines.append(f" {horse.index}. {horse.name} - 主人: {owner_display}") lines.append(f"\n共 {len(room.horses)} 匹马") await race_list_cmd.finish("\n".join(lines)) start_cmd = on_command("赛马开赛", priority=5) @start_cmd.handle() async def handle_start(bot: Bot, event: Event): """Handle race start - only participants or admins can start.""" if not await check_access(bot, event): await start_cmd.finish("无权限访问此功能") return scope = get_scope(event) user_id = get_event_id(event) lock = room_store.get_lock(scope) async with lock: room = room_store.get_room(scope) if not room: await start_cmd.finish("房间不存在,请先报名") return if room.state != RoomState.WAITING: await start_cmd.finish("比赛已经在进行中") return if len(room.horses) < 2: await start_cmd.finish("至少需要2匹马才能开赛") return is_participant = user_id in [h.owner_id for h in room.horses.values()] is_admin = False if isinstance(event, GroupMessageEvent): try: member_info = await bot.get_group_member_info( group_id=event.group_id, user_id=int(user_id) ) role = member_info.get("role", "") is_admin = role in ("admin", "owner") except Exception: pass if not is_participant and not is_admin: await start_cmd.finish("只有参赛者或群管理员可以开赛") return for horse in room.horses.values(): horse.state = HorseState.RACING await start_cmd.send("比赛开始!") task = asyncio.create_task(run_race_with_settlement(bot, room, scope)) race_engine.register_task(scope, task) cancel_race_cmd = on_command("赛马取消", priority=5) @cancel_race_cmd.handle() async def handle_cancel_race(bot: Bot, event: Event): """取消当前进行的比赛,退还所有下注积分。仅参赛者或管理员可操作。""" if not await check_access(bot, event): await cancel_race_cmd.finish("无权限访问此功能") return scope = get_scope(event) user_id = get_event_id(event) lock = room_store.get_lock(scope) async with lock: room = room_store.get_room(scope) if not room: await cancel_race_cmd.finish("房间不存在") return if room.state != RoomState.RACING: await cancel_race_cmd.finish("当前没有进行中的比赛") return is_participant = user_id in [h.owner_id for h in room.horses.values()] is_admin = False if isinstance(event, GroupMessageEvent): try: member_info = await bot.get_group_member_info( group_id=event.group_id, user_id=int(user_id) ) role = member_info.get("role", "") is_admin = role in ("admin", "owner") except Exception: pass if not is_participant and not is_admin: await cancel_race_cmd.finish("只有参赛者或群管理员可以取消比赛") return race_engine.stop_race(scope) total_refund = 0 for bet in room.bets[:]: success, _ = await points_service.refund_bet_points( bet.user_id, bet.amount, "比赛取消退还下注" ) if success: total_refund += bet.amount room.bets.clear() for horse in room.horses.values(): horse.state = HorseState.WAITING room.state = RoomState.WAITING room.tick_count = 0 await _send_to_scope(bot, scope, f"🏇 比赛已取消!共退还 {total_refund} 积分。")