2015-10-28 19:21:27 +01:00
/ *
_ _ _ ____ _ _____
/ \ _ __ ___ | | __ ( _ ) / ___ | | | _ ___ __ _ _ __ ___ | ___ | __ _ _ __ _ __ ___
/ _ \ | ' __ | / __ | | ' _ \ | | \ ___ \ | __ | / _ \ / _ ` | | ' _ ` _ \ | | _ / _ ` | | ' __ | | ' _ ` _ \
/ ___ \ | | | ( __ | | | | | | ___ ) | | | _ | __ / | ( _ | | | | | | | | | _ | | ( _ | | | | | | | | | |
/ _ / \ _ \ | _ | \ ___ | | _ | | _ | | _ | | ____ / \ __ | \ ___ | \ __ , _ | | _ | | _ | | _ | | _ | \ __ , _ | | _ | | _ | | _ | | _ |
2016-01-16 04:21:36 +01:00
Copyright 2015 - 2016 Ł ukasz "JustArchi" Domeradzki
2015-10-28 19:21:27 +01:00
Contact : JustArchi @JustArchi . net
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
2015-12-11 22:53:28 +01:00
using Newtonsoft.Json ;
2015-10-28 19:21:27 +01:00
using SteamKit2 ;
2015-12-21 10:24:29 +01:00
using SteamKit2.Internal ;
2015-10-25 06:16:50 +01:00
using System ;
using System.Collections.Generic ;
using System.IO ;
2016-05-13 06:32:42 +02:00
using System.Linq ;
2015-10-25 06:16:50 +01:00
using System.Security.Cryptography ;
2016-01-13 11:17:58 +02:00
using System.Threading ;
2015-10-25 06:16:50 +01:00
using System.Threading.Tasks ;
2016-01-10 20:22:46 +02:00
using System.Text ;
2016-04-20 23:44:20 +02:00
using System.Text.RegularExpressions ;
2016-05-13 06:32:42 +02:00
using ArchiSteamFarm.JSON ;
2016-07-08 09:02:53 +02:00
using SteamKit2.Discovery ;
2015-10-25 06:16:50 +01:00
namespace ArchiSteamFarm {
2016-07-08 07:41:36 +02:00
internal sealed class Bot : IDisposable {
2015-12-21 10:06:37 +01:00
private const ulong ArchiSCFarmGroup = 103582791440160998 ;
2015-10-28 19:21:27 +01:00
private const ushort CallbackSleep = 500 ; // In miliseconds
2016-04-07 03:14:49 +02:00
private const ushort MaxSteamMessageLength = 2048 ;
2015-10-25 06:16:50 +01:00
2016-03-06 14:09:08 +01:00
internal static readonly Dictionary < string , Bot > Bots = new Dictionary < string , Bot > ( ) ;
2015-12-23 09:40:42 +01:00
2016-02-22 18:34:45 +01:00
private static readonly uint LoginID = MsgClientLogon . ObfuscationMask ; // This must be the same for all ASF bots and all ASF processes
2016-06-24 22:26:52 +02:00
private static readonly SemaphoreSlim GiftsSemaphore = new SemaphoreSlim ( 1 ) ;
2016-04-24 23:32:23 +02:00
private static readonly SemaphoreSlim LoginSemaphore = new SemaphoreSlim ( 1 ) ;
2016-02-22 18:34:45 +01:00
internal readonly string BotName ;
internal readonly ArchiHandler ArchiHandler ;
internal readonly ArchiWebHandler ArchiWebHandler ;
2016-03-06 02:20:41 +01:00
internal readonly BotConfig BotConfig ;
2016-02-22 18:34:45 +01:00
internal readonly SteamClient SteamClient ;
2016-03-18 14:39:59 +01:00
private readonly string SentryFile ;
2016-05-13 06:32:42 +02:00
private readonly BotDatabase BotDatabase ;
2016-01-22 11:01:33 +01:00
private readonly CallbackManager CallbackManager ;
2016-06-20 21:20:38 +02:00
[JsonProperty]
2016-01-22 11:01:33 +01:00
private readonly CardsFarmer CardsFarmer ;
2016-06-20 21:20:38 +02:00
2016-06-24 20:27:23 +02:00
private readonly ConcurrentHashSet < ulong > HandledGifts = new ConcurrentHashSet < ulong > ( ) ;
2016-01-22 11:01:33 +01:00
private readonly SteamApps SteamApps ;
private readonly SteamFriends SteamFriends ;
private readonly SteamUser SteamUser ;
2016-06-13 18:08:19 +02:00
private readonly Timer AcceptConfirmationsTimer , SendItemsTimer ;
2016-01-22 11:01:33 +01:00
private readonly Trading Trading ;
2015-10-25 06:16:50 +01:00
2016-06-20 21:20:38 +02:00
[JsonProperty]
2016-03-26 22:51:19 +01:00
internal bool KeepRunning { get ; private set ; }
2016-06-20 21:20:38 +02:00
2016-05-30 00:09:42 +02:00
internal bool PlayingBlocked { get ; private set ; }
2015-10-31 03:27:58 +01:00
2016-05-30 00:09:42 +02:00
private bool FirstTradeSent , InvalidPassword , SkipFirstShutdown ;
2016-04-08 17:12:08 +02:00
private string AuthCode , TwoFactorCode ;
2016-01-07 22:29:55 +01:00
2016-07-08 09:02:53 +02:00
internal static void InitializeCMs ( uint cellID , IServerListProvider serverListProvider ) {
if ( serverListProvider = = null ) {
Logging . LogNullError ( nameof ( serverListProvider ) ) ;
return ;
2016-01-24 17:38:45 +01:00
}
2016-02-21 22:19:55 +01:00
2016-07-08 09:02:53 +02:00
CMClient . Servers . CellID = cellID ;
CMClient . Servers . ServerListProvider = serverListProvider ;
2016-01-24 17:38:45 +01:00
}
2016-03-18 09:02:09 +01:00
private static bool IsOwner ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID ! = 0 ) {
return steamID = = Program . GlobalConfig . SteamOwnerID ;
2016-03-18 09:02:09 +01:00
}
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) ) ;
return false ;
2016-03-18 09:02:09 +01:00
}
2016-05-30 01:57:06 +02:00
private static bool IsValidCdKey ( string key ) {
if ( ! string . IsNullOrEmpty ( key ) ) {
2016-07-16 00:18:36 +02:00
return Regex . IsMatch ( key , @"^[0-9A-Z]{4,5}-[0-9A-Z]{4,5}-[0-9A-Z]{4,5}(?:(?:-[0-9A-Z]{4,5})?(?:-[0-9A-Z]{4,5}))?$" , RegexOptions . IgnoreCase ) ;
2016-05-30 01:57:06 +02:00
}
Logging . LogNullError ( nameof ( key ) ) ;
return false ;
}
2016-02-22 18:34:45 +01:00
2016-06-24 22:26:52 +02:00
private static async Task LimitGiftsRequestsAsync ( ) {
await GiftsSemaphore . WaitAsync ( ) . ConfigureAwait ( false ) ;
Task . Run ( async ( ) = > {
await Task . Delay ( Program . GlobalConfig . GiftsLimiterDelay * 1000 ) . ConfigureAwait ( false ) ;
GiftsSemaphore . Release ( ) ;
} ) . Forget ( ) ;
}
2016-04-24 23:32:23 +02:00
private static async Task LimitLoginRequestsAsync ( ) {
await LoginSemaphore . WaitAsync ( ) . ConfigureAwait ( false ) ;
2016-04-23 16:36:43 +02:00
Task . Run ( async ( ) = > {
2016-06-24 22:26:52 +02:00
await Task . Delay ( Program . GlobalConfig . LoginLimiterDelay * 1000 ) . ConfigureAwait ( false ) ;
2016-04-24 23:32:23 +02:00
LoginSemaphore . Release ( ) ;
2016-04-23 16:36:43 +02:00
} ) . Forget ( ) ;
}
2016-02-12 16:06:57 +01:00
internal Bot ( string botName ) {
2016-02-26 22:39:03 +01:00
if ( string . IsNullOrEmpty ( botName ) ) {
2016-05-13 06:32:42 +02:00
throw new ArgumentNullException ( nameof ( botName ) ) ;
2015-11-01 02:04:44 +01:00
}
2016-06-27 00:38:38 +02:00
if ( Bots . ContainsKey ( botName ) ) {
throw new Exception ( "That bot is already defined!" ) ;
}
2015-10-25 06:16:50 +01:00
2016-02-22 18:34:45 +01:00
string botPath = Path . Combine ( Program . ConfigDirectory , botName ) ;
2015-10-25 06:16:50 +01:00
2016-06-27 00:38:38 +02:00
BotName = botName ;
SentryFile = botPath + ".bin" ;
2016-03-06 02:20:41 +01:00
BotConfig = BotConfig . Load ( botPath + ".json" ) ;
if ( BotConfig = = null ) {
2016-03-26 22:12:55 +01:00
Logging . LogGenericError ( "Your bot config is invalid, refusing to start this bot instance!" , botName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2015-10-28 19:21:27 +01:00
2016-03-06 02:20:41 +01:00
if ( ! BotConfig . Enabled ) {
2016-06-13 18:08:19 +02:00
Logging . LogGenericInfo ( "Not initializing this instance because it's disabled in config file" , botName ) ;
2016-02-26 22:39:03 +01:00
return ;
}
2016-02-05 20:10:15 +01:00
2016-04-24 23:32:23 +02:00
BotDatabase = BotDatabase . Load ( botPath + ".db" ) ;
if ( BotDatabase = = null ) {
Logging . LogGenericError ( "Bot database could not be loaded, refusing to start this bot instance!" , botName ) ;
return ;
}
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator ! = null ) {
BotDatabase . MobileAuthenticator . Init ( this ) ;
} else {
2016-03-18 14:39:59 +01:00
// Support and convert SDA files
string maFilePath = botPath + ".maFile" ;
if ( File . Exists ( maFilePath ) ) {
ImportAuthenticator ( maFilePath ) ;
}
2016-03-07 15:42:38 +01:00
}
2015-10-31 03:27:58 +01:00
// Initialize
2016-03-19 11:33:39 +01:00
SteamClient = new SteamClient ( Program . GlobalConfig . SteamProtocol ) ;
2015-10-31 03:27:58 +01:00
2016-03-13 21:22:52 +01:00
if ( Program . GlobalConfig . Debug & & ! Debugging . NetHookAlreadyInitialized & & Directory . Exists ( Program . DebugDirectory ) ) {
2016-03-07 18:12:05 +01:00
try {
Debugging . NetHookAlreadyInitialized = true ;
2016-04-24 23:32:23 +02:00
SteamClient . DebugNetworkListener = new NetHookNetworkListener ( Program . DebugDirectory ) ;
2016-03-07 18:12:05 +01:00
} catch ( Exception e ) {
Logging . LogGenericException ( e , botName ) ;
}
}
2016-04-08 04:30:51 +02:00
ArchiHandler = new ArchiHandler ( this ) ;
2015-10-31 03:27:58 +01:00
SteamClient . AddHandler ( ArchiHandler ) ;
CallbackManager = new CallbackManager ( SteamClient ) ;
CallbackManager . Subscribe < SteamClient . ConnectedCallback > ( OnConnected ) ;
CallbackManager . Subscribe < SteamClient . DisconnectedCallback > ( OnDisconnected ) ;
2016-01-22 10:56:06 +01:00
SteamApps = SteamClient . GetHandler < SteamApps > ( ) ;
CallbackManager . Subscribe < SteamApps . FreeLicenseCallback > ( OnFreeLicense ) ;
2016-03-27 23:07:00 +02:00
CallbackManager . Subscribe < SteamApps . GuestPassListCallback > ( OnGuestPassList ) ;
2016-01-22 10:56:06 +01:00
2015-10-31 03:27:58 +01:00
SteamFriends = SteamClient . GetHandler < SteamFriends > ( ) ;
2015-12-21 19:28:59 +01:00
CallbackManager . Subscribe < SteamFriends . ChatInviteCallback > ( OnChatInvite ) ;
CallbackManager . Subscribe < SteamFriends . ChatMsgCallback > ( OnChatMsg ) ;
2015-10-31 03:27:58 +01:00
CallbackManager . Subscribe < SteamFriends . FriendsListCallback > ( OnFriendsList ) ;
CallbackManager . Subscribe < SteamFriends . FriendMsgCallback > ( OnFriendMsg ) ;
2015-12-21 10:55:55 +01:00
CallbackManager . Subscribe < SteamFriends . FriendMsgHistoryCallback > ( OnFriendMsgHistory ) ;
2015-10-31 03:27:58 +01:00
SteamUser = SteamClient . GetHandler < SteamUser > ( ) ;
CallbackManager . Subscribe < SteamUser . AccountInfoCallback > ( OnAccountInfo ) ;
CallbackManager . Subscribe < SteamUser . LoggedOffCallback > ( OnLoggedOff ) ;
CallbackManager . Subscribe < SteamUser . LoggedOnCallback > ( OnLoggedOn ) ;
2015-12-11 22:53:28 +01:00
CallbackManager . Subscribe < SteamUser . LoginKeyCallback > ( OnLoginKey ) ;
2015-10-31 03:27:58 +01:00
CallbackManager . Subscribe < SteamUser . UpdateMachineAuthCallback > ( OnMachineAuth ) ;
2016-03-29 14:33:05 +02:00
CallbackManager . Subscribe < SteamUser . WebAPIUserNonceCallback > ( OnWebAPIUserNonce ) ;
2015-10-31 03:27:58 +01:00
2016-01-02 17:22:35 +01:00
CallbackManager . Subscribe < ArchiHandler . NotificationsCallback > ( OnNotifications ) ;
2015-12-20 19:48:58 +01:00
CallbackManager . Subscribe < ArchiHandler . OfflineMessageCallback > ( OnOfflineMessage ) ;
2016-05-30 00:09:42 +02:00
CallbackManager . Subscribe < ArchiHandler . PlayingSessionStateCallback > ( OnPlayingSessionState ) ;
2015-10-31 03:27:58 +01:00
CallbackManager . Subscribe < ArchiHandler . PurchaseResponseCallback > ( OnPurchaseResponse ) ;
2016-03-06 02:20:41 +01:00
ArchiWebHandler = new ArchiWebHandler ( this ) ;
2015-10-31 03:27:58 +01:00
CardsFarmer = new CardsFarmer ( this ) ;
Trading = new Trading ( this ) ;
2016-05-13 06:32:42 +02:00
if ( ( AcceptConfirmationsTimer = = null ) & & ( BotConfig . AcceptConfirmationsPeriod > 0 ) ) {
2016-03-10 21:17:48 +01:00
AcceptConfirmationsTimer = new Timer (
2016-04-05 03:41:59 +02:00
async e = > await AcceptConfirmations ( true ) . ConfigureAwait ( false ) ,
2016-03-10 21:17:48 +01:00
null ,
2016-07-13 20:02:50 +02:00
TimeSpan . FromMinutes ( BotConfig . AcceptConfirmationsPeriod ) + TimeSpan . FromMinutes ( Bots . Count ) , // Delay
2016-03-10 22:54:59 +01:00
TimeSpan . FromMinutes ( BotConfig . AcceptConfirmationsPeriod ) // Period
2016-03-10 21:17:48 +01:00
) ;
}
2016-05-13 06:32:42 +02:00
if ( ( SendItemsTimer = = null ) & & ( BotConfig . SendTradePeriod > 0 ) ) {
2016-01-14 02:24:55 +01:00
SendItemsTimer = new Timer (
2016-06-24 16:58:49 +02:00
async e = > await ResponseLoot ( BotConfig . SteamMasterID ) . ConfigureAwait ( false ) ,
2016-01-14 02:24:55 +01:00
null ,
2016-07-13 20:02:50 +02:00
TimeSpan . FromHours ( BotConfig . SendTradePeriod ) + TimeSpan . FromMinutes ( Bots . Count ) , // Delay
2016-03-06 02:20:41 +01:00
TimeSpan . FromHours ( BotConfig . SendTradePeriod ) // Period
2016-01-14 02:48:56 +01:00
) ;
2016-01-14 02:24:55 +01:00
}
2016-02-05 20:11:04 +01:00
2016-06-27 00:38:38 +02:00
// Register bot as available for ASF
Bots [ botName ] = this ;
2016-03-06 02:20:41 +01:00
if ( ! BotConfig . StartOnLaunch ) {
2016-02-05 20:11:04 +01:00
return ;
}
2016-01-14 02:24:55 +01:00
2015-10-31 03:27:58 +01:00
// Start
2016-03-22 11:21:45 +01:00
Start ( ) . Forget ( ) ;
2015-10-25 06:16:50 +01:00
}
2016-07-08 07:41:36 +02:00
public void Dispose ( ) {
GiftsSemaphore . Dispose ( ) ;
LoginSemaphore . Dispose ( ) ;
HandledGifts . Dispose ( ) ;
2016-07-10 20:17:35 +02:00
AcceptConfirmationsTimer ? . Dispose ( ) ;
ArchiWebHandler ? . Dispose ( ) ;
CardsFarmer ? . Dispose ( ) ;
SendItemsTimer ? . Dispose ( ) ;
Trading ? . Dispose ( ) ;
2016-07-08 07:41:36 +02:00
}
2016-06-19 07:25:02 +02:00
internal async Task AcceptConfirmations ( bool accept , Steam . ConfirmationDetails . EType acceptedType = Steam . ConfirmationDetails . EType . Unknown , ulong acceptedSteamID = 0 , HashSet < ulong > acceptedTradeIDs = null ) {
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator = = null ) {
return ;
2015-12-11 22:53:28 +01:00
}
2016-04-27 20:06:17 +02:00
2016-06-19 05:40:46 +02:00
HashSet < MobileAuthenticator . Confirmation > confirmations = await BotDatabase . MobileAuthenticator . GetConfirmations ( ) . ConfigureAwait ( false ) ;
2016-06-19 07:25:02 +02:00
if ( ( confirmations = = null ) | | ( confirmations . Count = = 0 ) ) {
2016-06-19 05:40:46 +02:00
return ;
2016-04-27 20:06:17 +02:00
}
2016-06-19 07:25:02 +02:00
if ( acceptedType ! = Steam . ConfirmationDetails . EType . Unknown ) {
2016-06-20 14:40:14 +02:00
if ( confirmations . RemoveWhere ( confirmation = > ( confirmation . Type ! = acceptedType ) & & ( confirmation . Type ! = Steam . ConfirmationDetails . EType . Other ) ) > 0 ) {
2016-06-19 07:25:02 +02:00
if ( confirmations . Count = = 0 ) {
return ;
}
}
}
if ( ( acceptedSteamID ! = 0 ) | | ( ( acceptedTradeIDs ! = null ) & & ( acceptedTradeIDs . Count > 0 ) ) ) {
2016-07-02 22:05:29 +02:00
Steam . ConfirmationDetails [ ] detailsResults = await Task . WhenAll ( confirmations . Select ( BotDatabase . MobileAuthenticator . GetConfirmationDetails ) ) . ConfigureAwait ( false ) ;
2016-06-20 06:51:42 +02:00
2016-07-15 16:13:36 +02:00
HashSet < MobileAuthenticator . Confirmation > ignoredConfirmations = new HashSet < MobileAuthenticator . Confirmation > ( detailsResults . Where ( details = > ( details ! = null ) & & (
2016-06-20 06:51:42 +02:00
( ( acceptedSteamID ! = 0 ) & & ( details . OtherSteamID64 ! = 0 ) & & ( acceptedSteamID ! = details . OtherSteamID64 ) ) | |
( ( acceptedTradeIDs ! = null ) & & ( details . TradeOfferID ! = 0 ) & & ! acceptedTradeIDs . Contains ( details . TradeOfferID ) )
2016-07-15 16:13:36 +02:00
) ) . Select ( details = > details . Confirmation ) ) ;
2016-06-19 07:25:02 +02:00
2016-07-15 16:13:36 +02:00
if ( ignoredConfirmations . Count > 0 ) {
confirmations . ExceptWith ( ignoredConfirmations ) ;
if ( confirmations . Count = = 0 ) {
return ;
2016-06-20 06:51:42 +02:00
}
2016-06-19 07:25:02 +02:00
}
}
2016-07-15 16:13:36 +02:00
await BotDatabase . MobileAuthenticator . HandleConfirmations ( confirmations , accept ) . ConfigureAwait ( false ) ;
2015-12-11 22:53:28 +01:00
}
2016-03-29 14:33:05 +02:00
internal async Task < bool > RefreshSession ( ) {
2016-03-22 08:53:55 +01:00
if ( ! SteamClient . IsConnected ) {
2016-03-29 14:33:05 +02:00
return false ;
2016-03-22 08:53:55 +01:00
}
2016-04-07 01:45:08 +02:00
SteamUser . WebAPIUserNonceCallback callback ;
try {
callback = await SteamUser . RequestWebAPIUserNonce ( ) ;
} catch ( Exception e ) {
Logging . LogGenericException ( e , BotName ) ;
2016-04-14 21:16:44 +02:00
Start ( ) . Forget ( ) ;
2016-04-07 01:45:08 +02:00
return false ;
}
2016-07-10 20:17:35 +02:00
if ( string . IsNullOrEmpty ( callback ? . Nonce ) ) {
2016-03-29 14:33:05 +02:00
Start ( ) . Forget ( ) ;
return false ;
}
2016-06-25 04:05:30 +02:00
if ( await ArchiWebHandler . Init ( SteamClient . SteamID , SteamClient . ConnectedUniverse , callback . Nonce , BotConfig . SteamParentalPIN ) . ConfigureAwait ( false ) ) {
2016-05-13 06:32:42 +02:00
return true ;
2016-03-29 14:33:05 +02:00
}
2016-05-13 06:32:42 +02:00
Start ( ) . Forget ( ) ;
return false ;
2015-12-22 16:51:37 +01:00
}
2016-06-28 07:14:51 +02:00
internal void Stop ( ) {
2016-06-28 07:18:39 +02:00
if ( ! KeepRunning ) {
return ;
}
2016-06-28 07:14:51 +02:00
Logging . LogGenericInfo ( "Stopping..." , BotName ) ;
KeepRunning = false ;
if ( SteamClient . IsConnected ) {
SteamClient . Disconnect ( ) ;
}
Program . OnBotShutdown ( ) ;
}
2016-06-06 17:38:21 +02:00
internal void OnFarmingStopped ( ) = > ResetGamesPlayed ( ) ;
2016-05-03 15:37:11 +02:00
internal async Task OnFarmingFinished ( bool farmedSomething ) {
2016-06-06 17:38:21 +02:00
OnFarmingStopped ( ) ;
2016-05-03 15:37:11 +02:00
if ( ( farmedSomething | | ! FirstTradeSent ) & & BotConfig . SendOnFarmingFinished ) {
FirstTradeSent = true ;
2016-06-24 16:58:49 +02:00
await ResponseLoot ( BotConfig . SteamMasterID ) . ConfigureAwait ( false ) ;
2016-02-24 06:20:35 +01:00
}
2016-03-18 14:39:59 +01:00
2016-03-06 02:20:41 +01:00
if ( BotConfig . ShutdownOnFarmingFinished ) {
2016-05-18 04:33:17 +02:00
if ( SkipFirstShutdown ) {
SkipFirstShutdown = false ;
} else {
Stop ( ) ;
}
2016-02-24 06:20:35 +01:00
}
}
2016-03-18 09:02:09 +01:00
internal async Task < string > Response ( ulong steamID , string message ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( message ) , BotName ) ;
2016-02-24 06:20:35 +01:00
return null ;
}
2016-04-21 20:14:15 +02:00
if ( message [ 0 ] ! = '!' ) {
2016-06-26 22:38:03 +02:00
if ( ! IsMaster ( steamID ) ) {
return null ;
}
2016-06-01 02:34:38 +02:00
return await ResponseRedeem ( steamID , message , true ) . ConfigureAwait ( false ) ;
2016-02-24 06:20:35 +01:00
}
2016-04-21 20:14:15 +02:00
if ( message . IndexOf ( ' ' ) < 0 ) {
2016-06-26 22:38:03 +02:00
switch ( message . ToUpper ( ) ) {
case "!2FA" :
2016-06-19 05:40:46 +02:00
return await Response2FA ( steamID ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!2FANO" :
2016-04-05 03:41:59 +02:00
return await Response2FAConfirm ( steamID , false ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!2FAOK" :
2016-04-05 03:41:59 +02:00
return await Response2FAConfirm ( steamID , true ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!API" :
2016-06-20 21:20:38 +02:00
return ResponseAPI ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!EXIT" :
2016-03-18 09:02:09 +01:00
return ResponseExit ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!FARM" :
2016-06-09 03:13:35 +02:00
return await ResponseFarm ( steamID ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!HELP" :
2016-03-26 02:47:25 +01:00
return ResponseHelp ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!LOOT" :
2016-06-24 16:58:49 +02:00
return await ResponseLoot ( steamID ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!LOOTALL" :
2016-06-24 16:58:49 +02:00
return await ResponseLootAll ( steamID ) . ConfigureAwait ( false ) ;
2016-06-28 04:32:48 +02:00
case "!PASSWORD" :
return ResponsePassword ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!PAUSE" :
2016-06-20 17:03:55 +02:00
return await ResponsePause ( steamID , true ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!REJOINCHAT" :
2016-03-18 09:02:09 +01:00
return ResponseRejoinChat ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!RESUME" :
2016-06-20 17:03:55 +02:00
return await ResponsePause ( steamID , false ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!RESTART" :
2016-03-18 09:02:09 +01:00
return ResponseRestart ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!STATUS" :
2016-03-18 09:02:09 +01:00
return ResponseStatus ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!STATUSALL" :
2016-03-18 09:02:09 +01:00
return ResponseStatusAll ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!STOP" :
2016-03-22 20:18:47 +01:00
return ResponseStop ( steamID ) ;
2016-06-26 22:38:03 +02:00
case "!UPDATE" :
2016-03-18 09:02:09 +01:00
return await ResponseUpdate ( steamID ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!VERSION" :
2016-06-06 05:27:11 +02:00
return ResponseVersion ( steamID ) ;
2016-02-24 06:20:35 +01:00
default :
2016-03-18 14:39:59 +01:00
return ResponseUnknown ( steamID ) ;
2016-02-24 06:20:35 +01:00
}
2016-05-13 06:32:42 +02:00
}
string [ ] args = message . Split ( ( char [ ] ) null , StringSplitOptions . RemoveEmptyEntries ) ;
2016-06-26 22:38:03 +02:00
switch ( args [ 0 ] . ToUpper ( ) ) {
case "!2FA" :
2016-06-19 05:40:46 +02:00
return await Response2FA ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!2FANO" :
2016-05-13 06:32:42 +02:00
return await Response2FAConfirm ( steamID , args [ 1 ] , false ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!2FAOK" :
2016-05-13 06:32:42 +02:00
return await Response2FAConfirm ( steamID , args [ 1 ] , true ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!ADDLICENSE" :
2016-05-13 06:32:42 +02:00
if ( args . Length > 2 ) {
return await ResponseAddLicense ( steamID , args [ 1 ] , args [ 2 ] ) . ConfigureAwait ( false ) ;
}
return await ResponseAddLicense ( steamID , BotName , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!FARM" :
2016-06-09 03:13:35 +02:00
return await ResponseFarm ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!LOOT" :
2016-06-24 16:58:49 +02:00
return await ResponseLoot ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!OWNS" :
2016-05-13 06:32:42 +02:00
if ( args . Length > 2 ) {
return await ResponseOwns ( steamID , args [ 1 ] , args [ 2 ] ) . ConfigureAwait ( false ) ;
}
return await ResponseOwns ( steamID , BotName , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-28 04:32:48 +02:00
case "!PASSWORD" :
return ResponsePassword ( steamID , args [ 1 ] ) ;
2016-06-26 22:38:03 +02:00
case "!PAUSE" :
2016-06-20 17:03:55 +02:00
return await ResponsePause ( steamID , args [ 1 ] , true ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!PLAY" :
2016-05-13 06:32:42 +02:00
if ( args . Length > 2 ) {
return await ResponsePlay ( steamID , args [ 1 ] , args [ 2 ] ) . ConfigureAwait ( false ) ;
}
return await ResponsePlay ( steamID , BotName , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!REDEEM" :
2016-05-13 06:32:42 +02:00
if ( args . Length > 2 ) {
2016-06-01 02:34:38 +02:00
return await ResponseRedeem ( steamID , args [ 1 ] , args [ 2 ] , false ) . ConfigureAwait ( false ) ;
2016-05-13 06:32:42 +02:00
}
2016-06-01 02:34:38 +02:00
return await ResponseRedeem ( steamID , BotName , args [ 1 ] , false ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!RESUME" :
2016-06-20 17:03:55 +02:00
return await ResponsePause ( steamID , args [ 1 ] , false ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!START" :
2016-05-13 06:32:42 +02:00
return await ResponseStart ( steamID , args [ 1 ] ) . ConfigureAwait ( false ) ;
2016-06-26 22:38:03 +02:00
case "!STATUS" :
2016-05-13 06:32:42 +02:00
return ResponseStatus ( steamID , args [ 1 ] ) ;
2016-06-26 22:38:03 +02:00
case "!STOP" :
2016-05-13 06:32:42 +02:00
return ResponseStop ( steamID , args [ 1 ] ) ;
default :
return ResponseUnknown ( steamID ) ;
2016-02-24 06:20:35 +01:00
}
}
private async Task Start ( ) {
2016-02-05 20:10:15 +01:00
if ( ! KeepRunning ) {
KeepRunning = true ;
2016-03-06 22:14:02 +01:00
Task . Run ( ( ) = > HandleCallbacks ( ) ) . Forget ( ) ;
2016-02-05 20:10:15 +01:00
}
2016-04-23 16:34:00 +02:00
// 2FA tokens are expiring soon, don't use limiter when user is providing one
2016-06-19 05:40:46 +02:00
if ( ( TwoFactorCode = = null ) | | ( BotDatabase . MobileAuthenticator ! = null ) ) {
2016-04-24 23:32:23 +02:00
await LimitLoginRequestsAsync ( ) . ConfigureAwait ( false ) ;
2015-12-06 19:38:09 +01:00
}
2016-03-22 20:18:47 +01:00
Logging . LogGenericInfo ( "Starting..." , BotName ) ;
2015-11-04 04:31:27 +01:00
SteamClient . Connect ( ) ;
2015-10-25 06:16:50 +01:00
}
2016-03-26 02:47:25 +01:00
private bool IsMaster ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID ! = 0 ) {
return ( steamID = = BotConfig . SteamMasterID ) | | IsOwner ( steamID ) ;
2016-03-26 02:47:25 +01:00
}
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
return false ;
2016-03-26 02:47:25 +01:00
}
2016-03-12 05:58:51 +01:00
private void ImportAuthenticator ( string maFilePath ) {
2016-06-19 05:40:46 +02:00
if ( ( BotDatabase . MobileAuthenticator ! = null ) | | ! File . Exists ( maFilePath ) ) {
2016-03-12 05:58:51 +01:00
return ;
}
2016-06-19 05:40:46 +02:00
Logging . LogGenericInfo ( "Converting .maFile into ASF format..." , BotName ) ;
2016-05-30 01:57:06 +02:00
2016-03-12 05:58:51 +01:00
try {
2016-06-19 05:40:46 +02:00
BotDatabase . MobileAuthenticator = JsonConvert . DeserializeObject < MobileAuthenticator > ( File . ReadAllText ( maFilePath ) ) ;
2016-03-12 05:58:51 +01:00
File . Delete ( maFilePath ) ;
} catch ( Exception e ) {
Logging . LogGenericException ( e , BotName ) ;
return ;
}
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator = = null ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( BotDatabase . MobileAuthenticator ) , BotName ) ;
2016-03-12 05:58:51 +01:00
return ;
}
2016-06-19 05:40:46 +02:00
BotDatabase . MobileAuthenticator . Init ( this ) ;
2016-03-12 05:58:51 +01:00
2016-06-19 05:40:46 +02:00
if ( ! BotDatabase . MobileAuthenticator . HasDeviceID ) {
string deviceID = Program . GetUserInput ( Program . EUserInputType . DeviceID , BotName ) ;
if ( string . IsNullOrEmpty ( deviceID ) ) {
BotDatabase . MobileAuthenticator = null ;
return ;
2016-03-12 05:58:51 +01:00
}
2016-06-19 05:40:46 +02:00
BotDatabase . MobileAuthenticator . CorrectDeviceID ( deviceID ) ;
BotDatabase . Save ( ) ;
2016-03-12 05:58:51 +01:00
}
Logging . LogGenericInfo ( "Successfully finished importing mobile authenticator!" , BotName ) ;
}
2016-06-28 04:32:48 +02:00
private string ResponsePassword ( ulong steamID ) {
if ( steamID = = 0 ) {
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
return null ;
}
if ( ! IsMaster ( steamID ) ) {
return null ;
}
if ( string . IsNullOrEmpty ( BotConfig . SteamPassword ) ) {
return "Can't encrypt null password!" ;
}
2016-06-28 05:24:30 +02:00
return Environment . NewLine +
"[" + CryptoHelper . ECryptoMethod . AES + "] password: " + CryptoHelper . Encrypt ( CryptoHelper . ECryptoMethod . AES , BotConfig . SteamPassword ) + Environment . NewLine +
"[" + CryptoHelper . ECryptoMethod . ProtectedDataForCurrentUser + "] password: " + CryptoHelper . Encrypt ( CryptoHelper . ECryptoMethod . ProtectedDataForCurrentUser , BotConfig . SteamPassword ) ;
2016-06-28 04:32:48 +02:00
}
private static string ResponsePassword ( ulong steamID , string botName ) {
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
return null ;
}
Bot bot ;
if ( Bots . TryGetValue ( botName , out bot ) ) {
return bot . ResponsePassword ( steamID ) ;
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
}
return null ;
}
2016-06-20 17:03:55 +02:00
private async Task < string > ResponsePause ( ulong steamID , bool pause ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-24 14:18:07 +01:00
return null ;
}
2016-06-20 17:03:55 +02:00
if ( pause ) {
if ( CardsFarmer . ManualMode ) {
return "Automatic farming is stopped already!" ;
}
await CardsFarmer . SwitchToManualMode ( true ) . ConfigureAwait ( false ) ;
return "Automatic farming is now stopped!" ;
}
if ( ! CardsFarmer . ManualMode ) {
return "Automatic farming is enabled already!" ;
2016-03-24 14:18:07 +01:00
}
2016-05-13 06:32:42 +02:00
2016-06-20 17:03:55 +02:00
await CardsFarmer . SwitchToManualMode ( false ) . ConfigureAwait ( false ) ;
return "Automatic farming is now enabled!" ;
2016-03-24 14:18:07 +01:00
}
2016-06-20 17:03:55 +02:00
private static async Task < string > ResponsePause ( ulong steamID , string botName , bool pause ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-03-24 14:18:07 +01:00
return null ;
}
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
2016-06-20 17:03:55 +02:00
return await bot . ResponsePause ( steamID , pause ) . ConfigureAwait ( false ) ;
2016-05-13 06:32:42 +02:00
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2016-03-24 14:18:07 +01:00
}
2016-05-13 06:32:42 +02:00
return null ;
2016-03-24 14:18:07 +01:00
}
2016-03-18 09:02:09 +01:00
private string ResponseStatus ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-06-02 08:21:44 +02:00
if ( ! SteamClient . IsConnected ) {
if ( KeepRunning ) {
return "Bot " + BotName + " is not connected." ;
}
return "Bot " + BotName + " is not running." ;
2016-05-13 06:32:42 +02:00
}
if ( CardsFarmer . ManualMode ) {
2016-04-23 19:14:31 +02:00
return "Bot " + BotName + " is running in manual mode." ;
2016-05-13 06:32:42 +02:00
}
2016-06-02 08:21:44 +02:00
if ( CardsFarmer . CurrentGamesFarming . Count > 0 ) {
return "Bot " + BotName + " is farming appIDs: " + string . Join ( ", " , CardsFarmer . CurrentGamesFarming ) + " and has a total of " + CardsFarmer . GamesToFarm . Count + " games left to farm." ;
2016-02-05 20:10:15 +01:00
}
2016-05-13 06:32:42 +02:00
2016-06-02 08:21:44 +02:00
return "Bot " + BotName + " is not farming anything." ;
2016-02-05 20:10:15 +01:00
}
2016-03-18 09:02:09 +01:00
private static string ResponseStatus ( ulong steamID , string botName ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-01-03 22:23:30 +01:00
return null ;
2016-01-10 18:50:17 +02:00
}
2015-11-18 22:10:24 +01:00
2016-01-10 19:31:21 +01:00
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
return bot . ResponseStatus ( steamID ) ;
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2015-11-18 22:10:24 +01:00
}
2016-01-10 19:31:21 +01:00
2016-05-13 06:32:42 +02:00
return null ;
2016-01-10 19:35:03 +01:00
}
2016-01-10 20:22:46 +02:00
2016-03-18 09:02:09 +01:00
private static string ResponseStatusAll ( ulong steamID ) {
if ( steamID = = 0 ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) ) ;
2016-03-18 09:02:09 +01:00
return null ;
}
if ( ! IsOwner ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-01-10 19:31:21 +01:00
StringBuilder result = new StringBuilder ( Environment . NewLine ) ;
2016-02-05 20:10:15 +01:00
2016-03-21 16:31:59 +01:00
byte runningBotsCount = 0 ;
2016-01-10 19:35:03 +01:00
foreach ( Bot bot in Bots . Values ) {
2016-03-18 09:02:09 +01:00
result . Append ( bot . ResponseStatus ( steamID ) + Environment . NewLine ) ;
2016-02-05 20:10:15 +01:00
if ( bot . KeepRunning ) {
runningBotsCount + + ;
}
2016-01-10 19:39:12 +02:00
}
2016-01-10 19:35:03 +01:00
2016-03-26 19:39:46 +01:00
result . Append ( "There are " + runningBotsCount + "/" + Bots . Count + " bots running." ) ;
2016-01-10 20:22:46 +02:00
return result . ToString ( ) ;
2016-01-10 19:39:12 +02:00
}
2016-06-24 16:58:49 +02:00
private async Task < string > ResponseLoot ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-03-06 02:20:41 +01:00
if ( BotConfig . SteamMasterID = = 0 ) {
2016-01-14 01:30:12 +01:00
return "Trade couldn't be send because SteamMasterID is not defined!" ;
2016-01-13 11:17:58 +02:00
}
2016-01-14 01:30:12 +01:00
2016-06-12 23:01:17 +02:00
if ( BotConfig . SteamMasterID = = SteamClient . SteamID ) {
return "You can't loot yourself!" ;
}
2016-01-26 23:05:53 +01:00
await Trading . LimitInventoryRequestsAsync ( ) . ConfigureAwait ( false ) ;
2016-07-19 20:14:21 +02:00
HashSet < Steam . Item > inventory = await ArchiWebHandler . GetMySteamInventory ( true ) . ConfigureAwait ( false ) ;
2016-05-13 06:32:42 +02:00
if ( ( inventory = = null ) | | ( inventory . Count = = 0 ) ) {
2016-01-14 01:30:12 +01:00
return "Nothing to send, inventory seems empty!" ;
2016-01-13 11:17:58 +02:00
}
2016-01-14 01:30:12 +01:00
2016-04-21 00:56:15 +02:00
// Remove from our pending inventory all items that are not steam cards and boosters
2016-05-13 06:32:42 +02:00
inventory . RemoveWhere ( item = > ( item . Type ! = Steam . Item . EType . TradingCard ) & & ( item . Type ! = Steam . Item . EType . FoilTradingCard ) & & ( item . Type ! = Steam . Item . EType . BoosterPack ) ) ;
2016-04-25 11:10:39 +02:00
2016-04-21 00:56:15 +02:00
if ( inventory . Count = = 0 ) {
return "Nothing to send, inventory seems empty!" ;
}
2016-05-13 06:32:42 +02:00
if ( ! await ArchiWebHandler . SendTradeOffer ( inventory , BotConfig . SteamMasterID , BotConfig . SteamTradeToken ) . ConfigureAwait ( false ) ) {
2016-01-14 01:30:12 +01:00
return "Trade offer failed due to error!" ;
2016-01-13 11:17:58 +02:00
}
2016-05-13 06:32:42 +02:00
2016-06-25 07:03:39 +02:00
await Task . Delay ( 1000 ) . ConfigureAwait ( false ) ; // Sometimes we can be too fast for Steam servers to generate confirmations, wait a short moment
2016-06-19 07:25:02 +02:00
await AcceptConfirmations ( true , Steam . ConfirmationDetails . EType . Trade , BotConfig . SteamMasterID ) . ConfigureAwait ( false ) ;
2016-05-13 06:32:42 +02:00
return "Trade offer sent successfully!" ;
2016-01-13 11:17:58 +02:00
}
2016-06-24 16:58:49 +02:00
private static async Task < string > ResponseLoot ( ulong steamID , string botName ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-01-04 00:02:18 +01:00
return null ;
2015-12-11 22:53:28 +01:00
}
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
2016-06-24 16:58:49 +02:00
return await bot . ResponseLoot ( steamID ) . ConfigureAwait ( false ) ;
2016-05-13 06:32:42 +02:00
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2015-12-11 22:53:28 +01:00
}
2016-05-13 06:32:42 +02:00
return null ;
2016-02-05 20:10:15 +01:00
}
2016-06-24 16:58:49 +02:00
private static async Task < string > ResponseLootAll ( ulong steamID ) {
if ( steamID = = 0 ) {
Logging . LogNullError ( nameof ( steamID ) ) ;
return null ;
}
if ( ! IsOwner ( steamID ) ) {
return null ;
}
2016-07-02 22:05:29 +02:00
await Task . WhenAll ( Bots . Values . Select ( bot = > bot . ResponseLoot ( steamID ) ) ) . ConfigureAwait ( false ) ;
2016-06-24 16:58:49 +02:00
return "Done!" ;
}
2016-06-19 05:40:46 +02:00
private async Task < string > Response2FA ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator = = null ) {
2016-01-04 00:02:18 +01:00
return "That bot doesn't have ASF 2FA enabled!" ;
2015-12-11 22:53:28 +01:00
}
2016-06-19 05:40:46 +02:00
byte timeLeft = ( byte ) ( 30 - await BotDatabase . MobileAuthenticator . GetSteamTime ( ) . ConfigureAwait ( false ) % 30 ) ;
return "2FA Token: " + await BotDatabase . MobileAuthenticator . GenerateToken ( ) . ConfigureAwait ( false ) + " (expires in " + timeLeft + " seconds)" ;
2015-12-11 22:53:28 +01:00
}
2016-06-19 05:40:46 +02:00
private static async Task < string > Response2FA ( ulong steamID , string botName ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-01-04 00:02:18 +01:00
return null ;
2015-12-11 22:53:28 +01:00
}
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
2016-06-19 05:40:46 +02:00
return await bot . Response2FA ( steamID ) . ConfigureAwait ( false ) ;
2016-02-05 20:10:15 +01:00
}
2016-05-13 06:32:42 +02:00
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
}
return null ;
2016-02-05 20:10:15 +01:00
}
2016-04-05 03:41:59 +02:00
private async Task < string > Response2FAConfirm ( ulong steamID , bool confirm ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator = = null ) {
2016-03-10 00:40:30 +01:00
return "That bot doesn't have ASF 2FA enabled!" ;
}
2016-04-05 03:41:59 +02:00
await AcceptConfirmations ( confirm ) . ConfigureAwait ( false ) ;
2016-03-10 00:40:30 +01:00
return "Done!" ;
}
2016-04-05 03:41:59 +02:00
private static async Task < string > Response2FAConfirm ( ulong steamID , string botName , bool confirm ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-03-10 00:40:30 +01:00
return null ;
}
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
return await bot . Response2FAConfirm ( steamID , confirm ) . ConfigureAwait ( false ) ;
2016-03-10 00:40:30 +01:00
}
2016-05-13 06:32:42 +02:00
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
}
return null ;
2016-03-10 00:40:30 +01:00
}
2016-06-20 21:20:38 +02:00
private static string ResponseAPI ( ulong steamID ) {
if ( steamID = = 0 ) {
Logging . LogNullError ( nameof ( steamID ) ) ;
return null ;
}
if ( ! IsOwner ( steamID ) ) {
return null ;
}
2016-06-24 01:55:39 +02:00
var response = new {
Bots
} ;
2016-06-20 21:20:38 +02:00
try {
2016-06-24 01:55:39 +02:00
return JsonConvert . SerializeObject ( response ) ;
2016-06-20 21:20:38 +02:00
} catch ( JsonException e ) {
Logging . LogGenericException ( e ) ;
return null ;
}
}
2016-03-18 09:02:09 +01:00
private static string ResponseExit ( ulong steamID ) {
if ( steamID = = 0 ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) ) ;
2016-03-18 09:02:09 +01:00
return null ;
}
if ( ! IsOwner ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-04-02 13:41:08 +02:00
// Schedule the task after some time so user can receive response
Task . Run ( async ( ) = > {
2016-06-24 22:26:52 +02:00
await Task . Delay ( 1000 ) . ConfigureAwait ( false ) ;
2016-04-02 13:41:08 +02:00
Program . Exit ( ) ;
2016-04-02 13:41:53 +02:00
} ) . Forget ( ) ;
2016-04-02 13:41:08 +02:00
2016-04-02 13:08:43 +02:00
return "Done!" ;
2016-03-18 09:02:09 +01:00
}
2016-06-09 03:13:35 +02:00
private async Task < string > ResponseFarm ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-03-21 03:39:35 +01:00
if ( ! SteamClient . IsConnected ) {
return "This bot instance is not connected!" ;
}
2016-06-09 03:13:35 +02:00
await CardsFarmer . StopFarming ( ) . ConfigureAwait ( false ) ;
2016-06-09 00:49:52 +02:00
CardsFarmer . StartFarming ( ) . Forget ( ) ;
2016-03-11 19:39:25 +01:00
return "Done!" ;
}
2016-06-09 03:13:35 +02:00
private static async Task < string > ResponseFarm ( ulong steamID , string botName ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-03-11 19:39:25 +01:00
return null ;
}
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
2016-06-09 03:13:35 +02:00
return await bot . ResponseFarm ( steamID ) . ConfigureAwait ( false ) ;
2016-03-11 19:39:25 +01:00
}
2016-05-13 06:32:42 +02:00
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
}
return null ;
2016-03-11 19:39:25 +01:00
}
2016-03-26 02:47:25 +01:00
private string ResponseHelp ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-02-03 21:53:30 +01:00
return null ;
}
2016-06-27 02:07:27 +02:00
return "https://github.com/" + SharedInfo . GithubRepo + "/wiki/Commands" ;
2016-03-26 02:47:25 +01:00
}
private async Task < string > ResponseRedeem ( ulong steamID , string message , bool validate ) {
2016-05-30 01:57:06 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( message ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-06-01 02:34:38 +02:00
message = message . Replace ( "," , Environment . NewLine ) ;
2016-01-10 20:36:56 +01:00
StringBuilder response = new StringBuilder ( ) ;
2016-04-02 19:23:09 +02:00
using ( StringReader reader = new StringReader ( message ) )
using ( IEnumerator < Bot > iterator = Bots . Values . GetEnumerator ( ) ) {
2016-01-25 19:15:22 +01:00
string key = reader . ReadLine ( ) ;
2016-01-25 09:42:59 +02:00
Bot currentBot = this ;
2016-05-13 06:32:42 +02:00
while ( ! string . IsNullOrEmpty ( key ) & & ( currentBot ! = null ) ) {
2016-01-11 04:49:12 +01:00
if ( validate & & ! IsValidCdKey ( key ) ) {
2016-04-02 19:23:09 +02:00
key = reader . ReadLine ( ) ; // Next key
2016-04-18 18:01:49 +02:00
continue ; // Keep current bot
2016-01-10 20:36:56 +01:00
}
2016-01-04 00:02:18 +01:00
2016-04-17 00:36:38 +02:00
if ( ! currentBot . SteamClient . IsConnected ) {
currentBot = null ; // Either bot will be changed, or loop aborted
} else {
2016-04-06 15:25:52 +02:00
ArchiHandler . PurchaseResponseCallback result = await currentBot . ArchiHandler . RedeemKey ( key ) . ConfigureAwait ( false ) ;
2016-04-17 00:36:38 +02:00
if ( result = = null ) {
2016-06-28 23:25:18 +02:00
response . Append ( Environment . NewLine + "<" + currentBot . BotName + "> Key: " + key + " | Status: Timeout!" ) ;
2016-04-17 00:36:38 +02:00
currentBot = null ; // Either bot will be changed, or loop aborted
} else {
2016-04-06 15:25:52 +02:00
switch ( result . PurchaseResult ) {
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . DuplicatedKey :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . InvalidKey :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . OK :
response . Append ( Environment . NewLine + "<" + currentBot . BotName + "> Key: " + key + " | Status: " + result . PurchaseResult + " | Items: " + string . Join ( "" , result . Items ) ) ;
key = reader . ReadLine ( ) ; // Next key
2016-04-18 18:01:49 +02:00
if ( result . PurchaseResult = = ArchiHandler . PurchaseResponseCallback . EPurchaseResult . OK ) {
break ; // Next bot (if needed)
}
2016-05-13 06:32:42 +02:00
continue ; // Keep current bot
2016-04-06 15:25:52 +02:00
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . AlreadyOwned :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . BaseGameRequired :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . OnCooldown :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . RegionLocked :
response . Append ( Environment . NewLine + "<" + currentBot . BotName + "> Key: " + key + " | Status: " + result . PurchaseResult + " | Items: " + string . Join ( "" , result . Items ) ) ;
if ( ! BotConfig . ForwardKeysToOtherBots ) {
key = reader . ReadLine ( ) ; // Next key
break ; // Next bot (if needed)
}
if ( BotConfig . DistributeKeys ) {
break ; // Next bot, without changing key
}
2016-07-19 05:05:23 +02:00
bool alreadyHandled = false ;
foreach ( Bot bot in Bots . Values . Where ( bot = > ( bot ! = this ) & & bot . SteamClient . IsConnected ) ) {
2016-04-06 15:25:52 +02:00
ArchiHandler . PurchaseResponseCallback otherResult = await bot . ArchiHandler . RedeemKey ( key ) . ConfigureAwait ( false ) ;
if ( otherResult = = null ) {
2016-06-28 23:25:18 +02:00
response . Append ( Environment . NewLine + "<" + bot . BotName + "> Key: " + key + " | Status: Timeout!" ) ;
2016-04-06 15:25:52 +02:00
continue ;
}
switch ( otherResult . PurchaseResult ) {
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . DuplicatedKey :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . InvalidKey :
case ArchiHandler . PurchaseResponseCallback . EPurchaseResult . OK :
2016-07-19 05:05:23 +02:00
alreadyHandled = true ; // This key is already handled, as we either redeemed it or we're sure it's dupe/invalid
2016-04-06 15:25:52 +02:00
break ;
}
response . Append ( Environment . NewLine + "<" + bot . BotName + "> Key: " + key + " | Status: " + otherResult . PurchaseResult + " | Items: " + string . Join ( "" , otherResult . Items ) ) ;
2016-04-06 15:30:03 +02:00
2016-07-19 05:05:23 +02:00
if ( alreadyHandled ) {
2016-04-06 15:30:03 +02:00
break ;
}
2016-04-06 15:25:52 +02:00
}
key = reader . ReadLine ( ) ; // Next key
break ; // Next bot (if needed)
2016-01-10 20:36:56 +01:00
}
2016-04-06 15:25:52 +02:00
}
2016-04-02 19:23:09 +02:00
}
2016-05-13 06:32:42 +02:00
if ( ! BotConfig . DistributeKeys ) {
continue ;
2016-01-10 20:36:56 +01:00
}
2016-01-02 17:22:35 +01:00
2016-05-13 06:32:42 +02:00
do {
currentBot = iterator . MoveNext ( ) ? iterator . Current : null ;
2016-07-19 05:05:23 +02:00
} while ( ( currentBot = = this ) | | ( ( currentBot ! = null ) & & ! currentBot . SteamClient . IsConnected ) ) ;
2016-05-13 06:32:42 +02:00
}
2016-01-02 17:22:35 +01:00
}
2016-06-28 22:57:54 +02:00
return response . Length = = 0 ? null : response . ToString ( ) ;
2016-01-10 20:36:56 +01:00
}
2016-03-18 09:02:09 +01:00
private static async Task < string > ResponseRedeem ( ulong steamID , string botName , string message , bool validate ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) | | string . IsNullOrEmpty ( message ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) + " || " + nameof ( message ) ) ;
2016-01-04 00:02:18 +01:00
return null ;
2016-01-02 17:22:35 +01:00
}
2016-01-10 20:36:56 +01:00
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
return await bot . ResponseRedeem ( steamID , message , validate ) . ConfigureAwait ( false ) ;
}
2016-06-27 00:38:38 +02:00
2016-05-13 06:32:42 +02:00
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2016-01-10 20:36:56 +01:00
}
2016-01-02 17:22:35 +01:00
2016-05-13 06:32:42 +02:00
return null ;
2016-01-02 17:22:35 +01:00
}
2016-03-18 09:02:09 +01:00
private static string ResponseRejoinChat ( ulong steamID ) {
if ( steamID = = 0 ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) ) ;
2016-03-18 09:02:09 +01:00
return null ;
}
if ( ! IsOwner ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-02-24 06:06:09 +01:00
foreach ( Bot bot in Bots . Values ) {
bot . JoinMasterChat ( ) ;
}
return "Done!" ;
}
2016-03-18 09:02:09 +01:00
private static string ResponseRestart ( ulong steamID ) {
if ( steamID = = 0 ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) ) ;
2016-03-18 09:02:09 +01:00
return null ;
}
if ( ! IsOwner ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-04-02 13:41:08 +02:00
// Schedule the task after some time so user can receive response
Task . Run ( async ( ) = > {
2016-06-24 22:26:52 +02:00
await Task . Delay ( 1000 ) . ConfigureAwait ( false ) ;
2016-04-02 13:41:08 +02:00
Program . Restart ( ) ;
2016-04-02 13:41:53 +02:00
} ) . Forget ( ) ;
2016-04-02 13:41:08 +02:00
2016-04-02 13:08:43 +02:00
return "Done!" ;
2016-03-18 09:02:09 +01:00
}
2016-05-13 06:32:42 +02:00
private async Task < string > ResponseAddLicense ( ulong steamID , ICollection < uint > gameIDs ) {
2016-05-30 01:57:06 +02:00
if ( ( steamID = = 0 ) | | ( gameIDs = = null ) | | ( gameIDs . Count = = 0 ) ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( gameIDs ) + " || " + nameof ( gameIDs . Count ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! SteamClient . IsConnected | | ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-02-16 08:08:06 +01:00
StringBuilder result = new StringBuilder ( ) ;
foreach ( uint gameID in gameIDs ) {
2016-03-30 13:10:00 +02:00
SteamApps . FreeLicenseCallback callback = await SteamApps . RequestFreeLicense ( gameID ) ;
if ( callback = = null ) {
2016-06-29 20:35:33 +02:00
result . AppendLine ( Environment . NewLine + "Result: Timeout!" ) ;
2016-06-29 20:33:52 +02:00
break ;
2016-02-16 08:08:06 +01:00
}
2016-06-29 20:35:33 +02:00
result . AppendLine ( Environment . NewLine + "Result: " + callback . Result + " | Granted apps: " + string . Join ( ", " , callback . GrantedApps ) + " " + string . Join ( ", " , callback . GrantedPackages ) ) ;
2016-02-16 08:08:06 +01:00
}
return result . ToString ( ) ;
2016-02-05 20:10:15 +01:00
}
2016-03-18 09:02:09 +01:00
private static async Task < string > ResponseAddLicense ( ulong steamID , string botName , string games ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) | | string . IsNullOrEmpty ( games ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) + " || " + nameof ( games ) ) ;
2016-01-22 10:56:06 +01:00
return null ;
}
Bot bot ;
if ( ! Bots . TryGetValue ( botName , out bot ) ) {
2016-05-06 18:07:03 +02:00
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
}
2016-05-13 06:32:42 +02:00
return null ;
2016-01-22 10:56:06 +01:00
}
2016-05-13 06:32:42 +02:00
string [ ] gameIDs = games . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
2016-02-16 08:08:06 +01:00
HashSet < uint > gamesToRedeem = new HashSet < uint > ( ) ;
2016-05-13 06:32:42 +02:00
foreach ( string game in gameIDs . Where ( game = > ! string . IsNullOrEmpty ( game ) ) ) {
2016-02-16 08:08:06 +01:00
uint gameID ;
if ( ! uint . TryParse ( game , out gameID ) ) {
2016-06-29 20:33:52 +02:00
return "Couldn't parse games list!" ;
2016-02-16 08:08:06 +01:00
}
2016-05-07 15:08:24 +02:00
2016-02-16 08:08:06 +01:00
gamesToRedeem . Add ( gameID ) ;
}
if ( gamesToRedeem . Count = = 0 ) {
2016-06-29 20:33:52 +02:00
return "List of games is empty!" ;
2016-01-22 10:56:06 +01:00
}
2016-03-18 09:02:09 +01:00
return await bot . ResponseAddLicense ( steamID , gamesToRedeem ) . ConfigureAwait ( false ) ;
2016-02-05 20:10:15 +01:00
}
2016-04-08 03:57:03 +02:00
private async Task < string > ResponseOwns ( ulong steamID , string query ) {
2016-05-30 01:57:06 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( query ) ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( query ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-04-29 15:44:11 +02:00
Dictionary < uint , string > ownedGames ;
if ( ! string . IsNullOrEmpty ( BotConfig . SteamApiKey ) ) {
ownedGames = ArchiWebHandler . GetOwnedGames ( SteamClient . SteamID ) ;
} else {
ownedGames = await ArchiWebHandler . GetOwnedGames ( ) . ConfigureAwait ( false ) ;
}
2016-05-13 06:32:42 +02:00
if ( ( ownedGames = = null ) | | ( ownedGames . Count = = 0 ) ) {
2016-03-15 04:20:28 +01:00
return "List of owned games is empty!" ;
}
StringBuilder response = new StringBuilder ( ) ;
2016-05-13 06:32:42 +02:00
string [ ] games = query . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
foreach ( string game in games . Where ( game = > ! string . IsNullOrEmpty ( game ) ) ) {
2016-04-08 03:57:03 +02:00
// Check if this is appID
uint appID ;
if ( uint . TryParse ( game , out appID ) ) {
string ownedName ;
if ( ownedGames . TryGetValue ( appID , out ownedName ) ) {
response . Append ( Environment . NewLine + "Owned already: " + appID + " | " + ownedName ) ;
} else {
response . Append ( Environment . NewLine + "Not owned yet: " + appID ) ;
}
2016-03-15 04:20:28 +01:00
continue ;
}
2016-04-08 03:57:03 +02:00
// This is a string, so check our entire library
2016-05-13 06:32:42 +02:00
foreach ( KeyValuePair < uint , string > ownedGame in ownedGames . Where ( ownedGame = > ownedGame . Value . IndexOf ( game , StringComparison . OrdinalIgnoreCase ) > = 0 ) ) {
2016-04-08 03:57:03 +02:00
response . Append ( Environment . NewLine + "Owned already: " + ownedGame . Key + " | " + ownedGame . Value ) ;
}
2016-03-15 04:20:28 +01:00
}
if ( response . Length > 0 ) {
return response . ToString ( ) ;
}
2016-05-13 06:32:42 +02:00
return "Not owned yet: " + query ;
2016-03-15 04:20:28 +01:00
}
2016-04-08 03:58:46 +02:00
private static async Task < string > ResponseOwns ( ulong steamID , string botName , string query ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) | | string . IsNullOrEmpty ( query ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) + " || " + nameof ( query ) ) ;
2016-03-15 04:20:28 +01:00
return null ;
}
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
return await bot . ResponseOwns ( steamID , query ) . ConfigureAwait ( false ) ;
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2016-03-15 04:20:28 +01:00
}
2016-05-13 06:32:42 +02:00
return null ;
2016-03-15 04:20:28 +01:00
}
2016-03-18 09:02:09 +01:00
private async Task < string > ResponsePlay ( ulong steamID , HashSet < uint > gameIDs ) {
2016-05-30 01:57:06 +02:00
if ( ( steamID = = 0 ) | | ( gameIDs = = null ) | | ( gameIDs . Count = = 0 ) ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( gameIDs ) + " || " + nameof ( gameIDs . Count ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-02-13 23:21:47 +01:00
if ( gameIDs . Contains ( 0 ) ) {
2016-05-13 06:32:42 +02:00
if ( ! CardsFarmer . ManualMode ) {
return "Done!" ;
2016-02-13 23:31:58 +01:00
}
2016-05-13 06:32:42 +02:00
await CardsFarmer . SwitchToManualMode ( false ) . ConfigureAwait ( false ) ;
2016-02-13 23:21:47 +01:00
} else {
2016-03-24 14:18:07 +01:00
if ( ! CardsFarmer . ManualMode ) {
await CardsFarmer . SwitchToManualMode ( true ) . ConfigureAwait ( false ) ;
}
2016-05-13 06:32:42 +02:00
2016-02-13 23:21:47 +01:00
ArchiHandler . PlayGames ( gameIDs ) ;
}
2016-02-05 20:10:15 +01:00
return "Done!" ;
2016-01-22 10:56:06 +01:00
}
2016-03-18 09:02:09 +01:00
private static async Task < string > ResponsePlay ( ulong steamID , string botName , string games ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) | | string . IsNullOrEmpty ( games ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) + " || " + nameof ( games ) ) ;
2016-01-22 10:45:01 +01:00
return null ;
}
Bot bot ;
if ( ! Bots . TryGetValue ( botName , out bot ) ) {
2016-05-06 18:07:03 +02:00
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
}
2016-05-13 06:32:42 +02:00
return null ;
2016-01-22 10:45:01 +01:00
}
2016-05-13 06:32:42 +02:00
string [ ] gameIDs = games . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ;
2016-02-13 23:21:47 +01:00
HashSet < uint > gamesToPlay = new HashSet < uint > ( ) ;
2016-05-13 06:32:42 +02:00
foreach ( string game in gameIDs . Where ( game = > ! string . IsNullOrEmpty ( game ) ) ) {
2016-02-13 23:21:47 +01:00
uint gameID ;
if ( ! uint . TryParse ( game , out gameID ) ) {
2016-06-29 20:33:52 +02:00
return "Couldn't parse games list!" ;
2016-02-13 23:21:47 +01:00
}
2016-05-07 15:08:24 +02:00
2016-02-13 23:21:47 +01:00
gamesToPlay . Add ( gameID ) ;
2016-06-27 21:15:30 +02:00
if ( gamesToPlay . Count > = CardsFarmer . MaxGamesPlayedConcurrently ) {
break ;
}
2016-02-13 23:21:47 +01:00
}
if ( gamesToPlay . Count = = 0 ) {
2016-06-29 20:33:52 +02:00
return "List of games is empty!" ;
2016-01-22 10:45:01 +01:00
}
2016-03-18 09:02:09 +01:00
return await bot . ResponsePlay ( steamID , gamesToPlay ) . ConfigureAwait ( false ) ;
2016-02-05 20:10:15 +01:00
}
2016-01-22 10:45:01 +01:00
2016-03-18 09:02:09 +01:00
private async Task < string > ResponseStart ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-02-05 20:10:15 +01:00
if ( KeepRunning ) {
return "That bot instance is already running!" ;
}
2016-05-18 04:33:17 +02:00
SkipFirstShutdown = true ;
2016-02-05 20:10:15 +01:00
await Start ( ) . ConfigureAwait ( false ) ;
2016-01-22 10:45:01 +01:00
return "Done!" ;
}
2016-03-18 09:02:09 +01:00
private static async Task < string > ResponseStart ( ulong steamID , string botName ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-01-04 00:02:18 +01:00
return null ;
2015-11-01 02:04:44 +01:00
}
2016-02-05 20:10:15 +01:00
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
return await bot . ResponseStart ( steamID ) . ConfigureAwait ( false ) ;
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2015-11-01 02:04:44 +01:00
}
2016-05-13 06:32:42 +02:00
return null ;
2016-02-05 20:10:15 +01:00
}
2016-03-22 20:18:47 +01:00
private string ResponseStop ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-02-05 20:10:15 +01:00
if ( ! KeepRunning ) {
return "That bot instance is already inactive!" ;
2015-11-01 02:04:44 +01:00
}
2016-02-05 20:10:15 +01:00
2016-03-22 20:18:47 +01:00
Stop ( ) ;
2016-02-05 20:10:15 +01:00
return "Done!" ;
2015-11-01 02:04:44 +01:00
}
2016-03-22 20:18:47 +01:00
private static string ResponseStop ( ulong steamID , string botName ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( botName ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( botName ) ) ;
2016-01-04 00:02:18 +01:00
return null ;
2015-11-01 02:04:44 +01:00
}
2016-01-04 00:02:18 +01:00
Bot bot ;
2016-05-13 06:32:42 +02:00
if ( Bots . TryGetValue ( botName , out bot ) ) {
return bot . ResponseStop ( steamID ) ;
}
if ( IsOwner ( steamID ) ) {
return "Couldn't find any bot named " + botName + "!" ;
2015-11-01 02:04:44 +01:00
}
2016-05-13 06:32:42 +02:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-03-18 14:39:59 +01:00
private string ResponseUnknown ( ulong steamID ) {
2016-05-30 01:57:06 +02:00
if ( steamID ! = 0 ) {
return ! IsMaster ( steamID ) ? null : "ERROR: Unknown command!" ;
2016-03-18 14:39:59 +01:00
}
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
return null ;
2016-03-18 14:39:59 +01:00
}
2016-03-18 09:02:09 +01:00
private static async Task < string > ResponseUpdate ( ulong steamID ) {
if ( steamID = = 0 ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) ) ;
2016-03-18 09:02:09 +01:00
return null ;
}
if ( ! IsOwner ( steamID ) ) {
2016-03-18 14:13:04 +01:00
return null ;
2016-03-18 09:02:09 +01:00
}
2016-05-18 02:25:31 +02:00
await Program . CheckForUpdate ( true ) . ConfigureAwait ( false ) ;
2016-03-18 09:02:09 +01:00
return "Done!" ;
2015-11-01 02:04:44 +01:00
}
2016-06-06 05:27:11 +02:00
private string ResponseVersion ( ulong steamID ) {
if ( steamID = = 0 ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( steamID ) , BotName ) ;
2016-06-06 05:27:11 +02:00
return null ;
}
if ( ! IsMaster ( steamID ) ) {
return null ;
}
return "ASF V" + Program . Version ;
}
2016-02-22 18:34:45 +01:00
private void HandleCallbacks ( ) {
TimeSpan timeSpan = TimeSpan . FromMilliseconds ( CallbackSleep ) ;
2016-03-03 16:11:46 +01:00
while ( KeepRunning | | SteamClient . IsConnected ) {
2016-03-30 01:41:53 +02:00
try {
CallbackManager . RunWaitCallbacks ( timeSpan ) ;
} catch ( Exception e ) {
Logging . LogGenericException ( e , BotName ) ;
}
2016-02-22 18:34:45 +01:00
}
}
2016-03-18 20:35:42 +01:00
private async Task HandleMessage ( ulong chatID , ulong steamID , string message ) {
2016-05-13 06:32:42 +02:00
if ( ( chatID = = 0 ) | | ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( chatID ) + " || " + nameof ( steamID ) + " || " + nameof ( message ) , BotName ) ;
2016-01-04 00:02:18 +01:00
return ;
}
2016-06-01 02:19:22 +02:00
string response = await Response ( steamID , message ) . ConfigureAwait ( false ) ;
if ( string . IsNullOrEmpty ( response ) ) { // We respond with null when user is not authorized (and similar)
return ;
}
SendMessage ( chatID , response ) ;
2016-01-04 00:02:18 +01:00
}
2016-02-22 18:34:45 +01:00
private void SendMessage ( ulong steamID , string message ) {
2016-05-13 06:32:42 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( message ) , BotName ) ;
2016-02-22 18:34:45 +01:00
return ;
}
2016-03-10 01:20:17 +01:00
if ( new SteamID ( steamID ) . IsChatAccount ) {
2016-04-07 03:14:49 +02:00
SendMessageToChannel ( steamID , message ) ;
2016-03-10 01:20:17 +01:00
} else {
2016-04-07 03:14:49 +02:00
SendMessageToUser ( steamID , message ) ;
}
}
private void SendMessageToChannel ( ulong steamID , string message ) {
2016-05-30 01:57:06 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( message ) , BotName ) ;
return ;
}
if ( ! SteamClient . IsConnected ) {
2016-04-07 03:14:49 +02:00
return ;
}
for ( int i = 0 ; i < message . Length ; i + = MaxSteamMessageLength - 6 ) {
string messagePart = ( i > 0 ? "..." : "" ) + message . Substring ( i , Math . Min ( MaxSteamMessageLength - 6 , message . Length - i ) ) + ( MaxSteamMessageLength - 6 < message . Length - i ? "..." : "" ) ;
SteamFriends . SendChatRoomMessage ( steamID , EChatEntryType . ChatMsg , messagePart ) ;
}
}
private void SendMessageToUser ( ulong steamID , string message ) {
2016-05-30 01:57:06 +02:00
if ( ( steamID = = 0 ) | | string . IsNullOrEmpty ( message ) ) {
Logging . LogNullError ( nameof ( steamID ) + " || " + nameof ( message ) , BotName ) ;
return ;
}
if ( ! SteamClient . IsConnected ) {
2016-04-07 03:14:49 +02:00
return ;
}
for ( int i = 0 ; i < message . Length ; i + = MaxSteamMessageLength - 6 ) {
string messagePart = ( i > 0 ? "..." : "" ) + message . Substring ( i , Math . Min ( MaxSteamMessageLength - 6 , message . Length - i ) ) + ( MaxSteamMessageLength - 6 < message . Length - i ? "..." : "" ) ;
SteamFriends . SendChatMessage ( steamID , EChatEntryType . ChatMsg , messagePart ) ;
2016-02-22 18:34:45 +01:00
}
}
2016-02-24 06:06:09 +01:00
private void JoinMasterChat ( ) {
2016-05-13 06:32:42 +02:00
if ( ! SteamClient . IsConnected | | ( BotConfig . SteamMasterClanID = = 0 ) ) {
2016-02-24 06:06:09 +01:00
return ;
}
2016-03-06 02:20:41 +01:00
SteamFriends . JoinChat ( BotConfig . SteamMasterClanID ) ;
2016-02-24 06:06:09 +01:00
}
2016-05-12 16:32:04 +02:00
private bool InitializeLoginAndPassword ( bool requiresPassword ) {
2016-03-12 05:58:51 +01:00
if ( string . IsNullOrEmpty ( BotConfig . SteamLogin ) ) {
2016-03-22 17:26:39 +01:00
BotConfig . SteamLogin = Program . GetUserInput ( Program . EUserInputType . Login , BotName ) ;
2016-04-06 16:37:45 +02:00
if ( string . IsNullOrEmpty ( BotConfig . SteamLogin ) ) {
return false ;
}
2016-03-12 05:58:51 +01:00
}
2016-05-14 00:11:41 +02:00
if ( ! string . IsNullOrEmpty ( BotConfig . SteamPassword ) | | ( ! requiresPassword & & ! string . IsNullOrEmpty ( BotDatabase . LoginKey ) ) ) {
2016-05-13 06:32:42 +02:00
return true ;
2016-03-12 05:58:51 +01:00
}
2016-04-06 16:37:45 +02:00
2016-05-13 06:32:42 +02:00
BotConfig . SteamPassword = Program . GetUserInput ( Program . EUserInputType . Password , BotName ) ;
return ! string . IsNullOrEmpty ( BotConfig . SteamPassword ) ;
2016-03-12 05:58:51 +01:00
}
2016-05-28 13:08:53 +02:00
private void ResetGamesPlayed ( ) {
2016-05-30 13:12:22 +02:00
if ( PlayingBlocked ) {
return ;
}
2016-07-12 04:40:56 +02:00
ArchiHandler . PlayGames ( BotConfig . GamesPlayedWhileIdle , BotConfig . CustomGamePlayedWhileIdle ) ;
2016-05-28 13:08:53 +02:00
}
2016-06-19 05:40:46 +02:00
private async void OnConnected ( SteamClient . ConnectedCallback callback ) {
2015-10-25 06:16:50 +01:00
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
if ( callback . Result ! = EResult . OK ) {
2016-01-24 18:08:27 +01:00
Logging . LogGenericError ( "Unable to connect to Steam: " + callback . Result , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Connected to Steam!" , BotName ) ;
2015-10-25 06:16:50 +01:00
2016-03-03 16:11:46 +01:00
if ( ! KeepRunning ) {
Logging . LogGenericInfo ( "Disconnecting..." , BotName ) ;
SteamClient . Disconnect ( ) ;
return ;
}
2015-10-25 06:16:50 +01:00
byte [ ] sentryHash = null ;
if ( File . Exists ( SentryFile ) ) {
2016-02-12 16:51:06 +01:00
try {
byte [ ] sentryFileContent = File . ReadAllBytes ( SentryFile ) ;
2016-06-28 04:32:48 +02:00
sentryHash = SteamKit2 . CryptoHelper . SHAHash ( sentryFileContent ) ;
2016-02-12 16:51:06 +01:00
} catch ( Exception e ) {
Logging . LogGenericException ( e , BotName ) ;
}
2015-10-25 06:16:50 +01:00
}
2016-05-12 16:32:04 +02:00
if ( ! InitializeLoginAndPassword ( false ) ) {
2016-04-06 16:37:45 +02:00
Stop ( ) ;
return ;
}
2015-10-28 23:29:50 +01:00
2016-03-13 22:58:52 +01:00
Logging . LogGenericInfo ( "Logging in..." , BotName ) ;
2016-03-14 20:38:17 +01:00
2016-04-08 17:12:08 +02:00
// If we have ASF 2FA enabled, we can always provide TwoFactorCode, and save a request
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator ! = null ) {
TwoFactorCode = await BotDatabase . MobileAuthenticator . GenerateToken ( ) . ConfigureAwait ( false ) ;
2016-04-08 17:12:08 +02:00
}
2016-07-12 03:56:35 +02:00
SteamUser . LogOnDetails logOnDetails = new SteamUser . LogOnDetails {
2016-07-08 07:16:42 +02:00
Username = BotConfig . SteamLogin ,
Password = BotConfig . SteamPassword ,
AuthCode = AuthCode ,
CellID = Program . GlobalDatabase . CellID ,
LoginID = LoginID ,
LoginKey = BotDatabase . LoginKey ,
TwoFactorCode = TwoFactorCode ,
SentryFileHash = sentryHash ,
ShouldRememberPassword = true
2016-07-12 03:56:35 +02:00
} ;
try {
SteamUser . LogOn ( logOnDetails ) ;
} catch {
// TODO: Remove me once https://github.com/SteamRE/SteamKit/issues/305 is fixed
ArchiHandler . LogOnWithoutMachineID ( logOnDetails ) ;
}
2015-10-25 06:16:50 +01:00
}
2015-11-01 02:04:44 +01:00
private async void OnDisconnected ( SteamClient . DisconnectedCallback callback ) {
2015-10-25 06:16:50 +01:00
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2015-10-28 22:34:53 +01:00
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Disconnected from Steam!" , BotName ) ;
2016-05-03 15:37:11 +02:00
2016-06-25 03:52:02 +02:00
ArchiWebHandler . OnDisconnected ( ) ;
CardsFarmer . OnDisconnected ( ) ;
Trading . OnDisconnected ( ) ;
2016-05-03 15:37:11 +02:00
FirstTradeSent = false ;
2016-06-24 20:27:23 +02:00
HandledGifts . ClearAndTrim ( ) ;
2015-12-22 16:51:37 +01:00
2016-03-22 20:18:47 +01:00
// If we initiated disconnect, do not attempt to reconnect
if ( callback . UserInitiated ) {
2015-12-23 10:58:14 +01:00
return ;
}
if ( InvalidPassword ) {
InvalidPassword = false ;
2016-03-06 02:20:41 +01:00
if ( ! string . IsNullOrEmpty ( BotDatabase . LoginKey ) ) { // InvalidPassword means usually that login key has expired, if we used it
BotDatabase . LoginKey = null ;
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Removed expired login key" , BotName ) ;
2015-12-23 10:58:14 +01:00
} else { // If we didn't use login key, InvalidPassword usually means we got captcha or other network-based throttling
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Will retry after 25 minutes..." , BotName ) ;
2016-06-24 22:26:52 +02:00
await Task . Delay ( 25 * 60 * 1000 ) . ConfigureAwait ( false ) ; // Captcha disappears after around 20 minutes, so we make it 25
2015-12-23 10:58:14 +01:00
}
2015-12-09 20:55:43 +01:00
}
2016-04-16 19:24:04 +02:00
if ( ! KeepRunning | | SteamClient . IsConnected ) {
return ;
}
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Reconnecting..." , BotName ) ;
2015-12-22 16:51:37 +01:00
2016-04-23 16:34:00 +02:00
// 2FA tokens are expiring soon, don't use limiter when user is providing one
2016-06-19 05:40:46 +02:00
if ( ( TwoFactorCode = = null ) | | ( BotDatabase . MobileAuthenticator ! = null ) ) {
2016-04-24 23:32:23 +02:00
await LimitLoginRequestsAsync ( ) . ConfigureAwait ( false ) ;
2015-12-21 09:28:59 +01:00
}
2015-10-25 06:16:50 +01:00
SteamClient . Connect ( ) ;
}
2016-05-30 01:57:06 +02:00
private void OnFreeLicense ( SteamApps . FreeLicenseCallback callback ) {
if ( callback = = null ) {
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
}
}
2016-01-22 10:56:06 +01:00
2016-03-27 23:07:00 +02:00
private async void OnGuestPassList ( SteamApps . GuestPassListCallback callback ) {
2016-07-10 20:17:35 +02:00
if ( callback ? . GuestPasses = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) + " || " + nameof ( callback . GuestPasses ) , BotName ) ;
return ;
}
if ( ( callback . CountGuestPassesToRedeem = = 0 ) | | ( callback . GuestPasses . Count = = 0 ) | | ! BotConfig . AcceptGifts ) {
2016-03-27 23:07:00 +02:00
return ;
}
2016-06-20 13:45:12 +02:00
for ( byte i = 0 ; ( i < Program . GlobalConfig . HttpTimeout ) & & ! ArchiWebHandler . Ready ; i + + ) {
await Task . Delay ( 1000 ) . ConfigureAwait ( false ) ;
}
if ( ! ArchiWebHandler . Ready ) {
return ;
}
2016-03-27 23:07:00 +02:00
bool acceptedSomething = false ;
2016-06-24 20:27:23 +02:00
foreach ( ulong gid in callback . GuestPasses . Select ( guestPass = > guestPass [ "gid" ] . AsUnsignedLong ( ) ) . Where ( gid = > ( gid ! = 0 ) & & ! HandledGifts . Contains ( gid ) ) ) {
2016-06-24 20:54:21 +02:00
HandledGifts . Add ( gid ) ;
2016-06-24 22:26:52 +02:00
2016-03-27 23:07:00 +02:00
Logging . LogGenericInfo ( "Accepting gift: " + gid + "..." , BotName ) ;
2016-06-24 22:26:52 +02:00
await LimitGiftsRequestsAsync ( ) . ConfigureAwait ( false ) ;
2016-03-27 23:07:00 +02:00
if ( await ArchiWebHandler . AcceptGift ( gid ) . ConfigureAwait ( false ) ) {
acceptedSomething = true ;
Logging . LogGenericInfo ( "Success!" , BotName ) ;
} else {
Logging . LogGenericInfo ( "Failed!" , BotName ) ;
}
}
if ( acceptedSomething ) {
2016-06-09 03:13:35 +02:00
await CardsFarmer . OnNewGameAdded ( ) . ConfigureAwait ( false ) ;
2016-03-27 23:07:00 +02:00
}
}
2015-12-21 19:28:59 +01:00
private void OnChatInvite ( SteamFriends . ChatInviteCallback callback ) {
2016-07-10 20:17:35 +02:00
if ( ( callback ? . ChatRoomID = = null ) | | ( callback . PatronID = = null ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) + " || " + nameof ( callback . ChatRoomID ) + " || " + nameof ( callback . PatronID ) , BotName ) ;
return ;
}
if ( ! IsMaster ( callback . PatronID ) ) {
2015-12-21 19:28:59 +01:00
return ;
}
SteamFriends . JoinChat ( callback . ChatRoomID ) ;
}
private async void OnChatMsg ( SteamFriends . ChatMsgCallback callback ) {
2016-05-30 13:11:29 +02:00
if ( callback = = null ) {
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return ;
}
if ( callback . ChatMsgType ! = EChatEntryType . ChatMsg ) {
2015-12-21 19:28:59 +01:00
return ;
}
2016-05-30 13:13:24 +02:00
if ( ( callback . ChatRoomID = = null ) | | ( callback . ChatterID = = null ) | | string . IsNullOrEmpty ( callback . Message ) ) {
Logging . LogNullError ( nameof ( callback . ChatRoomID ) + " || " + nameof ( callback . ChatterID ) + " || " + nameof ( callback . Message ) , BotName ) ;
2016-05-30 13:11:29 +02:00
return ;
}
2016-02-12 16:21:33 +01:00
switch ( callback . Message ) {
case "!leave" :
2016-03-26 02:47:25 +01:00
if ( ! IsMaster ( callback . ChatterID ) ) {
break ;
}
2016-02-12 16:21:33 +01:00
SteamFriends . LeaveChat ( callback . ChatRoomID ) ;
break ;
default :
2016-03-18 20:35:42 +01:00
await HandleMessage ( callback . ChatRoomID , callback . ChatterID , callback . Message ) . ConfigureAwait ( false ) ;
2016-02-12 16:21:33 +01:00
break ;
}
2015-12-21 19:28:59 +01:00
}
2015-10-25 06:16:50 +01:00
private void OnFriendsList ( SteamFriends . FriendsListCallback callback ) {
2016-07-10 20:17:35 +02:00
if ( callback ? . FriendList = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) + " || " + nameof ( callback . FriendList ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-05-13 06:32:42 +02:00
foreach ( SteamFriends . FriendsListCallback . Friend friend in callback . FriendList . Where ( friend = > friend . Relationship = = EFriendRelationship . RequestRecipient ) ) {
2016-06-13 18:08:19 +02:00
if ( IsMaster ( friend . SteamID ) ) {
SteamFriends . AddFriend ( friend . SteamID ) ;
} else if ( BotConfig . IsBotAccount ) {
SteamFriends . RemoveFriend ( friend . SteamID ) ;
2015-10-25 06:16:50 +01:00
}
}
}
2015-10-31 05:27:30 +01:00
private async void OnFriendMsg ( SteamFriends . FriendMsgCallback callback ) {
2016-05-30 13:11:29 +02:00
if ( callback = = null ) {
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2016-05-30 01:57:06 +02:00
return ;
}
if ( callback . EntryType ! = EChatEntryType . ChatMsg ) {
2015-10-25 06:16:50 +01:00
return ;
2015-12-21 19:28:59 +01:00
}
2016-05-30 13:11:29 +02:00
if ( ( callback . Sender = = null ) | | string . IsNullOrEmpty ( callback . Message ) ) {
2016-05-30 13:13:24 +02:00
Logging . LogNullError ( nameof ( callback . Sender ) + " || " + nameof ( callback . Message ) , BotName ) ;
2016-05-30 13:11:29 +02:00
return ;
}
2016-03-18 20:35:42 +01:00
await HandleMessage ( callback . Sender , callback . Sender , callback . Message ) . ConfigureAwait ( false ) ;
2015-12-21 10:55:55 +01:00
}
private async void OnFriendMsgHistory ( SteamFriends . FriendMsgHistoryCallback callback ) {
2016-07-10 20:17:35 +02:00
if ( ( callback ? . Messages = = null ) | | ( callback . SteamID = = null ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) + " || " + nameof ( callback . Messages ) + " || " + nameof ( callback . SteamID ) , BotName ) ;
return ;
}
if ( ( callback . Messages . Count = = 0 ) | | ! IsMaster ( callback . SteamID ) ) {
2015-11-01 02:04:44 +01:00
return ;
}
2015-12-21 10:55:55 +01:00
// Get last message
2016-05-13 06:32:42 +02:00
SteamFriends . FriendMsgHistoryCallback . FriendMessage lastMessage = callback . Messages [ callback . Messages . Count - 1 ] ;
2015-12-21 10:55:55 +01:00
// If message is read already, return
if ( ! lastMessage . Unread ) {
return ;
2015-10-31 05:27:30 +01:00
}
2015-12-21 10:55:55 +01:00
// If message is too old, return
if ( DateTime . UtcNow . Subtract ( lastMessage . Timestamp ) . TotalMinutes > 1 ) {
return ;
}
// Handle the message
2016-03-18 20:35:42 +01:00
await HandleMessage ( callback . SteamID , callback . SteamID , lastMessage . Message ) . ConfigureAwait ( false ) ;
2015-10-25 06:16:50 +01:00
}
private void OnAccountInfo ( SteamUser . AccountInfoCallback callback ) {
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-03-06 02:20:41 +01:00
if ( ! BotConfig . FarmOffline ) {
2015-12-20 19:01:05 +01:00
SteamFriends . SetPersonaState ( EPersonaState . Online ) ;
}
2015-10-25 06:16:50 +01:00
}
private void OnLoggedOff ( SteamUser . LoggedOffCallback callback ) {
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Logged off of Steam: " + callback . Result , BotName ) ;
2015-10-25 06:16:50 +01:00
}
private async void OnLoggedOn ( SteamUser . LoggedOnCallback callback ) {
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-07-19 05:01:52 +02:00
// Reset one-time-only access tokens
AuthCode = TwoFactorCode = null ;
2016-02-12 16:51:06 +01:00
switch ( callback . Result ) {
2015-10-25 06:16:50 +01:00
case EResult . AccountLogonDenied :
2016-03-22 17:26:39 +01:00
AuthCode = Program . GetUserInput ( Program . EUserInputType . SteamGuard , BotName ) ;
2016-04-06 16:37:45 +02:00
if ( string . IsNullOrEmpty ( AuthCode ) ) {
Stop ( ) ;
}
2016-05-13 06:32:42 +02:00
2015-10-25 06:16:50 +01:00
break ;
case EResult . AccountLoginDeniedNeedTwoFactor :
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator = = null ) {
2016-04-08 17:12:08 +02:00
TwoFactorCode = Program . GetUserInput ( Program . EUserInputType . TwoFactorAuthentication , BotName ) ;
if ( string . IsNullOrEmpty ( TwoFactorCode ) ) {
2016-04-06 16:37:45 +02:00
Stop ( ) ;
}
2015-12-11 22:53:28 +01:00
} else {
2016-04-08 17:33:00 +02:00
Logging . LogGenericWarning ( "2FA code was invalid despite of using ASF 2FA. Invalid authenticator or bad timing?" , BotName ) ;
2015-12-11 22:53:28 +01:00
}
2016-05-13 06:32:42 +02:00
2015-10-25 06:16:50 +01:00
break ;
2015-11-26 01:22:56 +01:00
case EResult . InvalidPassword :
2015-12-23 10:58:14 +01:00
InvalidPassword = true ;
2016-07-09 09:20:56 +02:00
Logging . LogGenericWarning ( "Unable to login to Steam: " + callback . Result + " / " + callback . ExtendedResult , BotName ) ;
2015-11-26 01:22:56 +01:00
break ;
2015-10-25 06:16:50 +01:00
case EResult . OK :
2016-01-24 18:08:27 +01:00
Logging . LogGenericInfo ( "Successfully logged on!" , BotName ) ;
2015-10-28 20:01:43 +01:00
2016-05-30 00:09:42 +02:00
PlayingBlocked = false ; // If playing is really blocked, we'll be notified in a callback, old status doesn't matter
2016-03-07 02:39:55 +01:00
if ( callback . CellID ! = 0 ) {
Program . GlobalDatabase . CellID = callback . CellID ;
}
2016-06-19 05:40:46 +02:00
if ( BotDatabase . MobileAuthenticator = = null ) {
2016-03-18 14:39:59 +01:00
// Support and convert SDA files
string maFilePath = Path . Combine ( Program . ConfigDirectory , callback . ClientSteamID . ConvertToUInt64 ( ) + ".maFile" ) ;
if ( File . Exists ( maFilePath ) ) {
ImportAuthenticator ( maFilePath ) ;
}
2015-12-11 22:53:28 +01:00
}
2016-03-06 02:20:41 +01:00
if ( string . IsNullOrEmpty ( BotConfig . SteamParentalPIN ) ) {
2016-03-22 17:26:39 +01:00
BotConfig . SteamParentalPIN = Program . GetUserInput ( Program . EUserInputType . SteamParentalPIN , BotName ) ;
2016-04-06 16:37:45 +02:00
if ( string . IsNullOrEmpty ( BotConfig . SteamParentalPIN ) ) {
Stop ( ) ;
return ;
}
2015-10-29 01:01:31 +01:00
}
2016-06-25 04:05:30 +02:00
if ( ! await ArchiWebHandler . Init ( callback . ClientSteamID , SteamClient . ConnectedUniverse , callback . WebAPIUserNonce , BotConfig . SteamParentalPIN ) . ConfigureAwait ( false ) ) {
2016-03-29 14:33:05 +02:00
if ( ! await RefreshSession ( ) . ConfigureAwait ( false ) ) {
return ;
}
2015-12-25 17:49:00 +01:00
}
2015-10-25 06:16:50 +01:00
2016-03-10 21:44:45 +01:00
if ( BotConfig . DismissInventoryNotifications ) {
2016-03-22 11:21:45 +01:00
ArchiWebHandler . MarkInventory ( ) . Forget ( ) ;
2016-03-10 21:44:45 +01:00
}
2016-03-06 02:20:41 +01:00
if ( BotConfig . SteamMasterClanID ! = 0 ) {
2016-03-18 14:47:52 +01:00
Task . Run ( async ( ) = > {
2016-04-24 23:32:23 +02:00
await ArchiWebHandler . JoinGroup ( BotConfig . SteamMasterClanID ) . ConfigureAwait ( false ) ;
2016-03-18 14:47:52 +01:00
JoinMasterChat ( ) ;
} ) . Forget ( ) ;
2015-10-28 19:21:27 +01:00
}
2015-10-25 06:16:50 +01:00
2016-03-09 05:02:07 +01:00
if ( Program . GlobalConfig . Statistics ) {
2016-07-03 05:57:33 +02:00
ArchiWebHandler . JoinGroup ( ArchiSCFarmGroup ) . Forget ( ) ;
2015-10-29 16:38:16 +01:00
}
2016-06-09 18:23:29 +02:00
Trading . CheckTrades ( ) . Forget ( ) ;
2015-12-13 15:25:00 +01:00
2016-06-24 22:26:52 +02:00
await Task . Delay ( 1000 ) . ConfigureAwait ( false ) ; // Wait a second for eventual PlayingSessionStateCallback
2016-03-22 11:21:45 +01:00
CardsFarmer . StartFarming ( ) . Forget ( ) ;
2015-10-25 06:16:50 +01:00
break ;
2015-12-23 16:34:57 +01:00
case EResult . NoConnection :
2015-12-02 17:17:47 +01:00
case EResult . ServiceUnavailable :
2015-10-28 20:01:43 +01:00
case EResult . Timeout :
case EResult . TryAnotherCM :
2016-07-09 09:20:56 +02:00
Logging . LogGenericWarning ( "Unable to login to Steam: " + callback . Result + " / " + callback . ExtendedResult , BotName ) ;
2015-10-25 06:16:50 +01:00
break ;
2015-12-23 10:58:14 +01:00
default : // Unexpected result, shutdown immediately
2016-07-09 09:20:56 +02:00
Logging . LogGenericError ( "Unable to login to Steam: " + callback . Result + " / " + callback . ExtendedResult , BotName ) ;
2016-03-22 20:18:47 +01:00
Stop ( ) ;
2015-10-28 20:01:43 +01:00
break ;
2015-10-25 06:16:50 +01:00
}
}
2015-12-11 22:53:28 +01:00
private void OnLoginKey ( SteamUser . LoginKeyCallback callback ) {
2016-07-10 20:17:35 +02:00
if ( string . IsNullOrEmpty ( callback ? . LoginKey ) ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) + " || " + nameof ( callback . LoginKey ) , BotName ) ;
2015-12-11 22:53:28 +01:00
return ;
}
2016-03-06 02:20:41 +01:00
BotDatabase . LoginKey = callback . LoginKey ;
2015-12-11 22:53:28 +01:00
SteamUser . AcceptNewLoginKey ( callback ) ;
}
2015-10-25 06:16:50 +01:00
private void OnMachineAuth ( SteamUser . UpdateMachineAuthCallback callback ) {
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-03-30 13:10:00 +02:00
int fileSize ;
byte [ ] sentryHash ;
2016-02-20 17:07:05 +01:00
2016-05-30 01:57:06 +02:00
try {
using ( FileStream fileStream = File . Open ( SentryFile , FileMode . OpenOrCreate , FileAccess . ReadWrite ) ) {
fileStream . Seek ( callback . Offset , SeekOrigin . Begin ) ;
fileStream . Write ( callback . Data , 0 , callback . BytesToWrite ) ;
fileSize = ( int ) fileStream . Length ;
fileStream . Seek ( 0 , SeekOrigin . Begin ) ;
using ( SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider ( ) ) {
sentryHash = sha . ComputeHash ( fileStream ) ;
}
2015-10-25 06:16:50 +01:00
}
2016-05-30 01:57:06 +02:00
} catch ( Exception e ) {
Logging . LogGenericException ( e , BotName ) ;
return ;
2016-02-12 16:51:06 +01:00
}
2016-03-30 13:10:00 +02:00
// Inform the steam servers that we're accepting this sentry file
SteamUser . SendMachineAuthResponse ( new SteamUser . MachineAuthDetails {
JobID = callback . JobID ,
FileName = callback . FileName ,
BytesWritten = callback . BytesToWrite ,
FileSize = fileSize ,
Offset = callback . Offset ,
Result = EResult . OK ,
LastError = 0 ,
OneTimePassword = callback . OneTimePassword ,
SentryFileHash = sentryHash
} ) ;
2015-10-25 06:16:50 +01:00
}
2016-05-30 01:57:06 +02:00
private void OnWebAPIUserNonce ( SteamUser . WebAPIUserNonceCallback callback ) {
if ( callback = = null ) {
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
}
}
2016-03-29 14:33:05 +02:00
2016-06-09 18:23:29 +02:00
private void OnNotifications ( ArchiHandler . NotificationsCallback callback ) {
2016-05-30 01:57:06 +02:00
if ( callback = = null ) {
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
return ;
}
if ( ( callback . Notifications = = null ) | | ( callback . Notifications . Count = = 0 ) ) {
2015-10-25 06:16:50 +01:00
return ;
}
2016-05-13 06:32:42 +02:00
foreach ( ArchiHandler . NotificationsCallback . ENotification notification in callback . Notifications ) {
2016-05-03 07:26:41 +02:00
switch ( notification ) {
case ArchiHandler . NotificationsCallback . ENotification . Items :
2016-06-08 23:26:37 +02:00
CardsFarmer . OnNewItemsNotification ( ) ;
if ( BotConfig . DismissInventoryNotifications ) {
2016-06-09 18:23:29 +02:00
ArchiWebHandler . MarkInventory ( ) . Forget ( ) ;
2016-06-08 23:26:37 +02:00
}
2016-02-28 03:40:59 +01:00
break ;
2016-05-03 07:26:41 +02:00
case ArchiHandler . NotificationsCallback . ENotification . Trading :
2016-06-09 18:23:29 +02:00
Trading . CheckTrades ( ) . Forget ( ) ;
2016-01-02 17:22:35 +01:00
break ;
}
}
2015-10-25 06:16:50 +01:00
}
2015-12-20 19:48:58 +01:00
private void OnOfflineMessage ( ArchiHandler . OfflineMessageCallback callback ) {
2016-05-30 01:57:06 +02:00
if ( callback = = null ) {
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-12-20 19:48:58 +01:00
return ;
}
2016-05-30 01:57:06 +02:00
if ( ( callback . OfflineMessagesCount = = 0 ) | | ! BotConfig . HandleOfflineMessages ) {
2015-12-20 19:48:58 +01:00
return ;
}
2015-12-21 10:55:55 +01:00
SteamFriends . RequestOfflineMessages ( ) ;
2015-12-20 19:50:54 +01:00
}
2015-12-20 19:48:58 +01:00
2016-05-30 00:09:42 +02:00
private void OnPlayingSessionState ( ArchiHandler . PlayingSessionStateCallback callback ) {
if ( callback = = null ) {
2016-06-19 12:20:12 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2016-05-30 00:09:42 +02:00
return ;
}
if ( callback . PlayingBlocked = = PlayingBlocked ) {
return ; // No status update, we're not interested
}
if ( callback . PlayingBlocked ) {
PlayingBlocked = true ;
Logging . LogGenericInfo ( "Account is currently being used, ASF will resume farming when it's free..." , BotName ) ;
} else {
PlayingBlocked = false ;
Logging . LogGenericInfo ( "Account is no longer occupied, farming process resumed!" , BotName ) ;
CardsFarmer . StartFarming ( ) . Forget ( ) ;
}
}
2016-06-09 03:13:35 +02:00
private async void OnPurchaseResponse ( ArchiHandler . PurchaseResponseCallback callback ) {
2015-10-25 06:16:50 +01:00
if ( callback = = null ) {
2016-05-30 01:57:06 +02:00
Logging . LogNullError ( nameof ( callback ) , BotName ) ;
2015-10-25 06:16:50 +01:00
return ;
}
2016-02-12 16:51:06 +01:00
if ( callback . PurchaseResult = = ArchiHandler . PurchaseResponseCallback . EPurchaseResult . OK ) {
2016-06-09 03:13:35 +02:00
await CardsFarmer . OnNewGameAdded ( ) . ConfigureAwait ( false ) ;
2015-10-25 06:16:50 +01:00
}
}
}
}