Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions app/marketguard_api/player_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,10 @@ def _bank_balance(profile: dict[str, Any]) -> float | None:


def _coin_purse(member: dict[str, Any]) -> float | None:
# Hypixel's v2 profile format keeps the purse under "currencies"; older payloads had it at the member root.
currencies = member.get("currencies")
if isinstance(currencies, dict) and "coin_purse" in currencies:
return _non_negative_number(currencies.get("coin_purse"))
return _non_negative_number(member.get("coin_purse"))


Expand Down Expand Up @@ -580,25 +584,29 @@ def _known_total(bank: float | None, purse: float | None, museum_value: object)


def _inventory(member: dict[str, Any], *keys: str) -> list[dict[str, object]] | None:
for key in keys:
inventory = member.get(key)
if not isinstance(inventory, dict):
# Hypixel's v2 profile format nests the inventories under "inventory"; older payloads had them at the member root.
for container in (member.get("inventory"), member):
if not isinstance(container, dict):
continue
encoded = inventory.get("data")
if not isinstance(encoded, str) or not encoded.strip():
continue
parsed = parse_inventory_nbt(encoded)
if parsed is None:
return None
return [
{
"slot": item.slot,
"id": item.item_id,
"name": item.name,
"count": item.count,
}
for item in parsed
]
for key in keys:
inventory = container.get(key)
if not isinstance(inventory, dict):
continue
encoded = inventory.get("data")
if not isinstance(encoded, str) or not encoded.strip():
continue
parsed = parse_inventory_nbt(encoded)
if parsed is None:
return None
return [
{
"slot": item.slot,
"id": item.item_id,
"name": item.name,
"count": item.count,
}
for item in parsed
]
return None


Expand Down
37 changes: 27 additions & 10 deletions tests/test_marketguard_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,18 @@ async def _hypixel_handler(request: httpx.Request) -> httpx.Response:
"banking": {"balance": 125_000_000},
"members": {
player_uuid: {
"coin_purse": 4_250_000.5,
"equippment_contents": {
"data": _encode_inventory_bytes(
[("GAUNTLET_OF_CONTAGION", "Gauntlet of Contagion", 1)]
)
},
"inv_armor": {
"data": _encode_inventory_bytes(
[("NECRON_HELMET", "Necron's Helmet", 1)]
)
"currencies": {"coin_purse": 4_250_000.5},
"inventory": {
"equipment_contents": {
"data": _encode_inventory_bytes(
[("GAUNTLET_OF_CONTAGION", "Gauntlet of Contagion", 1)]
)
},
"inv_armor": {
"data": _encode_inventory_bytes(
[("NECRON_HELMET", "Necron's Helmet", 1)]
)
},
},
"pets_data": {
"pets": [
Expand Down Expand Up @@ -3562,3 +3564,18 @@ async def add_page(self, auctions) -> None:
f"{live['peak']} pages were in flight at once, "
f"max_parallel_pages is {settings.max_parallel_pages}"
)


def test_member_purse_and_inventories_accept_v2_and_legacy_layouts() -> None:
from app.marketguard_api.player_service import _coin_purse, _inventory

armor = {"data": _encode_inventory_bytes([("NECRON_HELMET", "Necron's Helmet", 1)])}
v2_member = {"currencies": {"coin_purse": 12.5}, "inventory": {"inv_armor": armor}}
legacy_member = {"coin_purse": 7.0, "inv_armor": armor}

assert _coin_purse(v2_member) == 12.5
assert _coin_purse(legacy_member) == 7.0
assert _coin_purse({"currencies": {}}) is None
assert _inventory(v2_member, "inv_armor")[0]["id"] == "NECRON_HELMET"
assert _inventory(legacy_member, "inv_armor")[0]["id"] == "NECRON_HELMET"
assert _inventory({"inventory": {}}, "inv_armor") is None