445 lines
16 KiB
Python
445 lines
16 KiB
Python
"""
|
|
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=data.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=data.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=data.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=data.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=data.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=data.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 |