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
|
||||
"""
|
||||
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, List, Dict, Any
|
||||
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
|
||||
class NexusHealingTool(NexusItem):
|
||||
"""Healing tool from Entropia Nexus API."""
|
||||
|
|
@ -208,8 +218,8 @@ class NexusHealingTool(NexusItem):
|
|||
economy = props.get('Economy', {})
|
||||
heal = props.get('Heal', {})
|
||||
|
||||
decay = Decimal(str(economy.get('Decay', 0)))
|
||||
heal_amount = Decimal(str(heal.get('Amount', 0)))
|
||||
decay = safe_decimal(economy.get('Decay'))
|
||||
heal_amount = safe_decimal(heal.get('Amount'))
|
||||
heal_per_pec = heal_amount / decay if decay > 0 else Decimal('0')
|
||||
|
||||
return cls(
|
||||
|
|
@ -221,7 +231,7 @@ class NexusHealingTool(NexusItem):
|
|||
decay=decay,
|
||||
heal_per_pec=heal_per_pec,
|
||||
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', ''),
|
||||
)
|
||||
|
||||
|
|
@ -242,14 +252,14 @@ class NexusRing(NexusItem):
|
|||
props = data.get('Properties', {})
|
||||
economy = props.get('Economy', {})
|
||||
effects_data = props.get('Effects', {})
|
||||
|
||||
|
||||
# Parse effects (usually under "Effects on Equip")
|
||||
effects = {}
|
||||
if 'Effects on Equip' in effects_data:
|
||||
effects = effects_data['Effects on Equip']
|
||||
elif isinstance(effects_data, dict):
|
||||
effects = effects_data
|
||||
|
||||
|
||||
return cls(
|
||||
id=data.get('Id', 0),
|
||||
name=data.get('Name', 'Unknown'),
|
||||
|
|
@ -258,8 +268,8 @@ class NexusRing(NexusItem):
|
|||
slot=props.get('Slot', 'Left Finger'),
|
||||
gender=props.get('Gender', 'Both'),
|
||||
effects=effects,
|
||||
max_tt=Decimal(str(economy.get('MaxTT', 0))),
|
||||
min_tt=Decimal(str(economy.get('MinTT', 0))),
|
||||
max_tt=safe_decimal(economy.get('MaxTT')),
|
||||
min_tt=safe_decimal(economy.get('MinTT')),
|
||||
is_limited='(L)' in data.get('Name', ''),
|
||||
)
|
||||
|
||||
|
|
@ -270,13 +280,19 @@ class NexusClothing(NexusItem):
|
|||
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()}
|
||||
|
||||
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(
|
||||
id=data.get('Id', 0),
|
||||
name=data.get('Name', 'Unknown'),
|
||||
|
|
|
|||
Loading…
Reference in New Issue