From c8898f6aa2326f778bb5aa5cecc2a5969a0128bf Mon Sep 17 00:00:00 2001 From: JustArchi Date: Mon, 8 Jul 2019 12:41:56 +0200 Subject: [PATCH] Open a few more AWH functions --- ArchiSteamFarm/ArchiWebHandler.cs | 361 +++++++++++++++--------------- 1 file changed, 182 insertions(+), 179 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 6a2150b88..5105fd2f0 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -238,6 +238,188 @@ namespace ArchiSteamFarm { } } + [ItemCanBeNull] + [PublicAPI] + public async Task> GetMyOwnedGames() { + const string request = "/my/games?l=english&xml=1"; + + XmlDocument response = await UrlGetToXmlDocumentWithSession(SteamCommunityURL, request, false).ConfigureAwait(false); + + XmlNodeList xmlNodeList = response?.SelectNodes("gamesList/games/game"); + + if ((xmlNodeList == null) || (xmlNodeList.Count == 0)) { + return null; + } + + Dictionary result = new Dictionary(xmlNodeList.Count); + + foreach (XmlNode xmlNode in xmlNodeList) { + XmlNode appNode = xmlNode.SelectSingleNode("appID"); + + if (appNode == null) { + Bot.ArchiLogger.LogNullError(nameof(appNode)); + + return null; + } + + if (!uint.TryParse(appNode.InnerText, out uint appID) || (appID == 0)) { + Bot.ArchiLogger.LogNullError(nameof(appID)); + + return null; + } + + XmlNode nameNode = xmlNode.SelectSingleNode("name"); + + if (nameNode == null) { + Bot.ArchiLogger.LogNullError(nameof(nameNode)); + + return null; + } + + result[appID] = nameNode.InnerText; + } + + return result; + } + + [ItemCanBeNull] + [PublicAPI] + public async Task> GetOwnedGames(ulong steamID) { + if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount) { + Bot.ArchiLogger.LogNullError(nameof(steamID)); + + return null; + } + + (bool success, string steamApiKey) = await CachedApiKey.GetValue().ConfigureAwait(false); + + if (!success || string.IsNullOrEmpty(steamApiKey)) { + return null; + } + + KeyValue response = null; + + for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) { + using (WebAPI.AsyncInterface iPlayerService = Bot.SteamConfiguration.GetAsyncWebAPIInterface(IPlayerService)) { + iPlayerService.Timeout = WebBrowser.Timeout; + + try { + response = await WebLimitRequest( + WebAPI.DefaultBaseAddress.Host, + + // ReSharper disable once AccessToDisposedClosure + async () => await iPlayerService.CallAsync( + HttpMethod.Get, "GetOwnedGames", args: new Dictionary(3, StringComparer.Ordinal) { + { "include_appinfo", 1 }, + { "key", steamApiKey }, + { "steamid", steamID } + } + ).ConfigureAwait(false) + ).ConfigureAwait(false); + } catch (TaskCanceledException e) { + Bot.ArchiLogger.LogGenericDebuggingException(e); + } catch (Exception e) { + Bot.ArchiLogger.LogGenericWarningException(e); + } + } + } + + if (response == null) { + Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)); + + return null; + } + + List games = response["games"].Children; + + Dictionary result = new Dictionary(games.Count); + + foreach (KeyValue game in games) { + uint appID = game["appid"].AsUnsignedInteger(); + + if (appID == 0) { + Bot.ArchiLogger.LogNullError(nameof(appID)); + + return null; + } + + result[appID] = game["name"].AsString(); + } + + return result; + } + + [PublicAPI] + public async Task<(bool Success, HashSet MobileTradeOfferIDs)> SendTradeOffer(ulong steamID, IReadOnlyCollection itemsToGive = null, IReadOnlyCollection itemsToReceive = null, string token = null, bool forcedSingleOffer = false) { + if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount || (((itemsToGive == null) || (itemsToGive.Count == 0)) && ((itemsToReceive == null) || (itemsToReceive.Count == 0)))) { + Bot.ArchiLogger.LogNullError(nameof(steamID) + " || (" + nameof(itemsToGive) + " && " + nameof(itemsToReceive) + ")"); + + return (false, null); + } + + Steam.TradeOfferSendRequest singleTrade = new Steam.TradeOfferSendRequest(); + HashSet trades = new HashSet { singleTrade }; + + if (itemsToGive != null) { + foreach (Steam.Asset itemToGive in itemsToGive) { + if (!forcedSingleOffer && (singleTrade.ItemsToGive.Assets.Count + singleTrade.ItemsToReceive.Assets.Count >= Trading.MaxItemsPerTrade)) { + if (trades.Count >= Trading.MaxTradesPerAccount) { + break; + } + + singleTrade = new Steam.TradeOfferSendRequest(); + trades.Add(singleTrade); + } + + singleTrade.ItemsToGive.Assets.Add(itemToGive); + } + } + + if (itemsToReceive != null) { + foreach (Steam.Asset itemToReceive in itemsToReceive) { + if (!forcedSingleOffer && (singleTrade.ItemsToGive.Assets.Count + singleTrade.ItemsToReceive.Assets.Count >= Trading.MaxItemsPerTrade)) { + if (trades.Count >= Trading.MaxTradesPerAccount) { + break; + } + + singleTrade = new Steam.TradeOfferSendRequest(); + trades.Add(singleTrade); + } + + singleTrade.ItemsToReceive.Assets.Add(itemToReceive); + } + } + + const string request = "/tradeoffer/new/send"; + const string referer = SteamCommunityURL + "/tradeoffer/new"; + + // Extra entry for sessionID + Dictionary data = new Dictionary(6, StringComparer.Ordinal) { + { "partner", steamID.ToString() }, + { "serverid", "1" }, + { "trade_offer_create_params", !string.IsNullOrEmpty(token) ? new JObject { { "trade_offer_access_token", token } }.ToString(Formatting.None) : "" }, + { "tradeoffermessage", "Sent by " + SharedInfo.PublicIdentifier + "/" + SharedInfo.Version } + }; + + HashSet mobileTradeOfferIDs = new HashSet(); + + foreach (Steam.TradeOfferSendRequest trade in trades) { + data["json_tradeoffer"] = JsonConvert.SerializeObject(trade); + + Steam.TradeOfferSendResponse response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data, referer).ConfigureAwait(false); + + if (response == null) { + return (false, mobileTradeOfferIDs); + } + + if (response.RequiresMobileConfirmation) { + mobileTradeOfferIDs.Add(response.TradeOfferID); + } + } + + return (true, mobileTradeOfferIDs); + } + [PublicAPI] public async Task UrlGetToHtmlDocumentWithSession(string host, string request, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request)) { @@ -1584,115 +1766,6 @@ namespace ArchiSteamFarm { return await UrlGetToHtmlDocumentWithSession(SteamCommunityURL, request, false).ConfigureAwait(false); } - [ItemCanBeNull] - internal async Task> GetMyOwnedGames() { - const string request = "/my/games?l=english&xml=1"; - - XmlDocument response = await UrlGetToXmlDocumentWithSession(SteamCommunityURL, request, false).ConfigureAwait(false); - - XmlNodeList xmlNodeList = response?.SelectNodes("gamesList/games/game"); - - if ((xmlNodeList == null) || (xmlNodeList.Count == 0)) { - return null; - } - - Dictionary result = new Dictionary(xmlNodeList.Count); - - foreach (XmlNode xmlNode in xmlNodeList) { - XmlNode appNode = xmlNode.SelectSingleNode("appID"); - - if (appNode == null) { - Bot.ArchiLogger.LogNullError(nameof(appNode)); - - return null; - } - - if (!uint.TryParse(appNode.InnerText, out uint appID) || (appID == 0)) { - Bot.ArchiLogger.LogNullError(nameof(appID)); - - return null; - } - - XmlNode nameNode = xmlNode.SelectSingleNode("name"); - - if (nameNode == null) { - Bot.ArchiLogger.LogNullError(nameof(nameNode)); - - return null; - } - - result[appID] = nameNode.InnerText; - } - - return result; - } - - [ItemCanBeNull] - internal async Task> GetOwnedGames(ulong steamID) { - if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount) { - Bot.ArchiLogger.LogNullError(nameof(steamID)); - - return null; - } - - (bool success, string steamApiKey) = await CachedApiKey.GetValue().ConfigureAwait(false); - - if (!success || string.IsNullOrEmpty(steamApiKey)) { - return null; - } - - KeyValue response = null; - - for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) { - using (WebAPI.AsyncInterface iPlayerService = Bot.SteamConfiguration.GetAsyncWebAPIInterface(IPlayerService)) { - iPlayerService.Timeout = WebBrowser.Timeout; - - try { - response = await WebLimitRequest( - WebAPI.DefaultBaseAddress.Host, - - // ReSharper disable once AccessToDisposedClosure - async () => await iPlayerService.CallAsync( - HttpMethod.Get, "GetOwnedGames", args: new Dictionary(3, StringComparer.Ordinal) { - { "include_appinfo", 1 }, - { "key", steamApiKey }, - { "steamid", steamID } - } - ).ConfigureAwait(false) - ).ConfigureAwait(false); - } catch (TaskCanceledException e) { - Bot.ArchiLogger.LogGenericDebuggingException(e); - } catch (Exception e) { - Bot.ArchiLogger.LogGenericWarningException(e); - } - } - } - - if (response == null) { - Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)); - - return null; - } - - List games = response["games"].Children; - - Dictionary result = new Dictionary(games.Count); - - foreach (KeyValue game in games) { - uint appID = game["appid"].AsUnsignedInteger(); - - if (appID == 0) { - Bot.ArchiLogger.LogNullError(nameof(appID)); - - return null; - } - - result[appID] = game["name"].AsString(); - } - - return result; - } - internal async Task GetServerTime() { KeyValue response = null; @@ -2163,76 +2236,6 @@ namespace ArchiSteamFarm { return ((responseConfirmRedeem.PurchaseResultDetail == EPurchaseResultDetail.NoDetail) && (responseConfirmRedeem.Result == EResult.OK) ? responseConfirmRedeem.Result : EResult.Fail, responseConfirmRedeem.PurchaseResultDetail); } - internal async Task<(bool Success, HashSet MobileTradeOfferIDs)> SendTradeOffer(ulong steamID, IReadOnlyCollection itemsToGive = null, IReadOnlyCollection itemsToReceive = null, string token = null, bool forcedSingleOffer = false) { - if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount || (((itemsToGive == null) || (itemsToGive.Count == 0)) && ((itemsToReceive == null) || (itemsToReceive.Count == 0)))) { - Bot.ArchiLogger.LogNullError(nameof(steamID) + " || (" + nameof(itemsToGive) + " && " + nameof(itemsToReceive) + ")"); - - return (false, null); - } - - Steam.TradeOfferSendRequest singleTrade = new Steam.TradeOfferSendRequest(); - HashSet trades = new HashSet { singleTrade }; - - if (itemsToGive != null) { - foreach (Steam.Asset itemToGive in itemsToGive) { - if (!forcedSingleOffer && (singleTrade.ItemsToGive.Assets.Count + singleTrade.ItemsToReceive.Assets.Count >= Trading.MaxItemsPerTrade)) { - if (trades.Count >= Trading.MaxTradesPerAccount) { - break; - } - - singleTrade = new Steam.TradeOfferSendRequest(); - trades.Add(singleTrade); - } - - singleTrade.ItemsToGive.Assets.Add(itemToGive); - } - } - - if (itemsToReceive != null) { - foreach (Steam.Asset itemToReceive in itemsToReceive) { - if (!forcedSingleOffer && (singleTrade.ItemsToGive.Assets.Count + singleTrade.ItemsToReceive.Assets.Count >= Trading.MaxItemsPerTrade)) { - if (trades.Count >= Trading.MaxTradesPerAccount) { - break; - } - - singleTrade = new Steam.TradeOfferSendRequest(); - trades.Add(singleTrade); - } - - singleTrade.ItemsToReceive.Assets.Add(itemToReceive); - } - } - - const string request = "/tradeoffer/new/send"; - const string referer = SteamCommunityURL + "/tradeoffer/new"; - - // Extra entry for sessionID - Dictionary data = new Dictionary(6, StringComparer.Ordinal) { - { "partner", steamID.ToString() }, - { "serverid", "1" }, - { "trade_offer_create_params", string.IsNullOrEmpty(token) ? "" : new JObject { { "trade_offer_access_token", token } }.ToString(Formatting.None) }, - { "tradeoffermessage", "Sent by " + SharedInfo.PublicIdentifier + "/" + SharedInfo.Version } - }; - - HashSet mobileTradeOfferIDs = new HashSet(); - - foreach (Steam.TradeOfferSendRequest trade in trades) { - data["json_tradeoffer"] = JsonConvert.SerializeObject(trade); - - Steam.TradeOfferSendResponse response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data, referer).ConfigureAwait(false); - - if (response == null) { - return (false, mobileTradeOfferIDs); - } - - if (response.RequiresMobileConfirmation) { - mobileTradeOfferIDs.Add(response.TradeOfferID); - } - } - - return (true, mobileTradeOfferIDs); - } - internal async Task UnpackBooster(uint appID, ulong itemID) { if ((appID == 0) || (itemID == 0)) { Bot.ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(itemID));