diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 17fe5e438..576a0f991 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -556,13 +556,24 @@ namespace ArchiSteamFarm { } } - internal bool IsBlacklistedFromTrades(ulong steamID) { - if (steamID != 0) { - return BotDatabase.IsBlacklistedFromTrades(steamID); + internal bool IsBlacklistedFromIdling(uint appID) { + if (appID == 0) { + ArchiLogger.LogNullError(nameof(appID)); + return false; } - ArchiLogger.LogNullError(nameof(steamID)); - return false; + bool result = BotDatabase.IsBlacklistedFromIdling(appID); + return result; + } + + internal bool IsBlacklistedFromTrades(ulong steamID) { + if (steamID == 0) { + ArchiLogger.LogNullError(nameof(steamID)); + return false; + } + + bool result = BotDatabase.IsBlacklistedFromTrades(steamID); + return result; } internal bool IsMaster(ulong steamID) { @@ -745,6 +756,8 @@ namespace ArchiSteamFarm { return await ResponseFarm(steamID).ConfigureAwait(false); case "!HELP": return ResponseHelp(steamID); + case "!ID": + return ResponseIdleBlacklist(steamID); case "!IQ": return ResponseIdleQueue(steamID); case "!LEAVE": @@ -828,6 +841,20 @@ namespace ArchiSteamFarm { } goto default; + case "!ID": + return await ResponseIdleBlacklist(steamID, Utilities.GetArgsString(args, 1, ",")).ConfigureAwait(false); + case "!IDADD": + if (args.Length > 2) { + return await ResponseIdleBlacklistAdd(steamID, args[1], Utilities.GetArgsString(args, 2, ",")).ConfigureAwait(false); + } + + return await ResponseIdleBlacklistAdd(steamID, Utilities.GetArgsString(args, 1, ",")).ConfigureAwait(false); + case "!IDRM": + if (args.Length > 2) { + return await ResponseIdleBlacklistRemove(steamID, args[1], Utilities.GetArgsString(args, 2, ",")).ConfigureAwait(false); + } + + return await ResponseIdleBlacklistRemove(steamID, Utilities.GetArgsString(args, 1, ",")).ConfigureAwait(false); case "!IQ": return await ResponseIdleQueue(steamID, Utilities.GetArgsString(args, 1, ",")).ConfigureAwait(false); case "!IQADD": @@ -2430,6 +2457,20 @@ namespace ArchiSteamFarm { return GetAPIStatus(Bots.Where(kv => bots.Contains(kv.Value) && kv.Value.IsMaster(steamID)).ToDictionary(kv => kv.Key, kv => kv.Value)); } + 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)); @@ -2461,15 +2502,6 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } - private string ResponseBlacklist(ulong steamID) { - if (steamID != 0) { - return IsMaster(steamID) ? FormatBotResponse(string.Join(", ", BotDatabase.GetBlacklistedFromTradesSteamIDs())) : null; - } - - ArchiLogger.LogNullError(nameof(steamID)); - return null; - } - private async Task ResponseBlacklistAdd(ulong steamID, string targetsText) { if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); @@ -2530,6 +2562,35 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } + private async Task ResponseBlacklistRemove(ulong steamID, string targetsText) { + if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { + ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); + return null; + } + + if (!IsMaster(steamID)) { + return null; + } + + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + 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); + } + + if (targetIDs.Count == 0) { + return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targetIDs))); + } + + await BotDatabase.RemoveBlacklistedFromTradesSteamIDs(targetIDs).ConfigureAwait(false); + return FormatBotResponse(Strings.Done); + } + private static async Task ResponseBlacklistRemove(ulong steamID, string botNames, string targetsText) { if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetsText)) { ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetsText)); @@ -2561,35 +2622,6 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } - private async Task ResponseBlacklistRemove(ulong steamID, string targetsText) { - if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { - ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); - return null; - } - - if (!IsMaster(steamID)) { - return null; - } - - string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - 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); - } - - if (targetIDs.Count == 0) { - return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targetIDs))); - } - - await BotDatabase.RemoveBlacklistedFromTradesSteamIDs(targetIDs).ConfigureAwait(false); - return FormatBotResponse(Strings.Done); - } - private static string ResponseExit(ulong steamID) { if (steamID == 0) { ASF.ArchiLogger.LogNullError(nameof(steamID)); @@ -2672,6 +2704,185 @@ namespace ArchiSteamFarm { return 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("", responses) : null; + } + + private async Task ResponseIdleBlacklistAdd(ulong steamID, string targetsText) { + if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { + ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); + return null; + } + + if (!IsMaster(steamID)) { + return null; + } + + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + 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); + } + + if (appIDs.Count == 0) { + return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs))); + } + + await BotDatabase.AddIdlingBlacklistedAppIDs(appIDs).ConfigureAwait(false); + return FormatBotResponse(Strings.Done); + } + + private static async Task ResponseIdleBlacklistAdd(ulong steamID, string botNames, string targetsText) { + if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetsText)) { + ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetsText)); + 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, targetsText)); + 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("", responses) : null; + } + + private async Task ResponseIdleBlacklistRemove(ulong steamID, string targetsText) { + if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { + ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); + return null; + } + + if (!IsMaster(steamID)) { + return null; + } + + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + 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); + } + + if (appIDs.Count == 0) { + return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs))); + } + + await BotDatabase.RemoveIdlingBlacklistedAppIDs(appIDs).ConfigureAwait(false); + return FormatBotResponse(Strings.Done); + } + + private static async Task ResponseIdleBlacklistRemove(ulong steamID, string botNames, string targetsText) { + if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetsText)) { + ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetsText)); + 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, targetsText)); + 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("", 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)); @@ -2703,16 +2914,6 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } - private string ResponseIdleQueue(ulong steamID) { - if (steamID == 0) { - ArchiLogger.LogNullError(nameof(steamID)); - return null; - } - - string result = IsMaster(steamID) ? FormatBotResponse(string.Join(", ", BotDatabase.GetIdlingPriorityAppIDs())) : null; - return result; - } - private async Task ResponseIdleQueueAdd(ulong steamID, string targetsText) { if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); @@ -2773,6 +2974,35 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } + private async Task ResponseIdleQueueRemove(ulong steamID, string targetsText) { + if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { + ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); + return null; + } + + if (!IsMaster(steamID)) { + return null; + } + + string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + 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); + } + + if (appIDs.Count == 0) { + return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs))); + } + + await BotDatabase.RemoveIdlingPriorityAppIDs(appIDs).ConfigureAwait(false); + return FormatBotResponse(Strings.Done); + } + private static async Task ResponseIdleQueueRemove(ulong steamID, string botNames, string targetsText) { if ((steamID == 0) || string.IsNullOrEmpty(botNames) || string.IsNullOrEmpty(targetsText)) { ASF.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(botNames) + " || " + nameof(targetsText)); @@ -2804,35 +3034,6 @@ namespace ArchiSteamFarm { return responses.Count > 0 ? string.Join("", responses) : null; } - private async Task ResponseIdleQueueRemove(ulong steamID, string targetsText) { - if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) { - ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText)); - return null; - } - - if (!IsMaster(steamID)) { - return null; - } - - string[] targets = targetsText.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - 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); - } - - if (appIDs.Count == 0) { - return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs))); - } - - await BotDatabase.RemoveIdlingPriorityAppIDs(appIDs).ConfigureAwait(false); - return FormatBotResponse(Strings.Done); - } - 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)); diff --git a/ArchiSteamFarm/BotDatabase.cs b/ArchiSteamFarm/BotDatabase.cs index 3a1c59a53..271995dfa 100644 --- a/ArchiSteamFarm/BotDatabase.cs +++ b/ArchiSteamFarm/BotDatabase.cs @@ -36,6 +36,9 @@ namespace ArchiSteamFarm { private readonly SemaphoreSlim FileSemaphore = new SemaphoreSlim(1, 1); + [JsonProperty(Required = Required.DisallowNull)] + private readonly ConcurrentHashSet IdlingBlacklistedAppIDs = new ConcurrentHashSet(); + [JsonProperty(Required = Required.DisallowNull)] private readonly ConcurrentHashSet IdlingPriorityAppIDs = new ConcurrentHashSet(); @@ -79,6 +82,17 @@ namespace ArchiSteamFarm { } } + internal async Task AddIdlingBlacklistedAppIDs(HashSet appIDs) { + if ((appIDs == null) || (appIDs.Count == 0)) { + ASF.ArchiLogger.LogNullError(nameof(appIDs)); + return; + } + + if (IdlingBlacklistedAppIDs.AddRange(appIDs)) { + await Save().ConfigureAwait(false); + } + } + internal async Task AddIdlingPriorityAppIDs(HashSet appIDs) { if ((appIDs == null) || (appIDs.Count == 0)) { ASF.ArchiLogger.LogNullError(nameof(appIDs)); @@ -101,8 +115,19 @@ namespace ArchiSteamFarm { } } - internal IEnumerable GetBlacklistedFromTradesSteamIDs() => BlacklistedFromTradesSteamIDs; - internal IEnumerable GetIdlingPriorityAppIDs() => IdlingPriorityAppIDs; + internal IReadOnlyCollection GetBlacklistedFromTradesSteamIDs() => BlacklistedFromTradesSteamIDs; + internal IReadOnlyCollection GetIdlingBlacklistedAppIDs() => IdlingBlacklistedAppIDs; + internal IReadOnlyCollection GetIdlingPriorityAppIDs() => IdlingPriorityAppIDs; + + internal bool IsBlacklistedFromIdling(uint appID) { + if (appID == 0) { + ASF.ArchiLogger.LogNullError(nameof(appID)); + return false; + } + + bool result = IdlingBlacklistedAppIDs.Contains(appID); + return result; + } internal bool IsBlacklistedFromTrades(ulong steamID) { if (steamID == 0) { @@ -163,6 +188,17 @@ namespace ArchiSteamFarm { } } + internal async Task RemoveIdlingBlacklistedAppIDs(HashSet appIDs) { + if ((appIDs == null) || (appIDs.Count == 0)) { + ASF.ArchiLogger.LogNullError(nameof(appIDs)); + return; + } + + if (IdlingBlacklistedAppIDs.RemoveRange(appIDs)) { + await Save().ConfigureAwait(false); + } + } + internal async Task RemoveIdlingPriorityAppIDs(HashSet appIDs) { if ((appIDs == null) || (appIDs.Count == 0)) { ASF.ArchiLogger.LogNullError(nameof(appIDs)); diff --git a/ArchiSteamFarm/CardsFarmer.cs b/ArchiSteamFarm/CardsFarmer.cs index c894120de..d4d687210 100755 --- a/ArchiSteamFarm/CardsFarmer.cs +++ b/ArchiSteamFarm/CardsFarmer.cs @@ -366,7 +366,7 @@ namespace ArchiSteamFarm { continue; } - if (GlobalConfig.GamesBlacklist.Contains(appID) || GlobalConfig.SalesBlacklist.Contains(appID) || Program.GlobalConfig.Blacklist.Contains(appID)) { + if (GlobalConfig.GamesBlacklist.Contains(appID) || GlobalConfig.SalesBlacklist.Contains(appID) || Program.GlobalConfig.Blacklist.Contains(appID) || Bot.IsBlacklistedFromIdling(appID)) { // We have this appID blacklisted, so skip it continue; }