diff --git a/ArchiSteamFarm.sln.DotSettings b/ArchiSteamFarm.sln.DotSettings
index 7880f129f..1f0b89f02 100644
--- a/ArchiSteamFarm.sln.DotSettings
+++ b/ArchiSteamFarm.sln.DotSettings
@@ -79,6 +79,7 @@
WARNING
WARNING
SUGGESTION
+ HINT
SUGGESTION
WARNING
diff --git a/ArchiSteamFarm/ASF.cs b/ArchiSteamFarm/ASF.cs
index 2a0e37261..f6ac382a0 100644
--- a/ArchiSteamFarm/ASF.cs
+++ b/ArchiSteamFarm/ASF.cs
@@ -227,6 +227,15 @@ namespace ArchiSteamFarm {
FileSystemWatcher.EnableRaisingEvents = true;
}
+ internal static bool IsOwner(ulong steamID) {
+ if (steamID == 0) {
+ ArchiLogger.LogNullError(nameof(steamID));
+ return false;
+ }
+
+ return (steamID == Program.GlobalConfig.SteamOwnerID) || (Debugging.IsDebugBuild && (steamID == SharedInfo.ArchiSteamID));
+ }
+
private static bool IsValidBotName(string botName) {
if (string.IsNullOrEmpty(botName)) {
ArchiLogger.LogNullError(nameof(botName));
diff --git a/ArchiSteamFarm/Actions.cs b/ArchiSteamFarm/Actions.cs
new file mode 100644
index 000000000..3165946ce
--- /dev/null
+++ b/ArchiSteamFarm/Actions.cs
@@ -0,0 +1,247 @@
+// _ _ _ ____ _ _____
+// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
+// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
+// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
+// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
+//
+// Copyright 2015-2018 Łukasz "JustArchi" Domeradzki
+// Contact: JustArchi@JustArchi.net
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using ArchiSteamFarm.Collections;
+using ArchiSteamFarm.Json;
+using ArchiSteamFarm.Localization;
+using SteamKit2;
+
+namespace ArchiSteamFarm {
+ internal sealed class Actions : IDisposable {
+ private static readonly SemaphoreSlim GiftCardsSemaphore = new SemaphoreSlim(1, 1);
+ private static readonly SemaphoreSlim GiftsSemaphore = new SemaphoreSlim(1, 1);
+
+ private readonly Bot Bot;
+ private readonly ConcurrentHashSet HandledGifts = new ConcurrentHashSet();
+ private readonly SemaphoreSlim LootingSemaphore = new SemaphoreSlim(1, 1);
+
+ private bool LootingAllowed = true;
+ private bool LootingScheduled;
+ private bool ProcessingGiftsScheduled;
+
+ internal Actions(Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
+
+ public void Dispose() => LootingSemaphore.Dispose();
+
+ internal async Task AcceptConfirmations(bool accept, Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown, ulong acceptedSteamID = 0, IReadOnlyCollection acceptedTradeIDs = null) {
+ if (!Bot.HasMobileAuthenticator) {
+ return false;
+ }
+
+ HashSet confirmations = await Bot.BotDatabase.MobileAuthenticator.GetConfirmations(acceptedType).ConfigureAwait(false);
+ if ((confirmations == null) || (confirmations.Count == 0)) {
+ return true;
+ }
+
+ if ((acceptedSteamID == 0) && ((acceptedTradeIDs == null) || (acceptedTradeIDs.Count == 0))) {
+ return await Bot.BotDatabase.MobileAuthenticator.HandleConfirmations(confirmations, accept).ConfigureAwait(false);
+ }
+
+ IEnumerable> tasks = confirmations.Select(Bot.BotDatabase.MobileAuthenticator.GetConfirmationDetails);
+ ICollection results;
+
+ switch (Program.GlobalConfig.OptimizationMode) {
+ case GlobalConfig.EOptimizationMode.MinMemoryUsage:
+ results = new List(confirmations.Count);
+ foreach (Task task in tasks) {
+ results.Add(await task.ConfigureAwait(false));
+ }
+
+ break;
+ default:
+ results = await Task.WhenAll(tasks).ConfigureAwait(false);
+ break;
+ }
+
+ foreach (MobileAuthenticator.Confirmation confirmation in results.Where(details => (details != null) && ((acceptedType != details.Type) || ((acceptedSteamID != 0) && (details.OtherSteamID64 != 0) && (acceptedSteamID != details.OtherSteamID64)) || ((acceptedTradeIDs != null) && (details.TradeOfferID != 0) && !acceptedTradeIDs.Contains(details.TradeOfferID)))).Select(details => details.Confirmation)) {
+ confirmations.Remove(confirmation);
+ if (confirmations.Count == 0) {
+ return true;
+ }
+ }
+
+ return await Bot.BotDatabase.MobileAuthenticator.HandleConfirmations(confirmations, accept).ConfigureAwait(false);
+ }
+
+ internal async Task AcceptDigitalGiftCards() {
+ lock (GiftCardsSemaphore) {
+ if (ProcessingGiftsScheduled) {
+ return;
+ }
+
+ ProcessingGiftsScheduled = true;
+ }
+
+ await GiftCardsSemaphore.WaitAsync().ConfigureAwait(false);
+
+ try {
+ lock (GiftCardsSemaphore) {
+ ProcessingGiftsScheduled = false;
+ }
+
+ HashSet giftCardIDs = await Bot.ArchiWebHandler.GetDigitalGiftCards().ConfigureAwait(false);
+ if ((giftCardIDs == null) || (giftCardIDs.Count == 0)) {
+ return;
+ }
+
+ foreach (ulong giftCardID in giftCardIDs.Where(gid => !HandledGifts.Contains(gid))) {
+ HandledGifts.Add(giftCardID);
+
+ Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.BotAcceptingGift, giftCardID));
+ await LimitGiftsRequestsAsync().ConfigureAwait(false);
+
+ bool result = await Bot.ArchiWebHandler.AcceptDigitalGiftCard(giftCardID).ConfigureAwait(false);
+ if (result) {
+ Bot.ArchiLogger.LogGenericInfo(Strings.Success);
+ } else {
+ Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed);
+ }
+ }
+ } finally {
+ GiftCardsSemaphore.Release();
+ }
+ }
+
+ internal async Task AcceptGuestPasses(IReadOnlyCollection guestPassIDs) {
+ if ((guestPassIDs == null) || (guestPassIDs.Count == 0)) {
+ Bot.ArchiLogger.LogNullError(nameof(guestPassIDs));
+ return;
+ }
+
+ foreach (ulong guestPassID in guestPassIDs.Where(guestPassID => !HandledGifts.Contains(guestPassID))) {
+ HandledGifts.Add(guestPassID);
+
+ Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.BotAcceptingGift, guestPassID));
+ await LimitGiftsRequestsAsync().ConfigureAwait(false);
+
+ ArchiHandler.RedeemGuestPassResponseCallback response = await Bot.ArchiHandler.RedeemGuestPass(guestPassID).ConfigureAwait(false);
+ if (response != null) {
+ if (response.Result == EResult.OK) {
+ Bot.ArchiLogger.LogGenericInfo(Strings.Success);
+ } else {
+ Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, response.Result));
+ }
+ } else {
+ Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed);
+ }
+ }
+ }
+
+ internal async Task<(bool Success, string Output)> Loot(uint appID = Steam.Asset.SteamAppID, byte contextID = Steam.Asset.SteamCommunityContextID, ulong targetSteamID = 0, IReadOnlyCollection wantedTypes = null, IReadOnlyCollection wantedRealAppIDs = null) {
+ if ((appID == 0) || (contextID == 0)) {
+ Bot.ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(contextID));
+ return (false, null);
+ }
+
+ if (!Bot.IsConnectedAndLoggedOn) {
+ return (false, Strings.BotNotConnected);
+ }
+
+ if (!LootingAllowed) {
+ return (false, Strings.BotLootingTemporarilyDisabled);
+ }
+
+ if (Bot.BotConfig.LootableTypes.Count == 0) {
+ return (false, Strings.BotLootingNoLootableTypes);
+ }
+
+ if (targetSteamID == 0) {
+ targetSteamID = GetFirstSteamMasterID();
+
+ if (targetSteamID == 0) {
+ return (false, Strings.BotLootingMasterNotDefined);
+ }
+ }
+
+ if (targetSteamID == Bot.CachedSteamID) {
+ return (false, Strings.BotSendingTradeToYourself);
+ }
+
+ lock (LootingSemaphore) {
+ if (LootingScheduled) {
+ return (false, Strings.BotLootingTemporarilyDisabled);
+ }
+
+ LootingScheduled = true;
+ }
+
+ await LootingSemaphore.WaitAsync().ConfigureAwait(false);
+
+ try {
+ lock (LootingSemaphore) {
+ LootingScheduled = false;
+ }
+
+ HashSet inventory = await Bot.ArchiWebHandler.GetInventory(Bot.CachedSteamID, appID, contextID, true, wantedTypes, wantedRealAppIDs).ConfigureAwait(false);
+ if ((inventory == null) || (inventory.Count == 0)) {
+ return (false, string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
+ }
+
+ if (!await Bot.ArchiWebHandler.MarkSentTrades().ConfigureAwait(false) || !await Bot.ArchiWebHandler.SendTradeOffer(targetSteamID, inventory, Bot.BotConfig.SteamTradeToken).ConfigureAwait(false)) {
+ return (false, Strings.BotLootingFailed);
+ }
+
+ if (Bot.HasMobileAuthenticator) {
+ // Give Steam network some time to generate confirmations
+ await Task.Delay(3000).ConfigureAwait(false);
+ if (!await AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, targetSteamID).ConfigureAwait(false)) {
+ return (false, Strings.BotLootingFailed);
+ }
+ }
+ } finally {
+ LootingSemaphore.Release();
+ }
+
+ return (true, Strings.BotLootingSuccess);
+ }
+
+ internal void OnDisconnected() => HandledGifts.Clear();
+
+ internal async Task RedeemKey(string key) {
+ await LimitGiftsRequestsAsync().ConfigureAwait(false);
+
+ return await Bot.ArchiHandler.RedeemKey(key).ConfigureAwait(false);
+ }
+
+ internal bool SwitchLootingAllowed() => LootingAllowed = !LootingAllowed;
+
+ private ulong GetFirstSteamMasterID() => Bot.BotConfig.SteamUserPermissions.Where(kv => (kv.Key != 0) && (kv.Value == BotConfig.EPermission.Master)).Select(kv => kv.Key).OrderByDescending(steamID => steamID != Bot.CachedSteamID).ThenBy(steamID => steamID).FirstOrDefault();
+
+ private static async Task LimitGiftsRequestsAsync() {
+ if (Program.GlobalConfig.GiftsLimiterDelay == 0) {
+ return;
+ }
+
+ await GiftsSemaphore.WaitAsync().ConfigureAwait(false);
+ Utilities.InBackground(
+ async () => {
+ await Task.Delay(Program.GlobalConfig.GiftsLimiterDelay * 1000).ConfigureAwait(false);
+ GiftsSemaphore.Release();
+ }
+ );
+ }
+ }
+}
diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs
index a1b1d56d2..7c728b8c9 100755
--- a/ArchiSteamFarm/Bot.cs
+++ b/ArchiSteamFarm/Bot.cs
@@ -28,12 +28,10 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
-using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.Collections;
-using ArchiSteamFarm.Json;
using ArchiSteamFarm.Localization;
using ArchiSteamFarm.NLog;
using Newtonsoft.Json;
@@ -44,11 +42,11 @@ using SteamKit2.Unified.Internal;
namespace ArchiSteamFarm {
public sealed class Bot : IDisposable {
internal const ushort CallbackSleep = 500; // In milliseconds
+ internal const byte FamilySharingInactivityMinutes = 5;
internal const ushort MaxMessagePrefixLength = MaxMessageLength - ReservedMessageLength - 2; // 2 for a minimum of 2 characters (escape one and real one)
internal const byte MinPlayingBlockedTTL = 60; // Delay in seconds added when account was occupied during our disconnect, to not disconnect other Steam client session too soon
private const char DefaultBackgroundKeysRedeemerSeparator = '\t';
- private const byte FamilySharingInactivityMinutes = 5;
private const byte LoginCooldownInMinutes = 25; // Captcha disappears after around 20 minutes, so we make it 25
private const uint LoginID = 1242; // This must be the same for all ASF bots and all ASF processes
private const ushort MaxMessageLength = 5000; // This is a limitation enforced by Steam
@@ -59,55 +57,51 @@ namespace ArchiSteamFarm {
internal static readonly ConcurrentDictionary Bots = new ConcurrentDictionary();
private static readonly SemaphoreSlim BotsSemaphore = new SemaphoreSlim(1, 1);
- private static readonly SemaphoreSlim GiftCardsSemaphore = new SemaphoreSlim(1, 1);
- private static readonly SemaphoreSlim GiftsSemaphore = new SemaphoreSlim(1, 1);
private static readonly SemaphoreSlim LoginSemaphore = new SemaphoreSlim(1, 1);
private static SteamConfiguration SteamConfiguration;
+ internal readonly Actions Actions;
+ internal readonly ArchiHandler ArchiHandler;
internal readonly ArchiLogger ArchiLogger;
internal readonly ArchiWebHandler ArchiWebHandler;
+ internal readonly BotDatabase BotDatabase;
[JsonProperty]
internal readonly string BotName;
+ [JsonProperty]
+ internal readonly CardsFarmer CardsFarmer;
+
+ internal readonly Commands Commands;
internal readonly ConcurrentDictionary OwnedPackageIDs = new ConcurrentDictionary();
+ internal readonly SteamApps SteamApps;
+ internal readonly SteamFriends SteamFriends;
internal bool CanReceiveSteamCards => !IsAccountLimited && !IsAccountLocked;
internal bool HasMobileAuthenticator => BotDatabase?.MobileAuthenticator != null;
internal bool IsAccountLimited => AccountFlags.HasFlag(EAccountFlags.LimitedUser) || AccountFlags.HasFlag(EAccountFlags.LimitedUserForce);
+ internal bool IsAccountLocked => AccountFlags.HasFlag(EAccountFlags.Lockdown);
internal bool IsConnectedAndLoggedOn => SteamID != 0;
[JsonProperty]
internal bool IsPlayingPossible => !PlayingBlocked && (LibraryLockedBySteamID == 0);
- private readonly ArchiHandler ArchiHandler;
- private readonly BotDatabase BotDatabase;
- private readonly Dictionary CachedGamesOwned = new Dictionary();
private readonly CallbackManager CallbackManager;
private readonly SemaphoreSlim CallbackSemaphore = new SemaphoreSlim(1, 1);
-
- [JsonProperty]
- private readonly CardsFarmer CardsFarmer;
-
private readonly SemaphoreSlim GamesRedeemerInBackgroundSemaphore = new SemaphoreSlim(1, 1);
- private readonly ConcurrentHashSet HandledGifts = new ConcurrentHashSet();
private readonly Timer HeartBeatTimer;
private readonly SemaphoreSlim InitializationSemaphore = new SemaphoreSlim(1, 1);
- private readonly SemaphoreSlim LootingSemaphore = new SemaphoreSlim(1, 1);
private readonly SemaphoreSlim PICSSemaphore = new SemaphoreSlim(1, 1);
private readonly Statistics Statistics;
- private readonly SteamApps SteamApps;
private readonly SteamClient SteamClient;
private readonly ConcurrentHashSet SteamFamilySharingIDs = new ConcurrentHashSet();
- private readonly SteamFriends SteamFriends;
private readonly SteamUser SteamUser;
private readonly Trading Trading;
private string BotPath => Path.Combine(SharedInfo.ConfigDirectory, BotName);
private string ConfigFilePath => BotPath + SharedInfo.ConfigExtension;
private string DatabaseFilePath => BotPath + SharedInfo.DatabaseExtension;
- private bool IsAccountLocked => AccountFlags.HasFlag(EAccountFlags.Lockdown);
private string KeysToRedeemFilePath => BotPath + SharedInfo.KeysExtension;
private string KeysToRedeemUnusedFilePath => KeysToRedeemFilePath + SharedInfo.KeysUnusedExtension;
private string KeysToRedeemUsedFilePath => KeysToRedeemFilePath + SharedInfo.KeysUsedExtension;
@@ -128,7 +122,9 @@ namespace ArchiSteamFarm {
[JsonProperty]
internal bool KeepRunning { get; private set; }
+ internal bool PlayingBlocked { get; private set; }
internal bool PlayingWasBlocked { get; private set; }
+ internal bool SkipFirstShutdown { private get; set; }
[JsonProperty]
private EAccountFlags AccountFlags;
@@ -138,7 +134,6 @@ namespace ArchiSteamFarm {
[JsonProperty]
private string AvatarHash;
- private Timer CardsFarmerResumeTimer;
private Timer ConnectionFailureTimer;
private string DeviceID;
private Timer FamilySharingInactivityTimer;
@@ -150,15 +145,10 @@ namespace ArchiSteamFarm {
private EResult LastLogOnResult;
private DateTime LastLogonSessionReplaced;
private ulong LibraryLockedBySteamID;
- private bool LootingAllowed = true;
- private bool LootingScheduled;
private ulong MasterChatGroupID;
- private bool PlayingBlocked;
private Timer PlayingWasBlockedTimer;
- private bool ProcessingGiftsScheduled;
private bool ReconnectOnUserInitiated;
private Timer SendItemsTimer;
- private bool SkipFirstShutdown;
private SteamSaleEvent SteamSaleEvent;
private uint TradesCount;
private string TwoFactorCode;
@@ -232,8 +222,10 @@ namespace ArchiSteamFarm {
CallbackManager.Subscribe(OnUserNotifications);
CallbackManager.Subscribe(OnVanityURLChangedCallback);
+ Actions = new Actions(this);
ArchiWebHandler = new ArchiWebHandler(this);
CardsFarmer = new CardsFarmer(this);
+ Commands = new Commands(this);
Trading = new Trading(this);
if (!Debugging.IsDebugBuild && Program.GlobalConfig.Statistics) {
@@ -252,18 +244,17 @@ namespace ArchiSteamFarm {
public void Dispose() {
// Those are objects that are always being created if constructor doesn't throw exception
+ Actions.Dispose();
CallbackSemaphore.Dispose();
+ Commands.Dispose();
GamesRedeemerInBackgroundSemaphore.Dispose();
- GiftCardsSemaphore.Dispose();
InitializationSemaphore.Dispose();
- LootingSemaphore.Dispose();
PICSSemaphore.Dispose();
// Those are objects that might be null and the check should be in-place
ArchiWebHandler?.Dispose();
BotDatabase?.Dispose();
CardsFarmer?.Dispose();
- CardsFarmerResumeTimer?.Dispose();
ConnectionFailureTimer?.Dispose();
FamilySharingInactivityTimer?.Dispose();
GamesRedeemerInBackgroundTimer?.Dispose();
@@ -275,85 +266,6 @@ namespace ArchiSteamFarm {
Trading?.Dispose();
}
- internal async Task AcceptConfirmations(bool accept, Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown, ulong acceptedSteamID = 0, IReadOnlyCollection acceptedTradeIDs = null) {
- if (!HasMobileAuthenticator) {
- return false;
- }
-
- HashSet confirmations = await BotDatabase.MobileAuthenticator.GetConfirmations(acceptedType).ConfigureAwait(false);
- if ((confirmations == null) || (confirmations.Count == 0)) {
- return true;
- }
-
- if ((acceptedSteamID == 0) && ((acceptedTradeIDs == null) || (acceptedTradeIDs.Count == 0))) {
- return await BotDatabase.MobileAuthenticator.HandleConfirmations(confirmations, accept).ConfigureAwait(false);
- }
-
- IEnumerable> tasks = confirmations.Select(BotDatabase.MobileAuthenticator.GetConfirmationDetails);
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(confirmations.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- foreach (MobileAuthenticator.Confirmation confirmation in results.Where(details => (details != null) && ((acceptedType != details.Type) || ((acceptedSteamID != 0) && (details.OtherSteamID64 != 0) && (acceptedSteamID != details.OtherSteamID64)) || ((acceptedTradeIDs != null) && (details.TradeOfferID != 0) && !acceptedTradeIDs.Contains(details.TradeOfferID)))).Select(details => details.Confirmation)) {
- confirmations.Remove(confirmation);
- if (confirmations.Count == 0) {
- return true;
- }
- }
-
- return await BotDatabase.MobileAuthenticator.HandleConfirmations(confirmations, accept).ConfigureAwait(false);
- }
-
- private async Task AcceptDigitalGiftCards() {
- lock (GiftCardsSemaphore) {
- if (ProcessingGiftsScheduled) {
- return;
- }
-
- ProcessingGiftsScheduled = true;
- }
-
- await GiftCardsSemaphore.WaitAsync().ConfigureAwait(false);
-
- try {
- lock (GiftCardsSemaphore) {
- ProcessingGiftsScheduled = false;
- }
-
- HashSet giftCardIDs = await ArchiWebHandler.GetDigitalGiftCards().ConfigureAwait(false);
- if ((giftCardIDs == null) || (giftCardIDs.Count == 0)) {
- return;
- }
-
- foreach (ulong giftCardID in giftCardIDs.Where(gid => !HandledGifts.Contains(gid))) {
- HandledGifts.Add(giftCardID);
-
- ArchiLogger.LogGenericInfo(string.Format(Strings.BotAcceptingGift, giftCardID));
- await LimitGiftsRequestsAsync().ConfigureAwait(false);
-
- bool result = await ArchiWebHandler.AcceptDigitalGiftCard(giftCardID).ConfigureAwait(false);
- if (result) {
- ArchiLogger.LogGenericInfo(Strings.Success);
- } else {
- ArchiLogger.LogGenericWarning(Strings.WarningFailed);
- }
- }
- } finally {
- GiftCardsSemaphore.Release();
- }
- }
-
internal async Task DeleteAllRelatedFiles() {
await BotDatabase.MakeReadOnly().ConfigureAwait(false);
@@ -680,6 +592,15 @@ namespace ArchiSteamFarm {
return result;
}
+ internal BotConfig.EPermission GetSteamUserPermission(ulong steamID) {
+ if (steamID == 0) {
+ ArchiLogger.LogNullError(nameof(steamID));
+ return BotConfig.EPermission.None;
+ }
+
+ return BotConfig.SteamUserPermissions.TryGetValue(steamID, out BotConfig.EPermission permission) ? permission : BotConfig.EPermission.None;
+ }
+
internal async Task GetTradeHoldDuration(ulong steamID, ulong tradeID) {
if ((steamID == 0) || (tradeID == 0)) {
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(tradeID));
@@ -819,13 +740,22 @@ namespace ArchiSteamFarm {
return BotDatabase.IsBlacklistedFromTrades(steamID);
}
+ internal bool IsFamilySharing(ulong steamID) {
+ if (steamID == 0) {
+ ArchiLogger.LogNullError(nameof(steamID));
+ return false;
+ }
+
+ return ASF.IsOwner(steamID) || SteamFamilySharingIDs.Contains(steamID) || (GetSteamUserPermission(steamID) >= BotConfig.EPermission.FamilySharing);
+ }
+
internal bool IsMaster(ulong steamID) {
if (steamID == 0) {
ArchiLogger.LogNullError(nameof(steamID));
return false;
}
- return IsOwner(steamID) || (GetSteamUserPermission(steamID) >= BotConfig.EPermission.Master);
+ return ASF.IsOwner(steamID) || (GetSteamUserPermission(steamID) >= BotConfig.EPermission.Master);
}
internal bool IsPriorityIdling(uint appID) {
@@ -837,19 +767,6 @@ namespace ArchiSteamFarm {
return BotDatabase.IsPriorityIdling(appID);
}
- internal async Task LootIfNeeded() {
- if (!IsConnectedAndLoggedOn || !BotConfig.SendOnFarmingFinished) {
- return;
- }
-
- ulong steamMasterID = GetFirstSteamMasterID();
- if (steamMasterID == 0) {
- return;
- }
-
- await ResponseLoot(steamMasterID).ConfigureAwait(false);
- }
-
internal async Task OnConfigChanged(bool deleted) {
if (deleted) {
Destroy();
@@ -889,7 +806,10 @@ namespace ArchiSteamFarm {
if (farmedSomething || !FirstTradeSent) {
FirstTradeSent = true;
- await LootIfNeeded().ConfigureAwait(false);
+
+ if (BotConfig.SendOnFarmingFinished) {
+ await Actions.Loot().ConfigureAwait(false);
+ }
}
if (BotConfig.ShutdownOnFarmingFinished) {
@@ -995,249 +915,6 @@ namespace ArchiSteamFarm {
SteamFriends.RequestFriendInfo(CachedSteamID, EClientPersonaStateFlag.PlayerName | EClientPersonaStateFlag.Presence);
}
- internal async Task Response(ulong steamID, string message) {
- if ((steamID == 0) || string.IsNullOrEmpty(message)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(message));
- return null;
- }
-
- if (!string.IsNullOrEmpty(Program.GlobalConfig.CommandPrefix)) {
- if (!message.StartsWith(Program.GlobalConfig.CommandPrefix, StringComparison.Ordinal)) {
- return null;
- }
-
- message = message.Substring(Program.GlobalConfig.CommandPrefix.Length);
- }
-
- string[] args = message.Split((char[]) null, StringSplitOptions.RemoveEmptyEntries);
-
- switch (args.Length) {
- case 0:
- ArchiLogger.LogNullError(nameof(args));
- return null;
- case 1:
- switch (args[0].ToUpperInvariant()) {
- case "2FA":
- return await Response2FA(steamID).ConfigureAwait(false);
- case "2FANO":
- return await Response2FAConfirm(steamID, false).ConfigureAwait(false);
- case "2FAOK":
- return await Response2FAConfirm(steamID, true).ConfigureAwait(false);
- case "BL":
- return ResponseBlacklist(steamID);
- case "EXIT":
- return ResponseExit(steamID);
- case "FARM":
- return await ResponseFarm(steamID).ConfigureAwait(false);
- case "HELP":
- return ResponseHelp(steamID);
- case "IB":
- return ResponseIdleBlacklist(steamID);
- case "IQ":
- return ResponseIdleQueue(steamID);
- case "LOOT":
- return await ResponseLoot(steamID).ConfigureAwait(false);
- case "LOOT&":
- return ResponseLootSwitch(steamID);
- case "PASSWORD":
- return ResponsePassword(steamID);
- case "PAUSE":
- return await ResponsePause(steamID, true).ConfigureAwait(false);
- case "PAUSE~":
- return await ResponsePause(steamID, false).ConfigureAwait(false);
- case "RESUME":
- return ResponseResume(steamID);
- case "RESTART":
- return ResponseRestart(steamID);
- case "SA":
- return await ResponseStatus(steamID, SharedInfo.ASF).ConfigureAwait(false);
- case "START":
- return ResponseStart(steamID);
- case "STATS":
- return ResponseStats(steamID);
- case "STATUS":
- return ResponseStatus(steamID).Response;
- case "STOP":
- return ResponseStop(steamID);
- case "UNPACK":
- return await ResponseUnpackBoosters(steamID).ConfigureAwait(false);
- case "UPDATE":
- return await ResponseUpdate(steamID).ConfigureAwait(false);
- case "VERSION":
- return ResponseVersion(steamID);
- default:
- return ResponseUnknown(steamID);
- }
- default:
- switch (args[0].ToUpperInvariant()) {
- case "2FA":
- return await Response2FA(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "2FANO":
- return await Response2FAConfirm(steamID, Utilities.GetArgsAsText(args, 1, ","), false).ConfigureAwait(false);
- case "2FAOK":
- return await Response2FAConfirm(steamID, Utilities.GetArgsAsText(args, 1, ","), true).ConfigureAwait(false);
- case "ADDLICENSE":
- if (args.Length > 2) {
- return await ResponseAddLicense(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseAddLicense(steamID, args[1]).ConfigureAwait(false);
- case "BL":
- return await ResponseBlacklist(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "BLADD":
- if (args.Length > 2) {
- return await ResponseBlacklistAdd(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseBlacklistAdd(steamID, args[1]).ConfigureAwait(false);
- case "BLRM":
- if (args.Length > 2) {
- return await ResponseBlacklistRemove(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseBlacklistRemove(steamID, args[1]).ConfigureAwait(false);
- case "FARM":
- return await ResponseFarm(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "INPUT":
- if (args.Length > 3) {
- return await ResponseInput(steamID, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false);
- }
-
- if (args.Length > 2) {
- return ResponseInput(steamID, args[1], args[2]);
- }
-
- goto default;
- case "IB":
- return await ResponseIdleBlacklist(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "IBADD":
- if (args.Length > 2) {
- return await ResponseIdleBlacklistAdd(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseIdleBlacklistAdd(steamID, args[1]).ConfigureAwait(false);
- case "IBRM":
- if (args.Length > 2) {
- return await ResponseIdleBlacklistRemove(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseIdleBlacklistRemove(steamID, args[1]).ConfigureAwait(false);
- case "IQ":
- return await ResponseIdleQueue(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "IQADD":
- if (args.Length > 2) {
- return await ResponseIdleQueueAdd(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseIdleQueueAdd(steamID, args[1]).ConfigureAwait(false);
- case "IQRM":
- if (args.Length > 2) {
- return await ResponseIdleQueueRemove(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseIdleQueueRemove(steamID, args[1]).ConfigureAwait(false);
- case "LOOT":
- return await ResponseLoot(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "LOOT^":
- if (args.Length > 3) {
- return await ResponseAdvancedLoot(steamID, args[1], args[2], Utilities.GetArgsAsText(args, 3, ",")).ConfigureAwait(false);
- }
-
- if (args.Length > 2) {
- return await ResponseAdvancedLoot(steamID, args[1], args[2]).ConfigureAwait(false);
- }
-
- goto default;
- case "LOOT@":
- if (args.Length > 2) {
- return await ResponseLootByRealAppIDs(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseLootByRealAppIDs(steamID, args[1]).ConfigureAwait(false);
- case "LOOT&":
- return await ResponseLootSwitch(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "NICKNAME":
- if (args.Length > 2) {
- return await ResponseNickname(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
- }
-
- return ResponseNickname(steamID, args[1]);
- case "OA":
- return await ResponseOwns(steamID, SharedInfo.ASF, Utilities.GetArgsAsText(message, 1)).ConfigureAwait(false);
- case "OWNS":
- if (args.Length > 2) {
- return await ResponseOwns(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
- }
-
- return (await ResponseOwns(steamID, args[1]).ConfigureAwait(false)).Response;
- case "PASSWORD":
- return await ResponsePassword(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "PAUSE":
- return await ResponsePause(steamID, Utilities.GetArgsAsText(args, 1, ","), true).ConfigureAwait(false);
- case "PAUSE~":
- return await ResponsePause(steamID, Utilities.GetArgsAsText(args, 1, ","), false).ConfigureAwait(false);
- case "PAUSE&":
- if (args.Length > 2) {
- return await ResponsePause(steamID, args[1], true, Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponsePause(steamID, true, args[1]).ConfigureAwait(false);
- case "PLAY":
- if (args.Length > 2) {
- return await ResponsePlay(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponsePlay(steamID, args[1]).ConfigureAwait(false);
- case "PRIVACY":
- if (args.Length > 2) {
- return await ResponsePrivacy(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponsePrivacy(steamID, args[1]).ConfigureAwait(false);
- case "R":
- case "REDEEM":
- if (args.Length > 2) {
- return await ResponseRedeem(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
- }
-
- return await ResponseRedeem(steamID, args[1]).ConfigureAwait(false);
- case "R^":
- case "REDEEM^":
- if (args.Length > 3) {
- return await ResponseAdvancedRedeem(steamID, args[1], args[2], Utilities.GetArgsAsText(args, 3, ",")).ConfigureAwait(false);
- }
-
- if (args.Length > 2) {
- return await ResponseAdvancedRedeem(steamID, args[1], args[2]).ConfigureAwait(false);
- }
-
- goto default;
- case "RESUME":
- return await ResponseResume(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "START":
- return await ResponseStart(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "STATUS":
- return await ResponseStatus(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "STOP":
- return await ResponseStop(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- case "TRANSFER":
- if (args.Length > 3) {
- return await ResponseTransfer(steamID, args[1], args[2], Utilities.GetArgsAsText(args, 3, ",")).ConfigureAwait(false);
- }
-
- if (args.Length > 2) {
- return await ResponseTransfer(steamID, args[1], args[2]).ConfigureAwait(false);
- }
-
- goto default;
- case "UNPACK":
- return await ResponseUnpackBoosters(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
- default:
- return ResponseUnknown(steamID);
- }
- }
- }
-
internal async Task SendMessage(ulong steamID, string message) {
if ((steamID == 0) || string.IsNullOrEmpty(message)) {
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(message));
@@ -1312,13 +989,87 @@ namespace ArchiSteamFarm {
return true;
}
+ internal void SetUserInput(ASF.EUserInputType inputType, string inputValue) {
+ if ((inputType == ASF.EUserInputType.Unknown) || string.IsNullOrEmpty(inputValue)) {
+ ArchiLogger.LogNullError(nameof(inputType) + " || " + nameof(inputValue));
+ }
+
+ // This switch should cover ONLY bot properties
+ switch (inputType) {
+ case ASF.EUserInputType.DeviceID:
+ DeviceID = inputValue;
+ break;
+ case ASF.EUserInputType.Login:
+ if (BotConfig != null) {
+ BotConfig.SteamLogin = inputValue;
+ }
+
+ break;
+ case ASF.EUserInputType.Password:
+ if (BotConfig != null) {
+ BotConfig.SteamPassword = inputValue;
+ }
+
+ break;
+ case ASF.EUserInputType.SteamGuard:
+ AuthCode = inputValue;
+ break;
+ case ASF.EUserInputType.SteamParentalPIN:
+ if (BotConfig != null) {
+ BotConfig.SteamParentalPIN = inputValue;
+ }
+
+ break;
+ case ASF.EUserInputType.TwoFactorAuthentication:
+ TwoFactorCode = inputValue;
+ break;
+ default:
+ ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(inputType), inputType));
+ break;
+ }
+ }
+
+ internal async Task Start() {
+ if (KeepRunning) {
+ return;
+ }
+
+ KeepRunning = true;
+ Utilities.InBackground(HandleCallbacks, true);
+ ArchiLogger.LogGenericInfo(Strings.Starting);
+
+ // Support and convert 2FA files
+ if (!HasMobileAuthenticator && File.Exists(MobileAuthenticatorFilePath)) {
+ await ImportAuthenticator(MobileAuthenticatorFilePath).ConfigureAwait(false);
+ }
+
+ if (File.Exists(KeysToRedeemFilePath)) {
+ await ImportKeysToRedeem(KeysToRedeemFilePath).ConfigureAwait(false);
+ }
+
+ await Connect().ConfigureAwait(false);
+ }
+
+ internal void StartFamilySharingInactivityTimer() {
+ if (FamilySharingInactivityTimer != null) {
+ return;
+ }
+
+ FamilySharingInactivityTimer = new Timer(
+ async e => await CheckFamilySharingInactivity().ConfigureAwait(false),
+ null,
+ TimeSpan.FromMinutes(FamilySharingInactivityMinutes), // Delay
+ Timeout.InfiniteTimeSpan // Period
+ );
+ }
+
internal void Stop(bool skipShutdownEvent = false) {
if (!KeepRunning) {
return;
}
- ArchiLogger.LogGenericInfo(Strings.BotStopping);
KeepRunning = false;
+ ArchiLogger.LogGenericInfo(Strings.BotStopping);
if (SteamClient.IsConnected) {
Disconnect();
@@ -1329,6 +1080,15 @@ namespace ArchiSteamFarm {
}
}
+ internal void StopFamilySharingInactivityTimer() {
+ if (FamilySharingInactivityTimer == null) {
+ return;
+ }
+
+ FamilySharingInactivityTimer.Dispose();
+ FamilySharingInactivityTimer = null;
+ }
+
internal async Task ValidateAndAddGamesToRedeemInBackground(OrderedDictionary gamesToRedeemInBackground) {
if ((gamesToRedeemInBackground == null) || (gamesToRedeemInBackground.Count == 0)) {
ArchiLogger.LogNullError(nameof(gamesToRedeemInBackground));
@@ -1344,7 +1104,7 @@ namespace ArchiSteamFarm {
if (string.IsNullOrEmpty(key)) {
invalid = true;
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, nameof(key)));
- } else if (!IsValidCdKey(key)) {
+ } else if (!Utilities.IsValidCdKey(key)) {
invalid = true;
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, key));
}
@@ -1450,26 +1210,6 @@ namespace ArchiSteamFarm {
return message.Replace("\\", "\\\\").Replace("[", "\\[");
}
- private string FormatBotResponse(string response) {
- if (string.IsNullOrEmpty(response)) {
- ASF.ArchiLogger.LogNullError(nameof(response));
- return null;
- }
-
- return "<" + BotName + "> " + response;
- }
-
- private static string FormatStaticResponse(string response) {
- if (string.IsNullOrEmpty(response)) {
- ASF.ArchiLogger.LogNullError(nameof(response));
- return null;
- }
-
- return "<" + SharedInfo.ASF + "> " + response;
- }
-
- private ulong GetFirstSteamMasterID() => BotConfig.SteamUserPermissions.Where(kv => (kv.Key != 0) && (kv.Value == BotConfig.EPermission.Master)).Select(kv => kv.Key).OrderByDescending(steamID => steamID != CachedSteamID).ThenBy(steamID => steamID).FirstOrDefault();
-
private async Task> GetKeysFromFile(string filePath) {
if (string.IsNullOrEmpty(filePath)) {
ArchiLogger.LogNullError(nameof(filePath));
@@ -1511,15 +1251,6 @@ namespace ArchiSteamFarm {
}
}
- private BotConfig.EPermission GetSteamUserPermission(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return BotConfig.EPermission.None;
- }
-
- return BotConfig.SteamUserPermissions.TryGetValue(steamID, out BotConfig.EPermission permission) ? permission : BotConfig.EPermission.None;
- }
-
private void HandleCallbacks() {
TimeSpan timeSpan = TimeSpan.FromMilliseconds(CallbackSleep);
while (KeepRunning || SteamClient.IsConnected) {
@@ -1547,7 +1278,7 @@ namespace ArchiSteamFarm {
return;
}
- string response = await Response(steamID, message).ConfigureAwait(false);
+ string response = await Commands.Response(steamID, message).ConfigureAwait(false);
// We respond with null when user is not authorized (and similar)
if (string.IsNullOrEmpty(response)) {
@@ -1563,7 +1294,7 @@ namespace ArchiSteamFarm {
return;
}
- string response = await Response(steamID, message).ConfigureAwait(false);
+ string response = await Commands.Response(steamID, message).ConfigureAwait(false);
// We respond with null when user is not authorized (and similar)
if (string.IsNullOrEmpty(response)) {
@@ -1696,16 +1427,13 @@ namespace ArchiSteamFarm {
SendItemsTimer = null;
}
- if (BotConfig.SendTradePeriod > 0) {
- ulong steamMasterID = GetFirstSteamMasterID();
- if (steamMasterID != 0) {
- SendItemsTimer = new Timer(
- async e => await ResponseLoot(steamMasterID).ConfigureAwait(false),
- null,
- TimeSpan.FromHours(BotConfig.SendTradePeriod) + TimeSpan.FromSeconds(Program.LoadBalancingDelay * Bots.Count), // Delay
- TimeSpan.FromHours(BotConfig.SendTradePeriod) // Period
- );
- }
+ if ((BotConfig.SendTradePeriod > 0) && BotConfig.SteamUserPermissions.Values.Any(permission => permission >= BotConfig.EPermission.Master)) {
+ SendItemsTimer = new Timer(
+ async e => await Actions.Loot().ConfigureAwait(false),
+ null,
+ TimeSpan.FromHours(BotConfig.SendTradePeriod) + TimeSpan.FromSeconds(Program.LoadBalancingDelay * Bots.Count), // Delay
+ TimeSpan.FromHours(BotConfig.SendTradePeriod) // Period
+ );
}
if (SteamSaleEvent != null) {
@@ -1738,15 +1466,6 @@ namespace ArchiSteamFarm {
Utilities.InBackground(Start);
}
- private bool IsFamilySharing(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return false;
- }
-
- return IsOwner(steamID) || SteamFamilySharingIDs.Contains(steamID) || (GetSteamUserPermission(steamID) >= BotConfig.EPermission.FamilySharing);
- }
-
private bool IsMasterClanID(ulong steamID) {
if (steamID == 0) {
ArchiLogger.LogNullError(nameof(steamID));
@@ -1756,24 +1475,6 @@ namespace ArchiSteamFarm {
return steamID == BotConfig.SteamMasterClanID;
}
- private bool IsOperator(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return false;
- }
-
- return IsOwner(steamID) || (GetSteamUserPermission(steamID) >= BotConfig.EPermission.Operator);
- }
-
- private static bool IsOwner(ulong steamID) {
- if (steamID == 0) {
- ASF.ArchiLogger.LogNullError(nameof(steamID));
- return false;
- }
-
- return (steamID == Program.GlobalConfig.SteamOwnerID) || (Debugging.IsDebugBuild && (steamID == SharedInfo.ArchiSteamID));
- }
-
private static bool IsRefundable(EPaymentMethod method) {
if (method == EPaymentMethod.None) {
ASF.ArchiLogger.LogNullError(nameof(method));
@@ -1795,15 +1496,6 @@ namespace ArchiSteamFarm {
}
}
- private static bool IsValidCdKey(string key) {
- if (string.IsNullOrEmpty(key)) {
- ASF.ArchiLogger.LogNullError(nameof(key));
- return false;
- }
-
- return Regex.IsMatch(key, @"^[0-9A-Z]{4,7}-[0-9A-Z]{4,7}-[0-9A-Z]{4,7}(?:(?:-[0-9A-Z]{4,7})?(?:-[0-9A-Z]{4,7}))?$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
- }
-
private async Task JoinMasterChatGroupID() {
if (BotConfig.SteamMasterClanID == 0) {
return;
@@ -1826,20 +1518,6 @@ namespace ArchiSteamFarm {
await ArchiHandler.JoinChatRoomGroup(chatGroupID).ConfigureAwait(false);
}
- private static async Task LimitGiftsRequestsAsync() {
- if (Program.GlobalConfig.GiftsLimiterDelay == 0) {
- return;
- }
-
- await GiftsSemaphore.WaitAsync().ConfigureAwait(false);
- Utilities.InBackground(
- async () => {
- await Task.Delay(Program.GlobalConfig.GiftsLimiterDelay * 1000).ConfigureAwait(false);
- GiftsSemaphore.Release();
- }
- );
- }
-
private static async Task LimitLoginRequestsAsync() {
if (Program.GlobalConfig.LoginLimiterDelay == 0) {
return;
@@ -1956,12 +1634,12 @@ namespace ArchiSteamFarm {
ArchiLogger.LogGenericInfo(Strings.BotDisconnected);
+ Actions.OnDisconnected();
ArchiWebHandler.OnDisconnected();
CardsFarmer.OnDisconnected();
Trading.OnDisconnected();
FirstTradeSent = false;
- HandledGifts.Clear();
// If we initiated disconnect, do not attempt to reconnect
if (callback.UserInitiated && !ReconnectOnUserInitiated) {
@@ -2046,23 +1724,12 @@ namespace ArchiSteamFarm {
return;
}
- foreach (ulong gid in callback.GuestPasses.Select(guestPass => guestPass["gid"].AsUnsignedLong()).Where(gid => (gid != 0) && !HandledGifts.Contains(gid))) {
- HandledGifts.Add(gid);
-
- ArchiLogger.LogGenericInfo(string.Format(Strings.BotAcceptingGift, gid));
- await LimitGiftsRequestsAsync().ConfigureAwait(false);
-
- ArchiHandler.RedeemGuestPassResponseCallback response = await ArchiHandler.RedeemGuestPass(gid).ConfigureAwait(false);
- if (response != null) {
- if (response.Result == EResult.OK) {
- ArchiLogger.LogGenericInfo(Strings.Success);
- } else {
- ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, response.Result));
- }
- } else {
- ArchiLogger.LogGenericWarning(Strings.WarningFailed);
- }
+ HashSet guestPassIDs = callback.GuestPasses.Select(guestPass => guestPass["gid"].AsUnsignedLong()).Where(gid => gid != 0).ToHashSet();
+ if (guestPassIDs.Count == 0) {
+ return;
}
+
+ await Actions.AcceptGuestPasses(guestPassIDs).ConfigureAwait(false);
}
private async Task OnIncomingChatMessage(CChatRoom_IncomingChatMessage_Notification notification) {
@@ -2157,11 +1824,7 @@ namespace ArchiSteamFarm {
}
}
- lock (CachedGamesOwned) {
- CachedGamesOwned.Clear();
- CachedGamesOwned.TrimExcess();
- }
-
+ Commands.OnNewLicenseList();
OwnedPackageIDs.Clear();
bool refreshData = !BotConfig.IdleRefundableGames || BotConfig.FarmingOrders.Contains(BotConfig.EFarmingOrder.RedeemDateTimesAscending) || BotConfig.FarmingOrders.Contains(BotConfig.EFarmingOrder.RedeemDateTimesDescending);
@@ -2581,7 +2244,7 @@ namespace ArchiSteamFarm {
if (newGifts && BotConfig.AcceptGifts) {
ArchiLogger.LogGenericTrace(nameof(ArchiHandler.UserNotificationsCallback.EUserNotification.Gifts));
- Utilities.InBackground(AcceptDigitalGiftCards);
+ Utilities.InBackground(Actions.AcceptDigitalGiftCards);
}
break;
@@ -2619,9 +2282,7 @@ namespace ArchiSteamFarm {
break;
}
- await LimitGiftsRequestsAsync().ConfigureAwait(false);
-
- ArchiHandler.PurchaseResponseCallback result = await ArchiHandler.RedeemKey(key).ConfigureAwait(false);
+ ArchiHandler.PurchaseResponseCallback result = await Actions.RedeemKey(key).ConfigureAwait(false);
if (result == null) {
continue;
}
@@ -2712,2666 +2373,6 @@ namespace ArchiSteamFarm {
StopPlayingWasBlockedTimer();
}
- private async Task Response2FA(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!HasMobileAuthenticator) {
- return FormatBotResponse(Strings.BotNoASFAuthenticator);
- }
-
- string token = await BotDatabase.MobileAuthenticator.GenerateToken().ConfigureAwait(false);
- return FormatBotResponse(!string.IsNullOrEmpty(token) ? string.Format(Strings.BotAuthenticatorToken, token) : Strings.WarningFailed);
- }
-
- private static async Task Response2FA(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.Response2FA(steamID));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task Response2FAConfirm(ulong steamID, bool confirm) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- if (!HasMobileAuthenticator) {
- return FormatBotResponse(Strings.BotNoASFAuthenticator);
- }
-
- bool result = await AcceptConfirmations(confirm).ConfigureAwait(false);
- return FormatBotResponse(result ? Strings.Success : Strings.WarningFailed);
- }
-
- private static async Task Response2FAConfirm(ulong steamID, string botNames, bool confirm) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.Response2FAConfirm(steamID, confirm));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseAddLicense(ulong steamID, IReadOnlyCollection gameIDs) {
- if ((steamID == 0) || (gameIDs == null) || (gameIDs.Count == 0)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(gameIDs) + " || " + nameof(gameIDs.Count));
- return null;
- }
-
- if (!IsOperator(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- StringBuilder response = new StringBuilder();
-
- foreach (uint gameID in gameIDs) {
- await LimitGiftsRequestsAsync().ConfigureAwait(false);
-
- if (await ArchiWebHandler.AddFreeLicense(gameID).ConfigureAwait(false)) {
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotAddLicenseWithItems, gameID, EResult.OK, "sub/" + gameID)));
- continue;
- }
-
- SteamApps.FreeLicenseCallback callback;
-
- try {
- callback = await SteamApps.RequestFreeLicense(gameID);
- } catch (Exception e) {
- ArchiLogger.LogGenericWarningException(e);
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotAddLicense, gameID, EResult.Timeout)));
- break;
- }
-
- if (callback == null) {
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotAddLicense, gameID, EResult.Timeout)));
- break;
- }
-
- response.AppendLine(FormatBotResponse((callback.GrantedApps.Count > 0) || (callback.GrantedPackages.Count > 0) ? string.Format(Strings.BotAddLicenseWithItems, gameID, callback.Result, string.Join(", ", callback.GrantedApps.Select(appID => "app/" + appID).Union(callback.GrantedPackages.Select(subID => "sub/" + subID)))) : string.Format(Strings.BotAddLicense, gameID, callback.Result)));
- }
-
- return response.Length > 0 ? response.ToString() : null;
- }
-
- private async Task ResponseAddLicense(ulong steamID, string targetGameIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetGameIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetGameIDs));
- return null;
- }
-
- if (!IsOperator(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- string[] gameIDs = targetGameIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (gameIDs.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(gameIDs)));
- }
-
- HashSet gamesToRedeem = new HashSet();
-
- foreach (string game in gameIDs) {
- if (!uint.TryParse(game, out uint gameID) || (gameID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(gameID)));
- }
-
- gamesToRedeem.Add(gameID);
- }
-
- return await ResponseAddLicense(steamID, gamesToRedeem).ConfigureAwait(false);
- }
-
- private static async Task ResponseAddLicense(ulong steamID, string botNames, string targetGameIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetGameIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetGameIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseAddLicense(steamID, targetGameIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseAdvancedLoot(ulong steamID, string targetAppID, string targetContextID) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetAppID) || string.IsNullOrEmpty(targetContextID)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetAppID) + " || " + nameof(targetContextID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- if (!uint.TryParse(targetAppID, out uint appID) || (appID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(appID)));
- }
-
- if (!byte.TryParse(targetContextID, out byte contextID) || (contextID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(contextID)));
- }
-
- if (!LootingAllowed) {
- return FormatBotResponse(Strings.BotLootingTemporarilyDisabled);
- }
-
- if (BotConfig.LootableTypes.Count == 0) {
- return FormatBotResponse(Strings.BotLootingNoLootableTypes);
- }
-
- ulong targetSteamMasterID = GetFirstSteamMasterID();
- if (targetSteamMasterID == 0) {
- return FormatBotResponse(Strings.BotLootingMasterNotDefined);
- }
-
- if (targetSteamMasterID == CachedSteamID) {
- return FormatBotResponse(Strings.BotSendingTradeToYourself);
- }
-
- await LootingSemaphore.WaitAsync().ConfigureAwait(false);
-
- try {
- HashSet inventory = await ArchiWebHandler.GetInventory(CachedSteamID, appID, contextID, true).ConfigureAwait(false);
- if ((inventory == null) || (inventory.Count == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
- }
-
- if (!await ArchiWebHandler.MarkSentTrades().ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
-
- if (!await ArchiWebHandler.SendTradeOffer(targetSteamMasterID, inventory, BotConfig.SteamTradeToken).ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
-
- if (HasMobileAuthenticator) {
- // Give Steam network some time to generate confirmations
- await Task.Delay(3000).ConfigureAwait(false);
- if (!await AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, targetSteamMasterID).ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
- }
- } finally {
- LootingSemaphore.Release();
- }
-
- return FormatBotResponse(Strings.BotLootingSuccess);
- }
-
- private static async Task ResponseAdvancedLoot(ulong steamID, string botNames, string appID, string contextID) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(appID) || string.IsNullOrEmpty(contextID)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(appID) + " || " + nameof(contextID));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseAdvancedLoot(steamID, appID, contextID));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseAdvancedRedeem(ulong steamID, string options, string keys) {
- if ((steamID == 0) || string.IsNullOrEmpty(options) || string.IsNullOrEmpty(keys)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(options) + " || " + nameof(keys));
- return null;
- }
-
- if (!IsOperator(steamID)) {
- return null;
- }
-
- string[] flags = options.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (flags.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(flags)));
- }
-
- ERedeemFlags redeemFlags = ERedeemFlags.None;
-
- foreach (string flag in flags) {
- switch (flag.ToUpperInvariant()) {
- case "FD":
- redeemFlags |= ERedeemFlags.ForceDistributing;
- break;
- case "FF":
- redeemFlags |= ERedeemFlags.ForceForwarding;
- break;
- case "FKMG":
- redeemFlags |= ERedeemFlags.ForceKeepMissingGames;
- break;
- case "SD":
- redeemFlags |= ERedeemFlags.SkipDistributing;
- break;
- case "SF":
- redeemFlags |= ERedeemFlags.SkipForwarding;
- break;
- case "SI":
- redeemFlags |= ERedeemFlags.SkipInitial;
- break;
- case "SKMG":
- redeemFlags |= ERedeemFlags.SkipKeepMissingGames;
- break;
- case "V":
- redeemFlags |= ERedeemFlags.Validate;
- break;
- default:
- return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, flag));
- }
- }
-
- return await ResponseRedeem(steamID, keys, redeemFlags).ConfigureAwait(false);
- }
-
- private static async Task ResponseAdvancedRedeem(ulong steamID, string botNames, string options, string keys) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(options) || string.IsNullOrEmpty(keys)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(options) + " || " + nameof(keys));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseAdvancedRedeem(steamID, options, keys));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private string ResponseBlacklist(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- IReadOnlyCollection blacklist = BotDatabase.GetBlacklistedFromTradesSteamIDs();
- return FormatBotResponse(blacklist.Count > 0 ? string.Join(", ", blacklist) : string.Format(Strings.ErrorIsEmpty, nameof(blacklist)));
- }
-
- private static async Task ResponseBlacklist(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => Task.Run(() => bot.ResponseBlacklist(steamID)));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseBlacklistAdd(ulong steamID, string targetSteamIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetSteamIDs)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetSteamIDs));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- string[] targets = targetSteamIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (targets.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targets)));
- }
-
- HashSet targetIDs = new HashSet();
-
- foreach (string target in targets) {
- if (!ulong.TryParse(target, out ulong targetID) || (targetID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(targetID)));
- }
-
- targetIDs.Add(targetID);
- }
-
- await BotDatabase.AddBlacklistedFromTradesSteamIDs(targetIDs).ConfigureAwait(false);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseBlacklistAdd(ulong steamID, string botNames, string targetSteamIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetSteamIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetSteamIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseBlacklistAdd(steamID, targetSteamIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseBlacklistRemove(ulong steamID, string targetSteamIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetSteamIDs)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetSteamIDs));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- string[] targets = targetSteamIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (targets.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targets)));
- }
-
- HashSet targetIDs = new HashSet();
-
- foreach (string target in targets) {
- if (!ulong.TryParse(target, out ulong targetID) || (targetID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(targetID)));
- }
-
- targetIDs.Add(targetID);
- }
-
- await BotDatabase.RemoveBlacklistedFromTradesSteamIDs(targetIDs).ConfigureAwait(false);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseBlacklistRemove(ulong steamID, string botNames, string targetSteamIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetSteamIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetSteamIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseBlacklistRemove(steamID, targetSteamIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private static string ResponseExit(ulong steamID) {
- if (steamID == 0) {
- ASF.ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsOwner(steamID)) {
- return null;
- }
-
- // Schedule the task after some time so user can receive response
- Utilities.InBackground(
- async () => {
- await Task.Delay(1000).ConfigureAwait(false);
- await Program.Exit().ConfigureAwait(false);
- }
- );
-
- return FormatStaticResponse(Strings.Done);
- }
-
- private async Task ResponseFarm(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- if (CardsFarmer.NowFarming) {
- await CardsFarmer.StopFarming().ConfigureAwait(false);
- }
-
- Utilities.InBackground(CardsFarmer.StartFarming);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseFarm(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseFarm(steamID));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private string ResponseHelp(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- return IsFamilySharing(steamID) ? FormatBotResponse("https://github.com/" + SharedInfo.GithubRepo + "/wiki/Commands") : null;
- }
-
- private string ResponseIdleBlacklist(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- IReadOnlyCollection idleBlacklist = BotDatabase.GetIdlingBlacklistedAppIDs();
- return FormatBotResponse(idleBlacklist.Count > 0 ? string.Join(", ", idleBlacklist) : string.Format(Strings.ErrorIsEmpty, nameof(idleBlacklist)));
- }
-
- private static async Task ResponseIdleBlacklist(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => Task.Run(() => bot.ResponseIdleBlacklist(steamID)));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseIdleBlacklistAdd(ulong steamID, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetAppIDs)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- string[] targets = targetAppIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (targets.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targets)));
- }
-
- HashSet appIDs = new HashSet();
-
- foreach (string target in targets) {
- if (!uint.TryParse(target, out uint appID) || (appID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(appID)));
- }
-
- appIDs.Add(appID);
- }
-
- await BotDatabase.AddIdlingBlacklistedAppIDs(appIDs).ConfigureAwait(false);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseIdleBlacklistAdd(ulong steamID, string botNames, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetAppIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseIdleBlacklistAdd(steamID, targetAppIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseIdleBlacklistRemove(ulong steamID, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetAppIDs)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- string[] targets = targetAppIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (targets.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targets)));
- }
-
- HashSet appIDs = new HashSet();
-
- foreach (string target in targets) {
- if (!uint.TryParse(target, out uint appID) || (appID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(appID)));
- }
-
- appIDs.Add(appID);
- }
-
- await BotDatabase.RemoveIdlingBlacklistedAppIDs(appIDs).ConfigureAwait(false);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseIdleBlacklistRemove(ulong steamID, string botNames, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetAppIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseIdleBlacklistRemove(steamID, targetAppIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private string ResponseIdleQueue(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- IReadOnlyCollection idleQueue = BotDatabase.GetIdlingPriorityAppIDs();
- return FormatBotResponse(idleQueue.Count > 0 ? string.Join(", ", idleQueue) : string.Format(Strings.ErrorIsEmpty, nameof(idleQueue)));
- }
-
- private static async Task ResponseIdleQueue(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => Task.Run(() => bot.ResponseIdleQueue(steamID)));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseIdleQueueAdd(ulong steamID, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetAppIDs)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- string[] targets = targetAppIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (targets.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targets)));
- }
-
- HashSet appIDs = new HashSet();
-
- foreach (string target in targets) {
- if (!uint.TryParse(target, out uint appID) || (appID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(appID)));
- }
-
- appIDs.Add(appID);
- }
-
- await BotDatabase.AddIdlingPriorityAppIDs(appIDs).ConfigureAwait(false);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseIdleQueueAdd(ulong steamID, string botNames, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetAppIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseIdleQueueAdd(steamID, targetAppIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseIdleQueueRemove(ulong steamID, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(targetAppIDs)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- string[] targets = targetAppIDs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (targets.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targets)));
- }
-
- HashSet appIDs = new HashSet();
-
- foreach (string target in targets) {
- if (!uint.TryParse(target, out uint appID) || (appID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorParsingObject, nameof(appID)));
- }
-
- appIDs.Add(appID);
- }
-
- await BotDatabase.RemoveIdlingPriorityAppIDs(appIDs).ConfigureAwait(false);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseIdleQueueRemove(ulong steamID, string botNames, string targetAppIDs) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetAppIDs)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetAppIDs));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseIdleQueueRemove(steamID, targetAppIDs));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private string ResponseInput(ulong steamID, string propertyName, string inputValue) {
- if ((steamID == 0) || string.IsNullOrEmpty(propertyName) || string.IsNullOrEmpty(inputValue)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(propertyName) + " || " + nameof(inputValue));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!Program.GlobalConfig.Headless) {
- return FormatBotResponse(Strings.ErrorFunctionOnlyInHeadlessMode);
- }
-
- if (!Enum.TryParse(propertyName, true, out ASF.EUserInputType inputType) || (inputType == ASF.EUserInputType.Unknown) || !Enum.IsDefined(typeof(ASF.EUserInputType), inputType)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inputType)));
- }
-
- SetUserInput(inputType, inputValue);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseInput(ulong steamID, string botNames, string propertyName, string inputValue) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(propertyName) || string.IsNullOrEmpty(inputValue)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(propertyName) + " || " + nameof(inputValue));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => Task.Run(() => bot.ResponseInput(steamID, propertyName, inputValue)));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseLoot(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- if (!LootingAllowed) {
- return FormatBotResponse(Strings.BotLootingTemporarilyDisabled);
- }
-
- if (BotConfig.LootableTypes.Count == 0) {
- return FormatBotResponse(Strings.BotLootingNoLootableTypes);
- }
-
- ulong targetSteamMasterID = GetFirstSteamMasterID();
- if (targetSteamMasterID == 0) {
- return FormatBotResponse(Strings.BotLootingMasterNotDefined);
- }
-
- if (targetSteamMasterID == CachedSteamID) {
- return FormatBotResponse(Strings.BotSendingTradeToYourself);
- }
-
- lock (LootingSemaphore) {
- if (LootingScheduled) {
- return FormatBotResponse(Strings.Done);
- }
-
- LootingScheduled = true;
- }
-
- await LootingSemaphore.WaitAsync().ConfigureAwait(false);
-
- try {
- lock (LootingSemaphore) {
- LootingScheduled = false;
- }
-
- HashSet inventory = await ArchiWebHandler.GetInventory(CachedSteamID, tradable: true, wantedTypes: BotConfig.LootableTypes).ConfigureAwait(false);
- if ((inventory == null) || (inventory.Count == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
- }
-
- if (!await ArchiWebHandler.MarkSentTrades().ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
-
- if (!await ArchiWebHandler.SendTradeOffer(targetSteamMasterID, inventory, BotConfig.SteamTradeToken).ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
-
- if (HasMobileAuthenticator) {
- // Give Steam network some time to generate confirmations
- await Task.Delay(3000).ConfigureAwait(false);
- if (!await AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, targetSteamMasterID).ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
- }
- } finally {
- LootingSemaphore.Release();
- }
-
- return FormatBotResponse(Strings.BotLootingSuccess);
- }
-
- private static async Task ResponseLoot(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseLoot(steamID));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task ResponseLootByRealAppIDs(ulong steamID, string realAppIDsText) {
- if ((steamID == 0) || string.IsNullOrEmpty(realAppIDsText)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(realAppIDsText));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- string[] appIDTexts = realAppIDsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (appIDTexts.Length == 0) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDTexts)));
- }
-
- HashSet realAppIDs = new HashSet();
-
- foreach (string appIDText in appIDTexts) {
- if (!uint.TryParse(appIDText, out uint appID) || (appID == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(appID)));
- }
-
- realAppIDs.Add(appID);
- }
-
- if (!LootingAllowed) {
- return FormatBotResponse(Strings.BotLootingTemporarilyDisabled);
- }
-
- if (BotConfig.LootableTypes.Count == 0) {
- return FormatBotResponse(Strings.BotLootingNoLootableTypes);
- }
-
- ulong targetSteamMasterID = GetFirstSteamMasterID();
- if (targetSteamMasterID == 0) {
- return FormatBotResponse(Strings.BotLootingMasterNotDefined);
- }
-
- if (targetSteamMasterID == CachedSteamID) {
- return FormatBotResponse(Strings.BotSendingTradeToYourself);
- }
-
- await LootingSemaphore.WaitAsync().ConfigureAwait(false);
-
- try {
- HashSet inventory = await ArchiWebHandler.GetInventory(CachedSteamID, tradable: true, wantedRealAppIDs: realAppIDs).ConfigureAwait(false);
- if ((inventory == null) || (inventory.Count == 0)) {
- return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
- }
-
- if (!await ArchiWebHandler.MarkSentTrades().ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
-
- if (!await ArchiWebHandler.SendTradeOffer(targetSteamMasterID, inventory, BotConfig.SteamTradeToken).ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
-
- if (HasMobileAuthenticator) {
- // Give Steam network some time to generate confirmations
- await Task.Delay(3000).ConfigureAwait(false);
- if (!await AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, targetSteamMasterID).ConfigureAwait(false)) {
- return FormatBotResponse(Strings.BotLootingFailed);
- }
- }
- } finally {
- LootingSemaphore.Release();
- }
-
- return FormatBotResponse(Strings.BotLootingSuccess);
- }
-
- private static async Task ResponseLootByRealAppIDs(ulong steamID, string botNames, string realAppIDsText) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(realAppIDsText)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(realAppIDsText));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => bot.ResponseLootByRealAppIDs(steamID, realAppIDsText));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private string ResponseLootSwitch(ulong steamID) {
- if (steamID == 0) {
- ArchiLogger.LogNullError(nameof(steamID));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- LootingAllowed = !LootingAllowed;
- return FormatBotResponse(LootingAllowed ? Strings.BotLootingNowEnabled : Strings.BotLootingNowDisabled);
- }
-
- private static async Task ResponseLootSwitch(ulong steamID, string botNames) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => Task.Run(() => bot.ResponseLootSwitch(steamID)));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private string ResponseNickname(ulong steamID, string nickname) {
- if ((steamID == 0) || string.IsNullOrEmpty(nickname)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(nickname));
- return null;
- }
-
- if (!IsMaster(steamID)) {
- return null;
- }
-
- if (!IsConnectedAndLoggedOn) {
- return FormatBotResponse(Strings.BotNotConnected);
- }
-
- SteamFriends.SetPersonaName(nickname);
- return FormatBotResponse(Strings.Done);
- }
-
- private static async Task ResponseNickname(ulong steamID, string botNames, string nickname) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(nickname)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(nickname));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable> tasks = bots.Select(bot => Task.Run(() => bot.ResponseNickname(steamID, nickname)));
- ICollection results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List(bots.Count);
- foreach (Task task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List responses = new List(results.Where(result => !string.IsNullOrEmpty(result)));
- return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
- }
-
- private async Task<(string Response, HashSet OwnedGameIDs)> ResponseOwns(ulong steamID, string query) {
- if ((steamID == 0) || string.IsNullOrEmpty(query)) {
- ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(query));
- return (null, null);
- }
-
- if (!IsOperator(steamID)) {
- return (null, null);
- }
-
- if (!IsConnectedAndLoggedOn) {
- return (FormatBotResponse(Strings.BotNotConnected), null);
- }
-
- Dictionary ownedGames = null;
-
- lock (CachedGamesOwned) {
- if (CachedGamesOwned.Count > 0) {
- ownedGames = new Dictionary(CachedGamesOwned);
- }
- }
-
- if (ownedGames == null) {
- await LimitGiftsRequestsAsync().ConfigureAwait(false);
-
- ownedGames = await ArchiWebHandler.HasValidApiKey().ConfigureAwait(false) ? await ArchiWebHandler.GetOwnedGames(CachedSteamID).ConfigureAwait(false) : await ArchiWebHandler.GetMyOwnedGames().ConfigureAwait(false);
- if ((ownedGames == null) || (ownedGames.Count == 0)) {
- return (FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(ownedGames))), null);
- }
-
- lock (CachedGamesOwned) {
- if (CachedGamesOwned.Count == 0) {
- foreach (KeyValuePair ownedGame in ownedGames) {
- CachedGamesOwned[ownedGame.Key] = ownedGame.Value;
- }
-
- CachedGamesOwned.TrimExcess();
- }
- }
- }
-
- StringBuilder response = new StringBuilder();
- HashSet ownedGameIDs = new HashSet();
-
- if (query.Equals("*")) {
- foreach (KeyValuePair ownedGame in ownedGames) {
- ownedGameIDs.Add(ownedGame.Key);
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotOwnedAlreadyWithName, ownedGame.Key, ownedGame.Value)));
- }
- } else {
- string[] games = query.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
-
- if (games.Length == 0) {
- return (FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(games))), null);
- }
-
- foreach (string game in games) {
- // Check if this is gameID
- if (uint.TryParse(game, out uint gameID) && (gameID != 0)) {
- if (OwnedPackageIDs.ContainsKey(gameID)) {
- ownedGameIDs.Add(gameID);
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotOwnedAlready, gameID)));
- continue;
- }
-
- if (ownedGames.TryGetValue(gameID, out string ownedName)) {
- ownedGameIDs.Add(gameID);
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotOwnedAlreadyWithName, gameID, ownedName)));
- } else {
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotNotOwnedYet, gameID)));
- }
-
- continue;
- }
-
- // This is a string, so check our entire library
- foreach (KeyValuePair ownedGame in ownedGames.Where(ownedGame => ownedGame.Value.IndexOf(game, StringComparison.OrdinalIgnoreCase) >= 0)) {
- ownedGameIDs.Add(ownedGame.Key);
- response.AppendLine(FormatBotResponse(string.Format(Strings.BotOwnedAlreadyWithName, ownedGame.Key, ownedGame.Value)));
- }
- }
- }
-
- return (response.Length > 0 ? response.ToString() : FormatBotResponse(string.Format(Strings.BotNotOwnedYet, query)), ownedGameIDs);
- }
-
- private static async Task ResponseOwns(ulong steamID, string botNames, string query) {
- if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(query)) {
- ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(query));
- return null;
- }
-
- HashSet bots = GetBots(botNames);
- if ((bots == null) || (bots.Count == 0)) {
- return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
- }
-
- IEnumerable OwnedGameIDs)>> tasks = bots.Select(bot => bot.ResponseOwns(steamID, query));
- ICollection<(string Response, HashSet OwnedGameIDs)> results;
-
- switch (Program.GlobalConfig.OptimizationMode) {
- case GlobalConfig.EOptimizationMode.MinMemoryUsage:
- results = new List<(string Response, HashSet OwnedGameIDs)>(bots.Count);
- foreach (Task<(string Response, HashSet OwnedGameIDs)> task in tasks) {
- results.Add(await task.ConfigureAwait(false));
- }
-
- break;
- default:
- results = await Task.WhenAll(tasks).ConfigureAwait(false);
- break;
- }
-
- List<(string Response, HashSet OwnedGameIDs)> validResults = new List<(string Response, HashSet