From 8c83b8c51f09a5e85e10197bde2d1f4c30cd37ed Mon Sep 17 00:00:00 2001 From: Archi Date: Tue, 16 May 2023 21:27:36 +0200 Subject: [PATCH] Closes #2900 Closes #2901 --- .../RemoteCommunication.cs | 25 +++++++++++++++++ .../Steam/Integration/ArchiHandler.cs | 27 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs b/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs index 7cf7516e7..d56ae0c68 100644 --- a/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs +++ b/ArchiSteamFarm.OfficialPlugins.ItemsMatcher/RemoteCommunication.cs @@ -44,6 +44,7 @@ using ArchiSteamFarm.Web; using ArchiSteamFarm.Web.Responses; using Newtonsoft.Json.Linq; using SteamKit2; +using SteamKit2.Internal; namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher; @@ -53,6 +54,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable { private const byte MaxTradeOffersActive = 10; // The actual upper limit is 30, but we should use lower amount to allow some bots to react before we hit the maximum allowed private const byte MinAnnouncementTTL = 5; // Minimum amount of minutes we must wait before the next Announcement private const byte MinHeartBeatTTL = 10; // Minimum amount of minutes we must wait before sending next HeartBeat + private const byte MinimumSteamGuardEnabledDays = 15; // As imposed by Steam limits private const byte MinPersonaStateTTL = 5; // Minimum amount of minutes we must wait before requesting persona state update private static readonly ImmutableHashSet AcceptedMatchableTypes = ImmutableHashSet.Create( @@ -525,6 +527,29 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable { return false; } + // Bot must pass some general trading requirements + CCredentials_GetSteamGuardDetails_Response? steamGuardStatus = await Bot.ArchiHandler.GetSteamGuardStatus().ConfigureAwait(false); + + if (steamGuardStatus == null) { + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(steamGuardStatus)}: null")); + + return null; + } + + // Bot must have SteamGuard active for at least 15 days + if (!steamGuardStatus.is_steamguard_enabled || (steamGuardStatus.timestamp_steamguard_enabled == 0) || ((DateTimeOffset.UtcNow - DateTimeOffset.FromUnixTimeSeconds(steamGuardStatus.timestamp_steamguard_enabled)).TotalDays < MinimumSteamGuardEnabledDays)) { + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(steamGuardStatus.is_steamguard_enabled)}/{nameof(steamGuardStatus.timestamp_steamguard_enabled)}: {steamGuardStatus.is_steamguard_enabled}/{steamGuardStatus.timestamp_steamguard_enabled}")); + + return false; + } + + // Bot must have 2FA enabled for matching to work + if (!steamGuardStatus.is_twofactor_enabled) { + Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(steamGuardStatus.is_twofactor_enabled)}: false")); + + return false; + } + // Bot must have valid API key (e.g. not being restricted account) bool? hasValidApiKey = await Bot.ArchiWebHandler.HasValidApiKey().ConfigureAwait(false); diff --git a/ArchiSteamFarm/Steam/Integration/ArchiHandler.cs b/ArchiSteamFarm/Steam/Integration/ArchiHandler.cs index 8cc97a05f..297836eb1 100644 --- a/ArchiSteamFarm/Steam/Integration/ArchiHandler.cs +++ b/ArchiSteamFarm/Steam/Integration/ArchiHandler.cs @@ -41,6 +41,7 @@ public sealed class ArchiHandler : ClientMsgHandler { private readonly ArchiLogger ArchiLogger; private readonly SteamUnifiedMessages.UnifiedService UnifiedChatRoomService; private readonly SteamUnifiedMessages.UnifiedService UnifiedClanChatRoomsService; + private readonly SteamUnifiedMessages.UnifiedService UnifiedCredentialsService; private readonly SteamUnifiedMessages.UnifiedService UnifiedEconService; private readonly SteamUnifiedMessages.UnifiedService UnifiedFriendMessagesService; private readonly SteamUnifiedMessages.UnifiedService UnifiedPlayerService; @@ -54,6 +55,7 @@ public sealed class ArchiHandler : ClientMsgHandler { ArchiLogger = archiLogger ?? throw new ArgumentNullException(nameof(archiLogger)); UnifiedChatRoomService = steamUnifiedMessages.CreateService(); UnifiedClanChatRoomsService = steamUnifiedMessages.CreateService(); + UnifiedCredentialsService = steamUnifiedMessages.CreateService(); UnifiedEconService = steamUnifiedMessages.CreateService(); UnifiedFriendMessagesService = steamUnifiedMessages.CreateService(); UnifiedPlayerService = steamUnifiedMessages.CreateService(); @@ -130,6 +132,31 @@ public sealed class ArchiHandler : ClientMsgHandler { return body.games.ToDictionary(static game => (uint) game.appid, static game => game.name); } + [PublicAPI] + public async Task GetSteamGuardStatus() { + if (Client == null) { + throw new InvalidOperationException(nameof(Client)); + } + + if (!Client.IsConnected) { + return null; + } + + CCredentials_GetSteamGuardDetails_Request request = new(); + + SteamUnifiedMessages.ServiceMethodResponse response; + + try { + response = await UnifiedCredentialsService.SendMessage(x => x.GetSteamGuardDetails(request)).ToLongRunningTask().ConfigureAwait(false); + } catch (Exception e) { + ArchiLogger.LogGenericWarningException(e); + + return null; + } + + return response.Result == EResult.OK ? response.GetDeserializedResponse() : null; + } + [PublicAPI] public async Task GetTradeToken() { if (Client == null) {