mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-22 00:11:49 +00:00
Closes #3163
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user