From c3d6a6103e150c3105af0c4ca29b4b7bd8526f57 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sun, 23 Jul 2017 03:43:20 +0200 Subject: [PATCH] Closes #537 --- ArchiSteamFarm/ArchiWebHandler.cs | 27 +++++++ ArchiSteamFarm/Bot.cs | 113 ++++++++++++++++++++++++------ ArchiSteamFarm/JSON/Steam.cs | 15 +++- ArchiSteamFarm/Utilities.cs | 27 ------- 4 files changed, 133 insertions(+), 49 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 43d552257..25ff7c724 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -1088,6 +1088,33 @@ namespace ArchiSteamFarm { return true; } + internal async Task UnpackBooster(uint appID, ulong itemID) { + if ((appID == 0) || (itemID == 0)) { + Bot.ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(itemID)); + return false; + } + + if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) { + return false; + } + + string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid"); + if (string.IsNullOrEmpty(sessionID)) { + Bot.ArchiLogger.LogNullError(nameof(sessionID)); + return false; + } + + string request = SteamCommunityURL + "/profiles/" + SteamID + "/ajaxunpackbooster"; + Dictionary data = new Dictionary(3) { + { "sessionid", sessionID }, + { "appid", appID.ToString() }, + { "communityitemid", itemID.ToString() } + }; + + Steam.GenericResponse response = await WebBrowser.UrlPostToJsonResultRetry(request, data).ConfigureAwait(false); + return response?.Result == EResult.OK; + } + private async Task GetApiKey() { if (CachedApiKey != null) { // We fetched API key already, and either got valid one, or permanent AccessDenied diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 172984db2..85dde7cb6 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -663,6 +663,8 @@ namespace ArchiSteamFarm { return ResponseStatus(steamID); case "!STOP": return ResponseStop(steamID); + case "!UNPACK": + return await ResponseUnpackBoosters(steamID).ConfigureAwait(false); case "!UPDATE": return await ResponseUpdate(steamID).ConfigureAwait(false); case "!VERSION": @@ -682,7 +684,7 @@ namespace ArchiSteamFarm { return await Response2FAConfirm(steamID, args[1], true).ConfigureAwait(false); case "!ADDLICENSE": if (args.Length > 2) { - return await ResponseAddLicense(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseAddLicense(steamID, args[1], args[2]).ConfigureAwait(false); } return await ResponseAddLicense(steamID, args[1]).ConfigureAwait(false); @@ -692,13 +694,13 @@ namespace ArchiSteamFarm { return await ResponseBlacklist(steamID, args[1]).ConfigureAwait(false); case "!BLADD": if (args.Length > 2) { - return await ResponseBlacklistAdd(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseBlacklistAdd(steamID, args[1], args[2]).ConfigureAwait(false); } return ResponseBlacklistAdd(steamID, args[1]); case "!BLRM": if (args.Length > 2) { - return await ResponseBlacklistRemove(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseBlacklistRemove(steamID, args[1], args[2]).ConfigureAwait(false); } return ResponseBlacklistRemove(steamID, args[1]); @@ -714,13 +716,13 @@ namespace ArchiSteamFarm { return await ResponseIdleQueue(steamID, args[1]).ConfigureAwait(false); case "!IQADD": if (args.Length > 2) { - return await ResponseIdleQueueAdd(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseIdleQueueAdd(steamID, args[1], args[2]).ConfigureAwait(false); } return ResponseIdleQueueAdd(steamID, args[1]); case "!IQRM": if (args.Length > 2) { - return await ResponseIdleQueueRemove(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseIdleQueueRemove(steamID, args[1], args[2]).ConfigureAwait(false); } return ResponseIdleQueueRemove(steamID, args[1]); @@ -730,7 +732,7 @@ namespace ArchiSteamFarm { return await ResponseLootSwitch(steamID, args[1]).ConfigureAwait(false); case "!NICKNAME": if (args.Length > 2) { - return await ResponseNickname(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseNickname(steamID, args[1], args[2]).ConfigureAwait(false); } return await ResponseNickname(steamID, args[1]).ConfigureAwait(false); @@ -738,7 +740,7 @@ namespace ArchiSteamFarm { return await ResponseOwns(steamID, SharedInfo.ASF, args[1]).ConfigureAwait(false); case "!OWNS": if (args.Length > 2) { - return await ResponseOwns(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseOwns(steamID, args[1], args[2]).ConfigureAwait(false); } return await ResponseOwns(steamID, args[1]).ConfigureAwait(false); @@ -750,21 +752,21 @@ namespace ArchiSteamFarm { return await ResponsePause(steamID, args[1], false).ConfigureAwait(false); case "!PLAY": if (args.Length > 2) { - return await ResponsePlay(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponsePlay(steamID, args[1], args[2]).ConfigureAwait(false); } return await ResponsePlay(steamID, args[1]).ConfigureAwait(false); case "!R": case "!REDEEM": if (args.Length > 2) { - return await ResponseRedeem(steamID, args[1], args.GetArgsAsString(2)).ConfigureAwait(false); + return await ResponseRedeem(steamID, args[1], args[2]).ConfigureAwait(false); } return await ResponseRedeem(steamID, args[1]).ConfigureAwait(false); case "!R^": case "!REDEEM^": if (args.Length > 3) { - return await ResponseAdvancedRedeem(steamID, args[1], args[2], args.GetArgsAsString(3)).ConfigureAwait(false); + return await ResponseAdvancedRedeem(steamID, args[1], args[2], args[3]).ConfigureAwait(false); } if (args.Length > 2) { @@ -782,6 +784,8 @@ namespace ArchiSteamFarm { return await ResponseStatus(steamID, args[1]).ConfigureAwait(false); case "!STOP": return await ResponseStop(steamID, args[1]).ConfigureAwait(false); + case "!UNPACK": + return await ResponseUnpackBoosters(steamID, args[1]).ConfigureAwait(false); default: return ResponseUnknown(steamID); } @@ -916,7 +920,7 @@ namespace ArchiSteamFarm { return null; } - string[] botNames = args.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] botNames = args.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet result = new HashSet(); foreach (string botName in botNames) { @@ -2116,7 +2120,7 @@ namespace ArchiSteamFarm { return FormatBotResponse(Strings.BotNotConnected); } - string[] gameIDs = games.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] gameIDs = games.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet gamesToRedeem = new HashSet(); foreach (string game in gameIDs) { @@ -2177,7 +2181,7 @@ namespace ArchiSteamFarm { ERedeemFlags redeemFlags = ERedeemFlags.None; - string[] flags = options.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] flags = options.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string flag in flags) { switch (flag.ToUpperInvariant()) { case "FD": @@ -2316,7 +2320,7 @@ namespace ArchiSteamFarm { return null; } - string[] targets = targetsText.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet targetIDs = new HashSet(); foreach (string target in targets) { @@ -2407,7 +2411,7 @@ namespace ArchiSteamFarm { return null; } - string[] targets = targetsText.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet targetIDs = new HashSet(); foreach (string target in targets) { @@ -2556,7 +2560,7 @@ namespace ArchiSteamFarm { return null; } - string[] targets = targetsText.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet appIDs = new HashSet(); foreach (string target in targets) { @@ -2647,7 +2651,7 @@ namespace ArchiSteamFarm { return null; } - string[] targets = targetsText.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet appIDs = new HashSet(); foreach (string target in targets) { @@ -2953,7 +2957,7 @@ namespace ArchiSteamFarm { response.Append(FormatBotResponse(string.Format(Strings.BotOwnedAlreadyWithName, ownedGame.Key, ownedGame.Value))); } } else { - string[] games = query.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] games = query.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string game in games) { // Check if this is gameID @@ -3161,7 +3165,7 @@ namespace ArchiSteamFarm { return FormatBotResponse(Strings.BotNotConnected); } - string[] gameIDs = games.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] gameIDs = games.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet gamesToPlay = new HashSet(); foreach (string game in gameIDs) { @@ -3233,7 +3237,7 @@ namespace ArchiSteamFarm { bool distribute = !redeemFlags.HasFlag(ERedeemFlags.SkipDistribution) && (redeemFlags.HasFlag(ERedeemFlags.ForceDistribution) || BotConfig.RedeemingPreferences.HasFlag(BotConfig.ERedeemingPreferences.Distributing)); bool keepMissingGames = !redeemFlags.HasFlag(ERedeemFlags.SkipKeepMissingGames) && (redeemFlags.HasFlag(ERedeemFlags.ForceKeepMissingGames) || BotConfig.RedeemingPreferences.HasFlag(BotConfig.ERedeemingPreferences.KeepMissingGames)); - string[] keysList = keys.Split(new[] { ",", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + string[] keysList = keys.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); keys = string.Join(Environment.NewLine, keysList); HashSet unusedKeys = new HashSet(); @@ -3751,6 +3755,75 @@ namespace ArchiSteamFarm { return null; } + private async Task ResponseUnpackBoosters(ulong steamID) { + if (steamID == 0) { + ArchiLogger.LogNullError(nameof(steamID)); + return null; + } + + if (!IsMaster(steamID)) { + return null; + } + + if (!IsConnectedAndLoggedOn) { + return FormatBotResponse(Strings.BotNotConnected); + } + + HashSet inventory = await ArchiWebHandler.GetMySteamInventory(false, new HashSet { Steam.Item.EType.BoosterPack }).ConfigureAwait(false); + if ((inventory == null) || (inventory.Count == 0)) { + return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(inventory))); + } + + IEnumerable> tasks = inventory.Select(item => ArchiWebHandler.UnpackBooster(item.RealAppID, item.AssetID)); + ICollection results; + + switch (Program.GlobalConfig.OptimizationMode) { + case GlobalConfig.EOptimizationMode.MinMemoryUsage: + results = new List(inventory.Count); + foreach (Task task in tasks) { + results.Add(await task.ConfigureAwait(false)); + } + + break; + default: + results = await Task.WhenAll(tasks).ConfigureAwait(false); + break; + } + + return FormatBotResponse(results.All(result => result) ? Strings.Done : Strings.WarningFailed); + } + + private static async Task ResponseUnpackBoosters(ulong steamID, string botNames) { + if ((steamID == 0) || string.IsNullOrEmpty(botNames)) { + ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames)); + return null; + } + + HashSet bots = GetBots(botNames); + if ((bots == null) || (bots.Count == 0)) { + return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null; + } + + IEnumerable> tasks = bots.Select(bot => bot.ResponseUnpackBoosters(steamID)); + ICollection results; + + switch (Program.GlobalConfig.OptimizationMode) { + case GlobalConfig.EOptimizationMode.MinMemoryUsage: + results = new List(bots.Count); + foreach (Task task in tasks) { + results.Add(await task.ConfigureAwait(false)); + } + + break; + default: + results = await Task.WhenAll(tasks).ConfigureAwait(false); + break; + } + + List responses = new List(results.Where(result => !string.IsNullOrEmpty(result))); + return responses.Count > 0 ? string.Join("", responses) : null; + } + private static async Task ResponseUpdate(ulong steamID) { if (steamID == 0) { ASF.ArchiLogger.LogNullError(nameof(steamID)); diff --git a/ArchiSteamFarm/JSON/Steam.cs b/ArchiSteamFarm/JSON/Steam.cs index 9177169cb..e700800b7 100644 --- a/ArchiSteamFarm/JSON/Steam.cs +++ b/ArchiSteamFarm/JSON/Steam.cs @@ -220,6 +220,18 @@ namespace ArchiSteamFarm.JSON { private ConfirmationResponse() { } } + [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] + [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] + internal sealed class GenericResponse { +#pragma warning disable 649 + [JsonProperty(PropertyName = "success", Required = Required.Always)] + internal readonly EResult Result; +#pragma warning restore 649 + + // Deserialized from JSON + private GenericResponse() { } + } + // REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService#CEcon_Asset internal sealed class Item { internal const ushort SteamAppID = 753; @@ -227,13 +239,12 @@ namespace ArchiSteamFarm.JSON { internal uint Amount { get; private set; } internal uint AppID { get; set; } + internal ulong AssetID { get; private set; } internal ulong ClassID { get; private set; } internal ulong ContextID { get; set; } internal uint RealAppID { get; set; } internal EType Type { get; set; } - private ulong AssetID; - [JsonProperty(PropertyName = "amount", Required = Required.Always)] [SuppressMessage("ReSharper", "UnusedMember.Local")] private string AmountString { diff --git a/ArchiSteamFarm/Utilities.cs b/ArchiSteamFarm/Utilities.cs index 2c2b6a9f4..1d87da265 100644 --- a/ArchiSteamFarm/Utilities.cs +++ b/ArchiSteamFarm/Utilities.cs @@ -40,16 +40,6 @@ namespace ArchiSteamFarm { [SuppressMessage("ReSharper", "UnusedParameter.Global")] internal static void Forget(this object obj) { } - internal static string GetArgsAsString(this string[] args, byte argsToSkip = 1) { - if ((args == null) || (args.Length < argsToSkip)) { - ASF.ArchiLogger.LogNullError(nameof(args)); - return null; - } - - string result = string.Join(" ", args.GetArgs(argsToSkip)); - return result; - } - internal static string GetCookieValue(this CookieContainer cookieContainer, string url, string name) { if ((cookieContainer == null) || string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) { ASF.ArchiLogger.LogNullError(nameof(cookieContainer) + " || " + nameof(url) + " || " + nameof(name)); @@ -130,22 +120,5 @@ namespace ArchiSteamFarm { } internal static string ToHumanReadable(this TimeSpan timeSpan) => timeSpan.Humanize(3); - - private static string[] GetArgs(this string[] args, byte argsToSkip = 1) { - if ((args == null) || (args.Length < argsToSkip)) { - ASF.ArchiLogger.LogNullError(nameof(args)); - return null; - } - - byte argsToCopy = (byte) (args.Length - argsToSkip); - - string[] result = new string[argsToCopy]; - - if (argsToCopy > 0) { - Array.Copy(args, argsToSkip, result, 0, argsToCopy); - } - - return result; - } } } \ No newline at end of file