internal async Task <HashSet <Steam.Item> > GetMySteamInventory(bool tradable) { if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) { return(null); } HashSet <Steam.Item> result = new HashSet <Steam.Item>(); string request = SteamCommunityURL + "/my/inventory/json/" + Steam.Item.SteamAppID + "/" + Steam.Item.SteamContextID + "?l=english&trading=" + (tradable ? "1" : "0") + "&start="; uint currentPage = 0; while (true) { JObject jObject = await WebBrowser.UrlGetToJObjectRetry(request + currentPage).ConfigureAwait(false); IEnumerable <JToken> descriptions = jObject?.SelectTokens("$.rgDescriptions.*"); if (descriptions == null) { return(null); // OK, empty inventory } Dictionary <ulong, Tuple <uint, Steam.Item.EType> > descriptionMap = new Dictionary <ulong, Tuple <uint, Steam.Item.EType> >(); foreach (JToken description in descriptions.Where(description => description != null)) { string classIDString = description["classid"].ToString(); if (string.IsNullOrEmpty(classIDString)) { Logging.LogNullError(nameof(classIDString), Bot.BotName); return(null); } ulong classID; if (!ulong.TryParse(classIDString, out classID) || (classID == 0)) { Logging.LogNullError(nameof(classID), Bot.BotName); return(null); } if (descriptionMap.ContainsKey(classID)) { continue; } uint appID = 0; string hashName = description["market_hash_name"].ToString(); if (!string.IsNullOrEmpty(hashName)) { appID = GetAppIDFromMarketHashName(hashName); } if (appID == 0) { string appIDString = description["appid"].ToString(); if (string.IsNullOrEmpty(appIDString)) { Logging.LogNullError(nameof(appIDString), Bot.BotName); return(null); } if (!uint.TryParse(appIDString, out appID)) { Logging.LogNullError(nameof(appID), Bot.BotName); return(null); } } Steam.Item.EType type = Steam.Item.EType.Unknown; string descriptionType = description["type"].ToString(); if (!string.IsNullOrEmpty(descriptionType)) { type = GetItemType(descriptionType); } descriptionMap[classID] = new Tuple <uint, Steam.Item.EType>(appID, type); } IEnumerable <JToken> items = jObject.SelectTokens("$.rgInventory.*"); if (items == null) { Logging.LogNullError(nameof(items), Bot.BotName); return(null); } foreach (JToken item in items.Where(item => item != null)) { Steam.Item steamItem; try { steamItem = item.ToObject <Steam.Item>(); } catch (JsonException e) { Logging.LogGenericException(e, Bot.BotName); return(null); } if (steamItem == null) { Logging.LogNullError(nameof(steamItem), Bot.BotName); return(null); } Tuple <uint, Steam.Item.EType> description; if (descriptionMap.TryGetValue(steamItem.ClassID, out description)) { steamItem.RealAppID = description.Item1; steamItem.Type = description.Item2; } result.Add(steamItem); } bool more; if (!bool.TryParse(jObject["more"].ToString(), out more) || !more) { break; // OK, last page } uint nextPage; if (!uint.TryParse(jObject["more_start"].ToString(), out nextPage) || (nextPage <= currentPage)) { Logging.LogNullError(nameof(nextPage), Bot.BotName); return(null); } currentPage = nextPage; } return(result); }