mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-13 00:17:21 +00:00
Closes #3066
This commit is contained in:
parent
263c77da12
commit
adbf0748f8
5 changed files with 31 additions and 29 deletions
|
@ -26,6 +26,7 @@ using System.Collections.Immutable;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Core;
|
||||
using ArchiSteamFarm.Helpers;
|
||||
|
@ -324,14 +325,14 @@ internal sealed class GlobalCache : SerializableFile {
|
|||
return (depotKey.Length == 64) && Utilities.IsValidHexadecimalText(depotKey);
|
||||
}
|
||||
|
||||
private static async Task<(bool Success, ImmutableHashSet<uint>? Result)> ResolveKnownDepotIDs() {
|
||||
private static async Task<(bool Success, ImmutableHashSet<uint>? Result)> ResolveKnownDepotIDs(CancellationToken cancellationToken = default) {
|
||||
if (ASF.WebBrowser == null) {
|
||||
throw new InvalidOperationException(nameof(ASF.WebBrowser));
|
||||
}
|
||||
|
||||
Uri request = new($"{SharedInfo.ServerURL}/knowndepots.csv");
|
||||
|
||||
StreamResponse? response = await ASF.WebBrowser.UrlGetToStream(request).ConfigureAwait(false);
|
||||
StreamResponse? response = await ASF.WebBrowser.UrlGetToStream(request, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (response?.Content == null) {
|
||||
return (false, null);
|
||||
|
@ -341,7 +342,7 @@ internal sealed class GlobalCache : SerializableFile {
|
|||
try {
|
||||
using StreamReader reader = new(response.Content);
|
||||
|
||||
string? countText = await reader.ReadLineAsync().ConfigureAwait(false);
|
||||
string? countText = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(countText) || !int.TryParse(countText, out int count) || (count <= 0)) {
|
||||
ASF.ArchiLogger.LogNullError(countText);
|
||||
|
@ -351,7 +352,7 @@ internal sealed class GlobalCache : SerializableFile {
|
|||
|
||||
HashSet<uint> result = new(count);
|
||||
|
||||
while (await reader.ReadLineAsync().ConfigureAwait(false) is { Length: > 0 } line) {
|
||||
while (await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false) is { Length: > 0 } line) {
|
||||
if (!uint.TryParse(line, out uint depotID) || (depotID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(depotID);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ using System.Collections.Immutable;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Dom;
|
||||
using ArchiSteamFarm.Helpers;
|
||||
|
@ -170,7 +171,7 @@ internal static class ArchiNet {
|
|||
return authenticateResponse.Content?.Result == bot.SteamID ? HttpStatusCode.OK : HttpStatusCode.Unauthorized;
|
||||
}
|
||||
|
||||
private static async Task<(bool Success, IReadOnlyCollection<ulong>? Result)> ResolveCachedBadBots() {
|
||||
private static async Task<(bool Success, IReadOnlyCollection<ulong>? Result)> ResolveCachedBadBots(CancellationToken cancellationToken = default) {
|
||||
if (ASF.GlobalDatabase == null) {
|
||||
throw new InvalidOperationException(nameof(ASF.WebBrowser));
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ internal static class ArchiNet {
|
|||
|
||||
Uri request = new(URL, "/Api/BadBots");
|
||||
|
||||
ObjectResponse<GenericResponse<ImmutableHashSet<ulong>>>? response = await ASF.WebBrowser.UrlGetToJsonObject<GenericResponse<ImmutableHashSet<ulong>>>(request).ConfigureAwait(false);
|
||||
ObjectResponse<GenericResponse<ImmutableHashSet<ulong>>>? response = await ASF.WebBrowser.UrlGetToJsonObject<GenericResponse<ImmutableHashSet<ulong>>>(request, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (response?.Content?.Result == null) {
|
||||
return (false, ASF.GlobalDatabase.CachedBadBots);
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ArchiSteamFarm.Helpers;
|
|||
public sealed class ArchiCacheable<T> : IDisposable {
|
||||
private readonly TimeSpan CacheLifetime;
|
||||
private readonly SemaphoreSlim InitSemaphore = new(1, 1);
|
||||
private readonly Func<Task<(bool Success, T? Result)>> ResolveFunction;
|
||||
private readonly Func<CancellationToken, Task<(bool Success, T? Result)>> ResolveFunction;
|
||||
|
||||
private bool IsInitialized => InitializedAt > DateTime.MinValue;
|
||||
private bool IsPermanentCache => CacheLifetime == Timeout.InfiniteTimeSpan;
|
||||
|
@ -39,7 +39,7 @@ public sealed class ArchiCacheable<T> : IDisposable {
|
|||
private DateTime InitializedAt;
|
||||
private T? InitializedValue;
|
||||
|
||||
public ArchiCacheable(Func<Task<(bool Success, T? Result)>> resolveFunction, TimeSpan? cacheLifetime = null) {
|
||||
public ArchiCacheable(Func<CancellationToken, Task<(bool Success, T? Result)>> resolveFunction, TimeSpan? cacheLifetime = null) {
|
||||
ArgumentNullException.ThrowIfNull(resolveFunction);
|
||||
|
||||
ResolveFunction = resolveFunction;
|
||||
|
@ -49,7 +49,7 @@ public sealed class ArchiCacheable<T> : IDisposable {
|
|||
public void Dispose() => InitSemaphore.Dispose();
|
||||
|
||||
[PublicAPI]
|
||||
public async Task<(bool Success, T? Result)> GetValue(ECacheFallback cacheFallback = ECacheFallback.DefaultForType) {
|
||||
public async Task<(bool Success, T? Result)> GetValue(ECacheFallback cacheFallback = ECacheFallback.DefaultForType, CancellationToken cancellationToken = default) {
|
||||
if (!Enum.IsDefined(cacheFallback)) {
|
||||
throw new InvalidEnumArgumentException(nameof(cacheFallback), (int) cacheFallback, typeof(ECacheFallback));
|
||||
}
|
||||
|
@ -58,14 +58,14 @@ public sealed class ArchiCacheable<T> : IDisposable {
|
|||
return (true, InitializedValue);
|
||||
}
|
||||
|
||||
await InitSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
await InitSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
if (IsInitialized && IsRecent) {
|
||||
return (true, InitializedValue);
|
||||
}
|
||||
|
||||
(bool success, T? result) = await ResolveFunction().ConfigureAwait(false);
|
||||
(bool success, T? result) = await ResolveFunction(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!success) {
|
||||
return cacheFallback switch {
|
||||
|
@ -86,12 +86,12 @@ public sealed class ArchiCacheable<T> : IDisposable {
|
|||
}
|
||||
|
||||
[PublicAPI]
|
||||
public async Task Reset() {
|
||||
public async Task Reset(CancellationToken cancellationToken = default) {
|
||||
if (!IsInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
await InitSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
await InitSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
if (!IsInitialized) {
|
||||
|
|
|
@ -2275,9 +2275,9 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
internal void OnDisconnected() {
|
||||
Initialized = false;
|
||||
|
||||
Utilities.InBackground(CachedAccessToken.Reset);
|
||||
Utilities.InBackground(CachedApiKey.Reset);
|
||||
Utilities.InBackground(CachedEconomyBan.Reset);
|
||||
Utilities.InBackground(() => CachedAccessToken.Reset());
|
||||
Utilities.InBackground(() => CachedApiKey.Reset());
|
||||
Utilities.InBackground(() => CachedEconomyBan.Reset());
|
||||
}
|
||||
|
||||
internal void OnVanityURLChanged(string? vanityURL = null) => VanityURL = !string.IsNullOrEmpty(vanityURL) ? vanityURL : null;
|
||||
|
@ -2329,10 +2329,10 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
return response?.Content?.Result == EResult.OK;
|
||||
}
|
||||
|
||||
private async Task<(ESteamApiKeyState State, string? Key)> GetApiKeyState() {
|
||||
private async Task<(ESteamApiKeyState State, string? Key)> GetApiKeyState(CancellationToken cancellationToken = default) {
|
||||
Uri request = new(SteamCommunityURL, "/dev/apikey?l=english");
|
||||
|
||||
using HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request, checkSessionPreemptively: false).ConfigureAwait(false);
|
||||
using HtmlDocumentResponse? response = await UrlGetToHtmlDocumentWithSession(request, checkSessionPreemptively: false, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (response?.Content == null) {
|
||||
return (ESteamApiKeyState.Timeout, null);
|
||||
|
@ -2611,21 +2611,21 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
return await UrlPostWithSession(request, data: data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<(bool Success, string? Result)> ResolveAccessToken() {
|
||||
private async Task<(bool Success, string? Result)> ResolveAccessToken(CancellationToken cancellationToken = default) {
|
||||
Uri request = new(SteamStoreURL, "/pointssummary/ajaxgetasyncconfig");
|
||||
|
||||
ObjectResponse<AccessTokenResponse>? response = await UrlGetToJsonObjectWithSession<AccessTokenResponse>(request).ConfigureAwait(false);
|
||||
ObjectResponse<AccessTokenResponse>? response = await UrlGetToJsonObjectWithSession<AccessTokenResponse>(request, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return !string.IsNullOrEmpty(response?.Content?.Data.WebAPIToken) ? (true, response.Content.Data.WebAPIToken) : (false, null);
|
||||
}
|
||||
|
||||
private async Task<(bool Success, string? Result)> ResolveApiKey() {
|
||||
private async Task<(bool Success, string? Result)> ResolveApiKey(CancellationToken cancellationToken = default) {
|
||||
if (Bot.IsAccountLimited) {
|
||||
// API key is permanently unavailable for limited accounts
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
(ESteamApiKeyState State, string? Key) result = await GetApiKeyState().ConfigureAwait(false);
|
||||
(ESteamApiKeyState State, string? Key) result = await GetApiKeyState(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
switch (result.State) {
|
||||
case ESteamApiKeyState.AccessDenied:
|
||||
|
@ -2641,7 +2641,7 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
}
|
||||
|
||||
// We should have the key ready, so let's fetch it again
|
||||
result = await GetApiKeyState().ConfigureAwait(false);
|
||||
result = await GetApiKeyState(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (result.State == ESteamApiKeyState.Timeout) {
|
||||
// Request timed out, bad luck, we'll try again later
|
||||
|
@ -2669,8 +2669,8 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<(bool Success, bool? Result)> ResolveEconomyBan() {
|
||||
(_, string? steamApiKey) = await CachedApiKey.GetValue(ECacheFallback.SuccessPreviously).ConfigureAwait(false);
|
||||
private async Task<(bool Success, bool? Result)> ResolveEconomyBan(CancellationToken cancellationToken = default) {
|
||||
(_, string? steamApiKey) = await CachedApiKey.GetValue(ECacheFallback.SuccessPreviously, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(steamApiKey)) {
|
||||
return (false, null);
|
||||
|
@ -2680,7 +2680,7 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
byte connectionTimeout = ASF.GlobalConfig?.ConnectionTimeout ?? GlobalConfig.DefaultConnectionTimeout;
|
||||
|
||||
for (byte i = 0; (i < connectionTimeout) && !Initialized && Bot.IsConnectedAndLoggedOn; i++) {
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!Initialized) {
|
||||
|
@ -2699,7 +2699,7 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
|
||||
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
|
||||
if ((i > 0) && (WebLimiterDelay > 0)) {
|
||||
await Task.Delay(WebLimiterDelay).ConfigureAwait(false);
|
||||
await Task.Delay(WebLimiterDelay, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
using WebAPI.AsyncInterface service = Bot.SteamConfiguration.GetAsyncWebAPIInterface(SteamUserService);
|
||||
|
@ -2711,7 +2711,7 @@ public sealed class ArchiWebHandler : IDisposable {
|
|||
WebAPI.DefaultBaseAddress,
|
||||
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await service.CallAsync(HttpMethod.Get, "GetPlayerBans", args: arguments).ConfigureAwait(false)
|
||||
async () => await service.CallAsync(HttpMethod.Get, "GetPlayerBans", args: arguments).ConfigureAwait(false), cancellationToken
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
|
|
|
@ -375,7 +375,7 @@ public sealed class MobileAuthenticator : IDisposable {
|
|||
);
|
||||
}
|
||||
|
||||
private async Task<(bool Success, string? Result)> ResolveDeviceID() {
|
||||
private async Task<(bool Success, string? Result)> ResolveDeviceID(CancellationToken cancellationToken = default) {
|
||||
if (Bot == null) {
|
||||
throw new InvalidOperationException(nameof(Bot));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue