From f807bdb660e75dee5a34994f2ea70970ca6d0492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Domeradzki?= Date: Tue, 8 Feb 2022 23:17:03 +0100 Subject: [PATCH] Fix permissions when proxifying commands (#2509) * Fix permissions when proxifying commands * Version bump --- ArchiSteamFarm/Steam/Interaction/Commands.cs | 283 ++++++++++--------- Directory.Build.props | 2 +- 2 files changed, 154 insertions(+), 131 deletions(-) diff --git a/ArchiSteamFarm/Steam/Interaction/Commands.cs b/ArchiSteamFarm/Steam/Interaction/Commands.cs index 71644b113..121c10566 100644 --- a/ArchiSteamFarm/Steam/Interaction/Commands.cs +++ b/ArchiSteamFarm/Steam/Interaction/Commands.cs @@ -137,7 +137,7 @@ public sealed class Commands { case "RESTART": return ResponseRestart(access); case "SA": - return await ResponseStatus(access, SharedInfo.ASF).ConfigureAwait(false); + return await ResponseStatus(access, SharedInfo.ASF, steamID).ConfigureAwait(false); case "START": return ResponseStart(access); case "STATS": @@ -162,106 +162,106 @@ public sealed class Commands { default: switch (args[0].ToUpperInvariant()) { case "2FA": - return await Response2FA(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await Response2FA(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "2FANO": - return await Response2FAConfirm(access, Utilities.GetArgsAsText(args, 1, ","), false).ConfigureAwait(false); + return await Response2FAConfirm(access, Utilities.GetArgsAsText(args, 1, ","), false, steamID).ConfigureAwait(false); case "2FAOK": - return await Response2FAConfirm(access, Utilities.GetArgsAsText(args, 1, ","), true).ConfigureAwait(false); + return await Response2FAConfirm(access, Utilities.GetArgsAsText(args, 1, ","), true, steamID).ConfigureAwait(false); case "ADDLICENSE" when args.Length > 2: - return await ResponseAddLicense(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseAddLicense(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "ADDLICENSE": return await ResponseAddLicense(access, args[1]).ConfigureAwait(false); case "BALANCE": - return await ResponseWalletBalance(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseWalletBalance(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "BGR": - return await ResponseBackgroundGamesRedeemer(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseBackgroundGamesRedeemer(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "ENCRYPT" when args.Length > 2: return ResponseEncrypt(access, args[1], Utilities.GetArgsAsText(message, 2)); case "FARM": - return await ResponseFarm(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseFarm(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "FB": - return await ResponseFarmingBlacklist(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseFarmingBlacklist(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "FBADD" when args.Length > 2: - return await ResponseFarmingBlacklistAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseFarmingBlacklistAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "FBADD": return ResponseFarmingBlacklistAdd(access, args[1]); case "FBRM" when args.Length > 2: - return await ResponseFarmingBlacklistRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseFarmingBlacklistRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "FBRM": return ResponseFarmingBlacklistRemove(access, args[1]); case "FQ": - return await ResponseFarmingQueue(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseFarmingQueue(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "FQADD" when args.Length > 2: - return await ResponseFarmingQueueAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseFarmingQueueAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "FQADD": return ResponseFarmingQueueAdd(access, args[1]); case "FQRM" when args.Length > 2: - return await ResponseFarmingQueueRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseFarmingQueueRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "FQRM": return ResponseFarmingQueueRemove(access, args[1]); case "HASH" when args.Length > 2: return ResponseHash(access, args[1], Utilities.GetArgsAsText(message, 2)); case "INPUT" when args.Length > 3: - return await ResponseInput(access, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false); + return await ResponseInput(access, args[1], args[2], Utilities.GetArgsAsText(message, 3), steamID).ConfigureAwait(false); case "INPUT" when args.Length > 2: return ResponseInput(access, args[1], args[2]); case "LEVEL": - return await ResponseLevel(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseLevel(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "LOOT": - return await ResponseLoot(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseLoot(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "LOOT^" when args.Length > 3: - return await ResponseAdvancedLoot(access, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false); + return await ResponseAdvancedLoot(access, args[1], args[2], Utilities.GetArgsAsText(message, 3), steamID).ConfigureAwait(false); case "LOOT^" when args.Length > 2: return await ResponseAdvancedLoot(access, args[1], args[2]).ConfigureAwait(false); case "LOOT@" when args.Length > 2: - return await ResponseLootByRealAppIDs(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseLootByRealAppIDs(access, args[1], Utilities.GetArgsAsText(args, 2, ","), false, steamID).ConfigureAwait(false); case "LOOT@": - return await ResponseLootByRealAppIDs(access, args[1]).ConfigureAwait(false); + return await ResponseLootByRealAppIDs(access, args[1], false).ConfigureAwait(false); case "LOOT%" when args.Length > 2: - return await ResponseLootByRealAppIDs(access, args[1], Utilities.GetArgsAsText(args, 2, ","), true).ConfigureAwait(false); + return await ResponseLootByRealAppIDs(access, args[1], Utilities.GetArgsAsText(args, 2, ","), true, steamID).ConfigureAwait(false); case "LOOT%": return await ResponseLootByRealAppIDs(access, args[1], true).ConfigureAwait(false); case "MAB": - return await ResponseMatchActivelyBlacklist(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseMatchActivelyBlacklist(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "MABADD" when args.Length > 2: - return await ResponseMatchActivelyBlacklistAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseMatchActivelyBlacklistAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "MABADD": return ResponseMatchActivelyBlacklistAdd(access, args[1]); case "MABRM" when args.Length > 2: - return await ResponseMatchActivelyBlacklistRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseMatchActivelyBlacklistRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "MABRM": return ResponseMatchActivelyBlacklistRemove(access, args[1]); case "NICKNAME" when args.Length > 2: - return await ResponseNickname(access, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false); + return await ResponseNickname(access, args[1], Utilities.GetArgsAsText(message, 2), steamID).ConfigureAwait(false); case "NICKNAME": return ResponseNickname(access, args[1]); case "OA": - return await ResponseOwns(access, SharedInfo.ASF, Utilities.GetArgsAsText(message, 1)).ConfigureAwait(false); + return await ResponseOwns(access, SharedInfo.ASF, Utilities.GetArgsAsText(message, 1), steamID).ConfigureAwait(false); case "OWNS" when args.Length > 2: - return await ResponseOwns(access, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false); + return await ResponseOwns(access, args[1], Utilities.GetArgsAsText(message, 2), steamID).ConfigureAwait(false); case "OWNS": return (await ResponseOwns(access, args[1]).ConfigureAwait(false)).Response; case "PAUSE": - return await ResponsePause(access, Utilities.GetArgsAsText(args, 1, ","), true).ConfigureAwait(false); + return await ResponsePause(access, Utilities.GetArgsAsText(args, 1, ","), true, steamID: steamID).ConfigureAwait(false); case "PAUSE~": - return await ResponsePause(access, Utilities.GetArgsAsText(args, 1, ","), false).ConfigureAwait(false); + return await ResponsePause(access, Utilities.GetArgsAsText(args, 1, ","), false, steamID: steamID).ConfigureAwait(false); case "PAUSE&" when args.Length > 2: - return await ResponsePause(access, args[1], true, Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false); + return await ResponsePause(access, args[1], true, Utilities.GetArgsAsText(message, 2), steamID).ConfigureAwait(false); case "PAUSE&": return await ResponsePause(access, true, args[1]).ConfigureAwait(false); case "PLAY" when args.Length > 2: - return await ResponsePlay(access, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false); + return await ResponsePlay(access, args[1], Utilities.GetArgsAsText(message, 2), steamID).ConfigureAwait(false); case "PLAY": return await ResponsePlay(access, args[1]).ConfigureAwait(false); case "POINTS": - return await ResponsePointsBalance(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponsePointsBalance(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "PRIVACY" when args.Length > 2: - return await ResponsePrivacy(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponsePrivacy(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "PRIVACY": return await ResponsePrivacy(access, args[1]).ConfigureAwait(false); case "R" when args.Length > 2: case "REDEEM" when args.Length > 2: - return await ResponseRedeem(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); + return await ResponseRedeem(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID: steamID).ConfigureAwait(false); case "R": case "REDEEM": return await ResponseRedeem(access, args[1], steamID).ConfigureAwait(false); @@ -272,43 +272,43 @@ public sealed class Commands { case "REDEEM^" when args.Length > 2: return await ResponseAdvancedRedeem(access, args[1], args[2], steamID).ConfigureAwait(false); case "RESET": - return await ResponseReset(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseReset(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "RESUME": - return await ResponseResume(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseResume(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "START": - return await ResponseStart(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseStart(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "STATUS": - return await ResponseStatus(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseStatus(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "STOP": - return await ResponseStop(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseStop(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "TB": - return await ResponseTradingBlacklist(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseTradingBlacklist(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); case "TBADD" when args.Length > 2: - return await ResponseTradingBlacklistAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseTradingBlacklistAdd(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "TBADD": return ResponseTradingBlacklistAdd(access, args[1]); case "TBRM" when args.Length > 2: - return await ResponseTradingBlacklistRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false); + return await ResponseTradingBlacklistRemove(access, args[1], Utilities.GetArgsAsText(args, 2, ","), steamID).ConfigureAwait(false); case "TBRM": return ResponseTradingBlacklistRemove(access, args[1]); case "TRANSFER" when args.Length > 2: - return await ResponseTransfer(access, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false); + return await ResponseTransfer(access, args[1], Utilities.GetArgsAsText(message, 2), steamID).ConfigureAwait(false); case "TRANSFER": return await ResponseTransfer(access, args[1]).ConfigureAwait(false); case "TRANSFER^" when args.Length > 4: - return await ResponseAdvancedTransfer(access, args[1], args[2], args[3], Utilities.GetArgsAsText(message, 4)).ConfigureAwait(false); + return await ResponseAdvancedTransfer(access, args[1], args[2], args[3], Utilities.GetArgsAsText(message, 4), steamID).ConfigureAwait(false); case "TRANSFER^" when args.Length > 3: return await ResponseAdvancedTransfer(access, args[1], args[2], args[3]).ConfigureAwait(false); case "TRANSFER@" when args.Length > 3: - return await ResponseTransferByRealAppIDs(access, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false); + return await ResponseTransferByRealAppIDs(access, args[1], args[2], Utilities.GetArgsAsText(message, 3), false, steamID).ConfigureAwait(false); case "TRANSFER@" when args.Length > 2: - return await ResponseTransferByRealAppIDs(access, args[1], args[2]).ConfigureAwait(false); + return await ResponseTransferByRealAppIDs(access, args[1], args[2], false).ConfigureAwait(false); case "TRANSFER%" when args.Length > 3: - return await ResponseTransferByRealAppIDs(access, args[1], args[2], Utilities.GetArgsAsText(message, 3), true).ConfigureAwait(false); + return await ResponseTransferByRealAppIDs(access, args[1], args[2], Utilities.GetArgsAsText(message, 3), true, steamID).ConfigureAwait(false); case "TRANSFER%" when args.Length > 2: return await ResponseTransferByRealAppIDs(access, args[1], args[2], true).ConfigureAwait(false); case "UNPACK": - return await ResponseUnpackBoosters(access, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false); + return await ResponseUnpackBoosters(access, Utilities.GetArgsAsText(args, 1, ","), steamID).ConfigureAwait(false); default: string? pluginsResponse = await PluginsCore.OnBotCommand(Bot, access, message, args, steamID).ConfigureAwait(false); @@ -504,6 +504,29 @@ public sealed class Commands { return gamesOwned; } + private static EAccess ProxyAccess(Bot bot, EAccess access, ulong steamID = 0) { + // The objective here should be simple, calculating effective access of the user + // Problem is, history already proved nothing in this damn file is as simple as it seems + // We use this function for proxying commands such as !status 2 sent to bot 1, which should use 2's user access instead + ArgumentNullException.ThrowIfNull(bot); + + if (!Enum.IsDefined(access)) { + throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); + } + + if ((steamID != 0) && !new SteamID(steamID).IsIndividualAccount) { + throw new ArgumentOutOfRangeException(nameof(steamID)); + } + + // If we got executed with owner access or lack steamID entirely, then this is effective access + if ((access >= EAccess.Owner) || (steamID == 0)) { + return access; + } + + // Otherwise, effective access is the access of the user on target bot, whatever that would be, not this one + return bot.GetAccess(steamID); + } + private async Task Response2FA(EAccess access) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); @@ -518,7 +541,7 @@ public sealed class Commands { return FormatBotResponse(success && !string.IsNullOrEmpty(token) ? string.Format(CultureInfo.CurrentCulture, Strings.BotAuthenticatorToken, token) : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task Response2FA(EAccess access, string botNames) { + private static async Task Response2FA(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -533,7 +556,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.Response2FA(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.Response2FA(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -562,7 +585,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task Response2FAConfirm(EAccess access, string botNames, bool confirm) { + private static async Task Response2FAConfirm(EAccess access, string botNames, bool confirm, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -577,7 +600,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.Response2FAConfirm(access, confirm))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.Response2FAConfirm(ProxyAccess(bot, access, steamID), confirm))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -656,7 +679,7 @@ public sealed class Commands { return response.Length > 0 ? response.ToString() : null; } - private static async Task ResponseAddLicense(EAccess access, string botNames, string query) { + private static async Task ResponseAddLicense(EAccess access, string botNames, string query, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -675,7 +698,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAddLicense(access, query))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAddLicense(ProxyAccess(bot, access, steamID), query))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -716,7 +739,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseAdvancedLoot(EAccess access, string botNames, string appID, string contextID) { + private static async Task ResponseAdvancedLoot(EAccess access, string botNames, string appID, string contextID, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -739,7 +762,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAdvancedLoot(access, appID, contextID))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAdvancedLoot(ProxyAccess(bot, access, steamID), appID, contextID))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -854,7 +877,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAdvancedRedeem(access, options, keys, steamID))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAdvancedRedeem(ProxyAccess(bot, access, steamID), options, keys, steamID))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -927,7 +950,7 @@ public sealed class Commands { return await ResponseAdvancedTransfer(access, appID, contextID, targetBot).ConfigureAwait(false); } - private static async Task ResponseAdvancedTransfer(EAccess access, string botNames, string targetAppID, string targetContextID, string botNameTo) { + private static async Task ResponseAdvancedTransfer(EAccess access, string botNames, string targetAppID, string targetContextID, string botNameTo, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -968,7 +991,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNameTo)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAdvancedTransfer(access, appID, contextID, targetBot))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseAdvancedTransfer(ProxyAccess(bot, access, steamID), appID, contextID, targetBot))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -989,7 +1012,7 @@ public sealed class Commands { return FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotGamesToRedeemInBackgroundCount, count)); } - private static async Task ResponseBackgroundGamesRedeemer(EAccess access, string botNames) { + private static async Task ResponseBackgroundGamesRedeemer(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1004,7 +1027,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseBackgroundGamesRedeemer(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseBackgroundGamesRedeemer(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1073,7 +1096,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseFarm(EAccess access, string botNames) { + private static async Task ResponseFarm(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1088,7 +1111,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseFarm(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseFarm(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1103,7 +1126,7 @@ public sealed class Commands { return access < EAccess.Master ? null : FormatBotResponse(Bot.BotDatabase.FarmingBlacklistAppIDs.Count == 0 ? string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(Bot.BotDatabase.FarmingBlacklistAppIDs)) : string.Join(", ", Bot.BotDatabase.FarmingBlacklistAppIDs)); } - private static async Task ResponseFarmingBlacklist(EAccess access, string botNames) { + private static async Task ResponseFarmingBlacklist(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1118,7 +1141,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingBlacklist(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingBlacklist(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1170,7 +1193,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseFarmingBlacklistAdd(EAccess access, string botNames, string targetAppIDs) { + private static async Task ResponseFarmingBlacklistAdd(EAccess access, string botNames, string targetAppIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1189,7 +1212,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingBlacklistAdd(access, targetAppIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingBlacklistAdd(ProxyAccess(bot, access, steamID), targetAppIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1236,7 +1259,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseFarmingBlacklistRemove(EAccess access, string botNames, string targetAppIDs) { + private static async Task ResponseFarmingBlacklistRemove(EAccess access, string botNames, string targetAppIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1255,7 +1278,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingBlacklistRemove(access, targetAppIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingBlacklistRemove(ProxyAccess(bot, access, steamID), targetAppIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1270,7 +1293,7 @@ public sealed class Commands { return access < EAccess.Master ? null : FormatBotResponse(Bot.BotDatabase.FarmingPriorityQueueAppIDs.Count == 0 ? string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(Bot.BotDatabase.FarmingPriorityQueueAppIDs)) : string.Join(", ", Bot.BotDatabase.FarmingPriorityQueueAppIDs)); } - private static async Task ResponseFarmingQueue(EAccess access, string botNames) { + private static async Task ResponseFarmingQueue(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1285,7 +1308,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingQueue(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingQueue(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1344,7 +1367,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseFarmingQueueAdd(EAccess access, string botNames, string targetAppIDs) { + private static async Task ResponseFarmingQueueAdd(EAccess access, string botNames, string targetAppIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1363,7 +1386,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingQueueAdd(access, targetAppIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingQueueAdd(ProxyAccess(bot, access, steamID), targetAppIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1415,7 +1438,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseFarmingQueueRemove(EAccess access, string botNames, string targetAppIDs) { + private static async Task ResponseFarmingQueueRemove(EAccess access, string botNames, string targetAppIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1434,7 +1457,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingQueueRemove(access, targetAppIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseFarmingQueueRemove(ProxyAccess(bot, access, steamID), targetAppIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1507,7 +1530,7 @@ public sealed class Commands { return FormatBotResponse(result ? Strings.Done : Strings.WarningFailed); } - private static async Task ResponseInput(EAccess access, string botNames, string propertyName, string inputValue) { + private static async Task ResponseInput(EAccess access, string botNames, string propertyName, string inputValue, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1530,7 +1553,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseInput(access, propertyName, inputValue)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseInput(ProxyAccess(bot, access, steamID), propertyName, inputValue)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1555,7 +1578,7 @@ public sealed class Commands { return FormatBotResponse(level.HasValue ? string.Format(CultureInfo.CurrentCulture, Strings.BotLevel, level.Value) : Strings.WarningFailed); } - private static async Task ResponseLevel(EAccess access, string botNames) { + private static async Task ResponseLevel(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1570,7 +1593,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseLevel(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseLevel(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1599,7 +1622,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseLoot(EAccess access, string botNames) { + private static async Task ResponseLoot(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1614,14 +1637,14 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseLoot(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseLoot(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null; } - private async Task ResponseLootByRealAppIDs(EAccess access, string realAppIDsText, bool exclude = false) { + private async Task ResponseLootByRealAppIDs(EAccess access, string realAppIDsText, bool exclude) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1663,7 +1686,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseLootByRealAppIDs(EAccess access, string botNames, string realAppIDsText, bool exclude = false) { + private static async Task ResponseLootByRealAppIDs(EAccess access, string botNames, string realAppIDsText, bool exclude, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1682,7 +1705,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseLootByRealAppIDs(access, realAppIDsText, exclude))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseLootByRealAppIDs(ProxyAccess(bot, access, steamID), realAppIDsText, exclude))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1697,7 +1720,7 @@ public sealed class Commands { return access < EAccess.Master ? null : FormatBotResponse(Bot.BotDatabase.MatchActivelyBlacklistAppIDs.Count == 0 ? string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(Bot.BotDatabase.MatchActivelyBlacklistAppIDs)) : string.Join(", ", Bot.BotDatabase.MatchActivelyBlacklistAppIDs)); } - private static async Task ResponseMatchActivelyBlacklist(EAccess access, string botNames) { + private static async Task ResponseMatchActivelyBlacklist(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1712,7 +1735,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseMatchActivelyBlacklist(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseMatchActivelyBlacklist(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1751,7 +1774,7 @@ public sealed class Commands { return FormatBotResponse(Bot.BotDatabase.MatchActivelyBlacklistAppIDs.AddRange(appIDs) ? Strings.Done : Strings.NothingFound); } - private static async Task ResponseMatchActivelyBlacklistAdd(EAccess access, string botNames, string targetAppIDs) { + private static async Task ResponseMatchActivelyBlacklistAdd(EAccess access, string botNames, string targetAppIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1770,7 +1793,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseMatchActivelyBlacklistAdd(access, targetAppIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseMatchActivelyBlacklistAdd(ProxyAccess(bot, access, steamID), targetAppIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1809,7 +1832,7 @@ public sealed class Commands { return FormatBotResponse(Bot.BotDatabase.MatchActivelyBlacklistAppIDs.RemoveRange(appIDs) ? Strings.Done : Strings.NothingFound); } - private static async Task ResponseMatchActivelyBlacklistRemove(EAccess access, string botNames, string targetAppIDs) { + private static async Task ResponseMatchActivelyBlacklistRemove(EAccess access, string botNames, string targetAppIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1828,7 +1851,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseMatchActivelyBlacklistRemove(access, targetAppIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseMatchActivelyBlacklistRemove(ProxyAccess(bot, access, steamID), targetAppIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -1857,7 +1880,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseNickname(EAccess access, string botNames, string nickname) { + private static async Task ResponseNickname(EAccess access, string botNames, string nickname, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -1876,7 +1899,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseNickname(access, nickname)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseNickname(ProxyAccess(bot, access, steamID), nickname)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2035,7 +2058,7 @@ public sealed class Commands { return (response.Length > 0 ? response.ToString() : FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotOwnedYet, query)), result); } - private static async Task ResponseOwns(EAccess access, string botNames, string query) { + private static async Task ResponseOwns(EAccess access, string botNames, string query, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2054,7 +2077,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList<(string? Response, Dictionary? OwnedGames)> results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseOwns(access, query))).ConfigureAwait(false); + IList<(string? Response, Dictionary? OwnedGames)> results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseOwns(ProxyAccess(bot, access, steamID), query))).ConfigureAwait(false); List<(string Response, Dictionary OwnedGames)> validResults = new(results.Where(static result => !string.IsNullOrEmpty(result.Response) && (result.OwnedGames != null))!); @@ -2107,7 +2130,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponsePause(EAccess access, string botNames, bool permanent, string? resumeInSecondsText = null) { + private static async Task ResponsePause(EAccess access, string botNames, bool permanent, string? resumeInSecondsText = null, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2122,7 +2145,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePause(access, permanent, resumeInSecondsText))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePause(ProxyAccess(bot, access, steamID), permanent, resumeInSecondsText))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2200,7 +2223,7 @@ public sealed class Commands { return await ResponsePlay(access, gamesToPlay, gameName.Length > 0 ? gameName.ToString() : null).ConfigureAwait(false); } - private static async Task ResponsePlay(EAccess access, string botNames, string targetGameIDs) { + private static async Task ResponsePlay(EAccess access, string botNames, string targetGameIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2219,7 +2242,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePlay(access, targetGameIDs))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePlay(ProxyAccess(bot, access, steamID), targetGameIDs))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2244,7 +2267,7 @@ public sealed class Commands { return FormatBotResponse(points.HasValue ? string.Format(CultureInfo.CurrentCulture, Strings.BotPointsBalance, points) : Strings.WarningFailed); } - private static async Task ResponsePointsBalance(EAccess access, string botNames) { + private static async Task ResponsePointsBalance(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2259,7 +2282,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePointsBalance(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePointsBalance(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2400,7 +2423,7 @@ public sealed class Commands { return FormatBotResponse(await Bot.ArchiWebHandler.ChangePrivacySettings(userPrivacy).ConfigureAwait(false) ? Strings.Success : Strings.WarningFailed); } - private static async Task ResponsePrivacy(EAccess access, string botNames, string privacySettingsText) { + private static async Task ResponsePrivacy(EAccess access, string botNames, string privacySettingsText, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2419,7 +2442,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePrivacy(access, privacySettingsText))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponsePrivacy(ProxyAccess(bot, access, steamID), privacySettingsText))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2685,7 +2708,7 @@ public sealed class Commands { return response.Length > 0 ? response.ToString() : null; } - private static async Task ResponseRedeem(EAccess access, string botNames, string keysText, ulong steamID = 0, ERedeemFlags redeemFlags = ERedeemFlags.None) { + private static async Task ResponseRedeem(EAccess access, string botNames, string keysText, ERedeemFlags redeemFlags = ERedeemFlags.None, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2704,7 +2727,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseRedeem(access, keysText, steamID, redeemFlags))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseRedeem(ProxyAccess(bot, access, steamID), keysText, steamID, redeemFlags))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2729,7 +2752,7 @@ public sealed class Commands { return FormatBotResponse(Strings.Done); } - private static async Task ResponseReset(EAccess access, string botNames) { + private static async Task ResponseReset(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2744,7 +2767,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseReset(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseReset(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2779,7 +2802,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseResume(EAccess access, string botNames) { + private static async Task ResponseResume(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2794,7 +2817,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseResume(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseResume(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2815,7 +2838,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseStart(EAccess access, string botNames) { + private static async Task ResponseStart(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2830,7 +2853,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseStart(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseStart(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2894,7 +2917,7 @@ public sealed class Commands { return (FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotStatusIdling, soloGame.AppID, soloGame.GameName, soloGame.CardsRemaining, Bot.CardsFarmer.GamesToFarmReadOnly.Count, Bot.CardsFarmer.GamesToFarmReadOnly.Sum(static game => game.CardsRemaining), Bot.CardsFarmer.TimeRemaining.ToHumanReadable())), Bot); } - private static async Task ResponseStatus(EAccess access, string botNames) { + private static async Task ResponseStatus(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2909,7 +2932,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList<(string? Response, Bot Bot)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseStatus(access)))).ConfigureAwait(false); + IList<(string? Response, Bot Bot)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseStatus(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List<(string Response, Bot Bot)> validResults = new(results.Where(static result => !string.IsNullOrEmpty(result.Response))!); @@ -2938,7 +2961,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseStop(EAccess access, string botNames) { + private static async Task ResponseStop(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2953,7 +2976,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseStop(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseStop(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -2968,7 +2991,7 @@ public sealed class Commands { return access < EAccess.Master ? null : FormatBotResponse(Bot.BotDatabase.TradingBlacklistSteamIDs.Count == 0 ? string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(Bot.BotDatabase.TradingBlacklistSteamIDs)) : string.Join(", ", Bot.BotDatabase.TradingBlacklistSteamIDs)); } - private static async Task ResponseTradingBlacklist(EAccess access, string botNames) { + private static async Task ResponseTradingBlacklist(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -2983,7 +3006,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseTradingBlacklist(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseTradingBlacklist(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -3022,7 +3045,7 @@ public sealed class Commands { return FormatBotResponse(Bot.BotDatabase.TradingBlacklistSteamIDs.AddRange(targetIDs) ? Strings.Done : Strings.NothingFound); } - private static async Task ResponseTradingBlacklistAdd(EAccess access, string botNames, string targetSteamIDs) { + private static async Task ResponseTradingBlacklistAdd(EAccess access, string botNames, string targetSteamIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3041,7 +3064,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseTradingBlacklistAdd(access, targetSteamIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseTradingBlacklistAdd(ProxyAccess(bot, access, steamID), targetSteamIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -3080,7 +3103,7 @@ public sealed class Commands { return FormatBotResponse(Bot.BotDatabase.TradingBlacklistSteamIDs.RemoveRange(targetIDs) ? Strings.Done : Strings.NothingFound); } - private static async Task ResponseTradingBlacklistRemove(EAccess access, string botNames, string targetSteamIDs) { + private static async Task ResponseTradingBlacklistRemove(EAccess access, string botNames, string targetSteamIDs, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3099,7 +3122,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseTradingBlacklistRemove(access, targetSteamIDs)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseTradingBlacklistRemove(ProxyAccess(bot, access, steamID), targetSteamIDs)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -3146,7 +3169,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private static async Task ResponseTransfer(EAccess access, string botNames, string botNameTo) { + private static async Task ResponseTransfer(EAccess access, string botNames, string botNameTo, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3165,14 +3188,14 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseTransfer(access, botNameTo))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseTransfer(ProxyAccess(bot, access, steamID), botNameTo))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null; } - private async Task ResponseTransferByRealAppIDs(EAccess access, IReadOnlyCollection realAppIDs, Bot targetBot, bool exclude = false) { + private async Task ResponseTransferByRealAppIDs(EAccess access, IReadOnlyCollection realAppIDs, Bot targetBot, bool exclude) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3208,7 +3231,7 @@ public sealed class Commands { return FormatBotResponse(success ? message : string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, message)); } - private async Task ResponseTransferByRealAppIDs(EAccess access, string realAppIDsText, string botNameTo, bool exclude = false) { + private async Task ResponseTransferByRealAppIDs(EAccess access, string realAppIDsText, string botNameTo, bool exclude) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3250,7 +3273,7 @@ public sealed class Commands { return await ResponseTransferByRealAppIDs(access, realAppIDs, targetBot, exclude).ConfigureAwait(false); } - private static async Task ResponseTransferByRealAppIDs(EAccess access, string botNames, string realAppIDsText, string botNameTo, bool exclude = false) { + private static async Task ResponseTransferByRealAppIDs(EAccess access, string botNames, string realAppIDsText, string botNameTo, bool exclude, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3295,7 +3318,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNameTo)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseTransferByRealAppIDs(access, realAppIDs, targetBot, exclude))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseTransferByRealAppIDs(ProxyAccess(bot, access, steamID), realAppIDs, targetBot, exclude))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -3346,7 +3369,7 @@ public sealed class Commands { return FormatBotResponse(completeSuccess ? Strings.Success : Strings.Done); } - private static async Task ResponseUnpackBoosters(EAccess access, string botNames) { + private static async Task ResponseUnpackBoosters(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3361,7 +3384,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseUnpackBoosters(access))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => bot.Commands.ResponseUnpackBoosters(ProxyAccess(bot, access, steamID)))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); @@ -3402,7 +3425,7 @@ public sealed class Commands { return !Bot.IsConnectedAndLoggedOn ? FormatBotResponse(Strings.BotNotConnected) : FormatBotResponse(Bot.WalletCurrency != ECurrencyCode.Invalid ? string.Format(CultureInfo.CurrentCulture, Strings.BotWalletBalance, Bot.WalletBalance / 100.0, Bot.WalletCurrency.ToString()) : Strings.BotHasNoWallet); } - private static async Task ResponseWalletBalance(EAccess access, string botNames) { + private static async Task ResponseWalletBalance(EAccess access, string botNames, ulong steamID = 0) { if (!Enum.IsDefined(access)) { throw new InvalidEnumArgumentException(nameof(access), (int) access, typeof(EAccess)); } @@ -3417,7 +3440,7 @@ public sealed class Commands { return access >= EAccess.Owner ? FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null; } - IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseWalletBalance(access)))).ConfigureAwait(false); + IList results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.Commands.ResponseWalletBalance(ProxyAccess(bot, access, steamID))))).ConfigureAwait(false); List responses = new(results.Where(static result => !string.IsNullOrEmpty(result))!); diff --git a/Directory.Build.props b/Directory.Build.props index 2eab345fc..be7ba646b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 5.2.3.1 + 5.2.3.2