This commit is contained in:
Archi 2023-11-14 21:10:35 +01:00
parent 263c77da12
commit adbf0748f8
No known key found for this signature in database
GPG key ID: 6B138B4C64555AEA
5 changed files with 31 additions and 29 deletions

View file

@ -26,6 +26,7 @@ using System.Collections.Immutable;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ArchiSteamFarm.Core; using ArchiSteamFarm.Core;
using ArchiSteamFarm.Helpers; using ArchiSteamFarm.Helpers;
@ -324,14 +325,14 @@ internal sealed class GlobalCache : SerializableFile {
return (depotKey.Length == 64) && Utilities.IsValidHexadecimalText(depotKey); 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) { if (ASF.WebBrowser == null) {
throw new InvalidOperationException(nameof(ASF.WebBrowser)); throw new InvalidOperationException(nameof(ASF.WebBrowser));
} }
Uri request = new($"{SharedInfo.ServerURL}/knowndepots.csv"); 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) { if (response?.Content == null) {
return (false, null); return (false, null);
@ -341,7 +342,7 @@ internal sealed class GlobalCache : SerializableFile {
try { try {
using StreamReader reader = new(response.Content); 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)) { if (string.IsNullOrEmpty(countText) || !int.TryParse(countText, out int count) || (count <= 0)) {
ASF.ArchiLogger.LogNullError(countText); ASF.ArchiLogger.LogNullError(countText);
@ -351,7 +352,7 @@ internal sealed class GlobalCache : SerializableFile {
HashSet<uint> result = new(count); 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)) { if (!uint.TryParse(line, out uint depotID) || (depotID == 0)) {
ASF.ArchiLogger.LogNullError(depotID); ASF.ArchiLogger.LogNullError(depotID);

View file

@ -25,6 +25,7 @@ using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using ArchiSteamFarm.Helpers; using ArchiSteamFarm.Helpers;
@ -170,7 +171,7 @@ internal static class ArchiNet {
return authenticateResponse.Content?.Result == bot.SteamID ? HttpStatusCode.OK : HttpStatusCode.Unauthorized; 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) { if (ASF.GlobalDatabase == null) {
throw new InvalidOperationException(nameof(ASF.WebBrowser)); throw new InvalidOperationException(nameof(ASF.WebBrowser));
} }
@ -181,7 +182,7 @@ internal static class ArchiNet {
Uri request = new(URL, "/Api/BadBots"); 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) { if (response?.Content?.Result == null) {
return (false, ASF.GlobalDatabase.CachedBadBots); return (false, ASF.GlobalDatabase.CachedBadBots);

View file

@ -30,7 +30,7 @@ namespace ArchiSteamFarm.Helpers;
public sealed class ArchiCacheable<T> : IDisposable { public sealed class ArchiCacheable<T> : IDisposable {
private readonly TimeSpan CacheLifetime; private readonly TimeSpan CacheLifetime;
private readonly SemaphoreSlim InitSemaphore = new(1, 1); 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 IsInitialized => InitializedAt > DateTime.MinValue;
private bool IsPermanentCache => CacheLifetime == Timeout.InfiniteTimeSpan; private bool IsPermanentCache => CacheLifetime == Timeout.InfiniteTimeSpan;
@ -39,7 +39,7 @@ public sealed class ArchiCacheable<T> : IDisposable {
private DateTime InitializedAt; private DateTime InitializedAt;
private T? InitializedValue; 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); ArgumentNullException.ThrowIfNull(resolveFunction);
ResolveFunction = resolveFunction; ResolveFunction = resolveFunction;
@ -49,7 +49,7 @@ public sealed class ArchiCacheable<T> : IDisposable {
public void Dispose() => InitSemaphore.Dispose(); public void Dispose() => InitSemaphore.Dispose();
[PublicAPI] [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)) { if (!Enum.IsDefined(cacheFallback)) {
throw new InvalidEnumArgumentException(nameof(cacheFallback), (int) cacheFallback, typeof(ECacheFallback)); throw new InvalidEnumArgumentException(nameof(cacheFallback), (int) cacheFallback, typeof(ECacheFallback));
} }
@ -58,14 +58,14 @@ public sealed class ArchiCacheable<T> : IDisposable {
return (true, InitializedValue); return (true, InitializedValue);
} }
await InitSemaphore.WaitAsync().ConfigureAwait(false); await InitSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try { try {
if (IsInitialized && IsRecent) { if (IsInitialized && IsRecent) {
return (true, InitializedValue); return (true, InitializedValue);
} }
(bool success, T? result) = await ResolveFunction().ConfigureAwait(false); (bool success, T? result) = await ResolveFunction(cancellationToken).ConfigureAwait(false);
if (!success) { if (!success) {
return cacheFallback switch { return cacheFallback switch {
@ -86,12 +86,12 @@ public sealed class ArchiCacheable<T> : IDisposable {
} }
[PublicAPI] [PublicAPI]
public async Task Reset() { public async Task Reset(CancellationToken cancellationToken = default) {
if (!IsInitialized) { if (!IsInitialized) {
return; return;
} }
await InitSemaphore.WaitAsync().ConfigureAwait(false); await InitSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try { try {
if (!IsInitialized) { if (!IsInitialized) {

View file

@ -2275,9 +2275,9 @@ public sealed class ArchiWebHandler : IDisposable {
internal void OnDisconnected() { internal void OnDisconnected() {
Initialized = false; Initialized = false;
Utilities.InBackground(CachedAccessToken.Reset); Utilities.InBackground(() => CachedAccessToken.Reset());
Utilities.InBackground(CachedApiKey.Reset); Utilities.InBackground(() => CachedApiKey.Reset());
Utilities.InBackground(CachedEconomyBan.Reset); Utilities.InBackground(() => CachedEconomyBan.Reset());
} }
internal void OnVanityURLChanged(string? vanityURL = null) => VanityURL = !string.IsNullOrEmpty(vanityURL) ? vanityURL : null; 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; 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"); 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) { if (response?.Content == null) {
return (ESteamApiKeyState.Timeout, null); return (ESteamApiKeyState.Timeout, null);
@ -2611,21 +2611,21 @@ public sealed class ArchiWebHandler : IDisposable {
return await UrlPostWithSession(request, data: data).ConfigureAwait(false); 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"); 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); 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) { if (Bot.IsAccountLimited) {
// API key is permanently unavailable for limited accounts // API key is permanently unavailable for limited accounts
return (true, null); 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) { switch (result.State) {
case ESteamApiKeyState.AccessDenied: case ESteamApiKeyState.AccessDenied:
@ -2641,7 +2641,7 @@ public sealed class ArchiWebHandler : IDisposable {
} }
// We should have the key ready, so let's fetch it again // 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) { if (result.State == ESteamApiKeyState.Timeout) {
// Request timed out, bad luck, we'll try again later // 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() { private async Task<(bool Success, bool? Result)> ResolveEconomyBan(CancellationToken cancellationToken = default) {
(_, string? steamApiKey) = await CachedApiKey.GetValue(ECacheFallback.SuccessPreviously).ConfigureAwait(false); (_, string? steamApiKey) = await CachedApiKey.GetValue(ECacheFallback.SuccessPreviously, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(steamApiKey)) { if (string.IsNullOrEmpty(steamApiKey)) {
return (false, null); return (false, null);
@ -2680,7 +2680,7 @@ public sealed class ArchiWebHandler : IDisposable {
byte connectionTimeout = ASF.GlobalConfig?.ConnectionTimeout ?? GlobalConfig.DefaultConnectionTimeout; byte connectionTimeout = ASF.GlobalConfig?.ConnectionTimeout ?? GlobalConfig.DefaultConnectionTimeout;
for (byte i = 0; (i < connectionTimeout) && !Initialized && Bot.IsConnectedAndLoggedOn; i++) { 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) { if (!Initialized) {
@ -2699,7 +2699,7 @@ public sealed class ArchiWebHandler : IDisposable {
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) { for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
if ((i > 0) && (WebLimiterDelay > 0)) { 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); using WebAPI.AsyncInterface service = Bot.SteamConfiguration.GetAsyncWebAPIInterface(SteamUserService);
@ -2711,7 +2711,7 @@ public sealed class ArchiWebHandler : IDisposable {
WebAPI.DefaultBaseAddress, WebAPI.DefaultBaseAddress,
// ReSharper disable once AccessToDisposedClosure // 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); ).ConfigureAwait(false);
} catch (TaskCanceledException e) { } catch (TaskCanceledException e) {
Bot.ArchiLogger.LogGenericDebuggingException(e); Bot.ArchiLogger.LogGenericDebuggingException(e);

View file

@ -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) { if (Bot == null) {
throw new InvalidOperationException(nameof(Bot)); throw new InvalidOperationException(nameof(Bot));
} }