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