refactor: extract admin check helper & harden room_store JSON parsing
- Extract duplicated admin/owner check from race.py into shared._is_admin_or_owner() - Add try/except around JSON.loads in room_store.load_rooms for corrupted data resilience - Use .get() for safer dict access in room deserialization
This commit is contained in:
@@ -7,6 +7,7 @@ from .shared import (
|
|||||||
_send_to_scope, _build_race_image_message,
|
_send_to_scope, _build_race_image_message,
|
||||||
_get_user_name, _get_horses_in_order, _format_horse_label,
|
_get_user_name, _get_horses_in_order, _format_horse_label,
|
||||||
run_race_with_settlement, points_service,
|
run_race_with_settlement, points_service,
|
||||||
|
_is_admin_or_owner,
|
||||||
)
|
)
|
||||||
from ..models import RoomState, HorseState
|
from ..models import RoomState, HorseState
|
||||||
|
|
||||||
@@ -64,17 +65,7 @@ async def handle_start(bot: Bot, event: Event):
|
|||||||
return
|
return
|
||||||
|
|
||||||
is_participant = user_id in [h.owner_id for h in room.horses.values()]
|
is_participant = user_id in [h.owner_id for h in room.horses.values()]
|
||||||
is_admin = False
|
is_admin = await _is_admin_or_owner(bot, event)
|
||||||
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:
|
if not is_participant and not is_admin:
|
||||||
await start_cmd.finish("只有参赛者或群管理员可以开赛")
|
await start_cmd.finish("只有参赛者或群管理员可以开赛")
|
||||||
@@ -114,17 +105,7 @@ async def handle_cancel_race(bot: Bot, event: Event):
|
|||||||
return
|
return
|
||||||
|
|
||||||
is_participant = user_id in [h.owner_id for h in room.horses.values()]
|
is_participant = user_id in [h.owner_id for h in room.horses.values()]
|
||||||
is_admin = False
|
is_admin = await _is_admin_or_owner(bot, event)
|
||||||
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:
|
if not is_participant and not is_admin:
|
||||||
await cancel_race_cmd.finish("只有参赛者或群管理员可以取消比赛")
|
await cancel_race_cmd.finish("只有参赛者或群管理员可以取消比赛")
|
||||||
|
|||||||
@@ -132,6 +132,21 @@ def _describe_points_delta(delta: int) -> str:
|
|||||||
return "略有损失"
|
return "略有损失"
|
||||||
|
|
||||||
|
|
||||||
|
async def _is_admin_or_owner(bot: Bot, event: Event) -> bool:
|
||||||
|
"""Check if the event sender is a group admin or owner."""
|
||||||
|
if not isinstance(event, GroupMessageEvent):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
member_info = await bot.get_group_member_info(
|
||||||
|
group_id=event.group_id,
|
||||||
|
user_id=int(event.get_user_id()),
|
||||||
|
)
|
||||||
|
return member_info.get("role", "") in ("admin", "owner")
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _build_point_changes(room: Room, odds: dict[str, float]) -> tuple[dict[str, int], dict[str, str]]:
|
def _build_point_changes(room: Room, odds: dict[str, float]) -> tuple[dict[str, int], dict[str, str]]:
|
||||||
point_changes: dict[str, int] = {}
|
point_changes: dict[str, int] = {}
|
||||||
|
|
||||||
|
|||||||
@@ -120,22 +120,28 @@ class RoomStore:
|
|||||||
room.champion_name = champion_name or ""
|
room.champion_name = champion_name or ""
|
||||||
room.tick_count = tick_count or 0
|
room.tick_count = tick_count or 0
|
||||||
# Restore horses
|
# Restore horses
|
||||||
horses_data = json.loads(horses_json)
|
try:
|
||||||
|
horses_data = json.loads(horses_json) if horses_json else {}
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
horses_data = {}
|
||||||
for name, h_data in horses_data.items():
|
for name, h_data in horses_data.items():
|
||||||
horse = Horse(
|
horse = Horse(
|
||||||
owner_id=h_data["owner_id"],
|
owner_id=h_data.get("owner_id", ""),
|
||||||
name=h_data["name"],
|
name=h_data.get("name", name),
|
||||||
index=h_data["index"],
|
index=h_data.get("index", 0),
|
||||||
)
|
)
|
||||||
horse.position = h_data.get("position", 0.0)
|
horse.position = h_data.get("position", 0.0)
|
||||||
room.horses[name] = horse
|
room.horses[name] = horse
|
||||||
# Restore bets
|
# Restore bets
|
||||||
bets_data = json.loads(bets_json)
|
try:
|
||||||
|
bets_data = json.loads(bets_json) if bets_json else []
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
bets_data = []
|
||||||
for b in bets_data:
|
for b in bets_data:
|
||||||
room.bets.append(Bet(
|
room.bets.append(Bet(
|
||||||
user_id=b["user_id"],
|
user_id=b.get("user_id", ""),
|
||||||
horse_name=b["horse_name"],
|
horse_name=b.get("horse_name", ""),
|
||||||
amount=b["amount"],
|
amount=b.get("amount", 0),
|
||||||
))
|
))
|
||||||
room.next_horse_index = max((h.index for h in room.horses.values()), default=0) + 1
|
room.next_horse_index = max((h.index for h in room.horses.values()), default=0) + 1
|
||||||
self.rooms[scope] = room
|
self.rooms[scope] = room
|
||||||
|
|||||||
Reference in New Issue
Block a user