""" Complete Entropia Nexus API Integration for Lemontropia Suite Fetches all gear types: weapons, armors, plates, attachments, enhancers, healing, rings, clothes, pets """ from decimal import Decimal from dataclasses import dataclass from typing import Optional, List, Dict, Any import requests import json import logging from functools import lru_cache logger = logging.getLogger(__name__) NEXUS_API_BASE = "https://api.entropianexus.com" # Cache durations CACHE_WEAPONS = 3600 # 1 hour CACHE_ARMORS = 3600 CACHE_HEALING = 3600 @dataclass class NexusItem: """Base class for all Nexus items.""" id: int name: str item_id: str category: str @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusItem": """Create from API response.""" raise NotImplementedError @dataclass class NexusWeapon(NexusItem): """Weapon from Entropia Nexus API.""" damage: Decimal decay: Decimal # PEC ammo_burn: int uses_per_minute: int dpp: Decimal cost_per_hour: Decimal efficiency: Decimal range_val: Decimal type: str = "" @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusWeapon": """Create from API response.""" props = data.get('Properties', {}) economy = props.get('Economy', {}) damage = props.get('Damage', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='weapon', damage=Decimal(str(damage.get('Total', 0))), decay=Decimal(str(economy.get('Decay', 0))), ammo_burn=int(economy.get('AmmoBurn', 0)), uses_per_minute=int(economy.get('UsesPerMinute', 0)), dpp=Decimal(str(economy.get('DPP', 0))), cost_per_hour=Decimal(str(economy.get('CostPerHour', 0))), efficiency=Decimal(str(props.get('Efficiency', 0))), range_val=Decimal(str(props.get('Range', 0))), type=props.get('Type', ''), ) @dataclass class NexusArmor(NexusItem): """Armor from Entropia Nexus API.""" durability: int protection_impact: Decimal protection_cut: Decimal protection_stab: Decimal protection_burn: Decimal protection_cold: Decimal protection_acid: Decimal protection_electric: Decimal type: str = "" @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusArmor": """Create from API response.""" props = data.get('Properties', {}) protection = props.get('Protection', {}) economy = props.get('Economy', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='armor', durability=int(economy.get('Durability', 2000)), protection_impact=Decimal(str(protection.get('Impact', 0))), protection_cut=Decimal(str(protection.get('Cut', 0))), protection_stab=Decimal(str(protection.get('Stab', 0))), protection_burn=Decimal(str(protection.get('Burn', 0))), protection_cold=Decimal(str(protection.get('Cold', 0))), protection_acid=Decimal(str(protection.get('Acid', 0))), protection_electric=Decimal(str(protection.get('Electric', 0))), type=props.get('Type', ''), ) @dataclass class NexusPlate(NexusItem): """Armor plate from Entropia Nexus API.""" protection_impact: Decimal protection_cut: Decimal protection_stab: Decimal protection_burn: Decimal protection_cold: Decimal decay: Decimal @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusPlate": """Create from API response.""" props = data.get('Properties', {}) protection = props.get('Protection', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='plate', protection_impact=Decimal(str(protection.get('Impact', 0))), protection_cut=Decimal(str(protection.get('Cut', 0))), protection_stab=Decimal(str(protection.get('Stab', 0))), protection_burn=Decimal(str(protection.get('Burn', 0))), protection_cold=Decimal(str(protection.get('Cold', 0))), decay=Decimal(str(props.get('Decay', 0))), ) @dataclass class NexusAttachment(NexusItem): """Weapon attachment from Entropia Nexus API.""" attachment_type: str # 'scope', 'sight', 'amplifier', 'absorber' damage_bonus: Decimal range_bonus: Decimal decay: Decimal efficiency_bonus: Decimal @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusAttachment": """Create from API response.""" props = data.get('Properties', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='attachment', attachment_type=props.get('Type', ''), damage_bonus=Decimal(str(props.get('DamageBonus', 0))), range_bonus=Decimal(str(props.get('RangeBonus', 0))), decay=Decimal(str(props.get('Decay', 0))), efficiency_bonus=Decimal(str(props.get('Efficiency', 0))), ) @dataclass class NexusEnhancer(NexusItem): """Weapon/Armor enhancer from Entropia Nexus API.""" enhancer_type: str # 'damage', 'economy', 'range', 'accuracy', etc. tier: int effect_value: Decimal break_chance: Decimal @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusEnhancer": """Create from API response.""" props = data.get('Properties', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='enhancer', enhancer_type=props.get('Type', ''), tier=int(props.get('Tier', 1)), effect_value=Decimal(str(props.get('Effect', 0))), break_chance=Decimal(str(props.get('BreakChance', 0.01))), ) @dataclass class NexusHealingTool(NexusItem): """Healing tool from Entropia Nexus API.""" heal_amount: Decimal decay: Decimal # PEC per heal heal_per_pec: Decimal type: str # 'fap', 'chip', 'pack' profession_level: int = 0 is_limited: bool = False @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusHealingTool": """Create from API response.""" props = data.get('Properties', {}) economy = props.get('Economy', {}) heal = props.get('Heal', {}) decay = Decimal(str(economy.get('Decay', 0))) heal_amount = Decimal(str(heal.get('Amount', 0))) heal_per_pec = heal_amount / decay if decay > 0 else Decimal('0') return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='healing', heal_amount=heal_amount, decay=decay, heal_per_pec=heal_per_pec, type=props.get('Type', 'fap'), profession_level=int(props.get('RequiredLevel', 0)), is_limited='(L)' in data.get('Name', ''), ) @dataclass class NexusRing(NexusItem): """Ring from Entropia Nexus API.""" effect_type: str effect_value: Decimal is_limited: bool @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusRing": """Create from API response.""" props = data.get('Properties', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='ring', effect_type=props.get('EffectType', ''), effect_value=Decimal(str(props.get('EffectValue', 0))), is_limited='(L)' in data.get('Name', ''), ) @dataclass class NexusClothing(NexusItem): """Clothing item from Entropia Nexus API.""" slot: str # 'face', 'body', 'legs', 'feet' buffs: Dict[str, Decimal] is_cosmetic: bool @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusClothing": """Create from API response.""" props = data.get('Properties', {}) buffs = {k: Decimal(str(v)) for k, v in props.get('Buffs', {}).items()} return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='clothing', slot=props.get('Slot', 'body'), buffs=buffs, is_cosmetic=props.get('IsCosmetic', True), ) @dataclass class NexusPet(NexusItem): """Pet from Entropia Nexus API.""" effect_type: str effect_value: Decimal level_required: int @classmethod def from_api(cls, data: Dict[str, Any]) -> "NexusPet": """Create from API response.""" props = data.get('Properties', {}) return cls( id=data.get('Id', 0), name=data.get('Name', 'Unknown'), item_id=str(data.get('Id', 0)), category='pet', effect_type=props.get('EffectType', ''), effect_value=Decimal(str(props.get('EffectValue', 0))), level_required=int(props.get('LevelRequired', 0)), ) class EntropiaNexusFullAPI: """Complete Entropia Nexus API client for all gear types.""" def __init__(self): self.base_url = NEXUS_API_BASE self._weapons_cache: Optional[List[NexusWeapon]] = None self._armors_cache: Optional[List[NexusArmor]] = None self._plates_cache: Optional[List[NexusPlate]] = None self._attachments_cache: Optional[List[NexusAttachment]] = None self._enhancers_cache: Optional[List[NexusEnhancer]] = None self._healing_cache: Optional[List[NexusHealingTool]] = None self._rings_cache: Optional[List[NexusRing]] = None self._clothing_cache: Optional[List[NexusClothing]] = None self._pets_cache: Optional[List[NexusPet]] = None def _fetch(self, endpoint: str) -> List[Dict]: """Fetch data from API endpoint.""" try: url = f"{self.base_url}/{endpoint}" logger.info(f"Fetching from {url}") response = requests.get(url, timeout=30) response.raise_for_status() return response.json() except Exception as e: logger.error(f"Failed to fetch {endpoint}: {e}") return [] def get_all_weapons(self, force_refresh: bool = False) -> List[NexusWeapon]: """Fetch all weapons from Nexus API.""" if self._weapons_cache is None or force_refresh: data = self._fetch("weapons") self._weapons_cache = [NexusWeapon.from_api(item) for item in data] logger.info(f"Loaded {len(self._weapons_cache)} weapons") return self._weapons_cache def get_all_armors(self, force_refresh: bool = False) -> List[NexusArmor]: """Fetch all armors from Nexus API.""" if self._armors_cache is None or force_refresh: data = self._fetch("armors") self._armors_cache = [NexusArmor.from_api(item) for item in data] logger.info(f"Loaded {len(self._armors_cache)} armors") return self._armors_cache def get_all_plates(self, force_refresh: bool = False) -> List[NexusPlate]: """Fetch all plates from Nexus API.""" if self._plates_cache is None or force_refresh: data = self._fetch("plates") self._plates_cache = [NexusPlate.from_api(item) for item in data] logger.info(f"Loaded {len(self._plates_cache)} plates") return self._plates_cache def get_all_attachments(self, force_refresh: bool = False) -> List[NexusAttachment]: """Fetch all attachments from Nexus API.""" if self._attachments_cache is None or force_refresh: data = self._fetch("attachments") self._attachments_cache = [NexusAttachment.from_api(item) for item in data] logger.info(f"Loaded {len(self._attachments_cache)} attachments") return self._attachments_cache def get_all_enhancers(self, force_refresh: bool = False) -> List[NexusEnhancer]: """Fetch all enhancers from Nexus API.""" if self._enhancers_cache is None or force_refresh: data = self._fetch("enhancers") self._enhancers_cache = [NexusEnhancer.from_api(item) for item in data] logger.info(f"Loaded {len(self._enhancers_cache)} enhancers") return self._enhancers_cache def get_all_healing_tools(self, force_refresh: bool = False) -> List[NexusHealingTool]: """Fetch all healing tools from Nexus API.""" if self._healing_cache is None or force_refresh: data = self._fetch("medicaltools") self._healing_cache = [NexusHealingTool.from_api(item) for item in data] logger.info(f"Loaded {len(self._healing_cache)} healing tools") return self._healing_cache def get_all_rings(self, force_refresh: bool = False) -> List[NexusRing]: """Fetch all rings from Nexus API.""" if self._rings_cache is None or force_refresh: data = self._fetch("rings") self._rings_cache = [NexusRing.from_api(item) for item in data] logger.info(f"Loaded {len(self._rings_cache)} rings") return self._rings_cache def get_all_clothing(self, force_refresh: bool = False) -> List[NexusClothing]: """Fetch all clothing from Nexus API.""" if self._clothing_cache is None or force_refresh: data = self._fetch("clothing") self._clothing_cache = [NexusClothing.from_api(item) for item in data] logger.info(f"Loaded {len(self._clothing_cache)} clothing items") return self._clothing_cache def get_all_pets(self, force_refresh: bool = False) -> List[NexusPet]: """Fetch all pets from Nexus API.""" if self._pets_cache is None or force_refresh: data = self._fetch("pets") self._pets_cache = [NexusPet.from_api(item) for item in data] logger.info(f"Loaded {len(self._pets_cache)} pets") return self._pets_cache def search_weapons(self, query: str) -> List[NexusWeapon]: """Search weapons by name.""" weapons = self.get_all_weapons() query_lower = query.lower() return [w for w in weapons if query_lower in w.name.lower()] def search_armors(self, query: str) -> List[NexusArmor]: """Search armors by name.""" armors = self.get_all_armors() query_lower = query.lower() return [a for a in armors if query_lower in a.name.lower()] def search_healing_tools(self, query: str) -> List[NexusHealingTool]: """Search healing tools by name.""" tools = self.get_all_healing_tools() query_lower = query.lower() return [t for t in tools if query_lower in t.name.lower()] def search_plates(self, query: str) -> List[NexusPlate]: """Search plates by name.""" plates = self.get_all_plates() query_lower = query.lower() return [p for p in plates if query_lower in p.name.lower()] def search_all(self, query: str) -> Dict[str, List]: """Search across all gear types.""" return { 'weapons': self.search_weapons(query), 'armors': self.search_armors(query), 'plates': self.search_plates(query), 'healing': self.search_healing_tools(query), 'attachments': [a for a in self.get_all_attachments() if query.lower() in a.name.lower()], 'enhancers': [e for e in self.get_all_enhancers() if query.lower() in e.name.lower()], 'rings': [r for r in self.get_all_rings() if query.lower() in r.name.lower()], 'clothing': [c for c in self.get_all_clothing() if query.lower() in c.name.lower()], 'pets': [p for p in self.get_all_pets() if query.lower() in p.name.lower()], } # Global API instance _nexus_api = None def get_nexus_api() -> EntropiaNexusFullAPI: """Get the global Nexus API instance.""" global _nexus_api if _nexus_api is None: _nexus_api = EntropiaNexusFullAPI() return _nexus_api