From 53b84a92718a1b08beb088784630afe314cb8148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Domeradzki?= Date: Fri, 13 Jun 2025 13:41:36 +0200 Subject: [PATCH] Closes #3436 --- .../IPC/Controllers/Api/BotController.cs | 4 + .../Steam/Integration/ArchiWebHandler.cs | 2 +- ArchiSteamFarm/Steam/Storage/BotConfig.cs | 84 +++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs index 8b3d6758f..ec5cd2e1d 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs @@ -153,6 +153,10 @@ public sealed class BotController : ArchiController { request.BotConfig.SteamParentalCode = bot.BotConfig.SteamParentalCode; } + if (!request.BotConfig.IsWebProxyPasswordSet && bot.BotConfig.IsWebProxyPasswordSet) { + request.BotConfig.WebProxyPassword = bot.BotConfig.WebProxyPassword; + } + if (bot.BotConfig.AdditionalProperties?.Count > 0) { request.BotConfig.AdditionalProperties ??= new Dictionary(bot.BotConfig.AdditionalProperties.Count, bot.BotConfig.AdditionalProperties.Comparer); diff --git a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs index d45908c89..865362395 100644 --- a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs +++ b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs @@ -91,7 +91,7 @@ public sealed class ArchiWebHandler : IDisposable { ArgumentNullException.ThrowIfNull(bot); Bot = bot; - WebBrowser = new WebBrowser(bot.ArchiLogger, ASF.GlobalConfig?.WebProxy); + WebBrowser = new WebBrowser(bot.ArchiLogger, bot.BotConfig.WebProxy ?? ASF.GlobalConfig?.WebProxy); } public void Dispose() { diff --git a/ArchiSteamFarm/Steam/Storage/BotConfig.cs b/ArchiSteamFarm/Steam/Storage/BotConfig.cs index b3a9f29c6..0f57c914a 100644 --- a/ArchiSteamFarm/Steam/Storage/BotConfig.cs +++ b/ArchiSteamFarm/Steam/Storage/BotConfig.cs @@ -29,6 +29,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; +using System.Net; using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; @@ -116,6 +117,15 @@ public sealed class BotConfig { [PublicAPI] public const EUIMode DefaultUserInterfaceMode = EUIMode.VGUI; + [PublicAPI] + public const string? DefaultWebProxyPassword = null; + + [PublicAPI] + public const string? DefaultWebProxyText = null; + + [PublicAPI] + public const string? DefaultWebProxyUsername = null; + internal const byte SteamParentalCodeLength = 4; internal const byte SteamTradeTokenLength = 8; @@ -140,6 +150,51 @@ public sealed class BotConfig { [PublicAPI] public static readonly ImmutableHashSet DefaultTransferableTypes = [EAssetType.BoosterPack, EAssetType.FoilTradingCard, EAssetType.TradingCard]; + [JsonIgnore] + [PublicAPI] + public WebProxy? WebProxy { + get { + if (field != null) { + return field; + } + + if (string.IsNullOrEmpty(WebProxyText)) { + return null; + } + + Uri uri; + + try { + uri = new Uri(WebProxyText); + } catch (UriFormatException e) { + ASF.ArchiLogger.LogGenericException(e); + + return null; + } + + WebProxy proxy = new() { + Address = uri, + BypassProxyOnLocal = true + }; + + if (!string.IsNullOrEmpty(WebProxyUsername) || !string.IsNullOrEmpty(WebProxyPassword)) { + NetworkCredential credentials = new(); + + if (!string.IsNullOrEmpty(WebProxyUsername)) { + credentials.UserName = WebProxyUsername; + } + + if (!string.IsNullOrEmpty(WebProxyPassword)) { + credentials.Password = WebProxyPassword; + } + + proxy.Credentials = credentials; + } + + return field = proxy; + } + } + [JsonInclude] public bool AcceptGifts { get; private init; } = DefaultAcceptGifts; @@ -275,6 +330,13 @@ public sealed class BotConfig { [JsonInclude] public EUIMode UserInterfaceMode { get; private init; } = DefaultUserInterfaceMode; + [JsonInclude] + [JsonPropertyName(nameof(WebProxy))] + public string? WebProxyText { get; private init; } = DefaultWebProxyText; + + [JsonInclude] + public string? WebProxyUsername { get; private init; } = DefaultWebProxyUsername; + [JsonExtensionData] [JsonInclude] internal Dictionary? AdditionalProperties { get; set; } @@ -282,8 +344,21 @@ public sealed class BotConfig { internal bool IsSteamLoginSet { get; set; } internal bool IsSteamParentalCodeSet { get; set; } internal bool IsSteamPasswordSet { get; set; } + internal bool IsWebProxyPasswordSet { get; private set; } + internal bool Saving { get; set; } + [JsonInclude] + [SwaggerSecurityCritical] + internal string? WebProxyPassword { + get; + + set { + IsWebProxyPasswordSet = true; + field = value; + } + } = DefaultWebProxyPassword; + [JsonDisallowNull] [JsonInclude] [JsonPropertyName($"{SharedInfo.UlongCompatibilityStringPrefix}{nameof(SteamMasterClanID)}")] @@ -394,6 +469,15 @@ public sealed class BotConfig { [UsedImplicitly] public bool ShouldSerializeUserInterfaceMode() => !Saving || (UserInterfaceMode != DefaultUserInterfaceMode); + [UsedImplicitly] + public bool ShouldSerializeWebProxyPassword() => Saving && IsWebProxyPasswordSet && (WebProxyPassword != DefaultWebProxyPassword); + + [UsedImplicitly] + public bool ShouldSerializeWebProxyText() => !Saving || (WebProxyText != DefaultWebProxyText); + + [UsedImplicitly] + public bool ShouldSerializeWebProxyUsername() => !Saving || (WebProxyUsername != DefaultWebProxyUsername); + [PublicAPI] public static async Task Write(string filePath, BotConfig botConfig) { ArgumentException.ThrowIfNullOrEmpty(filePath);