2016-08-02 06:13:58 +02:00
using System ;
2017-02-01 00:44:52 +01:00
using System.Collections.Generic ;
2016-08-02 08:50:31 +02:00
using System.IO ;
using System.Linq ;
using System.Reflection ;
using System.Threading ;
using System.Threading.Tasks ;
2016-08-02 06:13:58 +02:00
using System.Windows.Forms ;
2017-02-01 00:49:49 +01:00
using ArchiSteamFarm.Localization ;
2016-11-24 07:32:16 +01:00
using SteamKit2 ;
2016-08-02 06:13:58 +02:00
namespace ArchiSteamFarm {
internal static class Program {
2016-12-23 18:49:52 +01:00
internal static readonly ArchiLogger ArchiLogger = new ArchiLogger ( SharedInfo . ASF ) ;
2016-08-02 06:13:58 +02:00
internal static GlobalConfig GlobalConfig { get ; private set ; }
internal static GlobalDatabase GlobalDatabase { get ; private set ; }
internal static WebBrowser WebBrowser { get ; private set ; }
2017-02-01 00:44:52 +01:00
private static bool ShutdownSequenceInitialized ;
2017-02-01 00:49:49 +01:00
internal static async Task Exit ( byte exitCode = 0 ) {
if ( exitCode ! = 0 ) {
ASF . ArchiLogger . LogGenericError ( Strings . ErrorExitingWithNonZeroErrorCode ) ;
}
await Shutdown ( ) . ConfigureAwait ( false ) ;
2016-08-02 08:50:31 +02:00
Environment . Exit ( exitCode ) ;
2016-08-02 06:13:58 +02:00
}
2016-11-24 07:32:16 +01:00
internal static string GetUserInput ( ASF . EUserInputType userInputType , string botName = SharedInfo . ASF , string extraInformation = null ) {
return null ; // TODO
2016-08-02 06:13:58 +02:00
}
2017-02-01 00:44:52 +01:00
internal static async Task < bool > InitShutdownSequence ( ) {
if ( ShutdownSequenceInitialized ) {
return false ;
2016-08-02 08:50:31 +02:00
}
2017-02-01 00:44:52 +01:00
ShutdownSequenceInitialized = true ;
IEnumerable < Task > tasks = Bot . Bots . Values . Select ( bot = > Task . Run ( ( ) = > bot . Stop ( ) ) ) ;
await Task . WhenAny ( Task . WhenAll ( tasks ) , Task . Delay ( 10 * 1000 ) ) ;
return true ;
2016-08-02 08:50:31 +02:00
}
2017-02-01 00:44:52 +01:00
internal static async Task Restart ( ) {
2017-02-01 00:49:49 +01:00
if ( ! await InitShutdownSequence ( ) . ConfigureAwait ( false ) ) {
return ;
2016-08-02 08:50:31 +02:00
}
2017-02-01 00:49:49 +01:00
Application . Restart ( ) ;
2016-08-02 08:50:31 +02:00
}
2017-02-01 00:44:52 +01:00
private static async Task Init ( ) {
2016-08-02 08:50:31 +02:00
AppDomain . CurrentDomain . UnhandledException + = UnhandledExceptionHandler ;
TaskScheduler . UnobservedTaskException + = UnobservedTaskExceptionHandler ;
Logging . InitCoreLoggers ( ) ;
2016-08-02 22:51:09 +02:00
if ( ! Runtime . IsRuntimeSupported ) {
2016-12-23 18:49:52 +01:00
ArchiLogger . LogGenericError ( "ASF detected unsupported runtime version, program might NOT run correctly in current environment. You're running it at your own risk!" ) ;
2016-08-02 08:50:31 +02:00
}
string homeDirectory = Path . GetDirectoryName ( Assembly . GetEntryAssembly ( ) . Location ) ;
if ( ! string . IsNullOrEmpty ( homeDirectory ) ) {
Directory . SetCurrentDirectory ( homeDirectory ) ;
// Allow loading configs from source tree if it's a debug build
if ( Debugging . IsDebugBuild ) {
// Common structure is bin/(x64/)Debug/ArchiSteamFarm.exe, so we allow up to 4 directories up
for ( byte i = 0 ; i < 4 ; i + + ) {
Directory . SetCurrentDirectory ( ".." ) ;
if ( ! Directory . Exists ( SharedInfo . ASFDirectory ) ) {
continue ;
}
Directory . SetCurrentDirectory ( SharedInfo . ASFDirectory ) ;
break ;
}
// If config directory doesn't exist after our adjustment, abort all of that
if ( ! Directory . Exists ( SharedInfo . ConfigDirectory ) ) {
Directory . SetCurrentDirectory ( homeDirectory ) ;
}
}
}
2017-02-01 00:44:52 +01:00
await InitServices ( ) . ConfigureAwait ( false ) ;
2016-08-02 08:50:31 +02:00
// If debugging is on, we prepare debug directory prior to running
if ( GlobalConfig . Debug ) {
if ( Directory . Exists ( SharedInfo . DebugDirectory ) ) {
Directory . Delete ( SharedInfo . DebugDirectory , true ) ;
Thread . Sleep ( 1000 ) ; // Dirty workaround giving Windows some time to sync
}
2016-08-31 13:56:09 +02:00
2016-08-02 08:50:31 +02:00
Directory . CreateDirectory ( SharedInfo . DebugDirectory ) ;
2016-11-24 07:32:16 +01:00
DebugLog . AddListener ( new Debugging . DebugListener ( ) ) ;
DebugLog . Enabled = true ;
2016-08-02 08:50:31 +02:00
}
Logging . InitEnhancedLoggers ( ) ;
}
2017-02-01 00:44:52 +01:00
private static async Task InitServices ( ) {
2016-11-24 07:32:16 +01:00
string globalConfigFile = Path . Combine ( SharedInfo . ConfigDirectory , SharedInfo . GlobalConfigFileName ) ;
GlobalConfig = GlobalConfig . Load ( globalConfigFile ) ;
if ( GlobalConfig = = null ) {
2016-12-23 18:49:52 +01:00
ArchiLogger . LogGenericError ( "Global config could not be loaded, please make sure that " + globalConfigFile + " exists and is valid!" ) ;
2017-02-01 00:44:52 +01:00
await Exit ( 1 ) . ConfigureAwait ( false ) ;
2016-11-24 07:32:16 +01:00
}
string globalDatabaseFile = Path . Combine ( SharedInfo . ConfigDirectory , SharedInfo . GlobalDatabaseFileName ) ;
GlobalDatabase = GlobalDatabase . Load ( globalDatabaseFile ) ;
if ( GlobalDatabase = = null ) {
2016-12-23 18:49:52 +01:00
ArchiLogger . LogGenericError ( "Global database could not be loaded, if issue persists, please remove " + globalDatabaseFile + " in order to recreate database!" ) ;
2017-02-01 00:44:52 +01:00
await Exit ( 1 ) . ConfigureAwait ( false ) ;
2016-11-24 07:32:16 +01:00
}
ArchiWebHandler . Init ( ) ;
WebBrowser . Init ( ) ;
2016-12-23 18:49:52 +01:00
WebBrowser = new WebBrowser ( ArchiLogger ) ;
2016-11-24 07:32:16 +01:00
}
2016-08-02 06:13:58 +02:00
/// <summary>
2016-11-24 07:32:16 +01:00
/// The main entry point for the application.
2016-08-02 06:13:58 +02:00
/// </summary>
[STAThread]
private static void Main ( ) {
2017-02-01 00:44:52 +01:00
Init ( ) . Wait ( ) ;
2016-08-02 06:13:58 +02:00
Application . EnableVisualStyles ( ) ;
Application . SetCompatibleTextRenderingDefault ( false ) ;
2016-08-02 08:50:31 +02:00
Application . Run ( new MainForm ( ) ) ;
2016-08-02 06:13:58 +02:00
}
2016-11-24 07:32:16 +01:00
2017-02-01 00:49:49 +01:00
private static async Task Shutdown ( ) {
if ( ! await InitShutdownSequence ( ) . ConfigureAwait ( false ) ) {
return ;
}
Application . Exit ( ) ;
}
2017-02-02 18:02:02 +01:00
private static async void UnhandledExceptionHandler ( object sender , UnhandledExceptionEventArgs args ) {
2016-11-24 07:32:16 +01:00
if ( args ? . ExceptionObject = = null ) {
2016-12-23 18:49:52 +01:00
ArchiLogger . LogNullError ( nameof ( args ) + " || " + nameof ( args . ExceptionObject ) ) ;
2016-11-24 07:32:16 +01:00
return ;
}
2016-12-23 18:49:52 +01:00
ArchiLogger . LogFatalException ( ( Exception ) args . ExceptionObject ) ;
2017-02-02 18:02:02 +01:00
await Exit ( 1 ) . ConfigureAwait ( false ) ;
2016-11-24 07:32:16 +01:00
}
private static void UnobservedTaskExceptionHandler ( object sender , UnobservedTaskExceptionEventArgs args ) {
if ( args ? . Exception = = null ) {
2016-12-23 18:49:52 +01:00
ArchiLogger . LogNullError ( nameof ( args ) + " || " + nameof ( args . Exception ) ) ;
2016-11-24 07:32:16 +01:00
return ;
}
2016-12-23 18:49:52 +01:00
ArchiLogger . LogFatalException ( args . Exception ) ;
2017-02-02 18:02:02 +01:00
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
// Thanks Valve.
2016-11-24 07:32:16 +01:00
}
2016-08-02 06:13:58 +02:00
}
2016-11-24 07:32:16 +01:00
}