diff --git a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs index 5c1fea88e..2b2d60b6a 100644 --- a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs +++ b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs @@ -99,6 +99,55 @@ public sealed class ArchiWebHandler : IDisposable { WebBrowser.Dispose(); } + [PublicAPI] + public async Task<(bool Success, bool RequiresMobileConfirmation)> AcceptTradeOffer(ulong tradeID) { + ArgumentOutOfRangeException.ThrowIfZero(tradeID); + + Uri request = new(SteamCommunityURL, $"/tradeoffer/{tradeID}/accept"); + Uri referer = new(SteamCommunityURL, $"/tradeoffer/{tradeID}"); + + // Extra entry for sessionID + Dictionary data = new(3, StringComparer.Ordinal) { + { "serverid", "1" }, + { "tradeofferid", tradeID.ToString(CultureInfo.InvariantCulture) } + }; + + ObjectResponse? response = null; + + for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) { + response = await UrlPostToJsonObjectWithSession(request, data: data, referer: referer, requestOptions: WebBrowser.ERequestOptions.ReturnServerErrors | WebBrowser.ERequestOptions.AllowInvalidBodyOnErrors).ConfigureAwait(false); + + if (response == null) { + return (false, false); + } + + if (response.StatusCode.IsServerErrorCode()) { + if (string.IsNullOrEmpty(response.Content?.ErrorText)) { + // This is a generic server error without a reason, try again + response = null; + + continue; + } + + // This is actually client error with a reason, so it doesn't make sense to retry + Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(response.Content.ErrorText)); + + return (false, false); + } + } + + return response?.Content != null ? (true, response.Content.RequiresMobileConfirmation) : (false, false); + } + + [PublicAPI] + public async Task DeclineTradeOffer(ulong tradeID) { + ArgumentOutOfRangeException.ThrowIfZero(tradeID); + + Uri request = new(SteamCommunityURL, $"/tradeoffer/{tradeID}/decline"); + + return await UrlPostWithSession(request).ConfigureAwait(false); + } + [PublicAPI] public async Task CancelTradeOffer(ulong tradeID) { ArgumentOutOfRangeException.ThrowIfZero(tradeID); @@ -1468,45 +1517,6 @@ public sealed class ArchiWebHandler : IDisposable { return true; } - internal async Task<(bool Success, bool RequiresMobileConfirmation)> AcceptTradeOffer(ulong tradeID) { - ArgumentOutOfRangeException.ThrowIfZero(tradeID); - - Uri request = new(SteamCommunityURL, $"/tradeoffer/{tradeID}/accept"); - Uri referer = new(SteamCommunityURL, $"/tradeoffer/{tradeID}"); - - // Extra entry for sessionID - Dictionary data = new(3, StringComparer.Ordinal) { - { "serverid", "1" }, - { "tradeofferid", tradeID.ToString(CultureInfo.InvariantCulture) } - }; - - ObjectResponse? response = null; - - for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) { - response = await UrlPostToJsonObjectWithSession(request, data: data, referer: referer, requestOptions: WebBrowser.ERequestOptions.ReturnServerErrors | WebBrowser.ERequestOptions.AllowInvalidBodyOnErrors).ConfigureAwait(false); - - if (response == null) { - return (false, false); - } - - if (response.StatusCode.IsServerErrorCode()) { - if (string.IsNullOrEmpty(response.Content?.ErrorText)) { - // This is a generic server error without a reason, try again - response = null; - - continue; - } - - // This is actually client error with a reason, so it doesn't make sense to retry - Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(response.Content.ErrorText)); - - return (false, false); - } - } - - return response?.Content != null ? (true, response.Content.RequiresMobileConfirmation) : (false, false); - } - internal async Task AcknowledgeTradeRestrictions() { Uri request = new(SteamCommunityURL, "/trade/new/acknowledge"); @@ -1621,14 +1631,6 @@ public sealed class ArchiWebHandler : IDisposable { return true; } - internal async Task DeclineTradeOffer(ulong tradeID) { - ArgumentOutOfRangeException.ThrowIfZero(tradeID); - - Uri request = new(SteamCommunityURL, $"/tradeoffer/{tradeID}/decline"); - - return await UrlPostWithSession(request).ConfigureAwait(false); - } - internal async Task?> GetAppList() { const string endpoint = "GetAppList"; HttpMethod method = HttpMethod.Get;