fix(api): handle null/None values in API parsing
Added safe_decimal() helper to handle None/empty values from API that were causing decimal.ConversionSyntax errors. Fixed parsers: - NexusHealingTool: Uses safe_decimal for decay/heal amounts - NexusRing: Uses safe_decimal for max_tt/min_tt - NexusClothing: Safely handles None buff values Errors were occurring when API returned null for numeric fields instead of 0.
This commit is contained in:
parent
ad3d8e535a
commit
9decd0ba5d
|
|
@ -3,7 +3,7 @@ Complete Entropia Nexus API Integration for Lemontropia Suite
|
||||||
Fetches all gear types: weapons, armors, plates, attachments, enhancers, healing, rings, clothes, pets
|
Fetches all gear types: weapons, armors, plates, attachments, enhancers, healing, rings, clothes, pets
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal, InvalidOperation
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional, List, Dict, Any
|
from typing import Optional, List, Dict, Any
|
||||||
import requests
|
import requests
|
||||||
|
|
@ -191,6 +191,16 @@ class NexusEnhancer(NexusItem):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def safe_decimal(value: Any, default: str = "0") -> Decimal:
|
||||||
|
"""Safely convert a value to Decimal, handling None and invalid values."""
|
||||||
|
if value is None or value == "":
|
||||||
|
return Decimal(default)
|
||||||
|
try:
|
||||||
|
return Decimal(str(value))
|
||||||
|
except (InvalidOperation, ValueError, TypeError):
|
||||||
|
return Decimal(default)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class NexusHealingTool(NexusItem):
|
class NexusHealingTool(NexusItem):
|
||||||
"""Healing tool from Entropia Nexus API."""
|
"""Healing tool from Entropia Nexus API."""
|
||||||
|
|
@ -208,8 +218,8 @@ class NexusHealingTool(NexusItem):
|
||||||
economy = props.get('Economy', {})
|
economy = props.get('Economy', {})
|
||||||
heal = props.get('Heal', {})
|
heal = props.get('Heal', {})
|
||||||
|
|
||||||
decay = Decimal(str(economy.get('Decay', 0)))
|
decay = safe_decimal(economy.get('Decay'))
|
||||||
heal_amount = Decimal(str(heal.get('Amount', 0)))
|
heal_amount = safe_decimal(heal.get('Amount'))
|
||||||
heal_per_pec = heal_amount / decay if decay > 0 else Decimal('0')
|
heal_per_pec = heal_amount / decay if decay > 0 else Decimal('0')
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
|
|
@ -221,7 +231,7 @@ class NexusHealingTool(NexusItem):
|
||||||
decay=decay,
|
decay=decay,
|
||||||
heal_per_pec=heal_per_pec,
|
heal_per_pec=heal_per_pec,
|
||||||
type=props.get('Type', 'fap'),
|
type=props.get('Type', 'fap'),
|
||||||
profession_level=int(props.get('RequiredLevel', 0)),
|
profession_level=int(props.get('RequiredLevel', 0) or 0),
|
||||||
is_limited='(L)' in data.get('Name', ''),
|
is_limited='(L)' in data.get('Name', ''),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -242,14 +252,14 @@ class NexusRing(NexusItem):
|
||||||
props = data.get('Properties', {})
|
props = data.get('Properties', {})
|
||||||
economy = props.get('Economy', {})
|
economy = props.get('Economy', {})
|
||||||
effects_data = props.get('Effects', {})
|
effects_data = props.get('Effects', {})
|
||||||
|
|
||||||
# Parse effects (usually under "Effects on Equip")
|
# Parse effects (usually under "Effects on Equip")
|
||||||
effects = {}
|
effects = {}
|
||||||
if 'Effects on Equip' in effects_data:
|
if 'Effects on Equip' in effects_data:
|
||||||
effects = effects_data['Effects on Equip']
|
effects = effects_data['Effects on Equip']
|
||||||
elif isinstance(effects_data, dict):
|
elif isinstance(effects_data, dict):
|
||||||
effects = effects_data
|
effects = effects_data
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
id=data.get('Id', 0),
|
id=data.get('Id', 0),
|
||||||
name=data.get('Name', 'Unknown'),
|
name=data.get('Name', 'Unknown'),
|
||||||
|
|
@ -258,8 +268,8 @@ class NexusRing(NexusItem):
|
||||||
slot=props.get('Slot', 'Left Finger'),
|
slot=props.get('Slot', 'Left Finger'),
|
||||||
gender=props.get('Gender', 'Both'),
|
gender=props.get('Gender', 'Both'),
|
||||||
effects=effects,
|
effects=effects,
|
||||||
max_tt=Decimal(str(economy.get('MaxTT', 0))),
|
max_tt=safe_decimal(economy.get('MaxTT')),
|
||||||
min_tt=Decimal(str(economy.get('MinTT', 0))),
|
min_tt=safe_decimal(economy.get('MinTT')),
|
||||||
is_limited='(L)' in data.get('Name', ''),
|
is_limited='(L)' in data.get('Name', ''),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -270,13 +280,19 @@ class NexusClothing(NexusItem):
|
||||||
slot: str # 'face', 'body', 'legs', 'feet'
|
slot: str # 'face', 'body', 'legs', 'feet'
|
||||||
buffs: Dict[str, Decimal]
|
buffs: Dict[str, Decimal]
|
||||||
is_cosmetic: bool
|
is_cosmetic: bool
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_api(cls, data: Dict[str, Any]) -> "NexusClothing":
|
def from_api(cls, data: Dict[str, Any]) -> "NexusClothing":
|
||||||
"""Create from API response."""
|
"""Create from API response."""
|
||||||
props = data.get('Properties', {})
|
props = data.get('Properties', {})
|
||||||
buffs = {k: Decimal(str(v)) for k, v in props.get('Buffs', {}).items()}
|
buffs_raw = props.get('Buffs', {}) or {}
|
||||||
|
buffs = {}
|
||||||
|
for k, v in buffs_raw.items():
|
||||||
|
try:
|
||||||
|
buffs[k] = safe_decimal(v)
|
||||||
|
except:
|
||||||
|
buffs[k] = Decimal('0')
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
id=data.get('Id', 0),
|
id=data.get('Id', 0),
|
||||||
name=data.get('Name', 'Unknown'),
|
name=data.get('Name', 'Unknown'),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue