This commit is contained in:
Archi
2024-03-19 13:03:09 +01:00
parent 04b534bda1
commit 6f2fd4eccc
5 changed files with 48 additions and 76 deletions

View File

@@ -2437,7 +2437,6 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
); );
} }
ArchiWebHandler.OnInitModules();
BotDatabase.MobileAuthenticator?.OnInitModules(); BotDatabase.MobileAuthenticator?.OnInitModules();
await PluginsCore.OnBotInitModules(this, BotConfig.AdditionalProperties).ConfigureAwait(false); await PluginsCore.OnBotInitModules(this, BotConfig.AdditionalProperties).ConfigureAwait(false);

View File

@@ -37,7 +37,6 @@ using AngleSharp.Dom;
using AngleSharp.XPath; using AngleSharp.XPath;
using ArchiSteamFarm.Collections; using ArchiSteamFarm.Collections;
using ArchiSteamFarm.Core; using ArchiSteamFarm.Core;
using ArchiSteamFarm.Helpers;
using ArchiSteamFarm.Localization; using ArchiSteamFarm.Localization;
using ArchiSteamFarm.Plugins; using ArchiSteamFarm.Plugins;
using ArchiSteamFarm.Steam.Data; using ArchiSteamFarm.Steam.Data;
@@ -1177,7 +1176,7 @@ public sealed class CardsFarmer : IAsyncDisposable, IDisposable {
GamesToFarm.Clear(); GamesToFarm.Clear();
(_, FrozenSet<uint>? privateAppIDs) = await Bot.ArchiWebHandler.CachedPrivateAppIDs.GetValue(ECacheFallback.SuccessPreviously).ConfigureAwait(false); HashSet<uint>? privateAppIDs = await Bot.ArchiHandler.GetPrivateAppIDs().ConfigureAwait(false);
ConcurrentHashSet<uint> parsedAppIDs = []; ConcurrentHashSet<uint> parsedAppIDs = [];
@@ -1276,7 +1275,7 @@ public sealed class CardsFarmer : IAsyncDisposable, IDisposable {
// Lastly, we forcefully apply random order to those considered the same in value, as we can't really afford massive amount of misses in a row // Lastly, we forcefully apply random order to those considered the same in value, as we can't really afford massive amount of misses in a row
Dictionary<uint, string> gamesToFarm = boosterCreatorEntries.Where(entry => !boosterElibility.Contains(entry.AppID) && (!Bot.BotDatabase.FarmingRiskyIgnoredAppIDs.TryGetValue(entry.AppID, out DateTime ignoredUntil) || (ignoredUntil < now)) && ShouldIdle(entry.AppID)).ToDictionary(static entry => entry.AppID, static entry => entry.Name); Dictionary<uint, string> gamesToFarm = boosterCreatorEntries.Where(entry => !boosterElibility.Contains(entry.AppID) && (!Bot.BotDatabase.FarmingRiskyIgnoredAppIDs.TryGetValue(entry.AppID, out DateTime ignoredUntil) || (ignoredUntil < now)) && ShouldIdle(entry.AppID)).ToDictionary(static entry => entry.AppID, static entry => entry.Name);
(_, FrozenSet<uint>? privateAppIDs) = await Bot.ArchiWebHandler.CachedPrivateAppIDs.GetValue(ECacheFallback.SuccessPreviously).ConfigureAwait(false); HashSet<uint>? privateAppIDs = await Bot.ArchiHandler.GetPrivateAppIDs().ConfigureAwait(false);
if (privateAppIDs != null) { if (privateAppIDs != null) {
foreach (uint appID in privateAppIDs) { foreach (uint appID in privateAppIDs) {

View File

@@ -36,6 +36,16 @@ using ArchiSteamFarm.Steam.Integration.CMsgs;
using JetBrains.Annotations; using JetBrains.Annotations;
using SteamKit2; using SteamKit2;
using SteamKit2.Internal; using SteamKit2.Internal;
using SteamKit2.WebUI.Internal;
using CMsgClientChangeStatus = SteamKit2.Internal.CMsgClientChangeStatus;
using CMsgClientCommentNotifications = SteamKit2.Internal.CMsgClientCommentNotifications;
using CMsgClientGamesPlayed = SteamKit2.Internal.CMsgClientGamesPlayed;
using CMsgClientItemAnnouncements = SteamKit2.Internal.CMsgClientItemAnnouncements;
using CMsgClientRedeemGuestPass = SteamKit2.Internal.CMsgClientRedeemGuestPass;
using CMsgClientRequestItemAnnouncements = SteamKit2.Internal.CMsgClientRequestItemAnnouncements;
using CMsgClientSharedLibraryLockStatus = SteamKit2.Internal.CMsgClientSharedLibraryLockStatus;
using CMsgClientUIMode = SteamKit2.Internal.CMsgClientUIMode;
using CMsgClientUserNotifications = SteamKit2.Internal.CMsgClientUserNotifications;
using EPersonaStateFlag = SteamKit2.EPersonaStateFlag; using EPersonaStateFlag = SteamKit2.EPersonaStateFlag;
namespace ArchiSteamFarm.Steam.Integration; namespace ArchiSteamFarm.Steam.Integration;
@@ -44,6 +54,8 @@ public sealed class ArchiHandler : ClientMsgHandler {
internal const byte MaxGamesPlayedConcurrently = 32; // This is limit introduced by Steam Network internal const byte MaxGamesPlayedConcurrently = 32; // This is limit introduced by Steam Network
private readonly ArchiLogger ArchiLogger; private readonly ArchiLogger ArchiLogger;
private readonly SteamUnifiedMessages.UnifiedService<IAccountPrivateApps> UnifiedAccountPrivateApps;
private readonly SteamUnifiedMessages.UnifiedService<IChatRoom> UnifiedChatRoomService; private readonly SteamUnifiedMessages.UnifiedService<IChatRoom> UnifiedChatRoomService;
private readonly SteamUnifiedMessages.UnifiedService<IClanChatRooms> UnifiedClanChatRoomsService; private readonly SteamUnifiedMessages.UnifiedService<IClanChatRooms> UnifiedClanChatRoomsService;
private readonly SteamUnifiedMessages.UnifiedService<ICredentials> UnifiedCredentialsService; private readonly SteamUnifiedMessages.UnifiedService<ICredentials> UnifiedCredentialsService;
@@ -60,6 +72,8 @@ public sealed class ArchiHandler : ClientMsgHandler {
ArgumentNullException.ThrowIfNull(steamUnifiedMessages); ArgumentNullException.ThrowIfNull(steamUnifiedMessages);
ArchiLogger = archiLogger; ArchiLogger = archiLogger;
UnifiedAccountPrivateApps = steamUnifiedMessages.CreateService<IAccountPrivateApps>();
UnifiedChatRoomService = steamUnifiedMessages.CreateService<IChatRoom>(); UnifiedChatRoomService = steamUnifiedMessages.CreateService<IChatRoom>();
UnifiedClanChatRoomsService = steamUnifiedMessages.CreateService<IClanChatRooms>(); UnifiedClanChatRoomsService = steamUnifiedMessages.CreateService<IClanChatRooms>();
UnifiedCredentialsService = steamUnifiedMessages.CreateService<ICredentials>(); UnifiedCredentialsService = steamUnifiedMessages.CreateService<ICredentials>();
@@ -253,6 +267,36 @@ public sealed class ArchiHandler : ClientMsgHandler {
} }
} }
internal async Task<HashSet<uint>?> GetPrivateAppIDs() {
if (Client == null) {
throw new InvalidOperationException(nameof(Client));
}
if (!Client.IsConnected) {
return null;
}
CAccountPrivateApps_GetPrivateAppList_Request request = new();
SteamUnifiedMessages.ServiceMethodResponse response;
try {
response = await UnifiedAccountPrivateApps.SendMessage(x => x.GetPrivateAppList(request)).ToLongRunningTask().ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
return null;
}
if (response.Result != EResult.OK) {
return null;
}
CAccountPrivateApps_GetPrivateAppList_Response body = response.GetDeserializedResponse<CAccountPrivateApps_GetPrivateAppList_Response>();
return body.private_apps.appids.Select(static appID => (uint) appID).ToHashSet();
}
[PublicAPI] [PublicAPI]
public async Task<Dictionary<uint, string>?> GetOwnedGames(ulong steamID) { public async Task<Dictionary<uint, string>?> GetOwnedGames(ulong steamID) {
if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount) { if ((steamID == 0) || !new SteamID(steamID).IsIndividualAccount) {

View File

@@ -22,7 +22,6 @@
// limitations under the License. // limitations under the License.
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
@@ -52,7 +51,6 @@ using SteamKit2;
namespace ArchiSteamFarm.Steam.Integration; namespace ArchiSteamFarm.Steam.Integration;
public sealed class ArchiWebHandler : IDisposable { public sealed class ArchiWebHandler : IDisposable {
private const string AccountPrivateAppsService = "IAccountPrivateAppsService";
private const string EconService = "IEconService"; private const string EconService = "IEconService";
private const string LoyaltyRewardsService = "ILoyaltyRewardsService"; private const string LoyaltyRewardsService = "ILoyaltyRewardsService";
private const ushort MaxItemsInSingleInventoryRequest = 5000; private const ushort MaxItemsInSingleInventoryRequest = 5000;
@@ -76,8 +74,6 @@ public sealed class ArchiWebHandler : IDisposable {
[PublicAPI] [PublicAPI]
public WebBrowser WebBrowser { get; } public WebBrowser WebBrowser { get; }
internal readonly ArchiCacheable<FrozenSet<uint>> CachedPrivateAppIDs;
private readonly Bot Bot; private readonly Bot Bot;
private readonly SemaphoreSlim SessionSemaphore = new(1, 1); private readonly SemaphoreSlim SessionSemaphore = new(1, 1);
@@ -91,12 +87,10 @@ public sealed class ArchiWebHandler : IDisposable {
ArgumentNullException.ThrowIfNull(bot); ArgumentNullException.ThrowIfNull(bot);
Bot = bot; Bot = bot;
CachedPrivateAppIDs = new ArchiCacheable<FrozenSet<uint>>(ResolvePrivateAppIDs, TimeSpan.FromMinutes(5));
WebBrowser = new WebBrowser(bot.ArchiLogger, ASF.GlobalConfig?.WebProxy); WebBrowser = new WebBrowser(bot.ArchiLogger, ASF.GlobalConfig?.WebProxy);
} }
public void Dispose() { public void Dispose() {
CachedPrivateAppIDs.Dispose();
SessionSemaphore.Dispose(); SessionSemaphore.Dispose();
WebBrowser.Dispose(); WebBrowser.Dispose();
} }
@@ -2123,8 +2117,6 @@ public sealed class ArchiWebHandler : IDisposable {
internal void OnDisconnected() => Initialized = false; internal void OnDisconnected() => Initialized = false;
internal void OnInitModules() => Utilities.InBackground(() => CachedPrivateAppIDs.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;
internal async Task<(EResult Result, EPurchaseResultDetail? PurchaseResult, string? BalanceText)?> RedeemWalletKey(string key) { internal async Task<(EResult Result, EPurchaseResultDetail? PurchaseResult, string? BalanceText)?> RedeemWalletKey(string key) {
@@ -2294,69 +2286,6 @@ public sealed class ArchiWebHandler : IDisposable {
} }
} }
private async Task<(bool Success, FrozenSet<uint>? Result)> ResolvePrivateAppIDs(CancellationToken cancellationToken) {
string? accessToken = Bot.AccessToken;
if (string.IsNullOrEmpty(accessToken)) {
return (false, null);
}
Dictionary<string, object?> arguments = new(1, StringComparer.Ordinal) {
{ "access_token", accessToken }
};
KeyValue? response = null;
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
if ((i > 0) && (WebLimiterDelay > 0)) {
await Task.Delay(WebLimiterDelay, cancellationToken).ConfigureAwait(false);
}
using WebAPI.AsyncInterface accountPrivateAppsService = Bot.SteamConfiguration.GetAsyncWebAPIInterface(AccountPrivateAppsService);
accountPrivateAppsService.Timeout = WebBrowser.Timeout;
try {
response = await WebLimitRequest(
WebAPI.DefaultBaseAddress,
// ReSharper disable once AccessToDisposedClosure
async () => await accountPrivateAppsService.CallAsync(HttpMethod.Get, "GetPrivateAppList", args: arguments).ConfigureAwait(false), cancellationToken
).ConfigureAwait(false);
} catch (TaskCanceledException e) {
Bot.ArchiLogger.LogGenericDebuggingException(e);
} catch (Exception e) {
Bot.ArchiLogger.LogGenericWarningException(e);
}
}
if (response == null) {
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries));
return (false, null);
}
List<KeyValue> nodes = response["private_apps"]["appids"].Children;
if (nodes.Count == 0) {
return (true, FrozenSet<uint>.Empty);
}
HashSet<uint> result = new(nodes.Count);
foreach (uint appID in nodes.Select(static node => node.AsUnsignedInteger())) {
if (appID == 0) {
Bot.ArchiLogger.LogNullError(appID);
return (false, null);
}
result.Add(appID);
}
return (true, result.ToFrozenSet());
}
private static void SetDescriptionsToAssets(IEnumerable<Asset> assets, [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")] Dictionary<(uint AppID, ulong ClassID, ulong InstanceID), InventoryDescription> descriptions) { private static void SetDescriptionsToAssets(IEnumerable<Asset> assets, [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")] Dictionary<(uint AppID, ulong ClassID, ulong InstanceID), InventoryDescription> descriptions) {
ArgumentNullException.ThrowIfNull(assets); ArgumentNullException.ThrowIfNull(assets);
ArgumentNullException.ThrowIfNull(descriptions); ArgumentNullException.ThrowIfNull(descriptions);

View File

@@ -44,7 +44,8 @@ namespace ArchiSteamFarm.Steam.Security;
public sealed class MobileAuthenticator : IDisposable { public sealed class MobileAuthenticator : IDisposable {
internal const byte BackupCodeDigits = 7; internal const byte BackupCodeDigits = 7;
internal const byte CodeDigits = 5; internal const byte CodeDigits = 5;
internal const byte CodeInterval = 30;
private const byte CodeInterval = 30;
// For how many minutes we can assume that SteamTimeDifference is correct // For how many minutes we can assume that SteamTimeDifference is correct
private const byte SteamTimeTTL = 15; private const byte SteamTimeTTL = 15;