mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 07:04:27 +00:00
Closes #3174
This commit is contained in:
parent
0ae4b6ff18
commit
9a02c79e0a
7 changed files with 70 additions and 37 deletions
|
@ -29,7 +29,6 @@ using System.Globalization;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -253,7 +252,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
|||
|
||||
try {
|
||||
inventory = await Bot.ArchiHandler.GetMyInventoryAsync().ToListAsync().ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
// This is actually a network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
|
@ -940,7 +939,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
|||
|
||||
try {
|
||||
assetsForMatching = await Bot.ArchiHandler.GetMyInventoryAsync().Where(item => item is { AssetID: > 0, Amount: > 0, ClassID: > 0, RealAppID: > 0, Type: > EAssetType.Unknown, Rarity: > EAssetRarity.Unknown, IsSteamPointsShopItem: false } && acceptedMatchableTypes.Contains(item.Type) && !Bot.BotDatabase.MatchActivelyBlacklistAppIDs.Contains(item.RealAppID)).ToHashSetAsync().ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
Bot.ArchiLogger.LogGenericWarningException(e);
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(assetsForMatching)));
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ using System.ComponentModel.DataAnnotations;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
@ -3669,7 +3668,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
|
|||
.Where(item => appIDs.Contains(item.RealAppID) && BotConfig.CompleteTypesToSend.Contains(item.Type))
|
||||
.ToHashSetAsync()
|
||||
.ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return;
|
||||
|
|
|
@ -25,7 +25,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Collections;
|
||||
|
@ -499,7 +498,7 @@ public sealed class Trading : IDisposable {
|
|||
|
||||
try {
|
||||
inventory = await Bot.ArchiHandler.GetMyInventoryAsync().Where(item => !item.IsSteamPointsShopItem && wantedSets.Contains((item.RealAppID, item.Type, item.Rarity))).ToHashSetAsync().ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
// If we can't check our inventory when not using MatchEverything, this is a temporary failure, try again later
|
||||
Bot.ArchiLogger.LogGenericWarningException(e);
|
||||
Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(inventory)));
|
||||
|
|
|
@ -26,7 +26,6 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Core;
|
||||
using ArchiSteamFarm.Localization;
|
||||
|
@ -34,6 +33,7 @@ using ArchiSteamFarm.NLog;
|
|||
using ArchiSteamFarm.Steam.Data;
|
||||
using ArchiSteamFarm.Steam.Integration.Callbacks;
|
||||
using ArchiSteamFarm.Steam.Integration.CMsgs;
|
||||
using ArchiSteamFarm.Web;
|
||||
using JetBrains.Annotations;
|
||||
using SteamKit2;
|
||||
using SteamKit2.Internal;
|
||||
|
@ -179,14 +179,15 @@ public sealed class ArchiHandler : ClientMsgHandler {
|
|||
ArgumentOutOfRangeException.ThrowIfZero(contextID);
|
||||
ArgumentOutOfRangeException.ThrowIfZero(itemsCountPerRequest);
|
||||
|
||||
if (Client.SteamID == null) {
|
||||
throw new InvalidOperationException(nameof(Client.SteamID));
|
||||
if (!Client.IsConnected || (Client.SteamID == null)) {
|
||||
throw new TimeoutException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(Client.IsConnected)));
|
||||
}
|
||||
|
||||
// We need to store asset IDs to make sure we won't get duplicate items
|
||||
HashSet<ulong>? assetIDs = null;
|
||||
ulong steamID = Client.SteamID;
|
||||
|
||||
Dictionary<(ulong ClassID, ulong InstanceID), InventoryDescription>? descriptions = null;
|
||||
if (steamID == 0) {
|
||||
throw new InvalidOperationException(nameof(Client.SteamID));
|
||||
}
|
||||
|
||||
CEcon_GetInventoryItemsWithDescriptions_Request request = new() {
|
||||
appid = appID,
|
||||
|
@ -198,23 +199,58 @@ public sealed class ArchiHandler : ClientMsgHandler {
|
|||
},
|
||||
|
||||
get_descriptions = true,
|
||||
steamid = Client.SteamID,
|
||||
steamid = steamID,
|
||||
count = itemsCountPerRequest
|
||||
};
|
||||
|
||||
// We need to store asset IDs to make sure we won't get duplicate items
|
||||
HashSet<ulong>? assetIDs = null;
|
||||
|
||||
Dictionary<(ulong ClassID, ulong InstanceID), InventoryDescription>? descriptions = null;
|
||||
|
||||
while (true) {
|
||||
SteamUnifiedMessages.ServiceMethodResponse serviceMethodResponse;
|
||||
SteamUnifiedMessages.ServiceMethodResponse? serviceMethodResponse = null;
|
||||
|
||||
try {
|
||||
serviceMethodResponse = await UnifiedEconService.SendMessage(x => x.GetInventoryItemsWithDescriptions(request)).ToLongRunningTask().ConfigureAwait(false);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
for (byte i = 0; (i < WebBrowser.MaxTries) && (serviceMethodResponse?.Result != EResult.OK) && Client.IsConnected && (Client.SteamID != null); i++) {
|
||||
if (i > 0) {
|
||||
// It seems 2 seconds is enough to win over DuplicateRequest, so we'll use that for this and also other network-related failures
|
||||
await Task.Delay(2000).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
throw new HttpRequestException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(serviceMethodResponse)));
|
||||
try {
|
||||
serviceMethodResponse = await UnifiedEconService.SendMessage(x => x.GetInventoryItemsWithDescriptions(request)).ToLongRunningTask().ConfigureAwait(false);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Interpret the result and see what we should do about it
|
||||
switch (serviceMethodResponse.Result) {
|
||||
case EResult.Busy:
|
||||
case EResult.DuplicateRequest:
|
||||
case EResult.ServiceUnavailable:
|
||||
// Those are generic failures that we should be able to retry
|
||||
ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, serviceMethodResponse.Result));
|
||||
|
||||
continue;
|
||||
case EResult.OK:
|
||||
// Success, we can continue
|
||||
break;
|
||||
default:
|
||||
// Unknown failures, report them and do not retry since we're unsure if we should
|
||||
ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(serviceMethodResponse.Result), serviceMethodResponse.Result));
|
||||
|
||||
throw new TimeoutException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, serviceMethodResponse.Result));
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceMethodResponse == null) {
|
||||
throw new TimeoutException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(serviceMethodResponse)));
|
||||
}
|
||||
|
||||
if (serviceMethodResponse.Result != EResult.OK) {
|
||||
throw new HttpRequestException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, serviceMethodResponse.Result));
|
||||
throw new TimeoutException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, serviceMethodResponse.Result));
|
||||
}
|
||||
|
||||
CEcon_GetInventoryItemsWithDescriptions_Response response = serviceMethodResponse.GetDeserializedResponse<CEcon_GetInventoryItemsWithDescriptions_Response>();
|
||||
|
|
|
@ -275,7 +275,7 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
ObjectResponse<InventoryResponse>? response = null;
|
||||
|
||||
try {
|
||||
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxTries) && (response?.StatusCode.IsSuccessCode() != true); i++) {
|
||||
if ((i > 0) && (rateLimitingDelay > 0)) {
|
||||
await Task.Delay(rateLimitingDelay).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -293,22 +293,24 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
if (response.StatusCode.IsServerErrorCode()) {
|
||||
if (string.IsNullOrEmpty(response.Content?.ErrorText)) {
|
||||
// This is a generic server error without a reason, try again
|
||||
response = null;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Interpret the reason and see if we should try again
|
||||
Bot.ArchiLogger.LogGenericDebug(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.Content.ErrorText));
|
||||
|
||||
// Try to interpret the failure reason and see if we should try again
|
||||
switch (response.Content.ErrorCode) {
|
||||
case EResult.Busy:
|
||||
case EResult.DuplicateRequest:
|
||||
case EResult.ServiceUnavailable:
|
||||
response = null;
|
||||
|
||||
// Those are generic failures that we should be able to retry
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
// Unknown failures, report them and do not retry since we're unsure if we should
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(response.Content.ErrorText), response.Content.ErrorText));
|
||||
|
||||
// This is actually client error with a reason, so it doesn't make sense to retry
|
||||
throw new HttpRequestException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.Content.ErrorText), null, response.StatusCode);
|
||||
throw new HttpRequestException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.Content.ErrorText), null, response.StatusCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -324,12 +326,12 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
if (response?.Content == null) {
|
||||
if (response == null) {
|
||||
throw new HttpRequestException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(response)));
|
||||
}
|
||||
|
||||
if (response.Content.Result is not EResult.OK) {
|
||||
throw new HttpRequestException(!string.IsNullOrEmpty(response.Content.ErrorText) ? string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.Content.ErrorText) : response.Content.Result.HasValue ? string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.Content.Result) : Strings.WarningFailed);
|
||||
if ((response.Content == null) || (response.StatusCode.IsSuccessCode() != true)) {
|
||||
throw new HttpRequestException(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, !string.IsNullOrEmpty(response.Content?.ErrorText) ? response.Content.ErrorText : response.Content?.Result.HasValue == true ? response.Content.Result : response.StatusCode));
|
||||
}
|
||||
|
||||
if ((response.Content.TotalInventoryCount == 0) || (response.Content.Assets.Count == 0)) {
|
||||
|
|
|
@ -27,7 +27,6 @@ using System.Collections.Immutable;
|
|||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Collections;
|
||||
|
@ -430,7 +429,7 @@ public sealed class Actions : IAsyncDisposable, IDisposable {
|
|||
}
|
||||
|
||||
inventory = await Bot.ArchiHandler.GetMyInventoryAsync(appID, contextID, true).Where(item => filterFunction(item)).ToHashSetAsync().ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
Bot.ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return (false, string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, e.Message));
|
||||
|
|
|
@ -26,7 +26,6 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -3114,7 +3113,7 @@ public sealed class Commands {
|
|||
completeSuccess = false;
|
||||
}
|
||||
}
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
Bot.ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
completeSuccess = false;
|
||||
|
|
Loading…
Reference in a new issue