diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index a8bc167a5..3d197bd7c 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -133,6 +133,44 @@ 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)); diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 86a9c9979..52af21338 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -1112,6 +1112,12 @@ 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]).ConfigureAwait(false); case "R": case "REDEEM": if (args.Length > 2) { @@ -4114,6 +4120,116 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } + private async Task ResponsePrivacy(ulong steamID, string privacySettingsText) { + if ((steamID == 0) || string.IsNullOrEmpty(privacySettingsText)) { + ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(privacySettingsText)); + return null; + } + + if (!IsMaster(steamID)) { + return null; + } + + if (!IsConnectedAndLoggedOn) { + return FormatBotResponse(Strings.BotNotConnected); + } + + if (privacySettingsText.Length != 6) { // There are only 6 privacy settings + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(privacySettingsText))); + } + + 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; + + // 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))); + } + + // Child setting can't be less restrictive than its parent + switch (digitPostition) { + case 0: + profile = privacySetting; + break; + case 1: + if (profile < privacySetting) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(profile))); + } + + ownedGames = privacySetting; + break; + case 2: + if (ownedGames < privacySetting) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(playtime))); + } + + playtime = privacySetting; + break; + case 3: + if (profile < privacySetting) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(profile))); + } + + inventory = privacySetting; + break; + case 4: + if (inventory < privacySetting) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inventoryGifts))); + } + + inventoryGifts = privacySetting; + break; + case 5: + if (profile < privacySetting) { + return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(profile))); + } + + comments = privacySetting; + break; + } + } + + Steam.PrivacyResponse privacySettings = new Steam.PrivacyResponse(profile, ownedGames, playtime, inventory, inventoryGifts, comments); + + return FormatBotResponse(await ArchiWebHandler.ChangePrivacySettings(privacySettings).ConfigureAwait(false) ? Strings.Success : Strings.WarningFailed); + } + + private async Task ResponsePrivacy(ulong steamID, string botNames, string privacySettingsText) { + if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(privacySettingsText)) { + ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(privacySettingsText)); + 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.ResponsePrivacy(steamID, privacySettingsText)); + 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; + } + [SuppressMessage("ReSharper", "FunctionComplexityOverflow")] private async Task ResponseRedeem(ulong steamID, string keys, ERedeemFlags redeemFlags = ERedeemFlags.None) { if ((steamID == 0) || string.IsNullOrEmpty(keys)) { diff --git a/ArchiSteamFarm/Json/Steam.cs b/ArchiSteamFarm/Json/Steam.cs index 53e112d2d..dcce94738 100644 --- a/ArchiSteamFarm/Json/Steam.cs +++ b/ArchiSteamFarm/Json/Steam.cs @@ -470,18 +470,51 @@ namespace ArchiSteamFarm.Json { [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")] internal sealed class PrivacyResponse { - [JsonProperty(PropertyName = "PrivacySettings", Required = Required.Always)] - internal readonly PrivacySettings Settings; - // 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; - // Deserialized from JSON - private PrivacySettings() { } + [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 { @@ -491,6 +524,12 @@ namespace ArchiSteamFarm.Json { Public } } + + internal enum ECommentPermission { + FriendsOnly = 0, + Public = 1, + Private = 2 + } } [SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]