Inheritance: IDisposable
Esempio n. 1
0
        internal Bot(string botName)
        {
            if (Bots.ContainsKey(botName))
            {
                return;
            }

            BotName = botName;

            ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml");
            SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin");

            if (!ReadConfig())
            {
                return;
            }

            if (!Enabled)
            {
                return;
            }

            lock (Bots) {
                Bots.Add(BotName, this);
            }

            // Initialize
            SteamClient = new SteamClient();

            ArchiHandler = new ArchiHandler();
            SteamClient.AddHandler(ArchiHandler);

            CallbackManager = new CallbackManager(SteamClient);
            CallbackManager.Subscribe <SteamClient.ConnectedCallback>(OnConnected);
            CallbackManager.Subscribe <SteamClient.DisconnectedCallback>(OnDisconnected);

            SteamFriends = SteamClient.GetHandler <SteamFriends>();
            CallbackManager.Subscribe <SteamFriends.FriendsListCallback>(OnFriendsList);
            CallbackManager.Subscribe <SteamFriends.FriendMsgCallback>(OnFriendMsg);
            CallbackManager.Subscribe <SteamFriends.PersonaStateCallback>(OnPersonaState);

            SteamUser = SteamClient.GetHandler <SteamUser>();
            CallbackManager.Subscribe <SteamUser.AccountInfoCallback>(OnAccountInfo);
            CallbackManager.Subscribe <SteamUser.LoggedOffCallback>(OnLoggedOff);
            CallbackManager.Subscribe <SteamUser.LoggedOnCallback>(OnLoggedOn);
            CallbackManager.Subscribe <SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);

            CallbackManager.Subscribe <ArchiHandler.NotificationCallback>(OnNotification);
            CallbackManager.Subscribe <ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);

            ArchiWebHandler = new ArchiWebHandler(this, SteamApiKey);
            CardsFarmer     = new CardsFarmer(this);
            Trading         = new Trading(this);

            // Start
            Start();
        }
Esempio n. 2
0
        internal async Task Stop()
        {
            if (!IsRunning)
            {
                return;
            }

            await CardsFarmer.StopFarming().ConfigureAwait(false);

            IsRunning = false;
            SteamClient.Disconnect();
        }
Esempio n. 3
0
		internal Bot(string botName) {
			BotName = botName;
			CardsFarmer = new CardsFarmer(this);

			ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml");
			SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin");

			ReadConfig();

			if (!Enabled) {
				return;
			}

			Start();
		}
Esempio n. 4
0
        private async void OnPurchaseResponse(ArchiHandler.PurchaseResponseCallback callback)
        {
            if (callback == null)
            {
                return;
            }

            var purchaseResult = callback.PurchaseResult;
            var items          = callback.Items;

            SendMessageToUser(SteamMasterID, "Status: " + purchaseResult + " | Items: " + string.Join("", items));

            if (purchaseResult == ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK)
            {
                await CardsFarmer.StartFarming().ConfigureAwait(false);
            }
        }
Esempio n. 5
0
        internal Bot(string botName)
        {
            BotName     = botName;
            CardsFarmer = new CardsFarmer(this);

            ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml");
            SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin");

            ReadConfig();

            if (!Enabled)
            {
                return;
            }

            Start();
        }
Esempio n. 6
0
		internal Bot(string botName) {
			if (string.IsNullOrEmpty(botName)) {
				throw new ArgumentNullException(nameof(botName));
			}

			if (Bots.ContainsKey(botName)) {
				throw new ArgumentException("That bot is already defined!");
			}

			string botPath = Path.Combine(SharedInfo.ConfigDirectory, botName);

			BotName = botName;
			SentryFile = botPath + ".bin";

			string botConfigFile = botPath + ".json";

			BotConfig = BotConfig.Load(botConfigFile);
			if (BotConfig == null) {
				Logging.LogGenericError("Your bot config is invalid, please verify content of " + botConfigFile + " and try again!", botName);
				return;
			}

			// Register bot as available for ASF
			if (!Bots.TryAdd(botName, this)) {
				throw new ArgumentException("That bot is already defined!");
			}

			string botDatabaseFile = botPath + ".db";

			BotDatabase = BotDatabase.Load(botDatabaseFile);
			if (BotDatabase == null) {
				Logging.LogGenericError("Bot database could not be loaded, refusing to create this bot instance! In order to recreate it, remove " + botDatabaseFile + " and try again!", botName);
				return;
			}

			if (BotDatabase.MobileAuthenticator != null) {
				BotDatabase.MobileAuthenticator.Init(this);
			} else {
				// Support and convert SDA files
				string maFilePath = botPath + ".maFile";
				if (File.Exists(maFilePath)) {
					ImportAuthenticator(maFilePath);
				}
			}

			// Initialize
			SteamClient = new SteamClient(Program.GlobalConfig.SteamProtocol);

			if (Program.GlobalConfig.Debug && Directory.Exists(SharedInfo.DebugDirectory)) {
				string debugListenerPath = Path.Combine(SharedInfo.DebugDirectory, botName);

				try {
					Directory.CreateDirectory(debugListenerPath);
					SteamClient.DebugNetworkListener = new NetHookNetworkListener(debugListenerPath);
				} catch (Exception e) {
					Logging.LogGenericException(e, botName);
				}
			}

			ArchiHandler = new ArchiHandler(this);
			SteamClient.AddHandler(ArchiHandler);

			CallbackManager = new CallbackManager(SteamClient);
			CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
			CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);

			SteamApps = SteamClient.GetHandler<SteamApps>();
			CallbackManager.Subscribe<SteamApps.FreeLicenseCallback>(OnFreeLicense);
			CallbackManager.Subscribe<SteamApps.GuestPassListCallback>(OnGuestPassList);
			CallbackManager.Subscribe<SteamApps.LicenseListCallback>(OnLicenseList);

			SteamFriends = SteamClient.GetHandler<SteamFriends>();
			CallbackManager.Subscribe<SteamFriends.ChatInviteCallback>(OnChatInvite);
			CallbackManager.Subscribe<SteamFriends.ChatMsgCallback>(OnChatMsg);
			CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
			CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
			CallbackManager.Subscribe<SteamFriends.FriendMsgHistoryCallback>(OnFriendMsgHistory);
			CallbackManager.Subscribe<SteamFriends.PersonaStateCallback>(OnPersonaState);

			SteamUser = SteamClient.GetHandler<SteamUser>();
			CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
			CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
			CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
			CallbackManager.Subscribe<SteamUser.LoginKeyCallback>(OnLoginKey);
			CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
			CallbackManager.Subscribe<SteamUser.WebAPIUserNonceCallback>(OnWebAPIUserNonce);

			CallbackManager.Subscribe<ArchiHandler.NotificationsCallback>(OnNotifications);
			CallbackManager.Subscribe<ArchiHandler.OfflineMessageCallback>(OnOfflineMessage);
			CallbackManager.Subscribe<ArchiHandler.PlayingSessionStateCallback>(OnPlayingSessionState);
			CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);
			CallbackManager.Subscribe<ArchiHandler.SharedLibraryLockStatusCallback>(OnSharedLibraryLockStatus);

			ArchiWebHandler = new ArchiWebHandler(this);

			CardsFarmer = new CardsFarmer(this) {
				Paused = BotConfig.Paused
			};

			Trading = new Trading(this);

			HeartBeatTimer = new Timer(
				async e => await HeartBeat().ConfigureAwait(false),
				null,
				TimeSpan.FromMinutes(1) + TimeSpan.FromMinutes(0.2 * Bots.Count), // Delay
				TimeSpan.FromMinutes(1) // Period
			);

			Initialize().Forget();
		}
Esempio n. 7
0
		internal Bot(string botName) {
			if (Bots.ContainsKey(botName)) {
				return;
			}

			BotName = botName;

			ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml");
			SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin");

			if (!ReadConfig()) {
				return;
			}

			if (!Enabled) {
				return;
			}

			lock (Bots) {
				Bots.Add(BotName, this);
			}

			// Initialize
			SteamClient = new SteamClient();

			ArchiHandler = new ArchiHandler();
			SteamClient.AddHandler(ArchiHandler);

			CallbackManager = new CallbackManager(SteamClient);
			CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
			CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);

			SteamFriends = SteamClient.GetHandler<SteamFriends>();
			CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
			CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
			CallbackManager.Subscribe<SteamFriends.PersonaStateCallback>(OnPersonaState);

			SteamUser = SteamClient.GetHandler<SteamUser>();
			CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
			CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
			CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
			CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);

			CallbackManager.Subscribe<ArchiHandler.NotificationCallback>(OnNotification);
			CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);

			ArchiWebHandler = new ArchiWebHandler(this, SteamApiKey);
			CardsFarmer = new CardsFarmer(this);
			Trading = new Trading(this);

			// Start
			Start();
		}
Esempio n. 8
0
        private async void OnLoggedOn(SteamUser.LoggedOnCallback callback)
        {
            if (callback == null)
            {
                return;
            }

            EResult result = callback.Result;

            switch (result)
            {
            case EResult.AccountLogonDenied:
                AuthCode = Program.GetUserInput(SteamLogin, Program.EUserInputType.SteamGuard);
                break;

            case EResult.AccountLoginDeniedNeedTwoFactor:
                TwoFactorAuth = Program.GetUserInput(SteamLogin, Program.EUserInputType.TwoFactorAuthentication);
                break;

            case EResult.OK:
                Logging.LogGenericInfo(BotName, "Successfully logged on!");

                if (!SteamNickname.Equals("null"))
                {
                    SteamFriends.SetPersonaName(SteamNickname);
                }

                if (SteamParentalPIN.Equals("null"))
                {
                    SteamParentalPIN = Program.GetUserInput(BotName, Program.EUserInputType.SteamParentalPIN);
                }

                await ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, callback.VanityURL, SteamParentalPIN).ConfigureAwait(false);

                ulong clanID = SteamMasterClanID;
                if (clanID != 0)
                {
                    SteamFriends.JoinChat(clanID);
                }

                if (Statistics)
                {
                    SteamFriends.JoinChat(Program.ArchiSCFarmGroup);
                    await ArchiWebHandler.JoinClan(Program.ArchiSCFarmGroup).ConfigureAwait(false);
                }

                await CardsFarmer.StartFarming().ConfigureAwait(false);

                break;

            case EResult.Timeout:
            case EResult.TryAnotherCM:
                Logging.LogGenericWarning(BotName, "Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult + ", retrying...");
                await Stop().ConfigureAwait(false);

                await Utilities.SleepAsync(CallbackSleep).ConfigureAwait(false);

                Start();
                break;

            default:
                Logging.LogGenericWarning(BotName, "Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult);
                await Shutdown().ConfigureAwait(false);

                break;
            }
        }
Esempio n. 9
0
        private async void OnFriendMsg(SteamFriends.FriendMsgCallback callback)
        {
            if (callback == null)
            {
                return;
            }

            if (callback.EntryType != EChatEntryType.ChatMsg)
            {
                return;
            }

            ulong steamID = callback.Sender;

            if (steamID != SteamMasterID)
            {
                return;
            }

            string message = callback.Message;

            if (string.IsNullOrEmpty(message))
            {
                return;
            }

            if (message.Length == 17 && message[5] == '-' && message[11] == '-')
            {
                ArchiHandler.RedeemKey(message);
                return;
            }

            if (!message.StartsWith("!"))
            {
                return;
            }

            if (!message.Contains(" "))
            {
                switch (message)
                {
                case "!exit":
                    await ShutdownAllBots().ConfigureAwait(false);

                    break;

                case "!farm":
                    await CardsFarmer.StartFarming().ConfigureAwait(false);

                    SendMessageToUser(steamID, "Done!");
                    break;

                case "!restart":
                    await Program.Restart().ConfigureAwait(false);

                    break;

                case "!status":
                    ResponseStatus(steamID);
                    break;

                case "!stop":
                    await Shutdown().ConfigureAwait(false);

                    break;
                }
            }
            else
            {
                string[] args = message.Split(' ');
                switch (args[0])
                {
                case "!start":
                    ResponseStart(steamID, args[1]);
                    break;

                case "!stop":
                    await ResponseStop(steamID, args[1]).ConfigureAwait(false);

                    break;
                }
            }
        }
Esempio n. 10
0
		internal Bot(string botName, bool initialLaunch = false) {
			if (Bots.ContainsKey(botName)) {
				return;
			}

			BotName = botName;

			ConfigFile = Path.Combine(Program.ConfigDirectory, BotName + ".xml");
			LoginKeyFile = Path.Combine(Program.ConfigDirectory, BotName + ".key");
			MobileAuthenticatorFile = Path.Combine(Program.ConfigDirectory, BotName + ".auth");
			SentryFile = Path.Combine(Program.ConfigDirectory, BotName + ".bin");

			if (!ReadConfig()) {
				return;
			}

			if (!Enabled) {
				return;
			}

			Bots.AddOrUpdate(BotName, this, (key, value) => this);

			// Initialize
			SteamClient = new SteamClient();

			ArchiHandler = new ArchiHandler();
			SteamClient.AddHandler(ArchiHandler);

			CallbackManager = new CallbackManager(SteamClient);
			CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
			CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);

			SteamApps = SteamClient.GetHandler<SteamApps>();
			CallbackManager.Subscribe<SteamApps.FreeLicenseCallback>(OnFreeLicense);

			SteamFriends = SteamClient.GetHandler<SteamFriends>();
			CallbackManager.Subscribe<SteamFriends.ChatInviteCallback>(OnChatInvite);
			CallbackManager.Subscribe<SteamFriends.ChatMsgCallback>(OnChatMsg);
			CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
			CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
			CallbackManager.Subscribe<SteamFriends.FriendMsgHistoryCallback>(OnFriendMsgHistory);

			if (UseAsfAsMobileAuthenticator && File.Exists(MobileAuthenticatorFile)) {
				SteamGuardAccount = JsonConvert.DeserializeObject<SteamGuardAccount>(File.ReadAllText(MobileAuthenticatorFile));
			}

			SteamUser = SteamClient.GetHandler<SteamUser>();
			CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
			CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
			CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
			CallbackManager.Subscribe<SteamUser.LoginKeyCallback>(OnLoginKey);
			CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);

			CallbackManager.Subscribe<ArchiHandler.NotificationsCallback>(OnNotifications);
			CallbackManager.Subscribe<ArchiHandler.OfflineMessageCallback>(OnOfflineMessage);
			CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);

			ArchiWebHandler = new ArchiWebHandler(this, SteamApiKey);
			CardsFarmer = new CardsFarmer(this);
			Trading = new Trading(this);

			if (SendTradePeriod > 0 && SendItemsTimer == null) {
				SendItemsTimer = new Timer(
					async e => await ResponseSendTrade(BotName).ConfigureAwait(false),
					null,
					TimeSpan.FromHours(SendTradePeriod), // Delay
					TimeSpan.FromHours(SendTradePeriod) // Period
				);
			}

			if (initialLaunch && !StartOnLaunch) {
				return;
			}

			// Start
			var start = Task.Run(async () => await Start().ConfigureAwait(false));
		}
Esempio n. 11
0
		internal Bot(string botName) {
			if (string.IsNullOrEmpty(botName)) {
				throw new ArgumentNullException(nameof(botName));
			}

			if (Bots.ContainsKey(botName)) {
				throw new Exception("That bot is already defined!");
			}

			string botPath = Path.Combine(Program.ConfigDirectory, botName);

			BotName = botName;
			SentryFile = botPath + ".bin";

			BotConfig = BotConfig.Load(botPath + ".json");
			if (BotConfig == null) {
				Logging.LogGenericError("Your bot config is invalid, refusing to start this bot instance!", botName);
				return;
			}

			if (!BotConfig.Enabled) {
				Logging.LogGenericInfo("Not initializing this instance because it's disabled in config file", botName);
				return;
			}

			BotDatabase = BotDatabase.Load(botPath + ".db");
			if (BotDatabase == null) {
				Logging.LogGenericError("Bot database could not be loaded, refusing to start this bot instance!", botName);
				return;
			}

			// TODO: Converter code will be removed soon
			if (BotDatabase.SteamGuardAccount != null) {
				Logging.LogGenericWarning("Converting old ASF 2FA V2.0 format into new ASF 2FA V2.1 format...", botName);
				BotDatabase.MobileAuthenticator = MobileAuthenticator.LoadFromSteamGuardAccount(BotDatabase.SteamGuardAccount);
				Logging.LogGenericInfo("Done! If you didn't make a copy of your revocation code yet, then it's a good moment to do so: " + BotDatabase.SteamGuardAccount.RevocationCode, botName);
				Logging.LogGenericWarning("ASF will not keep this code anymore!", botName);
				BotDatabase.SteamGuardAccount = null;
			}

			if (BotDatabase.MobileAuthenticator != null) {
				BotDatabase.MobileAuthenticator.Init(this);
			} else {
				// Support and convert SDA files
				string maFilePath = botPath + ".maFile";
				if (File.Exists(maFilePath)) {
					ImportAuthenticator(maFilePath);
				}
			}

			// Initialize
			SteamClient = new SteamClient(Program.GlobalConfig.SteamProtocol);

			if (Program.GlobalConfig.Debug && !Debugging.NetHookAlreadyInitialized && Directory.Exists(Program.DebugDirectory)) {
				try {
					Debugging.NetHookAlreadyInitialized = true;
					SteamClient.DebugNetworkListener = new NetHookNetworkListener(Program.DebugDirectory);
				} catch (Exception e) {
					Logging.LogGenericException(e, botName);
				}
			}

			ArchiHandler = new ArchiHandler(this);
			SteamClient.AddHandler(ArchiHandler);

			CallbackManager = new CallbackManager(SteamClient);
			CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
			CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);

			SteamApps = SteamClient.GetHandler<SteamApps>();
			CallbackManager.Subscribe<SteamApps.FreeLicenseCallback>(OnFreeLicense);
			CallbackManager.Subscribe<SteamApps.GuestPassListCallback>(OnGuestPassList);

			SteamFriends = SteamClient.GetHandler<SteamFriends>();
			CallbackManager.Subscribe<SteamFriends.ChatInviteCallback>(OnChatInvite);
			CallbackManager.Subscribe<SteamFriends.ChatMsgCallback>(OnChatMsg);
			CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
			CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
			CallbackManager.Subscribe<SteamFriends.FriendMsgHistoryCallback>(OnFriendMsgHistory);

			SteamUser = SteamClient.GetHandler<SteamUser>();
			CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
			CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
			CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
			CallbackManager.Subscribe<SteamUser.LoginKeyCallback>(OnLoginKey);
			CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
			CallbackManager.Subscribe<SteamUser.WebAPIUserNonceCallback>(OnWebAPIUserNonce);

			CallbackManager.Subscribe<ArchiHandler.NotificationsCallback>(OnNotifications);
			CallbackManager.Subscribe<ArchiHandler.OfflineMessageCallback>(OnOfflineMessage);
			CallbackManager.Subscribe<ArchiHandler.PlayingSessionStateCallback>(OnPlayingSessionState);
			CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);

			ArchiWebHandler = new ArchiWebHandler(this);
			CardsFarmer = new CardsFarmer(this);
			Trading = new Trading(this);

			if ((AcceptConfirmationsTimer == null) && (BotConfig.AcceptConfirmationsPeriod > 0)) {
				AcceptConfirmationsTimer = new Timer(
					async e => await AcceptConfirmations(true).ConfigureAwait(false),
					null,
					TimeSpan.FromMinutes(BotConfig.AcceptConfirmationsPeriod), // Delay
					TimeSpan.FromMinutes(BotConfig.AcceptConfirmationsPeriod) // Period
				);
			}

			if ((SendItemsTimer == null) && (BotConfig.SendTradePeriod > 0)) {
				SendItemsTimer = new Timer(
					async e => await ResponseLoot(BotConfig.SteamMasterID).ConfigureAwait(false),
					null,
					TimeSpan.FromHours(BotConfig.SendTradePeriod), // Delay
					TimeSpan.FromHours(BotConfig.SendTradePeriod) // Period
				);
			}

			// Register bot as available for ASF
			Bots[botName] = this;

			if (!BotConfig.StartOnLaunch) {
				return;
			}

			// Start
			Start().Forget();
		}
Esempio n. 12
0
		internal Bot(string botName) {
			if (string.IsNullOrEmpty(botName)) {
				throw new ArgumentNullException("botName");
			}

			BotName = botName;

			string botPath = Path.Combine(Program.ConfigDirectory, botName);

			BotConfig = BotConfig.Load(botPath + ".json");
			if (BotConfig == null) {
				Logging.LogGenericError("Your bot config is invalid, refusing to start this bot instance!", botName);
				return;
			}

			if (!BotConfig.Enabled) {
				return;
			}

			BotDatabase = BotDatabase.Load(botPath + ".db");
			if (BotDatabase == null) {
				Logging.LogGenericError("Bot database could not be loaded, refusing to start this bot instance!", botName);
				return;
			}

			bool alreadyExists;
			lock (Bots) {
				alreadyExists = Bots.ContainsKey(botName);
				if (!alreadyExists) {
					Bots[botName] = this;
				}
			}

			if (alreadyExists) {
				return;
			}

			SentryFile = botPath + ".bin";

			if (BotDatabase.SteamGuardAccount == null) {
				// Support and convert SDA files
				string maFilePath = botPath + ".maFile";
				if (File.Exists(maFilePath)) {
					ImportAuthenticator(maFilePath);
				}
			}

			// Initialize
			SteamClient = new SteamClient(Program.GlobalConfig.SteamProtocol);

			if (Program.GlobalConfig.Debug && !Debugging.NetHookAlreadyInitialized && Directory.Exists(Program.DebugDirectory)) {
				try {
					SteamClient.DebugNetworkListener = new NetHookNetworkListener(Program.DebugDirectory);
					Debugging.NetHookAlreadyInitialized = true;
				} catch (Exception e) {
					Logging.LogGenericException(e, botName);
				}
			}

			ArchiHandler = new ArchiHandler(this);
			SteamClient.AddHandler(ArchiHandler);

			CallbackManager = new CallbackManager(SteamClient);
			CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
			CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);

			SteamApps = SteamClient.GetHandler<SteamApps>();
			CallbackManager.Subscribe<SteamApps.FreeLicenseCallback>(OnFreeLicense);
			CallbackManager.Subscribe<SteamApps.GuestPassListCallback>(OnGuestPassList);

			SteamFriends = SteamClient.GetHandler<SteamFriends>();
			CallbackManager.Subscribe<SteamFriends.ChatInviteCallback>(OnChatInvite);
			CallbackManager.Subscribe<SteamFriends.ChatMsgCallback>(OnChatMsg);
			CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
			CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
			CallbackManager.Subscribe<SteamFriends.FriendMsgHistoryCallback>(OnFriendMsgHistory);

			SteamUser = SteamClient.GetHandler<SteamUser>();
			CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
			CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
			CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
			CallbackManager.Subscribe<SteamUser.LoginKeyCallback>(OnLoginKey);
			CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
			CallbackManager.Subscribe<SteamUser.WebAPIUserNonceCallback>(OnWebAPIUserNonce);

			CallbackManager.Subscribe<ArchiHandler.NotificationsCallback>(OnNotifications);
			CallbackManager.Subscribe<ArchiHandler.OfflineMessageCallback>(OnOfflineMessage);
			CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);

			ArchiWebHandler = new ArchiWebHandler(this);
			CardsFarmer = new CardsFarmer(this);
			Trading = new Trading(this);

			if (AcceptConfirmationsTimer == null && BotConfig.AcceptConfirmationsPeriod > 0) {
				AcceptConfirmationsTimer = new Timer(
					async e => await AcceptConfirmations(true).ConfigureAwait(false),
					null,
					TimeSpan.FromMinutes(BotConfig.AcceptConfirmationsPeriod), // Delay
					TimeSpan.FromMinutes(BotConfig.AcceptConfirmationsPeriod) // Period
				);
			}

			if (SendItemsTimer == null && BotConfig.SendTradePeriod > 0) {
				SendItemsTimer = new Timer(
					async e => await ResponseSendTrade(BotConfig.SteamMasterID).ConfigureAwait(false),
					null,
					TimeSpan.FromHours(BotConfig.SendTradePeriod), // Delay
					TimeSpan.FromHours(BotConfig.SendTradePeriod) // Period
				);
			}

			if (!BotConfig.StartOnLaunch) {
				return;
			}

			// Start
			Start().Forget();
		}