2019-02-16 17:34:17 +01:00
// _ _ _ ____ _ _____
2018-09-15 22:34:32 +02:00
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
2019-01-14 19:11:17 +01:00
// |
2020-02-01 23:33:35 +01:00
// Copyright 2015-2020 Łukasz "JustArchi" Domeradzki
2018-09-15 22:34:32 +02:00
// Contact: JustArchi@JustArchi.net
2019-01-14 19:11:17 +01:00
// |
2018-09-15 22:34:32 +02:00
// 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
2019-01-14 19:11:17 +01:00
// |
2018-09-15 22:34:32 +02:00
// http://www.apache.org/licenses/LICENSE-2.0
2019-01-14 19:11:17 +01:00
// |
2018-09-15 22:34:32 +02:00
// 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 ;
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
using System.Net.Http ;
2018-09-15 22:34:32 +02:00
using System.Text ;
2019-07-02 15:06:01 +02:00
using System.Text.RegularExpressions ;
2018-09-15 22:34:32 +02:00
using System.Threading.Tasks ;
using ArchiSteamFarm.Json ;
using ArchiSteamFarm.Localization ;
2019-01-10 22:33:07 +01:00
using ArchiSteamFarm.Plugins ;
using JetBrains.Annotations ;
2018-09-15 22:34:32 +02:00
using SteamKit2 ;
namespace ArchiSteamFarm {
2019-01-10 22:33:07 +01:00
public sealed class Commands {
2019-04-26 15:42:53 +02:00
private const ushort SteamTypingStatusDelay = 10 * 1000 ; // Steam client broadcasts typing status each 10 seconds
2019-02-24 17:11:47 +01:00
2018-09-15 22:34:32 +02:00
private readonly Bot Bot ;
private readonly Dictionary < uint , string > CachedGamesOwned = new Dictionary < uint , string > ( ) ;
2020-08-22 21:41:01 +02:00
internal Commands ( Bot bot ) = > Bot = bot ? ? throw new ArgumentNullException ( nameof ( bot ) ) ;
2018-09-15 22:34:32 +02:00
2019-01-10 22:33:07 +01:00
[PublicAPI]
public static string FormatBotResponse ( string response , string botName ) {
if ( string . IsNullOrEmpty ( response ) | | string . IsNullOrEmpty ( botName ) ) {
2020-08-22 21:41:01 +02:00
throw new ArgumentNullException ( nameof ( response ) + " || " + nameof ( botName ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-10 22:33:07 +01:00
return Environment . NewLine + "<" + botName + "> " + response ;
2018-09-15 22:34:32 +02:00
}
2019-01-10 22:33:07 +01:00
[PublicAPI]
public string FormatBotResponse ( string response ) {
if ( string . IsNullOrEmpty ( response ) ) {
2020-08-22 21:41:01 +02:00
throw new ArgumentNullException ( nameof ( response ) ) ;
2019-01-10 22:33:07 +01:00
}
return "<" + Bot . BotName + "> " + response ;
}
[PublicAPI]
public static string FormatStaticResponse ( string response ) {
if ( string . IsNullOrEmpty ( response ) ) {
2020-08-22 21:41:01 +02:00
throw new ArgumentNullException ( nameof ( response ) ) ;
2019-01-10 22:33:07 +01:00
}
return "<" + SharedInfo . ASF + "> " + response ;
}
2019-02-10 06:35:20 +01:00
[PublicAPI]
2020-08-22 21:41:01 +02:00
public async Task < string? > Response ( ulong steamID , string message ) {
2019-02-10 06:35:20 +01:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
2020-08-22 21:41:01 +02:00
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( message ) ) ;
2019-02-10 06:35:20 +01:00
}
2020-08-22 21:41:01 +02:00
string [ ] args = message . Split ( new char [ 0 ] , StringSplitOptions . RemoveEmptyEntries ) ;
2018-09-15 22:34:32 +02:00
switch ( args . Length ) {
case 0 :
2020-08-22 21:41:01 +02:00
throw new ArgumentOutOfRangeException ( nameof ( args . Length ) ) ;
2018-09-15 22:34:32 +02:00
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 ) ;
2018-11-03 19:42:40 +02:00
case "BALANCE" :
return ResponseWalletBalance ( steamID ) ;
2019-02-26 19:59:04 +01:00
case "BGR" :
return ResponseBackgroundGamesRedeemer ( steamID ) ;
2018-09-15 22:34:32 +02:00
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 ) ;
2018-11-14 21:51:21 +02:00
case "LEVEL" :
return await ResponseLevel ( steamID ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "LOOT" :
return await ResponseLoot ( steamID ) . ConfigureAwait ( false ) ;
case "PASSWORD" :
return ResponsePassword ( steamID ) ;
case "PAUSE" :
return await ResponsePause ( steamID , true ) . ConfigureAwait ( false ) ;
case "PAUSE~" :
return await ResponsePause ( steamID , false ) . ConfigureAwait ( false ) ;
2019-06-23 17:30:34 +02:00
case "RESET" :
return await ResponseReset ( steamID ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
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 :
2020-08-22 21:41:01 +02:00
string? pluginsResponse = await PluginsCore . OnBotCommand ( Bot , steamID , message , args ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-10 22:33:07 +01:00
return ! string . IsNullOrEmpty ( pluginsResponse ) ? pluginsResponse : ResponseUnknown ( steamID ) ;
2018-09-15 22:34:32 +02:00
}
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 ) ;
2018-11-24 03:20:04 +01:00
case "ADDLICENSE" when args . Length > 2 :
return await ResponseAddLicense ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "ADDLICENSE" :
return await ResponseAddLicense ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2018-11-03 19:42:40 +02:00
case "BALANCE" :
return await ResponseWalletBalance ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2019-02-26 19:59:04 +01:00
case "BGR" :
return await ResponseBackgroundGamesRedeemer ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "BL" :
return await ResponseBlacklist ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "BLADD" when args . Length > 2 :
return await ResponseBlacklistAdd ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "BLADD" :
2019-07-25 17:09:20 +02:00
return ResponseBlacklistAdd ( steamID , args [ 1 ] ) ;
2018-11-24 03:20:04 +01:00
case "BLRM" when args . Length > 2 :
return await ResponseBlacklistRemove ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "BLRM" :
2019-07-25 17:09:20 +02:00
return ResponseBlacklistRemove ( steamID , args [ 1 ] ) ;
2018-09-15 22:34:32 +02:00
case "FARM" :
return await ResponseFarm ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "INPUT" when args . Length > 3 :
return await ResponseInput ( steamID , args [ 1 ] , args [ 2 ] , Utilities . GetArgsAsText ( message , 3 ) ) . ConfigureAwait ( false ) ;
case "INPUT" when args . Length > 2 :
return ResponseInput ( steamID , args [ 1 ] , args [ 2 ] ) ;
2018-09-15 22:34:32 +02:00
case "IB" :
return await ResponseIdleBlacklist ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "IBADD" when args . Length > 2 :
return await ResponseIdleBlacklistAdd ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "IBADD" :
2019-07-25 17:09:20 +02:00
return ResponseIdleBlacklistAdd ( steamID , args [ 1 ] ) ;
2018-11-24 03:20:04 +01:00
case "IBRM" when args . Length > 2 :
return await ResponseIdleBlacklistRemove ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "IBRM" :
2019-07-25 17:09:20 +02:00
return ResponseIdleBlacklistRemove ( steamID , args [ 1 ] ) ;
2018-09-15 22:34:32 +02:00
case "IQ" :
return await ResponseIdleQueue ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "IQADD" when args . Length > 2 :
return await ResponseIdleQueueAdd ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "IQADD" :
2019-07-25 17:09:20 +02:00
return ResponseIdleQueueAdd ( steamID , args [ 1 ] ) ;
2018-11-24 03:20:04 +01:00
case "IQRM" when args . Length > 2 :
return await ResponseIdleQueueRemove ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "IQRM" :
2019-07-25 17:09:20 +02:00
return ResponseIdleQueueRemove ( steamID , args [ 1 ] ) ;
2018-11-14 21:51:21 +02:00
case "LEVEL" :
return await ResponseLevel ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "LOOT" :
return await ResponseLoot ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "LOOT^" when args . Length > 3 :
return await ResponseAdvancedLoot ( steamID , args [ 1 ] , args [ 2 ] , Utilities . GetArgsAsText ( message , 3 ) ) . ConfigureAwait ( false ) ;
case "LOOT^" when args . Length > 2 :
return await ResponseAdvancedLoot ( steamID , args [ 1 ] , args [ 2 ] ) . ConfigureAwait ( false ) ;
case "LOOT@" when args . Length > 2 :
return await ResponseLootByRealAppIDs ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "LOOT@" :
return await ResponseLootByRealAppIDs ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2019-12-26 18:57:02 +01:00
case "LOOT%" when args . Length > 2 :
return await ResponseLootByRealAppIDs ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) , true ) . ConfigureAwait ( false ) ;
case "LOOT%" :
return await ResponseLootByRealAppIDs ( steamID , args [ 1 ] , true ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "NICKNAME" when args . Length > 2 :
return await ResponseNickname ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( message , 2 ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "NICKNAME" :
return ResponseNickname ( steamID , args [ 1 ] ) ;
case "OA" :
return await ResponseOwns ( steamID , SharedInfo . ASF , Utilities . GetArgsAsText ( message , 1 ) ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "OWNS" when args . Length > 2 :
return await ResponseOwns ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( message , 2 ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "OWNS" :
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 ) ;
2018-11-24 03:20:04 +01:00
case "PAUSE&" when args . Length > 2 :
return await ResponsePause ( steamID , args [ 1 ] , true , Utilities . GetArgsAsText ( message , 2 ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "PAUSE&" :
return await ResponsePause ( steamID , true , args [ 1 ] ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "PLAY" when args . Length > 2 :
return await ResponsePlay ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( message , 2 ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "PLAY" :
return await ResponsePlay ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "PRIVACY" when args . Length > 2 :
return await ResponsePrivacy ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "PRIVACY" :
return await ResponsePrivacy ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "R" when args . Length > 2 :
case "REDEEM" when args . Length > 2 :
return await ResponseRedeem ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( args , 2 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "R" :
case "REDEEM" :
return await ResponseRedeem ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "R^" when args . Length > 3 :
case "REDEEM^" when args . Length > 3 :
return await ResponseAdvancedRedeem ( steamID , args [ 1 ] , args [ 2 ] , Utilities . GetArgsAsText ( args , 3 , "," ) ) . ConfigureAwait ( false ) ;
case "R^" when args . Length > 2 :
case "REDEEM^" when args . Length > 2 :
return await ResponseAdvancedRedeem ( steamID , args [ 1 ] , args [ 2 ] ) . ConfigureAwait ( false ) ;
2019-06-23 17:30:34 +02:00
case "RESET" :
return await ResponseReset ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
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 ) ;
2018-11-24 03:20:04 +01:00
case "TRANSFER" when args . Length > 2 :
return await ResponseTransfer ( steamID , args [ 1 ] , Utilities . GetArgsAsText ( message , 2 ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "TRANSFER" :
2018-10-06 02:24:04 +02:00
return await ResponseTransfer ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2018-11-24 03:20:04 +01:00
case "TRANSFER^" when args . Length > 4 :
return await ResponseAdvancedTransfer ( steamID , args [ 1 ] , args [ 2 ] , args [ 3 ] , Utilities . GetArgsAsText ( message , 4 ) ) . ConfigureAwait ( false ) ;
case "TRANSFER^" when args . Length > 3 :
return await ResponseAdvancedTransfer ( steamID , args [ 1 ] , args [ 2 ] , args [ 3 ] ) . ConfigureAwait ( false ) ;
case "TRANSFER@" when args . Length > 3 :
return await ResponseTransferByRealAppIDs ( steamID , args [ 1 ] , args [ 2 ] , Utilities . GetArgsAsText ( message , 3 ) ) . ConfigureAwait ( false ) ;
case "TRANSFER@" when args . Length > 2 :
return await ResponseTransferByRealAppIDs ( steamID , args [ 1 ] , args [ 2 ] ) . ConfigureAwait ( false ) ;
2019-12-26 19:36:53 +01:00
case "TRANSFER%" when args . Length > 3 :
return await ResponseTransferByRealAppIDs ( steamID , args [ 1 ] , args [ 2 ] , Utilities . GetArgsAsText ( message , 3 ) , true ) . ConfigureAwait ( false ) ;
case "TRANSFER%" when args . Length > 2 :
return await ResponseTransferByRealAppIDs ( steamID , args [ 1 ] , args [ 2 ] , true ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
case "UNPACK" :
return await ResponseUnpackBoosters ( steamID , Utilities . GetArgsAsText ( args , 1 , "," ) ) . ConfigureAwait ( false ) ;
default :
2020-08-22 21:41:01 +02:00
string? pluginsResponse = await PluginsCore . OnBotCommand ( Bot , steamID , message , args ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-10 22:33:07 +01:00
return ! string . IsNullOrEmpty ( pluginsResponse ) ? pluginsResponse : ResponseUnknown ( steamID ) ;
2018-09-15 22:34:32 +02:00
}
}
}
2019-02-10 06:35:20 +01:00
internal async Task HandleMessage ( ulong steamID , string message ) {
2019-07-18 15:57:48 +02:00
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( message ) ) {
2020-08-22 21:41:01 +02:00
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( message ) ) ;
2019-02-10 06:35:20 +01:00
}
2020-08-23 20:45:24 +02:00
string? commandPrefix = ASF . GlobalConfig ! = null ? ASF . GlobalConfig . CommandPrefix : GlobalConfig . DefaultCommandPrefix ;
2020-08-22 21:41:01 +02:00
if ( ! string . IsNullOrEmpty ( commandPrefix ) ) {
2020-08-23 20:45:24 +02:00
if ( ! message . StartsWith ( commandPrefix ! , StringComparison . OrdinalIgnoreCase ) ) {
2020-08-22 21:41:01 +02:00
string? pluginsResponse = await PluginsCore . OnBotMessage ( Bot , steamID , message ) . ConfigureAwait ( false ) ;
2019-02-10 06:35:20 +01:00
if ( ! string . IsNullOrEmpty ( pluginsResponse ) ) {
2020-08-22 21:41:01 +02:00
if ( ! await Bot . SendMessage ( steamID , pluginsResponse ! ) . ConfigureAwait ( false ) ) {
2019-05-19 15:38:06 +02:00
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendMessage ) ) ) ;
Bot . ArchiLogger . LogGenericDebug ( string . Format ( Strings . Content , pluginsResponse ) ) ;
}
2019-02-10 06:35:20 +01:00
}
return ;
}
2020-08-23 20:45:24 +02:00
message = message . Substring ( commandPrefix ! . Length ) ;
2019-02-10 06:35:20 +01:00
}
2020-08-22 21:41:01 +02:00
Task < string? > responseTask = Response ( steamID , message ) ;
2019-02-24 17:11:47 +01:00
2019-02-10 06:35:20 +01:00
bool feedback = Bot . HasPermission ( steamID , BotConfig . EPermission . FamilySharing ) ;
2019-02-24 18:40:27 +01:00
if ( feedback & & ! responseTask . IsCompleted ) {
2019-05-19 15:38:06 +02:00
if ( ! await Bot . SendTypingMessage ( steamID ) . ConfigureAwait ( false ) ) {
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendTypingMessage ) ) ) ;
}
2019-02-24 17:11:47 +01:00
while ( ! responseTask . IsCompleted & & ( await Task . WhenAny ( responseTask , Task . Delay ( SteamTypingStatusDelay ) ) . ConfigureAwait ( false ) ! = responseTask ) ) {
2019-05-19 15:38:06 +02:00
if ( ! await Bot . SendTypingMessage ( steamID ) . ConfigureAwait ( false ) ) {
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendTypingMessage ) ) ) ;
}
2019-02-24 17:11:47 +01:00
}
2019-02-10 06:35:20 +01:00
}
2020-08-22 21:41:01 +02:00
string? response = await responseTask . ConfigureAwait ( false ) ;
2019-02-10 06:35:20 +01:00
if ( string . IsNullOrEmpty ( response ) ) {
if ( ! feedback ) {
return ;
}
Bot . ArchiLogger . LogNullError ( nameof ( response ) ) ;
response = FormatBotResponse ( Strings . UnknownCommand ) ;
}
2020-08-22 21:41:01 +02:00
if ( ! await Bot . SendMessage ( steamID , response ! ) . ConfigureAwait ( false ) ) {
2019-05-19 15:38:06 +02:00
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendMessage ) ) ) ;
Bot . ArchiLogger . LogGenericDebug ( string . Format ( Strings . Content , response ) ) ;
}
2019-02-10 06:35:20 +01:00
}
internal async Task HandleMessage ( ulong chatGroupID , ulong chatID , ulong steamID , string message ) {
2019-07-18 15:57:48 +02:00
if ( ( chatGroupID = = 0 ) | | ( chatID = = 0 ) | | ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( message ) ) {
2020-08-22 21:41:01 +02:00
throw new ArgumentNullException ( nameof ( chatGroupID ) + " || " + nameof ( chatID ) + " || " + nameof ( steamID ) + " || " + nameof ( message ) ) ;
2019-02-10 06:35:20 +01:00
}
2020-08-23 20:45:24 +02:00
string? commandPrefix = ASF . GlobalConfig ! = null ? ASF . GlobalConfig . CommandPrefix : GlobalConfig . DefaultCommandPrefix ;
2020-08-22 21:41:01 +02:00
if ( ! string . IsNullOrEmpty ( commandPrefix ) ) {
2020-08-23 20:45:24 +02:00
if ( ! message . StartsWith ( commandPrefix ! , StringComparison . OrdinalIgnoreCase ) ) {
2020-08-22 21:41:01 +02:00
string? pluginsResponse = await PluginsCore . OnBotMessage ( Bot , steamID , message ) . ConfigureAwait ( false ) ;
2019-02-10 06:35:20 +01:00
if ( ! string . IsNullOrEmpty ( pluginsResponse ) ) {
2020-08-22 21:41:01 +02:00
if ( ! await Bot . SendMessage ( chatGroupID , chatID , pluginsResponse ! ) . ConfigureAwait ( false ) ) {
2019-05-19 15:38:06 +02:00
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendMessage ) ) ) ;
Bot . ArchiLogger . LogGenericDebug ( string . Format ( Strings . Content , pluginsResponse ) ) ;
}
2019-02-10 06:35:20 +01:00
}
return ;
}
2020-08-23 20:45:24 +02:00
message = message . Substring ( commandPrefix ! . Length ) ;
2019-02-10 06:35:20 +01:00
}
2020-08-22 21:41:01 +02:00
Task < string? > responseTask = Response ( steamID , message ) ;
2019-02-24 17:11:47 +01:00
2019-02-10 06:35:20 +01:00
bool feedback = Bot . HasPermission ( steamID , BotConfig . EPermission . FamilySharing ) ;
2019-02-24 18:40:27 +01:00
if ( feedback & & ! responseTask . IsCompleted ) {
2019-02-24 17:13:39 +01:00
string pleaseWaitMessage = FormatBotResponse ( Strings . PleaseWait ) ;
2019-05-19 15:38:06 +02:00
if ( ! await Bot . SendMessage ( chatGroupID , chatID , pleaseWaitMessage ) . ConfigureAwait ( false ) ) {
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendMessage ) ) ) ;
}
2019-02-24 17:11:47 +01:00
while ( ! responseTask . IsCompleted & & ( await Task . WhenAny ( responseTask , Task . Delay ( SteamTypingStatusDelay ) ) . ConfigureAwait ( false ) ! = responseTask ) ) {
2019-05-19 15:38:06 +02:00
if ( ! await Bot . SendMessage ( chatGroupID , chatID , pleaseWaitMessage ) . ConfigureAwait ( false ) ) {
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendMessage ) ) ) ;
}
2019-02-24 17:11:47 +01:00
}
2019-02-10 06:35:20 +01:00
}
2020-08-22 21:41:01 +02:00
string? response = await responseTask . ConfigureAwait ( false ) ;
2019-02-10 06:35:20 +01:00
if ( string . IsNullOrEmpty ( response ) ) {
if ( ! feedback ) {
return ;
}
Bot . ArchiLogger . LogNullError ( nameof ( response ) ) ;
response = FormatBotResponse ( Strings . UnknownCommand ) ;
}
2020-08-22 21:41:01 +02:00
if ( ! await Bot . SendMessage ( chatGroupID , chatID , response ! ) . ConfigureAwait ( false ) ) {
2019-05-19 15:38:06 +02:00
Bot . ArchiLogger . LogGenericWarning ( string . Format ( Strings . WarningFailedWithError , nameof ( Bot . SendMessage ) ) ) ;
Bot . ArchiLogger . LogGenericDebug ( string . Format ( Strings . Content , response ) ) ;
}
2019-02-10 06:35:20 +01:00
}
2019-01-10 22:33:07 +01:00
internal void OnNewLicenseList ( ) {
lock ( CachedGamesOwned ) {
CachedGamesOwned . Clear ( ) ;
CachedGamesOwned . TrimExcess ( ) ;
2018-09-15 22:34:32 +02:00
}
}
2020-08-22 21:41:01 +02:00
private async Task < Dictionary < uint , string > ? > FetchGamesOwned ( bool cachedOnly = false ) {
2019-07-02 15:06:01 +02:00
lock ( CachedGamesOwned ) {
if ( CachedGamesOwned . Count > 0 ) {
return new Dictionary < uint , string > ( CachedGamesOwned ) ;
}
}
2019-07-02 22:04:28 +02:00
if ( cachedOnly ) {
return null ;
}
2019-07-02 15:06:01 +02:00
bool? hasValidApiKey = await Bot . ArchiWebHandler . HasValidApiKey ( ) . ConfigureAwait ( false ) ;
2020-08-22 21:41:01 +02:00
Dictionary < uint , string > ? gamesOwned = hasValidApiKey . GetValueOrDefault ( ) ? await Bot . ArchiWebHandler . GetOwnedGames ( Bot . SteamID ) . ConfigureAwait ( false ) : await Bot . ArchiWebHandler . GetMyOwnedGames ( ) . ConfigureAwait ( false ) ;
2019-07-02 15:06:01 +02:00
if ( ( gamesOwned ! = null ) & & ( gamesOwned . Count > 0 ) ) {
lock ( CachedGamesOwned ) {
if ( CachedGamesOwned . Count = = 0 ) {
foreach ( ( uint appID , string gameName ) in gamesOwned ) {
CachedGamesOwned [ appID ] = gameName ;
}
CachedGamesOwned . TrimExcess ( ) ;
}
}
}
return gamesOwned ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > Response2FA ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2020-08-22 21:41:01 +02:00
( bool success , string? token , string message ) = await Bot . Actions . GenerateTwoFactorAuthenticationToken ( ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2020-08-22 21:41:01 +02:00
return FormatBotResponse ( success & & ! string . IsNullOrEmpty ( token ) ? string . Format ( Strings . BotAuthenticatorToken , token ) : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > Response2FA ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . Response2FA ( steamID ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > Response2FAConfirm ( ulong steamID , bool confirm ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
if ( ! Bot . HasMobileAuthenticator ) {
return FormatBotResponse ( Strings . BotNoASFAuthenticator ) ;
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = await Bot . Actions . HandleTwoFactorAuthenticationConfirmations ( confirm ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > Response2FAConfirm ( ulong steamID , string botNames , bool confirm ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . Response2FAConfirm ( steamID , confirm ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseAddLicense ( ulong steamID , string query ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( query ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( query ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
StringBuilder response = new StringBuilder ( ) ;
2019-07-04 15:44:53 +02:00
string [ ] entries = query . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
2018-12-15 00:27:15 +01:00
2019-07-04 15:44:53 +02:00
foreach ( string entry in entries ) {
uint gameID ;
string type ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
int index = entry . IndexOf ( '/' ) ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
if ( ( index > 0 ) & & ( entry . Length > index + 1 ) ) {
if ( ! uint . TryParse ( entry . Substring ( index + 1 ) , out gameID ) | | ( gameID = = 0 ) ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( gameID ) ) ) ) ;
2018-12-15 00:27:15 +01:00
2019-07-04 15:44:53 +02:00
continue ;
}
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
type = entry . Substring ( 0 , index ) ;
} else if ( uint . TryParse ( entry , out gameID ) & & ( gameID > 0 ) ) {
type = "SUB" ;
} else {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( gameID ) ) ) ) ;
2018-12-15 00:27:15 +01:00
2019-07-04 15:44:53 +02:00
continue ;
2018-09-15 22:34:32 +02:00
}
2019-07-04 15:44:53 +02:00
switch ( type . ToUpperInvariant ( ) ) {
case "A" :
case "APP" :
SteamApps . FreeLicenseCallback callback ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
try {
2020-06-15 16:55:57 +02:00
callback = await Bot . SteamApps . RequestFreeLicense ( gameID ) . ToLongRunningTask ( ) . ConfigureAwait ( false ) ;
2019-07-04 15:44:53 +02:00
} catch ( Exception e ) {
Bot . ArchiLogger . LogGenericWarningException ( e ) ;
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotAddLicense , "app/" + gameID , EResult . Timeout ) ) ) ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
break ;
}
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
response . AppendLine ( FormatBotResponse ( ( callback . GrantedApps . Count > 0 ) | | ( callback . GrantedPackages . Count > 0 ) ? string . Format ( Strings . BotAddLicenseWithItems , "app/" + gameID , callback . Result , string . Join ( ", " , callback . GrantedApps . Select ( appID = > "app/" + appID ) . Union ( callback . GrantedPackages . Select ( subID = > "sub/" + subID ) ) ) ) : string . Format ( Strings . BotAddLicense , "app/" + gameID , callback . Result ) ) ) ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
break ;
default :
if ( ! await Bot . ArchiWebHandler . AddFreeLicense ( gameID ) . ConfigureAwait ( false ) ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotAddLicense , "sub/" + gameID , EResult . Fail ) ) ) ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
continue ;
}
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotAddLicenseWithItems , gameID , EResult . OK , "sub/" + gameID ) ) ) ;
2018-09-15 22:34:32 +02:00
2019-07-04 15:44:53 +02:00
break ;
2018-09-15 22:34:32 +02:00
}
}
2019-07-04 15:44:53 +02:00
return response . Length > 0 ? response . ToString ( ) : null ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseAddLicense ( ulong steamID , string botNames , string query ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( query ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( query ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseAddLicense ( steamID , query ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseAdvancedLoot ( ulong steamID , string targetAppID , string targetContextID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetAppID ) | | string . IsNullOrEmpty ( targetContextID ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetAppID ) + " || " + nameof ( targetContextID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
if ( ! uint . TryParse ( targetAppID , out uint appID ) | | ( appID = = 0 ) ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( appID ) ) ) ;
}
2019-02-22 04:42:36 +01:00
if ( ! ulong . TryParse ( targetContextID , out ulong contextID ) | | ( contextID = = 0 ) ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( contextID ) ) ) ;
}
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
( bool success , string message ) = await Bot . Actions . SendInventory ( appID , contextID ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseAdvancedLoot ( ulong steamID , string botNames , string appID , string contextID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( appID ) | | string . IsNullOrEmpty ( contextID ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( appID ) + " || " + nameof ( contextID ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseAdvancedLoot ( steamID , appID , contextID ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseAdvancedRedeem ( ulong steamID , string options , string keys ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( options ) | | string . IsNullOrEmpty ( keys ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( options ) + " || " + nameof ( keys ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ) {
2018-09-15 22:34:32 +02:00
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 ( ) ) {
2019-08-05 15:41:37 +03:00
case "FAWK" :
case "FORCEASSUMEWALLETKEY" :
redeemFlags | = ERedeemFlags . ForceAssumeWalletKeyOnBadActivationCode ;
break ;
2018-09-15 22:34:32 +02:00
case "FD" :
2019-07-03 01:03:10 +02:00
case "FORCEDISTRIBUTING" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . ForceDistributing ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case "FF" :
2019-07-03 01:03:10 +02:00
case "FORCEFORWARDING" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . ForceForwarding ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case "FKMG" :
2019-07-03 01:03:10 +02:00
case "FORCEKEEPMISSINGGAMES" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . ForceKeepMissingGames ;
2018-12-15 00:27:15 +01:00
2019-08-05 15:41:37 +03:00
break ;
case "SAWK" :
case "SKIPASSUMEWALLETKEY" :
redeemFlags | = ERedeemFlags . SkipAssumeWalletKeyOnBadActivationCode ;
2018-09-15 22:34:32 +02:00
break ;
case "SD" :
2019-07-03 01:03:10 +02:00
case "SKIPDISTRIBUTING" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . SkipDistributing ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case "SF" :
2019-07-03 01:03:10 +02:00
case "SKIPFORWARDING" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . SkipForwarding ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case "SI" :
2019-07-03 01:03:10 +02:00
case "SKIPINITIAL" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . SkipInitial ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case "SKMG" :
2019-07-03 01:03:10 +02:00
case "SKIPKEEPMISSINGGAMES" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . SkipKeepMissingGames ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case "V" :
2019-07-03 01:03:10 +02:00
case "VALIDATE" :
2018-09-15 22:34:32 +02:00
redeemFlags | = ERedeemFlags . Validate ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
default :
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , flag ) ) ;
}
}
return await ResponseRedeem ( steamID , keys , redeemFlags ) . ConfigureAwait ( false ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseAdvancedRedeem ( ulong steamID , string botNames , string options , string keys ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( options ) | | string . IsNullOrEmpty ( keys ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( options ) + " || " + nameof ( keys ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseAdvancedRedeem ( steamID , options , keys ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseAdvancedTransfer ( ulong steamID , uint appID , ulong contextID , Bot targetBot ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | ( appID = = 0 ) | | ( contextID = = 0 ) | | ( targetBot = = null ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( appID ) + " || " + nameof ( contextID ) + " || " + nameof ( targetBot ) ) ;
2018-09-24 20:28:48 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-24 20:28:48 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
if ( ! targetBot . IsConnectedAndLoggedOn ) {
2018-10-16 00:13:56 +03:00
return FormatBotResponse ( Strings . TargetBotNotConnected ) ;
2018-09-24 20:28:48 +02:00
}
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
( bool success , string message ) = await Bot . Actions . SendInventory ( appID , contextID , targetBot . SteamID ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-29 22:20:35 +02:00
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseAdvancedTransfer ( ulong steamID , string targetAppID , string targetContextID , string botNameTo ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetAppID ) | | string . IsNullOrEmpty ( targetContextID ) | | string . IsNullOrEmpty ( botNameTo ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetAppID ) + " || " + nameof ( targetContextID ) + " || " + nameof ( botNameTo ) ) ;
2018-09-29 22:20:35 +02:00
}
2020-08-22 21:41:01 +02:00
Bot ? targetBot = Bot . GetBot ( botNameTo ) ;
2019-02-25 23:49:20 +01:00
if ( targetBot = = null ) {
2018-09-29 22:20:35 +02:00
return ASF . IsOwner ( steamID ) ? FormatBotResponse ( string . Format ( Strings . BotNotFound , botNameTo ) ) : null ;
2018-09-24 20:28:48 +02:00
}
2018-09-30 22:03:45 +02:00
if ( ! uint . TryParse ( targetAppID , out uint appID ) | | ( appID = = 0 ) ) {
2018-09-24 20:28:48 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( appID ) ) ) ;
}
2019-02-22 04:42:36 +01:00
if ( ! ulong . TryParse ( targetContextID , out ulong contextID ) | | ( contextID = = 0 ) ) {
2018-09-24 20:28:48 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( contextID ) ) ) ;
}
2018-09-29 22:20:35 +02:00
return await ResponseAdvancedTransfer ( steamID , appID , contextID , targetBot ) . ConfigureAwait ( false ) ;
2018-09-24 20:28:48 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseAdvancedTransfer ( ulong steamID , string botNames , string targetAppID , string targetContextID , string botNameTo ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetAppID ) | | string . IsNullOrEmpty ( targetContextID ) | | string . IsNullOrEmpty ( botNameTo ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetAppID ) + " || " + nameof ( targetContextID ) + " || " + nameof ( botNameTo ) ) ;
2018-09-24 20:28:48 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-24 20:28:48 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2018-09-30 22:03:45 +02:00
if ( ! uint . TryParse ( targetAppID , out uint appID ) | | ( appID = = 0 ) ) {
2018-09-29 22:20:35 +02:00
return FormatStaticResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( appID ) ) ) ;
}
2019-02-22 04:42:36 +01:00
if ( ! ulong . TryParse ( targetContextID , out ulong contextID ) | | ( contextID = = 0 ) ) {
2018-09-29 22:20:35 +02:00
return FormatStaticResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( contextID ) ) ) ;
}
2020-08-22 21:41:01 +02:00
Bot ? targetBot = Bot . GetBot ( botNameTo ) ;
2019-02-25 23:49:20 +01:00
if ( targetBot = = null ) {
2018-09-29 22:20:35 +02:00
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNameTo ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseAdvancedTransfer ( steamID , appID , contextID , targetBot ) ) ) . ConfigureAwait ( false ) ;
2018-09-24 20:28:48 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-24 20:28:48 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseBackgroundGamesRedeemer ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2019-02-26 19:59:04 +01:00
}
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
return null ;
}
uint count = Bot . GamesToRedeemInBackgroundCount ;
return FormatBotResponse ( string . Format ( Strings . BotGamesToRedeemInBackgroundCount , count ) ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseBackgroundGamesRedeemer ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2019-02-26 19:59:04 +01:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2019-02-26 19:59:04 +01:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseBackgroundGamesRedeemer ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2019-02-26 19:59:04 +01:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2019-02-26 19:59:04 +01:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseBlacklist ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
IReadOnlyCollection < ulong > blacklist = Bot . BotDatabase . GetBlacklistedFromTradesSteamIDs ( ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( blacklist . Count > 0 ? string . Join ( ", " , blacklist ) : string . Format ( Strings . ErrorIsEmpty , nameof ( blacklist ) ) ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseBlacklist ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseBlacklist ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseBlacklistAdd ( ulong steamID , string targetSteamIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetSteamIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetSteamIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
string [ ] targets = targetSteamIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( targets . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( targets ) ) ) ;
}
HashSet < ulong > targetIDs = new HashSet < ulong > ( ) ;
foreach ( string target in targets ) {
2019-04-03 16:41:47 +02:00
if ( ! ulong . TryParse ( target , out ulong targetID ) | | ( targetID = = 0 ) | | ! new SteamID ( targetID ) . IsIndividualAccount ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorParsingObject , nameof ( targetID ) ) ) ;
}
targetIDs . Add ( targetID ) ;
}
2019-07-25 17:09:20 +02:00
Bot . BotDatabase . AddBlacklistedFromTradesSteamIDs ( targetIDs ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseBlacklistAdd ( ulong steamID , string botNames , string targetSteamIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetSteamIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetSteamIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseBlacklistAdd ( steamID , targetSteamIDs ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseBlacklistRemove ( ulong steamID , string targetSteamIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetSteamIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetSteamIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
string [ ] targets = targetSteamIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( targets . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( targets ) ) ) ;
}
HashSet < ulong > targetIDs = new HashSet < ulong > ( ) ;
foreach ( string target in targets ) {
2019-04-03 16:41:47 +02:00
if ( ! ulong . TryParse ( target , out ulong targetID ) | | ( targetID = = 0 ) | | ! new SteamID ( targetID ) . IsIndividualAccount ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorParsingObject , nameof ( targetID ) ) ) ;
}
targetIDs . Add ( targetID ) ;
}
2019-07-25 17:09:20 +02:00
Bot . BotDatabase . RemoveBlacklistedFromTradesSteamIDs ( targetIDs ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseBlacklistRemove ( ulong steamID , string botNames , string targetSteamIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetSteamIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetSteamIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseBlacklistRemove ( steamID , targetSteamIDs ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private static string? ResponseExit ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
if ( ! ASF . IsOwner ( steamID ) ) {
return null ;
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = Actions . Exit ( ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatStaticResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseFarm ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
if ( Bot . CardsFarmer . NowFarming ) {
await Bot . CardsFarmer . StopFarming ( ) . ConfigureAwait ( false ) ;
}
Utilities . InBackground ( Bot . CardsFarmer . StartFarming ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseFarm ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseFarm ( steamID ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseHelp ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
return Bot . HasPermission ( steamID , BotConfig . EPermission . FamilySharing ) ? FormatBotResponse ( SharedInfo . ProjectURL + "/wiki/Commands" ) : null ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private string? ResponseIdleBlacklist ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
IReadOnlyCollection < uint > idleBlacklist = Bot . BotDatabase . GetIdlingBlacklistedAppIDs ( ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( idleBlacklist . Count > 0 ? string . Join ( ", " , idleBlacklist ) : string . Format ( Strings . ErrorIsEmpty , nameof ( idleBlacklist ) ) ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseIdleBlacklist ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseIdleBlacklist ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseIdleBlacklistAdd ( ulong steamID , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
string [ ] targets = targetAppIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( targets . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( targets ) ) ) ;
}
HashSet < uint > appIDs = new HashSet < uint > ( ) ;
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 ) ;
}
2019-07-25 17:09:20 +02:00
Bot . BotDatabase . AddIdlingBlacklistedAppIDs ( appIDs ) ;
2018-12-15 00:27:15 +01:00
2020-04-11 18:56:12 +02:00
if ( Bot . CardsFarmer . NowFarming & & Bot . CardsFarmer . GamesToFarmReadOnly . Any ( game = > appIDs . Contains ( game . AppID ) ) ) {
Utilities . InBackground (
async ( ) = > {
await Bot . CardsFarmer . StopFarming ( ) . ConfigureAwait ( false ) ;
await Bot . CardsFarmer . StartFarming ( ) . ConfigureAwait ( false ) ;
}
) ;
}
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseIdleBlacklistAdd ( ulong steamID , string botNames , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseIdleBlacklistAdd ( steamID , targetAppIDs ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseIdleBlacklistRemove ( ulong steamID , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
string [ ] targets = targetAppIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( targets . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( targets ) ) ) ;
}
HashSet < uint > appIDs = new HashSet < uint > ( ) ;
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 ) ;
}
2019-07-25 17:09:20 +02:00
Bot . BotDatabase . RemoveIdlingBlacklistedAppIDs ( appIDs ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseIdleBlacklistRemove ( ulong steamID , string botNames , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseIdleBlacklistRemove ( steamID , targetAppIDs ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseIdleQueue ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
IReadOnlyCollection < uint > idleQueue = Bot . BotDatabase . GetIdlingPriorityAppIDs ( ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( idleQueue . Count > 0 ? string . Join ( ", " , idleQueue ) : string . Format ( Strings . ErrorIsEmpty , nameof ( idleQueue ) ) ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseIdleQueue ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseIdleQueue ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseIdleQueueAdd ( ulong steamID , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
string [ ] targets = targetAppIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( targets . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( targets ) ) ) ;
}
HashSet < uint > appIDs = new HashSet < uint > ( ) ;
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 ) ;
}
2019-07-25 17:09:20 +02:00
Bot . BotDatabase . AddIdlingPriorityAppIDs ( appIDs ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseIdleQueueAdd ( ulong steamID , string botNames , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseIdleQueueAdd ( steamID , targetAppIDs ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseIdleQueueRemove ( ulong steamID , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
string [ ] targets = targetAppIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( targets . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( targets ) ) ) ;
}
HashSet < uint > appIDs = new HashSet < uint > ( ) ;
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 ) ;
}
2019-07-25 17:09:20 +02:00
Bot . BotDatabase . RemoveIdlingPriorityAppIDs ( appIDs ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseIdleQueueRemove ( ulong steamID , string botNames , string targetAppIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetAppIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetAppIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseIdleQueueRemove ( steamID , targetAppIDs ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseInput ( ulong steamID , string propertyName , string inputValue ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( propertyName ) | | string . IsNullOrEmpty ( inputValue ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( propertyName ) + " || " + nameof ( inputValue ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2020-08-22 21:41:01 +02:00
bool headless = ASF . GlobalConfig ? . Headless ? ? GlobalConfig . DefaultHeadless ;
if ( ! headless ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . ErrorFunctionOnlyInHeadlessMode ) ;
}
2020-06-03 19:26:59 +02:00
if ( ! Enum . TryParse ( propertyName , true , out ASF . EUserInputType inputType ) | | ( inputType = = ASF . EUserInputType . None ) | | ! Enum . IsDefined ( typeof ( ASF . EUserInputType ) , inputType ) ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( inputType ) ) ) ;
}
2020-07-01 15:22:59 +02:00
bool result = Bot . SetUserInput ( inputType , inputValue ) ;
2018-12-15 00:27:15 +01:00
2020-07-01 15:22:59 +02:00
return FormatBotResponse ( result ? Strings . Done : Strings . WarningFailed ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseInput ( ulong steamID , string botNames , string propertyName , string inputValue ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( propertyName ) | | string . IsNullOrEmpty ( inputValue ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( propertyName ) + " || " + nameof ( inputValue ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseInput ( steamID , propertyName , inputValue ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-11-14 21:51:21 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseLevel ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-11-14 21:51:21 +02:00
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-11-14 21:51:21 +02:00
return null ;
}
uint? level = await Bot . ArchiHandler . GetLevel ( ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2018-12-03 01:24:33 +01:00
return FormatBotResponse ( level . HasValue ? string . Format ( Strings . BotLevel , level . Value ) : Strings . WarningFailed ) ;
2018-11-14 21:51:21 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseLevel ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-11-14 21:51:21 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-11-14 21:51:21 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseLevel ( steamID ) ) ) . ConfigureAwait ( false ) ;
2018-11-14 21:51:21 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseLoot ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
2018-12-04 02:05:09 +01:00
if ( Bot . BotConfig . LootableTypes . Count = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( Bot . BotConfig . LootableTypes ) ) ) ;
}
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
( bool success , string message ) = await Bot . Actions . SendInventory ( filterFunction : item = > Bot . BotConfig . LootableTypes . Contains ( item . Type ) ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseLoot ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseLoot ( steamID ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseLootByRealAppIDs ( ulong steamID , string realAppIDsText , bool exclude = false ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( realAppIDsText ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( realAppIDsText ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
2018-12-04 02:05:09 +01:00
if ( Bot . BotConfig . LootableTypes . Count = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( Bot . BotConfig . LootableTypes ) ) ) ;
}
2018-09-15 22:34:32 +02:00
string [ ] appIDTexts = realAppIDsText . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( appIDTexts . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( appIDTexts ) ) ) ;
}
HashSet < uint > realAppIDs = new HashSet < uint > ( ) ;
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 ) ;
}
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
( bool success , string message ) = await Bot . Actions . SendInventory ( filterFunction : item = > Bot . BotConfig . LootableTypes . Contains ( item . Type ) & & ( exclude ^ realAppIDs . Contains ( item . RealAppID ) ) ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseLootByRealAppIDs ( ulong steamID , string botNames , string realAppIDsText , bool exclude = false ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( realAppIDsText ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( realAppIDsText ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseLootByRealAppIDs ( steamID , realAppIDsText , exclude ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseNickname ( ulong steamID , string nickname ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( nickname ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( nickname ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
Bot . SteamFriends . SetPersonaName ( nickname ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . Done ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseNickname ( ulong steamID , string botNames , string nickname ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( nickname ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( nickname ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseNickname ( steamID , nickname ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < ( string? Response , Dictionary < string , string > ? OwnedGames ) > ResponseOwns ( ulong steamID , string query ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( query ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( query ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ) {
2018-09-15 22:34:32 +02:00
return ( null , null ) ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return ( FormatBotResponse ( Strings . BotNotConnected ) , null ) ;
}
2020-08-22 21:41:01 +02:00
Dictionary < uint , string > ? gamesOwned = await FetchGamesOwned ( true ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
StringBuilder response = new StringBuilder ( ) ;
2019-07-02 21:17:27 +02:00
Dictionary < string , string > result = new Dictionary < string , string > ( ) ;
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
string [ ] entries = query . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
2019-04-05 15:12:54 +02:00
2019-07-02 15:06:01 +02:00
foreach ( string entry in entries ) {
string game ;
string type ;
2018-12-15 00:27:15 +01:00
2019-07-02 15:06:01 +02:00
int index = entry . IndexOf ( '/' ) ;
if ( ( index > 0 ) & & ( entry . Length > index + 1 ) ) {
game = entry . Substring ( index + 1 ) ;
type = entry . Substring ( 0 , index ) ;
} else if ( uint . TryParse ( entry , out uint appID ) & & ( appID > 0 ) ) {
game = entry ;
2019-07-03 00:54:12 +02:00
type = "APP" ;
2019-07-02 15:06:01 +02:00
} else {
game = entry ;
2019-07-03 00:54:12 +02:00
type = "NAME" ;
2018-09-15 22:34:32 +02:00
}
2019-07-03 00:54:12 +02:00
switch ( type . ToUpperInvariant ( ) ) {
case "A" when uint . TryParse ( game , out uint appID ) & & ( appID > 0 ) :
case "APP" when uint . TryParse ( game , out appID ) & & ( appID > 0 ) :
2020-08-22 21:41:01 +02:00
HashSet < uint > ? packageIDs = ASF . GlobalDatabase ? . GetPackageIDs ( appID , Bot . OwnedPackageIDs . Keys ) ;
2019-07-02 15:06:01 +02:00
if ( ( packageIDs ! = null ) & & ( packageIDs . Count > 0 ) ) {
2020-08-22 21:41:01 +02:00
if ( ( gamesOwned ! = null ) & & gamesOwned . TryGetValue ( appID , out string? cachedGameName ) ) {
2019-07-02 22:04:28 +02:00
result [ "app/" + appID ] = cachedGameName ;
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotOwnedAlreadyWithName , "app/" + appID , cachedGameName ) ) ) ;
} else {
2020-08-22 21:41:01 +02:00
result [ "app/" + appID ] = appID . ToString ( ) ;
2019-07-02 22:04:28 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotOwnedAlready , "app/" + appID ) ) ) ;
}
2019-07-02 15:06:01 +02:00
} else {
if ( gamesOwned = = null ) {
gamesOwned = await FetchGamesOwned ( ) . ConfigureAwait ( false ) ;
if ( gamesOwned = = null ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( gamesOwned ) ) ) ) ;
break ;
}
}
2020-08-22 21:41:01 +02:00
if ( gamesOwned . TryGetValue ( appID , out string? gameName ) ) {
2019-07-02 21:17:27 +02:00
result [ "app/" + appID ] = gameName ;
2019-07-02 21:50:18 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotOwnedAlreadyWithName , "app/" + appID , gameName ) ) ) ;
2019-07-02 15:06:01 +02:00
} else {
2019-07-02 21:50:18 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotNotOwnedYet , "app/" + appID ) ) ) ;
2019-07-02 15:06:01 +02:00
}
2018-09-15 22:34:32 +02:00
}
2019-07-02 15:06:01 +02:00
break ;
2019-07-03 00:54:12 +02:00
case "R" :
case "REGEX" :
2019-07-02 15:06:01 +02:00
Regex regex ;
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
try {
regex = new Regex ( game ) ;
} catch ( ArgumentException e ) {
Bot . ArchiLogger . LogGenericWarningException ( e ) ;
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( regex ) ) ) ) ;
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
break ;
}
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
if ( gamesOwned = = null ) {
gamesOwned = await FetchGamesOwned ( ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
if ( gamesOwned = = null ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( gamesOwned ) ) ) ) ;
2018-12-15 00:27:15 +01:00
2019-07-02 15:06:01 +02:00
break ;
}
2018-09-15 22:34:32 +02:00
}
2019-07-02 15:06:01 +02:00
bool foundWithRegex = false ;
2019-07-02 15:28:37 +02:00
foreach ( ( uint appID , string gameName ) in gamesOwned . Where ( gameOwned = > regex . IsMatch ( gameOwned . Value ) ) ) {
2019-07-02 15:06:01 +02:00
foundWithRegex = true ;
2019-07-02 21:17:27 +02:00
result [ "app/" + appID ] = gameName ;
2019-07-02 21:50:18 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotOwnedAlreadyWithName , "app/" + appID , gameName ) ) ) ;
2019-07-02 15:06:01 +02:00
}
if ( ! foundWithRegex ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotNotOwnedYet , entry ) ) ) ;
2018-09-15 22:34:32 +02:00
}
continue ;
2019-07-03 00:54:12 +02:00
case "S" when uint . TryParse ( game , out uint packageID ) & & ( packageID > 0 ) :
case "SUB" when uint . TryParse ( game , out packageID ) & & ( packageID > 0 ) :
2019-07-02 15:06:01 +02:00
if ( Bot . OwnedPackageIDs . ContainsKey ( packageID ) ) {
2020-08-22 21:41:01 +02:00
result [ "sub/" + packageID ] = packageID . ToString ( ) ;
2019-07-02 21:50:18 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotOwnedAlready , "sub/" + packageID ) ) ) ;
2019-07-02 15:06:01 +02:00
} else {
2019-07-02 21:50:18 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotNotOwnedYet , "sub/" + packageID ) ) ) ;
2019-07-02 15:06:01 +02:00
}
2018-09-15 22:34:32 +02:00
2019-07-02 15:06:01 +02:00
break ;
default :
if ( gamesOwned = = null ) {
gamesOwned = await FetchGamesOwned ( ) . ConfigureAwait ( false ) ;
if ( gamesOwned = = null ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( gamesOwned ) ) ) ) ;
break ;
}
}
bool foundWithName = false ;
2019-07-02 15:28:37 +02:00
foreach ( ( uint appID , string gameName ) in gamesOwned . Where ( gameOwned = > gameOwned . Value . IndexOf ( game , StringComparison . OrdinalIgnoreCase ) > = 0 ) ) {
2019-07-02 15:06:01 +02:00
foundWithName = true ;
2019-07-02 21:17:27 +02:00
result [ "app/" + appID ] = gameName ;
2019-07-02 21:50:18 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotOwnedAlreadyWithName , "app/" + appID , gameName ) ) ) ;
2019-07-02 15:06:01 +02:00
}
if ( ! foundWithName ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotNotOwnedYet , entry ) ) ) ;
}
break ;
2018-09-15 22:34:32 +02:00
}
}
2019-07-02 15:06:01 +02:00
return ( response . Length > 0 ? response . ToString ( ) : FormatBotResponse ( string . Format ( Strings . BotNotOwnedYet , query ) ) , result ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseOwns ( ulong steamID , string botNames , string query ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( query ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( query ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < ( string? Response , Dictionary < string , string > ? OwnedGames ) > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseOwns ( steamID , query ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < ( string Response , Dictionary < string , string > OwnedGames ) > validResults = new List < ( string Response , Dictionary < string , string > OwnedGames ) > ( results . Where ( result = > ! string . IsNullOrEmpty ( result . Response ) & & ( result . OwnedGames ! = null ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( validResults . Count = = 0 ) {
return null ;
}
2019-07-02 21:17:27 +02:00
Dictionary < string , ( ushort Count , string GameName ) > ownedGamesStats = new Dictionary < string , ( ushort Count , string GameName ) > ( ) ;
2018-12-15 00:27:15 +01:00
2020-08-23 20:45:24 +02:00
foreach ( ( string gameID , string gameName ) in validResults . Where ( validResult = > validResult . OwnedGames . Count > 0 ) . SelectMany ( validResult = > validResult . OwnedGames ) ) {
2019-07-02 21:17:27 +02:00
if ( ownedGamesStats . TryGetValue ( gameID , out ( ushort Count , string GameName ) ownedGameStats ) ) {
ownedGameStats . Count + + ;
2019-07-02 21:40:37 +02:00
} else {
ownedGameStats . Count = 1 ;
2019-07-02 21:17:27 +02:00
}
if ( ! string . IsNullOrEmpty ( gameName ) ) {
ownedGameStats . GameName = gameName ;
}
ownedGamesStats [ gameID ] = ownedGameStats ;
2018-09-15 22:34:32 +02:00
}
2019-07-02 21:30:55 +02:00
IEnumerable < string > extraResponses = ownedGamesStats . Select ( kv = > FormatStaticResponse ( string . Format ( Strings . BotOwnsOverviewPerGame , kv . Value . Count , validResults . Count , kv . Key + ( ! string . IsNullOrEmpty ( kv . Value . GameName ) ? " | " + kv . Value . GameName : "" ) ) ) ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return string . Join ( Environment . NewLine , validResults . Select ( result = > result . Response ) . Concat ( extraResponses ) ) ;
}
2020-08-22 21:41:01 +02:00
private string? ResponsePassword ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2018-09-22 15:50:11 +02:00
if ( string . IsNullOrEmpty ( Bot . BotConfig . DecryptedSteamPassword ) ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( BotConfig . DecryptedSteamPassword ) ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-05 12:14:08 +01:00
Dictionary < ArchiCryptoHelper . ECryptoMethod , string > encryptedPasswords = new Dictionary < ArchiCryptoHelper . ECryptoMethod , string > ( 2 ) {
2020-08-22 21:41:01 +02:00
{ ArchiCryptoHelper . ECryptoMethod . AES , ArchiCryptoHelper . Encrypt ( ArchiCryptoHelper . ECryptoMethod . AES , Bot . BotConfig . DecryptedSteamPassword ! ) ? ? "" } ,
{ ArchiCryptoHelper . ECryptoMethod . ProtectedDataForCurrentUser , ArchiCryptoHelper . Encrypt ( ArchiCryptoHelper . ECryptoMethod . ProtectedDataForCurrentUser , Bot . BotConfig . DecryptedSteamPassword ! ) ? ? "" }
2019-01-05 12:14:08 +01:00
} ;
2018-12-15 00:27:15 +01:00
2019-01-05 12:14:08 +01:00
return FormatBotResponse ( string . Join ( ", " , encryptedPasswords . Where ( kv = > ! string . IsNullOrEmpty ( kv . Value ) ) . Select ( kv = > string . Format ( Strings . BotEncryptedPassword , kv . Key , kv . Value ) ) ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponsePassword ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponsePassword ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponsePause ( ulong steamID , bool permanent , string? resumeInSecondsText = null ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . FamilySharing ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2019-01-12 18:48:00 +01:00
if ( permanent & & ! Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . ErrorAccessDenied ) ;
}
ushort resumeInSeconds = 0 ;
2018-09-19 21:11:58 +02:00
if ( ! string . IsNullOrEmpty ( resumeInSecondsText ) & & ( ! ushort . TryParse ( resumeInSecondsText , out resumeInSeconds ) | | ( resumeInSeconds = = 0 ) ) ) {
return string . Format ( Strings . ErrorIsInvalid , nameof ( resumeInSecondsText ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = await Bot . Actions . Pause ( permanent , resumeInSeconds ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponsePause ( ulong steamID , string botNames , bool permanent , string? resumeInSecondsText = null ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponsePause ( steamID , permanent , resumeInSecondsText ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponsePlay ( ulong steamID , IReadOnlyCollection < uint > gameIDs , string? gameName = null ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | ( gameIDs = = null ) | | ( gameIDs . Count > ArchiHandler . MaxGamesPlayedConcurrently ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( gameIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
2019-06-23 17:30:34 +02:00
( bool success , string message ) = await Bot . Actions . Play ( gameIDs , gameName ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-06-23 17:30:34 +02:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponsePlay ( ulong steamID , string targetGameIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( targetGameIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( targetGameIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
string [ ] games = targetGameIDs . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( games . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( games ) ) ) ;
}
HashSet < uint > gamesToPlay = new HashSet < uint > ( ) ;
StringBuilder gameName = new StringBuilder ( ) ;
foreach ( string game in games ) {
if ( ! uint . TryParse ( game , out uint gameID ) | | ( gameID = = 0 ) ) {
2018-11-14 12:22:02 +01:00
gameName . Append ( ( gameName . Length > 0 ? " " : "" ) + game ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
continue ;
}
if ( gamesToPlay . Count > = ArchiHandler . MaxGamesPlayedConcurrently ) {
2019-05-24 23:18:20 +02:00
return FormatBotResponse ( string . Format ( Strings . WarningFailedWithError , nameof ( gamesToPlay ) + " > " + ArchiHandler . MaxGamesPlayedConcurrently ) ) ;
2018-09-15 22:34:32 +02:00
}
gamesToPlay . Add ( gameID ) ;
}
2019-06-23 17:30:34 +02:00
return await ResponsePlay ( steamID , gamesToPlay , gameName . Length > 0 ? gameName . ToString ( ) : null ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponsePlay ( ulong steamID , string botNames , string targetGameIDs ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( targetGameIDs ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( targetGameIDs ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponsePlay ( steamID , targetGameIDs ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponsePrivacy ( ulong steamID , string privacySettingsText ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( privacySettingsText ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( privacySettingsText ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
string [ ] privacySettingsArgs = privacySettingsText . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( privacySettingsArgs . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( privacySettingsArgs ) ) ) ;
}
2018-09-27 17:28:03 +02:00
// There are only 7 privacy settings
if ( privacySettingsArgs . Length > 7 ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( privacySettingsArgs ) ) ) ;
}
2020-07-04 23:43:49 +02:00
ArchiHandler . EPrivacySetting profile = ArchiHandler . EPrivacySetting . Private ;
ArchiHandler . EPrivacySetting ownedGames = ArchiHandler . EPrivacySetting . Private ;
ArchiHandler . EPrivacySetting playtime = ArchiHandler . EPrivacySetting . Private ;
ArchiHandler . EPrivacySetting friendsList = ArchiHandler . EPrivacySetting . Private ;
ArchiHandler . EPrivacySetting inventory = ArchiHandler . EPrivacySetting . Private ;
ArchiHandler . EPrivacySetting inventoryGifts = ArchiHandler . EPrivacySetting . Private ;
2018-09-15 22:34:32 +02:00
Steam . UserPrivacy . ECommentPermission comments = Steam . UserPrivacy . ECommentPermission . Private ;
// Converting digits to enum
for ( byte index = 0 ; index < privacySettingsArgs . Length ; index + + ) {
2020-07-04 23:43:49 +02:00
if ( ! Enum . TryParse ( privacySettingsArgs [ index ] , true , out ArchiHandler . EPrivacySetting privacySetting ) | | ( privacySetting = = ArchiHandler . EPrivacySetting . Unknown ) | | ! Enum . IsDefined ( typeof ( ArchiHandler . EPrivacySetting ) , privacySetting ) ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( privacySettingsArgs ) ) ) ;
}
// Child setting can't be less restrictive than its parent
switch ( index ) {
2019-05-19 15:38:06 +02:00
case 0 :
// Profile
2018-09-15 22:34:32 +02:00
profile = privacySetting ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2019-05-19 15:38:06 +02:00
case 1 :
// OwnedGames, child of Profile
2018-09-15 22:34:32 +02:00
if ( profile < privacySetting ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( ownedGames ) ) ) ;
}
ownedGames = privacySetting ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2019-05-19 15:38:06 +02:00
case 2 :
// Playtime, child of OwnedGames
2018-09-15 22:34:32 +02:00
if ( ownedGames < privacySetting ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( playtime ) ) ) ;
}
playtime = privacySetting ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2019-05-19 15:38:06 +02:00
case 3 :
// FriendsList, child of Profile
2018-09-27 17:35:20 +02:00
if ( profile < privacySetting ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( ownedGames ) ) ) ;
}
friendsList = privacySetting ;
2018-12-15 00:27:15 +01:00
2018-09-27 17:35:20 +02:00
break ;
2019-05-19 15:38:06 +02:00
case 4 :
// Inventory, child of Profile
2018-09-15 22:34:32 +02:00
if ( profile < privacySetting ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( inventory ) ) ) ;
}
inventory = privacySetting ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2019-05-19 15:38:06 +02:00
case 5 :
// InventoryGifts, child of Inventory
2018-09-15 22:34:32 +02:00
if ( inventory < privacySetting ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( inventoryGifts ) ) ) ;
}
inventoryGifts = privacySetting ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2019-05-19 15:38:06 +02:00
case 6 :
// Comments, child of Profile
2018-09-15 22:34:32 +02:00
if ( profile < privacySetting ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( comments ) ) ) ;
}
// Comments use different numbers than everything else, but we want to have this command consistent for end-user, so we'll map them
switch ( privacySetting ) {
2020-07-04 23:43:49 +02:00
case ArchiHandler . EPrivacySetting . FriendsOnly :
2018-09-15 22:34:32 +02:00
comments = Steam . UserPrivacy . ECommentPermission . FriendsOnly ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2020-07-04 23:43:49 +02:00
case ArchiHandler . EPrivacySetting . Private :
2018-09-15 22:34:32 +02:00
comments = Steam . UserPrivacy . ECommentPermission . Private ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
2020-07-04 23:43:49 +02:00
case ArchiHandler . EPrivacySetting . Public :
2018-09-15 22:34:32 +02:00
comments = Steam . UserPrivacy . ECommentPermission . Public ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
default :
Bot . ArchiLogger . LogGenericError ( string . Format ( Strings . WarningUnknownValuePleaseReport , nameof ( privacySetting ) , privacySetting ) ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( privacySetting ) ) ) ;
}
break ;
default :
Bot . ArchiLogger . LogGenericError ( string . Format ( Strings . WarningUnknownValuePleaseReport , nameof ( index ) , index ) ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( index ) ) ) ;
}
}
2018-09-27 17:35:20 +02:00
Steam . UserPrivacy userPrivacy = new Steam . UserPrivacy ( new Steam . UserPrivacy . PrivacySettings ( profile , ownedGames , playtime , friendsList , inventory , inventoryGifts ) , comments ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( await Bot . ArchiWebHandler . ChangePrivacySettings ( userPrivacy ) . ConfigureAwait ( false ) ? Strings . Success : Strings . WarningFailed ) ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponsePrivacy ( ulong steamID , string botNames , string privacySettingsText ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( privacySettingsText ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( privacySettingsText ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponsePrivacy ( steamID , privacySettingsText ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseRedeem ( ulong steamID , string keysText , ERedeemFlags redeemFlags = ERedeemFlags . None ) {
2020-08-23 20:45:24 +02:00
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( keysText ) | | ( Bot . Bots = = null ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( keysText ) + " || " + nameof ( Bot . Bots ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
string [ ] keys = keysText . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
if ( keys . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( keys ) ) ) ;
}
bool forward = ! redeemFlags . HasFlag ( ERedeemFlags . SkipForwarding ) & & ( redeemFlags . HasFlag ( ERedeemFlags . ForceForwarding ) | | Bot . BotConfig . RedeemingPreferences . HasFlag ( BotConfig . ERedeemingPreferences . Forwarding ) ) ;
bool distribute = ! redeemFlags . HasFlag ( ERedeemFlags . SkipDistributing ) & & ( redeemFlags . HasFlag ( ERedeemFlags . ForceDistributing ) | | Bot . BotConfig . RedeemingPreferences . HasFlag ( BotConfig . ERedeemingPreferences . Distributing ) ) ;
bool keepMissingGames = ! redeemFlags . HasFlag ( ERedeemFlags . SkipKeepMissingGames ) & & ( redeemFlags . HasFlag ( ERedeemFlags . ForceKeepMissingGames ) | | Bot . BotConfig . RedeemingPreferences . HasFlag ( BotConfig . ERedeemingPreferences . KeepMissingGames ) ) ;
2019-08-05 15:41:37 +03:00
bool assumeWalletKeyOnBadActivationCode = ! redeemFlags . HasFlag ( ERedeemFlags . SkipAssumeWalletKeyOnBadActivationCode ) & & ( redeemFlags . HasFlag ( ERedeemFlags . ForceAssumeWalletKeyOnBadActivationCode ) | | Bot . BotConfig . RedeemingPreferences . HasFlag ( BotConfig . ERedeemingPreferences . AssumeWalletKeyOnBadActivationCode ) ) ;
2018-09-15 22:34:32 +02:00
2019-04-02 20:43:17 +02:00
HashSet < string > pendingKeys = keys . ToHashSet ( StringComparer . Ordinal ) ;
HashSet < string > unusedKeys = pendingKeys . ToHashSet ( StringComparer . Ordinal ) ;
2018-09-15 22:34:32 +02:00
2019-02-23 08:35:48 +01:00
HashSet < Bot > rateLimitedBots = new HashSet < Bot > ( ) ;
2019-11-13 21:25:37 +01:00
HashSet < Bot > triedBots = new HashSet < Bot > ( ) ;
2019-02-23 08:35:48 +01:00
2018-09-15 22:34:32 +02:00
StringBuilder response = new StringBuilder ( ) ;
using ( HashSet < string > . Enumerator keysEnumerator = pendingKeys . GetEnumerator ( ) ) {
2019-05-19 15:38:06 +02:00
// Initial key
2020-08-22 21:41:01 +02:00
string? key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
string? previousKey = key ;
2018-09-15 22:34:32 +02:00
while ( ! string . IsNullOrEmpty ( key ) ) {
2020-08-22 21:41:01 +02:00
string startingKey = key ! ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
using ( IEnumerator < Bot > botsEnumerator = Bot . Bots . Where ( bot = > ( bot . Value ! = Bot ) & & bot . Value . IsConnectedAndLoggedOn & & bot . Value . Commands . Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ) . OrderByDescending ( bot = > Bot . BotsComparer ? . Compare ( bot . Key , Bot . BotName ) > 0 ) . ThenBy ( bot = > bot . Key , Bot . BotsComparer ) . Select ( bot = > bot . Value ) . GetEnumerator ( ) ) {
Bot ? currentBot = Bot ;
2018-09-15 22:34:32 +02:00
while ( ! string . IsNullOrEmpty ( key ) & & ( currentBot ! = null ) ) {
2019-11-12 19:27:00 +01:00
if ( previousKey ! = key ) {
2019-11-13 21:25:37 +01:00
triedBots . Clear ( ) ;
2019-11-13 21:35:34 +01:00
previousKey = key ;
2019-11-12 19:27:00 +01:00
}
2020-08-22 21:41:01 +02:00
if ( redeemFlags . HasFlag ( ERedeemFlags . Validate ) & & ! Utilities . IsValidCdKey ( key ! ) ) {
2019-05-19 15:38:06 +02:00
// Next key
key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
2018-12-15 00:27:15 +01:00
2019-05-19 15:38:06 +02:00
// Keep current bot
continue ;
2018-09-15 22:34:32 +02:00
}
2019-10-13 13:10:07 +02:00
if ( ( currentBot = = Bot ) & & redeemFlags . HasFlag ( ERedeemFlags . SkipInitial ) ) {
2019-05-19 15:38:06 +02:00
// Either bot will be changed, or loop aborted
currentBot = null ;
2018-09-15 22:34:32 +02:00
} else {
2019-11-13 21:25:37 +01:00
bool skipRequest = triedBots . Contains ( currentBot ) | | rateLimitedBots . Contains ( currentBot ) ;
2020-08-22 21:41:01 +02:00
ArchiHandler . PurchaseResponseCallback ? result = skipRequest ? new ArchiHandler . PurchaseResponseCallback ( EResult . Fail , EPurchaseResultDetail . CancelledByUser ) : await currentBot . Actions . RedeemKey ( key ! ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( result = = null ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotRedeem , key , EPurchaseResultDetail . Timeout ) , currentBot . BotName ) ) ;
2019-05-19 15:38:06 +02:00
// Either bot will be changed, or loop aborted
currentBot = null ;
2018-09-15 22:34:32 +02:00
} else {
2019-11-13 21:25:37 +01:00
triedBots . Add ( currentBot ) ;
2019-11-13 18:24:59 +01:00
2019-08-05 15:41:37 +03:00
if ( ( ( result . PurchaseResultDetail = = EPurchaseResultDetail . CannotRedeemCodeFromClient ) | | ( ( result . PurchaseResultDetail = = EPurchaseResultDetail . BadActivationCode ) & & assumeWalletKeyOnBadActivationCode ) ) & & ( Bot . WalletCurrency ! = ECurrencyCode . Invalid ) ) {
2018-09-15 22:34:32 +02:00
// If it's a wallet code, we try to redeem it first, then handle the inner result as our primary one
2020-08-22 21:41:01 +02:00
( EResult Result , EPurchaseResultDetail ? PurchaseResult ) ? walletResult = await currentBot . ArchiWebHandler . RedeemWalletKey ( key ! ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
if ( walletResult ! = null ) {
result . Result = walletResult . Value . Result ;
2019-05-19 15:38:06 +02:00
// BadActivationCode is our smart guess in this case
result . PurchaseResultDetail = walletResult . Value . PurchaseResult . GetValueOrDefault ( walletResult . Value . Result = = EResult . OK ? EPurchaseResultDetail . NoDetail : EPurchaseResultDetail . BadActivationCode ) ;
2018-09-15 22:34:32 +02:00
} else {
result . Result = EResult . Timeout ;
result . PurchaseResultDetail = EPurchaseResultDetail . Timeout ;
}
}
2019-10-13 13:10:07 +02:00
if ( ( result . Items ! = null ) & & ( result . Items . Count > 0 ) ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotRedeemWithItems , key , result . Result + "/" + result . PurchaseResultDetail , string . Join ( ", " , result . Items ) ) , currentBot . BotName ) ) ;
2019-11-13 21:25:37 +01:00
} else if ( ! skipRequest ) {
2019-10-13 13:10:07 +02:00
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotRedeem , key , result . Result + "/" + result . PurchaseResultDetail ) , currentBot . BotName ) ) ;
}
2018-09-15 22:34:32 +02:00
switch ( result . PurchaseResultDetail ) {
case EPurchaseResultDetail . BadActivationCode :
case EPurchaseResultDetail . CannotRedeemCodeFromClient :
case EPurchaseResultDetail . DuplicateActivationCode :
case EPurchaseResultDetail . NoDetail : // OK
case EPurchaseResultDetail . Timeout :
if ( ( result . Result ! = EResult . Timeout ) & & ( result . PurchaseResultDetail ! = EPurchaseResultDetail . Timeout ) ) {
2020-08-22 21:41:01 +02:00
unusedKeys . Remove ( key ! ) ;
2018-09-15 22:34:32 +02:00
}
2019-05-19 15:38:06 +02:00
// Next key
key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
2018-09-15 22:34:32 +02:00
if ( result . PurchaseResultDetail = = EPurchaseResultDetail . NoDetail ) {
2019-05-19 15:38:06 +02:00
// Next bot (if needed)
break ;
2018-09-15 22:34:32 +02:00
}
2019-05-19 15:38:06 +02:00
// Keep current bot
continue ;
2018-09-15 22:34:32 +02:00
case EPurchaseResultDetail . AccountLocked :
case EPurchaseResultDetail . AlreadyPurchased :
2019-11-13 21:25:37 +01:00
case EPurchaseResultDetail . CancelledByUser :
2018-09-15 22:34:32 +02:00
case EPurchaseResultDetail . DoesNotOwnRequiredApp :
case EPurchaseResultDetail . RestrictedCountry :
if ( ! forward | | ( keepMissingGames & & ( result . PurchaseResultDetail ! = EPurchaseResultDetail . AlreadyPurchased ) ) ) {
2019-05-19 15:38:06 +02:00
// Next key
key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
2018-12-15 00:27:15 +01:00
2019-05-19 15:38:06 +02:00
// Next bot (if needed)
break ;
2018-09-15 22:34:32 +02:00
}
if ( distribute ) {
2019-05-19 15:38:06 +02:00
// Next bot, without changing key
break ;
2018-09-15 22:34:32 +02:00
}
Dictionary < uint , string > items = result . Items ? ? new Dictionary < uint , string > ( ) ;
bool alreadyHandled = false ;
2018-12-15 00:27:15 +01:00
2019-11-13 21:25:37 +01:00
foreach ( Bot innerBot in Bot . Bots . Where ( bot = > ( bot . Value ! = currentBot ) & & ( ! redeemFlags . HasFlag ( ERedeemFlags . SkipInitial ) | | ( bot . Value ! = Bot ) ) & & ! triedBots . Contains ( bot . Value ) & & ! rateLimitedBots . Contains ( bot . Value ) & & bot . Value . IsConnectedAndLoggedOn & & bot . Value . Commands . Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) & & ( ( items . Count = = 0 ) | | items . Keys . Any ( packageID = > ! bot . Value . OwnedPackageIDs . ContainsKey ( packageID ) ) ) ) . OrderBy ( bot = > bot . Key , Bot . BotsComparer ) . Select ( bot = > bot . Value ) ) {
2020-08-22 21:41:01 +02:00
ArchiHandler . PurchaseResponseCallback ? otherResult = await innerBot . Actions . RedeemKey ( key ! ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( otherResult = = null ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotRedeem , key , EResult . Timeout + "/" + EPurchaseResultDetail . Timeout ) , innerBot . BotName ) ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
continue ;
}
2019-11-13 21:25:37 +01:00
triedBots . Add ( innerBot ) ;
2019-11-12 19:27:00 +01:00
2018-09-15 22:34:32 +02:00
switch ( otherResult . PurchaseResultDetail ) {
case EPurchaseResultDetail . BadActivationCode :
case EPurchaseResultDetail . DuplicateActivationCode :
case EPurchaseResultDetail . NoDetail : // OK
2019-05-19 15:38:06 +02:00
// This key is already handled, as we either redeemed it or we're sure it's dupe/invalid
alreadyHandled = true ;
2020-08-22 21:41:01 +02:00
unusedKeys . Remove ( key ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
case EPurchaseResultDetail . RateLimited :
rateLimitedBots . Add ( innerBot ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
break ;
}
if ( ( otherResult . Items ! = null ) & & ( otherResult . Items . Count > 0 ) ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotRedeemWithItems , key , otherResult . Result + "/" + otherResult . PurchaseResultDetail , string . Join ( ", " , otherResult . Items ) ) , innerBot . BotName ) ) ;
} else {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . BotRedeem , key , otherResult . Result + "/" + otherResult . PurchaseResultDetail ) , innerBot . BotName ) ) ;
}
if ( alreadyHandled ) {
break ;
}
if ( otherResult . Items = = null ) {
continue ;
}
2019-01-11 00:16:20 +01:00
foreach ( ( uint packageID , string packageName ) in otherResult . Items . Where ( item = > ! items . ContainsKey ( item . Key ) ) ) {
items [ packageID ] = packageName ;
2018-09-15 22:34:32 +02:00
}
}
2019-05-19 15:38:06 +02:00
// Next key
key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
2018-12-15 00:27:15 +01:00
2019-05-19 15:38:06 +02:00
// Next bot (if needed)
break ;
2018-09-15 22:34:32 +02:00
case EPurchaseResultDetail . RateLimited :
rateLimitedBots . Add ( currentBot ) ;
2019-05-19 21:53:11 +02:00
2019-11-13 21:25:37 +01:00
goto case EPurchaseResultDetail . CancelledByUser ;
2018-09-15 22:34:32 +02:00
default :
ASF . ArchiLogger . LogGenericError ( string . Format ( Strings . WarningUnknownValuePleaseReport , nameof ( result . PurchaseResultDetail ) , result . PurchaseResultDetail ) ) ;
2020-08-22 21:41:01 +02:00
unusedKeys . Remove ( key ! ) ;
2018-09-15 22:34:32 +02:00
2019-05-19 15:38:06 +02:00
// Next key
key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
2018-12-15 00:27:15 +01:00
2019-05-19 15:38:06 +02:00
// Next bot (if needed)
break ;
2018-09-15 22:34:32 +02:00
}
}
}
// We want to change bot in two cases:
// a) When we have distribution enabled, obviously
// b) When we're skipping initial bot AND we have forwarding enabled, otherwise we won't get down to other accounts
if ( distribute | | ( forward & & redeemFlags . HasFlag ( ERedeemFlags . SkipInitial ) ) ) {
currentBot = botsEnumerator . MoveNext ( ) ? botsEnumerator . Current : null ;
}
}
}
if ( key = = startingKey ) {
2019-05-19 15:38:06 +02:00
// We ran out of bots to try for this key, so change it to avoid infinite loop, next key
key = keysEnumerator . MoveNext ( ) ? keysEnumerator . Current : null ;
2018-09-15 22:34:32 +02:00
}
}
}
if ( unusedKeys . Count > 0 ) {
response . AppendLine ( FormatBotResponse ( string . Format ( Strings . UnusedKeys , string . Join ( ", " , unusedKeys ) ) ) ) ;
}
return response . Length > 0 ? response . ToString ( ) : null ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseRedeem ( ulong steamID , string botNames , string keys , ERedeemFlags redeemFlags = ERedeemFlags . None ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( keys ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( keys ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseRedeem ( steamID , keys , redeemFlags ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseReset ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
}
2019-06-23 17:30:34 +02:00
2020-08-22 21:41:01 +02:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2019-06-23 17:30:34 +02:00
return null ;
}
2020-08-22 21:41:01 +02:00
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
2019-06-23 17:30:34 +02:00
}
2020-08-22 21:41:01 +02:00
( bool success , string message ) = await Bot . Actions . Play ( Enumerable . Empty < uint > ( ) , Bot . BotConfig . CustomGamePlayedWhileIdle ) . ConfigureAwait ( false ) ;
2019-06-23 17:30:34 +02:00
2020-08-22 21:41:01 +02:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2019-06-23 17:30:34 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseReset ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2019-06-23 17:30:34 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2019-06-23 17:30:34 +02:00
2020-08-22 21:41:01 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
2019-06-23 17:30:34 +02:00
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseReset ( steamID ) ) ) . ConfigureAwait ( false ) ;
2019-06-23 17:30:34 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2019-06-23 17:30:34 +02:00
2020-08-22 21:41:01 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2018-12-15 00:27:15 +01:00
2020-08-22 21:41:01 +02:00
private static string? ResponseRestart ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
if ( ! ASF . IsOwner ( steamID ) ) {
return null ;
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = Actions . Restart ( ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatStaticResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private string? ResponseResume ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . FamilySharing ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = Bot . Actions . Resume ( ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseResume ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseResume ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseStart ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = Bot . Actions . Start ( ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseStart ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseStart ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseStats ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
if ( ! ASF . IsOwner ( steamID ) ) {
return null ;
}
ushort memoryInMegabytes = ( ushort ) ( GC . GetTotalMemory ( false ) / 1024 / 1024 ) ;
2020-07-05 14:09:24 +02:00
TimeSpan uptime = DateTime . UtcNow . Subtract ( RuntimeCompatibility . ProcessStartTime . ToUniversalTime ( ) ) ;
2018-12-15 00:27:15 +01:00
2020-07-04 12:13:31 +02:00
return FormatBotResponse ( string . Format ( Strings . BotStats , memoryInMegabytes , uptime . ToHumanReadable ( ) ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private ( string? Response , Bot Bot ) ResponseStatus ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . FamilySharing ) ) {
2018-09-15 22:34:32 +02:00
return ( null , Bot ) ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return ( FormatBotResponse ( Bot . KeepRunning ? Strings . BotStatusConnecting : Strings . BotStatusNotRunning ) , Bot ) ;
}
if ( Bot . PlayingBlocked ) {
return ( FormatBotResponse ( Strings . BotStatusPlayingNotAvailable ) , Bot ) ;
}
if ( Bot . CardsFarmer . Paused ) {
return ( FormatBotResponse ( Strings . BotStatusPaused ) , Bot ) ;
}
if ( Bot . IsAccountLimited ) {
return ( FormatBotResponse ( Strings . BotStatusLimited ) , Bot ) ;
}
if ( Bot . IsAccountLocked ) {
return ( FormatBotResponse ( Strings . BotStatusLocked ) , Bot ) ;
}
2019-10-20 21:38:55 +02:00
if ( ! Bot . CardsFarmer . NowFarming | | ( Bot . CardsFarmer . CurrentGamesFarmingReadOnly . Count = = 0 ) ) {
2018-09-15 22:34:32 +02:00
return ( FormatBotResponse ( Strings . BotStatusNotIdling ) , Bot ) ;
}
2019-10-20 21:38:55 +02:00
if ( Bot . CardsFarmer . CurrentGamesFarmingReadOnly . Count > 1 ) {
return ( FormatBotResponse ( string . Format ( Strings . BotStatusIdlingList , string . Join ( ", " , Bot . CardsFarmer . CurrentGamesFarmingReadOnly . Select ( game = > game . AppID + " (" + game . GameName + ")" ) ) , Bot . CardsFarmer . GamesToFarmReadOnly . Count , Bot . CardsFarmer . GamesToFarmReadOnly . Sum ( game = > game . CardsRemaining ) , Bot . CardsFarmer . TimeRemaining . ToHumanReadable ( ) ) ) , Bot ) ;
2018-09-15 22:34:32 +02:00
}
2019-10-20 21:38:55 +02:00
CardsFarmer . Game soloGame = Bot . CardsFarmer . CurrentGamesFarmingReadOnly . First ( ) ;
2018-12-15 00:27:15 +01:00
2019-10-20 21:38:55 +02:00
return ( FormatBotResponse ( string . Format ( Strings . BotStatusIdling , soloGame . AppID , soloGame . GameName , soloGame . CardsRemaining , Bot . CardsFarmer . GamesToFarmReadOnly . Count , Bot . CardsFarmer . GamesToFarmReadOnly . Sum ( game = > game . CardsRemaining ) , Bot . CardsFarmer . TimeRemaining . ToHumanReadable ( ) ) ) , Bot ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseStatus ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < ( string? Response , Bot Bot ) > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseStatus ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < ( string Response , Bot Bot ) > validResults = new List < ( string Response , Bot Bot ) > ( results . Where ( result = > ! string . IsNullOrEmpty ( result . Response ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( validResults . Count = = 0 ) {
return null ;
}
HashSet < Bot > botsRunning = validResults . Where ( result = > result . Bot . KeepRunning ) . Select ( result = > result . Bot ) . ToHashSet ( ) ;
2019-10-20 21:38:55 +02:00
string extraResponse = string . Format ( Strings . BotStatusOverview , botsRunning . Count , validResults . Count , botsRunning . Sum ( bot = > bot . CardsFarmer . GamesToFarmReadOnly . Count ) , botsRunning . Sum ( bot = > bot . CardsFarmer . GamesToFarmReadOnly . Sum ( game = > game . CardsRemaining ) ) ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return string . Join ( Environment . NewLine , validResults . Select ( result = > result . Response ) . Union ( extraResponse . ToEnumerable ( ) ) ) ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseStop ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
2019-01-23 17:58:37 +01:00
( bool success , string message ) = Bot . Actions . Stop ( ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseStop ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseStop ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseTransfer ( ulong steamID , string botNameTo ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNameTo ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNameTo ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
2018-12-04 02:05:09 +01:00
if ( Bot . BotConfig . TransferableTypes . Count = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( Bot . BotConfig . TransferableTypes ) ) ) ;
}
2020-08-22 21:41:01 +02:00
Bot ? targetBot = Bot . GetBot ( botNameTo ) ;
2019-02-25 23:49:20 +01:00
if ( targetBot = = null ) {
2018-09-15 22:34:32 +02:00
return ASF . IsOwner ( steamID ) ? FormatBotResponse ( string . Format ( Strings . BotNotFound , botNameTo ) ) : null ;
}
if ( ! targetBot . IsConnectedAndLoggedOn ) {
2018-10-16 00:13:56 +03:00
return FormatBotResponse ( Strings . TargetBotNotConnected ) ;
2018-09-15 22:34:32 +02:00
}
2018-09-23 02:17:17 +02:00
if ( targetBot . SteamID = = Bot . SteamID ) {
2018-09-15 22:34:32 +02:00
return FormatBotResponse ( Strings . BotSendingTradeToYourself ) ;
}
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
( bool success , string message ) = await Bot . Actions . SendInventory ( targetSteamID : targetBot . SteamID , filterFunction : item = > Bot . BotConfig . TransferableTypes . Contains ( item . Type ) ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseTransfer ( ulong steamID , string botNames , string botNameTo ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( botNameTo ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( botNameTo ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseTransfer ( steamID , botNameTo ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseTransferByRealAppIDs ( ulong steamID , IReadOnlyCollection < uint > realAppIDs , Bot targetBot , bool exclude = false ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | ( realAppIDs = = null ) | | ( realAppIDs . Count = = 0 ) | | ( targetBot = = null ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( realAppIDs ) + " || " + nameof ( targetBot ) ) ;
2018-09-29 22:20:35 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-29 22:20:35 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
2018-12-04 02:05:09 +01:00
if ( Bot . BotConfig . TransferableTypes . Count = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( Bot . BotConfig . TransferableTypes ) ) ) ;
}
2018-09-29 22:20:35 +02:00
if ( ! targetBot . IsConnectedAndLoggedOn ) {
2018-10-16 00:13:56 +03:00
return FormatBotResponse ( Strings . TargetBotNotConnected ) ;
2018-09-29 22:20:35 +02:00
}
if ( targetBot . SteamID = = Bot . SteamID ) {
return FormatBotResponse ( Strings . BotSendingTradeToYourself ) ;
}
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
( bool success , string message ) = await Bot . Actions . SendInventory ( targetSteamID : targetBot . SteamID , filterFunction : item = > Bot . BotConfig . TransferableTypes . Contains ( item . Type ) & & ( exclude ^ realAppIDs . Contains ( item . RealAppID ) ) ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-23 17:58:37 +01:00
return FormatBotResponse ( success ? message : string . Format ( Strings . WarningFailedWithError , message ) ) ;
2018-09-29 22:20:35 +02:00
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseTransferByRealAppIDs ( ulong steamID , string realAppIDsText , string botNameTo , bool exclude = false ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( realAppIDsText ) | | string . IsNullOrEmpty ( botNameTo ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( realAppIDsText ) + " || " + nameof ( botNameTo ) ) ;
2018-09-29 22:20:35 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-29 22:20:35 +02:00
return null ;
}
2020-08-22 21:41:01 +02:00
Bot ? targetBot = Bot . GetBot ( botNameTo ) ;
2019-02-25 23:49:20 +01:00
if ( targetBot = = null ) {
2018-09-29 22:20:35 +02:00
return ASF . IsOwner ( steamID ) ? FormatBotResponse ( string . Format ( Strings . BotNotFound , botNameTo ) ) : null ;
}
string [ ] appIDTexts = realAppIDsText . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
2018-12-15 00:27:15 +01:00
2018-09-29 22:20:35 +02:00
if ( appIDTexts . Length = = 0 ) {
return FormatBotResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( appIDTexts ) ) ) ;
}
HashSet < uint > realAppIDs = new HashSet < uint > ( ) ;
2018-12-15 00:27:15 +01:00
2018-09-29 22:20:35 +02:00
foreach ( string appIDText in appIDTexts ) {
2018-09-30 22:03:45 +02:00
if ( ! uint . TryParse ( appIDText , out uint appID ) | | ( appID = = 0 ) ) {
2018-09-29 22:20:35 +02:00
return FormatBotResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( appID ) ) ) ;
}
realAppIDs . Add ( appID ) ;
}
2019-12-26 19:36:53 +01:00
return await ResponseTransferByRealAppIDs ( steamID , realAppIDs , targetBot , exclude ) . ConfigureAwait ( false ) ;
2018-09-29 22:20:35 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseTransferByRealAppIDs ( ulong steamID , string botNames , string realAppIDsText , string botNameTo , bool exclude = false ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) | | string . IsNullOrEmpty ( realAppIDsText ) | | string . IsNullOrEmpty ( botNameTo ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) + " || " + nameof ( realAppIDsText ) + " || " + nameof ( botNameTo ) ) ;
2018-09-29 22:20:35 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-29 22:20:35 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
string [ ] appIDTexts = realAppIDsText . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
2018-12-15 00:27:15 +01:00
2018-09-29 22:20:35 +02:00
if ( appIDTexts . Length = = 0 ) {
return FormatStaticResponse ( string . Format ( Strings . ErrorIsEmpty , nameof ( appIDTexts ) ) ) ;
}
HashSet < uint > realAppIDs = new HashSet < uint > ( ) ;
2018-12-15 00:27:15 +01:00
2018-09-29 22:20:35 +02:00
foreach ( string appIDText in appIDTexts ) {
2018-09-30 22:03:45 +02:00
if ( ! uint . TryParse ( appIDText , out uint appID ) | | ( appID = = 0 ) ) {
2018-09-29 22:20:35 +02:00
return FormatStaticResponse ( string . Format ( Strings . ErrorIsInvalid , nameof ( appID ) ) ) ;
}
realAppIDs . Add ( appID ) ;
}
2020-08-22 21:41:01 +02:00
Bot ? targetBot = Bot . GetBot ( botNameTo ) ;
2019-02-25 23:49:20 +01:00
if ( targetBot = = null ) {
2018-09-29 22:20:35 +02:00
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNameTo ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseTransferByRealAppIDs ( steamID , realAppIDs , targetBot , exclude ) ) ) . ConfigureAwait ( false ) ;
2018-09-29 22:20:35 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-29 22:20:35 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private string? ResponseUnknown ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
return Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ? FormatBotResponse ( Strings . UnknownCommand ) : null ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private async Task < string? > ResponseUnpackBoosters ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-09-15 22:34:32 +02:00
return null ;
}
if ( ! Bot . IsConnectedAndLoggedOn ) {
return FormatBotResponse ( Strings . BotNotConnected ) ;
}
// It'd make sense here to actually check return code of ArchiWebHandler.UnpackBooster(), but it lies most of the time | https://github.com/JustArchi/ArchiSteamFarm/issues/704
2019-05-19 15:38:06 +02:00
bool completeSuccess = true ;
2018-09-15 22:34:32 +02:00
// It'd also make sense to run all of this in parallel, but it seems that Steam has a lot of problems with inventory-related parallel requests | https://steamcommunity.com/groups/ascfarm/discussions/1/3559414588264550284/
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
try {
await foreach ( Steam . Asset item in Bot . ArchiWebHandler . GetInventoryAsync ( Bot . SteamID ) . Where ( item = > item . Type = = Steam . Asset . EType . BoosterPack ) . ConfigureAwait ( false ) ) {
if ( ! await Bot . ArchiWebHandler . UnpackBooster ( item . RealAppID , item . AssetID ) . ConfigureAwait ( false ) ) {
completeSuccess = false ;
}
2019-05-19 15:38:06 +02:00
}
2020-08-11 11:34:32 +02:00
} catch ( HttpRequestException e ) {
Bot . ArchiLogger . LogGenericWarningException ( e ) ;
Use IAsyncEnumerable for getting inventory (#1652)
* Use IAsyncEnumerable for getting inventory
* Don't suppress exceptions, catch them in ResponseUnpackBoosters
* Make sure we don't get duplicate assets during unpack
* Rewrite inventory filters to LINQ methods
* Add handling duplicate items, mark GetInventory as obsolete, catch exceptions from getting inventory errors
* Mark GetInventoryEnumerable as NotNull, don't check received inventory for null, use comparison with nullable values
* Use specific types of exceptions, log exceptions using LogGenericWarningException, handle IOException separately (without logging the exception), remove default null value
* Use old method signature for obsolete API
* Use error level for generic exceptions
* Fix wantedSets not being used
* Correct exception types, rename function
* Replace exception types
* Make SendTradeOfferAsync that accepts Func<Steam.Asset, bool> as a filter
* Fix missing targetSteamID in ResponseTransferByRealAppIDs
* Make parameter name readable
* Rename method
2020-02-22 20:03:22 +03:00
completeSuccess = false ;
} catch ( Exception e ) {
Bot . ArchiLogger . LogGenericException ( e ) ;
completeSuccess = false ;
2018-09-15 22:34:32 +02:00
}
2019-05-19 15:38:06 +02:00
return FormatBotResponse ( completeSuccess ? Strings . Success : Strings . Done ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseUnpackBoosters ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > bot . Commands . ResponseUnpackBoosters ( steamID ) ) ) . ConfigureAwait ( false ) ;
2018-09-15 22:34:32 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-09-15 22:34:32 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseUpdate ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
if ( ! ASF . IsOwner ( steamID ) ) {
return null ;
}
2020-08-22 21:41:01 +02:00
( bool success , string? message , Version ? version ) = await Actions . Update ( ) . ConfigureAwait ( false ) ;
2018-12-15 00:27:15 +01:00
2019-01-18 17:07:00 +01:00
return FormatStaticResponse ( ( success ? Strings . Success : Strings . WarningFailed ) + ( ! string . IsNullOrEmpty ( message ) ? " " + message : version ! = null ? " " + version : "" ) ) ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private string? ResponseVersion ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-09-15 22:34:32 +02:00
}
2019-01-12 18:48:00 +01:00
return Bot . HasPermission ( steamID , BotConfig . EPermission . Operator ) ? FormatBotResponse ( string . Format ( Strings . BotVersion , SharedInfo . ASF , SharedInfo . Version ) ) : null ;
2018-09-15 22:34:32 +02:00
}
2020-08-22 21:41:01 +02:00
private string? ResponseWalletBalance ( ulong steamID ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount ) {
throw new ArgumentNullException ( nameof ( steamID ) ) ;
2018-11-03 19:42:40 +02:00
}
2019-01-12 18:48:00 +01:00
if ( ! Bot . HasPermission ( steamID , BotConfig . EPermission . Master ) ) {
2018-11-03 19:42:40 +02:00
return null ;
}
2018-11-04 19:47:48 +01:00
return ! Bot . IsConnectedAndLoggedOn ? FormatBotResponse ( Strings . BotNotConnected ) : FormatBotResponse ( Bot . WalletCurrency ! = ECurrencyCode . Invalid ? string . Format ( Strings . BotWalletBalance , Bot . WalletBalance / 100.0 , Bot . WalletCurrency . ToString ( ) ) : Strings . BotHasNoWallet ) ;
2018-11-03 19:42:40 +02:00
}
2020-08-22 21:41:01 +02:00
private static async Task < string? > ResponseWalletBalance ( ulong steamID , string botNames ) {
if ( ( steamID = = 0 ) | | ! new SteamID ( steamID ) . IsIndividualAccount | | string . IsNullOrEmpty ( botNames ) ) {
throw new ArgumentNullException ( nameof ( steamID ) + " || " + nameof ( botNames ) ) ;
2018-11-03 19:42:40 +02:00
}
2020-08-22 21:41:01 +02:00
HashSet < Bot > ? bots = Bot . GetBots ( botNames ) ;
2018-12-15 00:27:15 +01:00
2018-11-03 19:42:40 +02:00
if ( ( bots = = null ) | | ( bots . Count = = 0 ) ) {
return ASF . IsOwner ( steamID ) ? FormatStaticResponse ( string . Format ( Strings . BotNotFound , botNames ) ) : null ;
}
2020-08-22 21:41:01 +02:00
IList < string? > results = await Utilities . InParallel ( bots . Select ( bot = > Task . Run ( ( ) = > bot . Commands . ResponseWalletBalance ( steamID ) ) ) ) . ConfigureAwait ( false ) ;
2018-11-03 19:42:40 +02:00
2020-08-22 21:41:01 +02:00
List < string > responses = new List < string > ( results . Where ( result = > ! string . IsNullOrEmpty ( result ) ) ! ) ;
2018-12-15 00:27:15 +01:00
2018-11-03 19:42:40 +02:00
return responses . Count > 0 ? string . Join ( Environment . NewLine , responses ) : null ;
}
2018-09-15 22:34:32 +02:00
[Flags]
2019-08-05 15:41:37 +03:00
private enum ERedeemFlags : ushort {
2018-09-15 22:34:32 +02:00
None = 0 ,
Validate = 1 ,
ForceForwarding = 2 ,
SkipForwarding = 4 ,
ForceDistributing = 8 ,
SkipDistributing = 16 ,
SkipInitial = 32 ,
ForceKeepMissingGames = 64 ,
2019-08-05 15:41:37 +03:00
SkipKeepMissingGames = 128 ,
ForceAssumeWalletKeyOnBadActivationCode = 256 ,
SkipAssumeWalletKeyOnBadActivationCode = 512
2018-09-15 22:34:32 +02:00
}
}
}