Skip to content

Commit

Permalink
🚑 Fix: parsing trade offers raise KeyError if asset from offer have…
Browse files Browse the repository at this point in the history
… non-predefined game/app. v0.6.1
  • Loading branch information
somespecialone committed Aug 21, 2024
1 parent f28200d commit 5423eea
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 11 deletions.
5 changes: 2 additions & 3 deletions aiosteampy/mixins/public.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,8 @@ def _find_game_for_asset(description_data: dict[str, int], assets: list[dict[str
try:
return Game(description_data["appid"])
except ValueError:
for asset in assets:
if asset["classid"] == description_data["classid"]:
return asset["appid"], int(asset["contextid"])
res: dict = next(filter(lambda a: a["classid"] == description_data["classid"], assets))
return res["appid"], int(res["contextid"])

@classmethod
def _parse_items(
Expand Down
33 changes: 26 additions & 7 deletions aiosteampy/mixins/trade.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from yarl import URL

from ..typed import TradeOffersSummary
from ..constants import STEAM_URL, CORO, T_HEADERS, T_PARAMS, T_PAYLOAD, EResult
from ..constants import STEAM_URL, CORO, T_HEADERS, T_PARAMS, T_PAYLOAD
from ..exceptions import EResultError, SteamError
from ..models import (
TradeOffer,
Expand Down Expand Up @@ -54,16 +54,30 @@ async def get_trade_offer(self, offer_id: int, *, params: T_PARAMS = {}, headers

data: dict[str, dict | list[dict]] = rj["response"]
item_descrc_map = {}
self._update_item_descrs_map_for_trades(data["descriptions"], item_descrc_map)
self._update_item_descrs_map_for_trades(data, item_descrc_map)

return self._create_trade_offer(data["offer"], item_descrc_map)

# temporary fix/workaround
@staticmethod
def _combine_assets(data: dict[str, dict[str, list[dict]]]) -> list[dict]:
res = []
for offer in [
*data.get("trade_offers_received", ()),
*data.get("trade_offers_sent", ()),
data.get("offer", {}),
]:
offer: dict
for asset in [*offer.get("items_to_give", ()), *offer.get("items_to_receive", ())]:
res.append(asset)
return res

@classmethod
def _update_item_descrs_map_for_trades(cls, data: list[dict], item_descrs_map: dict[str, dict]):
for desc in data:
def _update_item_descrs_map_for_trades(cls, data: dict, item_descrs_map: dict[str, dict]):
for desc in data["descriptions"]:
key = create_ident_code(desc["classid"], desc["appid"])
if key not in item_descrs_map:
item_descrs_map[key] = cls._create_item_description_kwargs(desc, [desc])
item_descrs_map[key] = cls._create_item_description_kwargs(desc, cls._combine_assets(data))

def _create_trade_offer(self, data: dict, item_descrs_map: dict[str, dict]) -> TradeOffer:
return TradeOffer(
Expand All @@ -87,7 +101,7 @@ def _parse_items_for_trade(cls, items: list[dict], item_descrs_map: dict[str, di
asset_id=a_data["assetid"],
amount=int(a_data["amount"]),
missing=a_data["missing"],
est_usd=int(a_data["est_usd"]),
est_usd=int(a_data.get("est_usd", 0)),
**item_descrs_map[create_ident_code(a_data["classid"], a_data["appid"])],
)
for a_data in items
Expand Down Expand Up @@ -138,6 +152,8 @@ async def get_trade_offers(
.. note:: You can paginate by yourself passing `cursor` arg.
Returned cursor with 0 value means that there is no more pages
.. seealso:: https://steamapi.xpaw.me/#IEconService/GetTradeOffers
:param active_only: fetch active, changed since `time_historical_cutoff` tradeoffs only or not
:param time_historical_cutoff: timestamp for `active_only`
:param historical_only: opposite for `active_only`
Expand Down Expand Up @@ -181,8 +197,11 @@ async def get_trade_offers(
raise EResultError("Failed to fetch trade offers", e.result, e.data) from e

data: dict[str, dict | list[dict]] = rj["response"]
self._update_item_descrs_map_for_trades(data["descriptions"], _item_descriptions_map)
self._update_item_descrs_map_for_trades(data, _item_descriptions_map)

# TODO rethink way of sharing descriptions instead of descr args
# TODO sometimes there is no descriptions for items in trades, because of course
# TODO check node-steam-tradaoffer-manager for this moment
sent_offers = [self._create_trade_offer(d, _item_descriptions_map) for d in data.get("trade_offers_sent", ())]
received_offers = [
self._create_trade_offer(d, _item_descriptions_map) for d in data.get("trade_offers_received", ())
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "aiosteampy"
version = "0.6.0"
version = "0.6.1"
description = "Trade and interact with steam market, webapi, guard"
license = "MIT"
authors = ["Dmytro Tkachenko <[email protected]>"]
Expand Down

0 comments on commit 5423eea

Please sign in to comment.