""" Card master data fetcher from external ai.json """ import httpx import json from typing import Dict, List, Optional from functools import lru_cache import logging logger = logging.getLogger(__name__) CARD_MASTER_URL = "https://git.syui.ai/ai/ai/raw/branch/main/ai.json" # Default CP ranges for cards (matching existing gacha.py values) DEFAULT_CP_RANGES = { 0: (10, 100), 1: (20, 120), 2: (30, 130), 3: (40, 140), 4: (50, 150), 5: (25, 125), 6: (15, 115), 7: (60, 160), 8: (80, 180), 9: (70, 170), 10: (90, 190), 11: (35, 135), 12: (65, 165), 13: (75, 175), 14: (100, 200), 15: (85, 185), 135: (95, 195), # world card } class CardMasterService: def __init__(self): self._cache = None self._cache_time = 0 self._cache_duration = 3600 # 1 hour cache @lru_cache(maxsize=1) def fetch_card_master_data(self) -> Optional[Dict]: """Fetch card master data from external source""" try: response = httpx.get(CARD_MASTER_URL, timeout=10.0) response.raise_for_status() data = response.json() return data except Exception as e: logger.error(f"Failed to fetch card master data: {e}") return None def get_card_info(self) -> Dict[int, Dict]: """Get card information in the format expected by gacha service""" master_data = self.fetch_card_master_data() if not master_data: # Fallback to hardcoded data return self._get_fallback_card_info() try: cards = master_data.get("ai", {}).get("card", {}).get("cards", []) card_info = {} for card in cards: card_id = card.get("id") if card_id is not None: # Use name from JSON, fallback to English name name = card.get("name", f"card_{card_id}") # Get CP range from defaults cp_range = DEFAULT_CP_RANGES.get(card_id, (50, 150)) card_info[card_id] = { "name": name, "base_cp_range": cp_range, "ja_name": card.get("lang", {}).get("ja", {}).get("name", name), "description": card.get("lang", {}).get("ja", {}).get("text", "") } return card_info except Exception as e: logger.error(f"Failed to parse card master data: {e}") return self._get_fallback_card_info() def _get_fallback_card_info(self) -> Dict[int, Dict]: """Fallback card info if external source fails""" return { 0: {"name": "ai", "base_cp_range": (10, 100)}, 1: {"name": "dream", "base_cp_range": (20, 120)}, 2: {"name": "radiance", "base_cp_range": (30, 130)}, 3: {"name": "neutron", "base_cp_range": (40, 140)}, 4: {"name": "sun", "base_cp_range": (50, 150)}, 5: {"name": "night", "base_cp_range": (25, 125)}, 6: {"name": "snow", "base_cp_range": (15, 115)}, 7: {"name": "thunder", "base_cp_range": (60, 160)}, 8: {"name": "ultimate", "base_cp_range": (80, 180)}, 9: {"name": "sword", "base_cp_range": (70, 170)}, 10: {"name": "destruction", "base_cp_range": (90, 190)}, 11: {"name": "earth", "base_cp_range": (35, 135)}, 12: {"name": "galaxy", "base_cp_range": (65, 165)}, 13: {"name": "create", "base_cp_range": (75, 175)}, 14: {"name": "supernova", "base_cp_range": (100, 200)}, 15: {"name": "world", "base_cp_range": (85, 185)}, } def get_all_cards(self) -> List[Dict]: """Get all cards with full information""" master_data = self.fetch_card_master_data() if not master_data: return [] try: cards = master_data.get("ai", {}).get("card", {}).get("cards", []) result = [] for card in cards: card_id = card.get("id") if card_id is not None: cp_range = DEFAULT_CP_RANGES.get(card_id, (50, 150)) result.append({ "id": card_id, "name": card.get("name", f"card_{card_id}"), "ja_name": card.get("lang", {}).get("ja", {}).get("name", ""), "description": card.get("lang", {}).get("ja", {}).get("text", ""), "base_cp_min": cp_range[0], "base_cp_max": cp_range[1] }) return result except Exception as e: logger.error(f"Failed to get all cards: {e}") return [] # Singleton instance card_master_service = CardMasterService()