From 4436e8dc43bb0ef6f8f97822165b040706961706 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Thu, 19 May 2022 21:34:57 +0200 Subject: [PATCH] Add STD command trigger for STD plugin --- .../SharedInfo.cs | 3 +- .../SteamTokenDumperPlugin.cs | 46 +++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SharedInfo.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SharedInfo.cs index 52096db36..1fe165bb9 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SharedInfo.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SharedInfo.cs @@ -24,10 +24,11 @@ namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper; internal static class SharedInfo { internal const byte ApiVersion = 2; internal const byte AppInfosPerSingleRequest = byte.MaxValue; + internal const byte HoursBetweenUploads = 24; internal const byte MaximumHoursBetweenRefresh = 8; // Per single bot account, makes sense to be 2 or 3 times less than MinimumHoursBetweenUploads internal const byte MaximumMinutesBeforeFirstUpload = 60; // Must be greater or equal to MinimumMinutesBeforeFirstUpload - internal const byte MinimumHoursBetweenUploads = 24; internal const byte MinimumMinutesBeforeFirstUpload = 10; // Must be less or equal to MaximumMinutesBeforeFirstUpload + internal const byte MinimumMinutesBetweenUploads = 5; // Rate limiting for the server internal const string ServerURL = "https://asf-token-dumper.xpaw.me"; internal const string Token = "STEAM_TOKEN_DUMPER_TOKEN"; // This is filled automatically during our CI build with API key provided by xPaw for ASF project diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs index 0875fbbc1..808deaad6 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; +using System.ComponentModel; using System.Composition; using System.Globalization; using System.Linq; @@ -43,7 +44,7 @@ using SteamKit2; namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper; [Export(typeof(IPlugin))] -internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotSteamClient, ISteamPICSChanges { +internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotCommand2, IBotSteamClient, ISteamPICSChanges { [JsonProperty] internal static SteamTokenDumperConfig? Config { get; private set; } @@ -53,6 +54,7 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotS private static readonly Timer SubmissionTimer = new(SubmitData); private static GlobalCache? GlobalCache; + private static DateTimeOffset LastUploadAt = DateTimeOffset.MinValue; [JsonProperty] public override string Name => nameof(SteamTokenDumperPlugin); @@ -138,12 +140,44 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotS // ReSharper disable once SuspiciousLockOverSynchronizationPrimitive - this is not a mistake, we need extra synchronization, and we can re-use the semaphore object for that lock (SubmissionSemaphore) { - SubmissionTimer.Change(startIn, TimeSpan.FromHours(SharedInfo.MinimumHoursBetweenUploads)); + SubmissionTimer.Change(startIn, TimeSpan.FromHours(SharedInfo.HoursBetweenUploads)); } ASF.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.PluginInitializedAndEnabled, nameof(SteamTokenDumperPlugin), startIn.ToHumanReadable())); } + public Task OnBotCommand(Bot bot, EAccess access, string message, string[] args, ulong steamID = 0) { + ArgumentNullException.ThrowIfNull(bot); + + if (!Enum.IsDefined(access)) { + throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); + } + + if ((args == null) || (args.Length == 0)) { + throw new ArgumentNullException(nameof(args)); + } + + switch (args[0].ToUpperInvariant()) { + case "STD" when access >= EAccess.Owner: + TimeSpan minimumTimeBetweenUpload = TimeSpan.FromMinutes(SharedInfo.MinimumMinutesBetweenUploads); + + if (LastUploadAt + minimumTimeBetweenUpload > DateTimeOffset.UtcNow) { + return Task.FromResult((string?) string.Format(CultureInfo.CurrentCulture, Strings.SubmissionFailedTooManyRequests, minimumTimeBetweenUpload.ToHumanReadable())); + } + + // ReSharper disable once SuspiciousLockOverSynchronizationPrimitive - this is not a mistake, we need extra synchronization, and we can re-use the semaphore object for that + lock (SubmissionSemaphore) { + SubmissionTimer.Change(TimeSpan.Zero, TimeSpan.FromHours(SharedInfo.HoursBetweenUploads)); + } + + return Task.FromResult((string?) ArchiSteamFarm.Localization.Strings.Done); + case "STD" when access > EAccess.None: + return Task.FromResult((string?) ArchiSteamFarm.Localization.Strings.ErrorAccessDenied); + default: + return Task.FromResult((string?) null); + } + } + public async Task OnBotDestroy(Bot bot) { ArgumentNullException.ThrowIfNull(bot); @@ -460,6 +494,10 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotS throw new InvalidOperationException(nameof(ASF.WebBrowser)); } + if (LastUploadAt + TimeSpan.FromMinutes(SharedInfo.MinimumMinutesBetweenUploads) > DateTimeOffset.UtcNow) { + return; + } + if (!await SubmissionSemaphore.WaitAsync(0).ConfigureAwait(false)) { return; } @@ -510,7 +548,7 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotS // ReSharper disable once SuspiciousLockOverSynchronizationPrimitive - this is not a mistake, we need extra synchronization, and we can re-use the semaphore object for that lock (SubmissionSemaphore) { - SubmissionTimer.Change(startIn, TimeSpan.FromHours(SharedInfo.MinimumHoursBetweenUploads)); + SubmissionTimer.Change(startIn, TimeSpan.FromHours(SharedInfo.HoursBetweenUploads)); } ASF.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.SubmissionFailedTooManyRequests, startIn.ToHumanReadable())); @@ -531,6 +569,8 @@ internal sealed class SteamTokenDumperPlugin : OfficialPlugin, IASF, IBot, IBotS return; } + LastUploadAt = DateTimeOffset.UtcNow; + ASF.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.SubmissionSuccessful, response.Content.Data.NewApps.Count, response.Content.Data.VerifiedApps.Count, response.Content.Data.NewPackages.Count, response.Content.Data.VerifiedPackages.Count, response.Content.Data.NewDepots.Count, response.Content.Data.VerifiedDepots.Count)); GlobalCache.UpdateSubmittedData(appTokens, packageTokens, depotKeys);