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:
LemonNexus 2026-02-09 14:35:12 +00:00
parent ad3d8e535a
commit 9decd0ba5d
1 changed files with 27 additions and 11 deletions

View File

@ -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'),