From ed2a068c515bc88650485cf2027e46a1aefb5bf7 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sat, 19 May 2018 20:50:26 +0200 Subject: [PATCH] Cleanup after #794 @vital7 Steam.cs: - Add missing constructor for json deserialization - Change name into UserPrivacy since we use it for both request and response, no longer response only - Move ECommentPermission one level above, it's not internal member of PrivacySettings - Make UserPrivacy constructor accept PrivacySettings, since PrivacySettings is internal and not private. - Make ECommentPermission underlying type of byte ArchiWebHandler.cs: - Put function in proper place alphabetically - Cast CommentPermission to new underlying type of byte - Remove mapping, AWH should not be in charge of correcting a caller, unless that caller can't be corrected earlier (e.g. direct Steam response). Since Bot is in charge of calling AWH, Bot should do the correction, not AWH. Bot.cs: - Change command to !privacy bot n,n,n,n,n,n, this makes it possible for mixing it with enum members (such as !privacy bot public,private,friendsonly,public,public), which would be preferred way of execution instead of cryptic numbers. - Make appropriate mapping between general and comments, since userspace is in charge of that. - Add comments and correct creating UserPrivacy object. - Make the default option private and let user skip extra options if he wants to edit e.g. only profile to public. Apart from that, general error handling and a lot of other misc fixed, including renaming NonZeroResponse to NumberResponse, which makes more sense. --- ArchiSteamFarm/ArchiWebHandler.cs | 78 +++++++---------- ArchiSteamFarm/Bot.cs | 72 ++++++++++------ ArchiSteamFarm/Json/Steam.cs | 135 +++++++++++++++--------------- 3 files changed, 145 insertions(+), 140 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 3d197bd7c..5b4c802b8 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -119,6 +119,28 @@ namespace ArchiSteamFarm { return htmlDocument?.DocumentNode.SelectSingleNode("//div[@class='add_free_content_success_area']") != null; } + internal async Task ChangePrivacySettings(Steam.UserPrivacy userPrivacy) { + string request = GetAbsoluteProfileURL() + "/ajaxsetprivacy"; + + // Extra entry for sessionID + Dictionary data = new Dictionary(3) { + { "eCommentPermission", ((byte) userPrivacy.CommentPermission).ToString() }, + { "Privacy", JsonConvert.SerializeObject(userPrivacy.Settings) } + }; + + Steam.NumberResponse response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data).ConfigureAwait(false); + if (response == null) { + return false; + } + + if (!response.Success) { + Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); + return false; + } + + return true; + } + internal async Task ClearFromDiscoveryQueue(uint appID) { if (appID == 0) { Bot.ArchiLogger.LogNullError(nameof(appID)); @@ -133,44 +155,6 @@ namespace ArchiSteamFarm { return await UrlPostWithSession(SteamStoreURL, request, data).ConfigureAwait(false); } - internal async Task ChangePrivacySettings(Steam.PrivacyResponse privacySettings) { - string request = GetAbsoluteProfileURL() + "/ajaxsetprivacy"; - - // We have to do this because Steam uses the same numbers for settings except comments, this has its special numbers, fuck Steam - Steam.PrivacyResponse.ECommentPermission commentPermission; - switch (privacySettings.Comments) { - case Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Public: - commentPermission = Steam.PrivacyResponse.ECommentPermission.Public; - break; - case Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.FriendsOnly: - commentPermission = Steam.PrivacyResponse.ECommentPermission.FriendsOnly; - break; - case Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Private: - commentPermission = Steam.PrivacyResponse.ECommentPermission.Private; - break; - default: - Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, nameof(commentPermission))); - return false; - } - - Dictionary data = new Dictionary(3) { - { "Privacy", JsonConvert.SerializeObject(privacySettings.Settings) }, - { "eCommentPermission", ((int) commentPermission).ToString() } - }; - - Steam.NonZeroResponse response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data).ConfigureAwait(false); - if (response == null) { - return false; - } - - if (!response.Success) { - Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); - return false; - } - - return true; - } - internal async Task DeclineTradeOffer(ulong tradeID) { if (tradeID == 0) { Bot.ArchiLogger.LogNullError(nameof(tradeID)); @@ -1318,28 +1302,28 @@ namespace ArchiSteamFarm { // This json is encoded as html attribute, don't forget to decode it json = WebUtility.HtmlDecode(json); - Steam.PrivacyResponse privacyResponse; + Steam.UserPrivacy userPrivacy; try { - privacyResponse = JsonConvert.DeserializeObject(json); + userPrivacy = JsonConvert.DeserializeObject(json); } catch (JsonException e) { Bot.ArchiLogger.LogGenericException(e); return null; } - if (privacyResponse == null) { - Bot.ArchiLogger.LogNullError(nameof(privacyResponse)); + if (userPrivacy == null) { + Bot.ArchiLogger.LogNullError(nameof(userPrivacy)); return null; } - switch (privacyResponse.Settings.Inventory) { - case Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.FriendsOnly: - case Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Private: + switch (userPrivacy.Settings.Inventory) { + case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.FriendsOnly: + case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private: return false; - case Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Public: + case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Public: return true; default: - Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(privacyResponse.Settings.Inventory), privacyResponse.Settings.Inventory)); + Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(userPrivacy.Settings.Inventory), userPrivacy.Settings.Inventory)); return null; } } diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 52af21338..b1a7f5d01 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -1114,7 +1114,7 @@ namespace ArchiSteamFarm { return await ResponsePlay(steamID, args[1]).ConfigureAwait(false); case "PRIVACY": if (args.Length > 2) { - return await ResponsePrivacy(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false); + return await ResponsePrivacy(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); } return await ResponsePrivacy(steamID, args[1]).ConfigureAwait(false); @@ -4134,69 +4134,89 @@ namespace ArchiSteamFarm { return FormatBotResponse(Strings.BotNotConnected); } - if (privacySettingsText.Length != 6) { // There are only 6 privacy settings - return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(privacySettingsText))); + string[] privacySettingsArgs = privacySettingsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + // There are only 6 privacy settings + if (privacySettingsArgs.Length > 6) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(privacySettingsArgs))); } - Steam.PrivacyResponse.PrivacySettings.EPrivacySetting profile = Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown; - Steam.PrivacyResponse.PrivacySettings.EPrivacySetting ownedGames = Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown; - Steam.PrivacyResponse.PrivacySettings.EPrivacySetting playtime = Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown; - Steam.PrivacyResponse.PrivacySettings.EPrivacySetting inventory = Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown; - Steam.PrivacyResponse.PrivacySettings.EPrivacySetting inventoryGifts = Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown; - Steam.PrivacyResponse.PrivacySettings.EPrivacySetting comments = Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown; + Steam.UserPrivacy.PrivacySettings.EPrivacySetting profile = Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private; + Steam.UserPrivacy.PrivacySettings.EPrivacySetting ownedGames = Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private; + Steam.UserPrivacy.PrivacySettings.EPrivacySetting playtime = Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private; + Steam.UserPrivacy.PrivacySettings.EPrivacySetting inventory = Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private; + Steam.UserPrivacy.PrivacySettings.EPrivacySetting inventoryGifts = Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private; + Steam.UserPrivacy.ECommentPermission comments = Steam.UserPrivacy.ECommentPermission.Private; // Converting digits to enum - for (int digitPostition = 0; digitPostition < 6; digitPostition++) { - if (!Enum.TryParse(privacySettingsText[digitPostition].ToString(), true, out Steam.PrivacyResponse.PrivacySettings.EPrivacySetting privacySetting) || (privacySetting == Steam.PrivacyResponse.PrivacySettings.EPrivacySetting.Unknown) || !Enum.IsDefined(typeof(Steam.PrivacyResponse.PrivacySettings.EPrivacySetting), privacySetting)) { - return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(privacySettingsText))); + for (byte digit = 0; digit < privacySettingsArgs.Length; digit++) { + if (!Enum.TryParse(privacySettingsArgs[digit], true, out Steam.UserPrivacy.PrivacySettings.EPrivacySetting privacySetting) || (privacySetting == Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Unknown) || !Enum.IsDefined(typeof(Steam.UserPrivacy.PrivacySettings.EPrivacySetting), privacySetting)) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(privacySettingsArgs))); } // Child setting can't be less restrictive than its parent - switch (digitPostition) { - case 0: + switch (digit) { + case 0: // Profile profile = privacySetting; break; - case 1: + case 1: // OwnedGames, parent of Profile if (profile < privacySetting) { - return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(profile))); + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(ownedGames))); } ownedGames = privacySetting; break; - case 2: + case 2: // Playtime, parent of OwnedGames if (ownedGames < privacySetting) { return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(playtime))); } playtime = privacySetting; break; - case 3: + case 3: // Inventory, parent of Profile if (profile < privacySetting) { - return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(profile))); + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inventory))); } inventory = privacySetting; break; - case 4: + case 4: // InventoryGifts, parent of Inventory if (inventory < privacySetting) { return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inventoryGifts))); } inventoryGifts = privacySetting; break; - case 5: + case 5: // Comments, parent of Profile if (profile < privacySetting) { - return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(profile))); + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(comments))); + } + + // Comments use different numbers than everything else, but we want to have this command consistent for end-user, so we'll map them + switch (privacySetting) { + case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.FriendsOnly: + comments = Steam.UserPrivacy.ECommentPermission.FriendsOnly; + break; + case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private: + comments = Steam.UserPrivacy.ECommentPermission.Private; + break; + case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Public: + comments = Steam.UserPrivacy.ECommentPermission.Public; + break; + default: + ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(privacySetting), privacySetting)); + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(privacySetting))); } - comments = privacySetting; break; + default: + ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(digit), digit)); + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(digit))); } } - Steam.PrivacyResponse privacySettings = new Steam.PrivacyResponse(profile, ownedGames, playtime, inventory, inventoryGifts, comments); - - return FormatBotResponse(await ArchiWebHandler.ChangePrivacySettings(privacySettings).ConfigureAwait(false) ? Strings.Success : Strings.WarningFailed); + Steam.UserPrivacy userPrivacy = new Steam.UserPrivacy(new Steam.UserPrivacy.PrivacySettings(profile, ownedGames, playtime, inventory, inventoryGifts), comments); + return FormatBotResponse(await ArchiWebHandler.ChangePrivacySettings(userPrivacy).ConfigureAwait(false) ? Strings.Success : Strings.WarningFailed); } private async Task ResponsePrivacy(ulong steamID, string botNames, string privacySettingsText) { diff --git a/ArchiSteamFarm/Json/Steam.cs b/ArchiSteamFarm/Json/Steam.cs index dcce94738..5750b1356 100644 --- a/ArchiSteamFarm/Json/Steam.cs +++ b/ArchiSteamFarm/Json/Steam.cs @@ -338,6 +338,7 @@ namespace ArchiSteamFarm.Json { Generic, Trade, Market, + // We're missing information about definition of number 4 type ChangePhoneNumber = 5 } @@ -353,7 +354,7 @@ namespace ArchiSteamFarm.Json { } [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] - internal sealed class InventoryResponse : NonZeroResponse { + internal sealed class InventoryResponse : NumberResponse { [JsonProperty(PropertyName = "assets", Required = Required.DisallowNull)] internal readonly HashSet Assets; @@ -444,7 +445,7 @@ namespace ArchiSteamFarm.Json { } [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] - internal class NonZeroResponse { + internal class NumberResponse { internal bool Success { get; private set; } [JsonProperty(PropertyName = "success", Required = Required.Always)] @@ -465,71 +466,7 @@ namespace ArchiSteamFarm.Json { } // Deserialized from JSON - protected NonZeroResponse() { } - } - - [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] - internal sealed class PrivacyResponse { - // Deserialized from JSON - private PrivacyResponse() { } - - internal PrivacyResponse(PrivacySettings.EPrivacySetting profile, PrivacySettings.EPrivacySetting ownedGames, PrivacySettings.EPrivacySetting playtime, PrivacySettings.EPrivacySetting inventory, PrivacySettings.EPrivacySetting inventoryGifts, PrivacySettings.EPrivacySetting comments) { - if ((profile == PrivacySettings.EPrivacySetting.Unknown) || (ownedGames == PrivacySettings.EPrivacySetting.Unknown) || (playtime == PrivacySettings.EPrivacySetting.Unknown) || (inventory == PrivacySettings.EPrivacySetting.Unknown) || (inventoryGifts == PrivacySettings.EPrivacySetting.Unknown) || (comments == PrivacySettings.EPrivacySetting.Unknown)) { - throw new ArgumentNullException(nameof(profile) + " || " + nameof(ownedGames) + " || " + nameof(playtime) + " || " + nameof(inventory) + " || " + nameof(inventoryGifts) + " || " + nameof(comments)); - } - - Settings = new PrivacySettings(profile, ownedGames, playtime, inventory, inventoryGifts); - Comments = comments; - } - - [JsonProperty(PropertyName = "PrivacySettings", Required = Required.Always)] - internal readonly PrivacySettings Settings; - - [JsonProperty(PropertyName = "eCommentPermission", Required = Required.Always)] - internal readonly PrivacySettings.EPrivacySetting Comments; - - internal sealed class PrivacySettings { - internal PrivacySettings(EPrivacySetting profile, EPrivacySetting ownedGames, EPrivacySetting playtime, EPrivacySetting inventory, EPrivacySetting inventoryGifts) { - if ((profile == EPrivacySetting.Unknown) || (ownedGames == EPrivacySetting.Unknown) || (playtime == EPrivacySetting.Unknown) || (inventory == EPrivacySetting.Unknown) || (inventoryGifts == EPrivacySetting.Unknown)) { - throw new ArgumentNullException(nameof(profile) + " || " + nameof(ownedGames) + " || " + nameof(playtime) + " || " + nameof(inventory) + " || " + nameof(inventoryGifts)); - } - - Profile = profile; - OwnedGames = ownedGames; - Playtime = playtime; - Inventory = inventory; - InventoryGifts = inventoryGifts; - } - - [JsonProperty(PropertyName = "PrivacyInventory", Required = Required.Always)] - internal readonly EPrivacySetting Inventory; - - [JsonProperty(PropertyName = "PrivacyProfile", Required = Required.Always)] - internal readonly EPrivacySetting Profile; - - [JsonProperty(PropertyName = "PrivacyInventoryGifts", Required = Required.Always)] - internal readonly EPrivacySetting InventoryGifts; - - [JsonProperty(PropertyName = "PrivacyOwnedGames", Required = Required.Always)] - internal readonly EPrivacySetting OwnedGames; - - [JsonProperty(PropertyName = "PrivacyPlaytime", Required = Required.Always)] - internal readonly EPrivacySetting Playtime; - - [SuppressMessage("ReSharper", "UnusedMember.Global")] - internal enum EPrivacySetting : byte { - Unknown, - Private, - FriendsOnly, - Public - } - } - - internal enum ECommentPermission { - FriendsOnly = 0, - Public = 1, - Private = 2 - } + protected NumberResponse() { } } [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] @@ -667,5 +604,69 @@ namespace ArchiSteamFarm.Json { internal readonly HashSet Assets = new HashSet(); } } + + [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] + internal sealed class UserPrivacy { + [JsonProperty(PropertyName = "eCommentPermission", Required = Required.Always)] + internal readonly ECommentPermission CommentPermission; + + [JsonProperty(PropertyName = "PrivacySettings", Required = Required.Always)] + internal readonly PrivacySettings Settings; + + // Constructed from privacy change request + internal UserPrivacy(PrivacySettings settings, ECommentPermission commentPermission) { + Settings = settings ?? throw new ArgumentNullException(nameof(settings)); + CommentPermission = commentPermission; + } + + // Deserialized from JSON + private UserPrivacy() { } + + internal sealed class PrivacySettings { + [JsonProperty(PropertyName = "PrivacyInventory", Required = Required.Always)] + internal readonly EPrivacySetting Inventory; + + [JsonProperty(PropertyName = "PrivacyInventoryGifts", Required = Required.Always)] + internal readonly EPrivacySetting InventoryGifts; + + [JsonProperty(PropertyName = "PrivacyOwnedGames", Required = Required.Always)] + internal readonly EPrivacySetting OwnedGames; + + [JsonProperty(PropertyName = "PrivacyPlaytime", Required = Required.Always)] + internal readonly EPrivacySetting Playtime; + + [JsonProperty(PropertyName = "PrivacyProfile", Required = Required.Always)] + internal readonly EPrivacySetting Profile; + + // Constructed from privacy change request + internal PrivacySettings(EPrivacySetting profile, EPrivacySetting ownedGames, EPrivacySetting playtime, EPrivacySetting inventory, EPrivacySetting inventoryGifts) { + if ((profile == EPrivacySetting.Unknown) || (ownedGames == EPrivacySetting.Unknown) || (playtime == EPrivacySetting.Unknown) || (inventory == EPrivacySetting.Unknown) || (inventoryGifts == EPrivacySetting.Unknown)) { + throw new ArgumentNullException(nameof(profile) + " || " + nameof(ownedGames) + " || " + nameof(playtime) + " || " + nameof(inventory) + " || " + nameof(inventoryGifts)); + } + + Profile = profile; + OwnedGames = ownedGames; + Playtime = playtime; + Inventory = inventory; + InventoryGifts = inventoryGifts; + } + + // Deserialized from JSON + private PrivacySettings() { } + + internal enum EPrivacySetting : byte { + Unknown, + Private, + FriendsOnly, + Public + } + } + + internal enum ECommentPermission : byte { + FriendsOnly, + Public, + Private + } + } } } \ No newline at end of file