Example #1
0
        private static void Main(string[] args)
        {
            Logging.LogGenericInfo("Main", "Archi's Steam Farm, version " + Version);

            Task.Run(async() => await CheckForUpdate().ConfigureAwait(false)).Wait();

            // Config directory may not be in the same directory as the .exe, check maximum of 3 levels lower
            for (var i = 0; i < 4 && !Directory.Exists(ConfigDirectoryPath); i++)
            {
                Directory.SetCurrentDirectory("..");
            }

            if (!Directory.Exists(ConfigDirectoryPath))
            {
                Logging.LogGenericError("Main", "Config directory doesn't exist!");
                Console.ReadLine();
                Exit(1);
            }

            lock (Bots) {
                foreach (var configFile in Directory.EnumerateFiles(ConfigDirectoryPath, "*.xml"))
                {
                    string botName = Path.GetFileNameWithoutExtension(configFile);
                    Bot    bot     = new Bot(botName);
                    Bots.Add(bot);
                    if (!bot.Enabled)
                    {
                        Logging.LogGenericInfo(botName, "Not starting this instance because it's disabled in config file");
                    }
                }
            }

            Thread.Sleep(Timeout.Infinite);
        }
Example #2
0
        private static void InitServices()
        {
            string globalConfigFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName);

            GlobalConfig = GlobalConfig.Load(globalConfigFile);
            if (GlobalConfig == null)
            {
                Logging.LogGenericError("Global config could not be loaded, please make sure that " + globalConfigFile + " exists and is valid!");
                Thread.Sleep(5000);
                Exit(1);
            }

            string globalDatabaseFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalDatabaseFileName);

            GlobalDatabase = GlobalDatabase.Load(globalDatabaseFile);
            if (GlobalDatabase == null)
            {
                Logging.LogGenericError("Global database could not be loaded, if issue persists, please remove " + globalDatabaseFile + " in order to recreate database!");
                Thread.Sleep(5000);
                Exit(1);
            }

            ArchiWebHandler.Init();
            WebBrowser.Init();
            WCF.Init();

            WebBrowser = new WebBrowser(SharedInfo.ASF);
        }
Example #3
0
        private static void OnDeleted(object sender, FileSystemEventArgs e)
        {
            if ((sender == null) || (e == null))
            {
                Logging.LogNullError(nameof(sender) + " || " + nameof(e));
                return;
            }

            string botName = Path.GetFileNameWithoutExtension(e.Name);

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

            if (botName.Equals(SharedInfo.ASF))
            {
                Logging.LogGenericError("Global config file has been removed, exiting...");
                Program.Exit(1);
                return;
            }

            Bot bot;

            if (Bot.Bots.TryGetValue(botName, out bot))
            {
                bot.OnNewConfigLoaded(new BotConfigEventArgs()).Forget();
            }
        }
        private async Task <HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary <string, string> data = null, string referer = null)
        {
            if (string.IsNullOrEmpty(request) || (httpMethod == null))
            {
                Logging.LogNullError(nameof(request) + " || " + nameof(httpMethod));
                return(null);
            }

            if (request.StartsWith("https://", StringComparison.Ordinal) && Program.GlobalConfig.ForceHttp)
            {
                return(null);
            }

            HttpResponseMessage responseMessage;

            using (HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, request)) {
                if ((data != null) && (data.Count > 0))
                {
                    try {
                        requestMessage.Content = new FormUrlEncodedContent(data);
                    } catch (UriFormatException e) {
                        Logging.LogGenericException(e, Identifier);
                        return(null);
                    }
                }

                if (!string.IsNullOrEmpty(referer))
                {
                    requestMessage.Headers.Referrer = new Uri(referer);
                }

                try {
                    responseMessage = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
                } catch {                 // Request failed, we don't need to know the exact reason, swallow exception
                    return(null);
                }
            }

            if (responseMessage == null)
            {
                return(null);
            }

            if (responseMessage.IsSuccessStatusCode)
            {
                return(responseMessage);
            }

            if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug)
            {
                Logging.LogGenericError("Request: " + request + " failed!", Identifier);
                Logging.LogGenericError("Status code: " + responseMessage.StatusCode, Identifier);
                Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false), Identifier);
            }

            responseMessage.Dispose();
            return(null);
        }
Example #5
0
        private bool FarmHours(ConcurrentHashSet <Game> games)
        {
            if ((games == null) || (games.Count == 0))
            {
                Logging.LogNullError(nameof(games), Bot.BotName);
                return(false);
            }

            float maxHour = games.Max(game => game.HoursPlayed);

            if (maxHour < 0)
            {
                Logging.LogNullError(nameof(maxHour), Bot.BotName);
                return(false);
            }

            if (maxHour >= 2)
            {
                Logging.LogGenericError("Received request for past-2h games!", Bot.BotName);
                return(true);
            }

            Bot.ArchiHandler.PlayGames(games.Select(game => game.AppID), Bot.BotConfig.CustomGamePlayedWhileFarming);

            bool success = true;

            while (maxHour < 2)
            {
                Logging.LogGenericInfo("Still farming: " + string.Join(", ", games.Select(game => game.AppID)), Bot.BotName);

                DateTime startFarmingPeriod = DateTime.Now;
                if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay))
                {
                    FarmResetEvent.Reset();
                    success = KeepFarming;
                }

                // Don't forget to update our GamesToFarm hours
                float timePlayed = (float)DateTime.Now.Subtract(startFarmingPeriod).TotalHours;
                foreach (Game game in games)
                {
                    game.HoursPlayed += timePlayed;
                }

                if (!success)
                {
                    break;
                }

                maxHour += timePlayed;
            }

            Logging.LogGenericInfo("Stopped farming: " + string.Join(", ", games.Select(game => game.AppID)), Bot.BotName);
            return(success);
        }
Example #6
0
        private async Task <ParseTradeResult> ParseTrade(Steam.TradeOffer tradeOffer)
        {
            if (tradeOffer == null)
            {
                Logging.LogNullError(nameof(tradeOffer), Bot.BotName);
                return(null);
            }

            if (tradeOffer.State != Steam.TradeOffer.ETradeOfferState.Active)
            {
                Logging.LogGenericError("Ignoring trade in non-active state!", Bot.BotName);
                return(null);
            }

            ParseTradeResult result = await ShouldAcceptTrade(tradeOffer).ConfigureAwait(false);

            if (result == null)
            {
                Logging.LogNullError(nameof(result), Bot.BotName);
                return(null);
            }

            switch (result.Result)
            {
            case ParseTradeResult.EResult.AcceptedWithItemLose:
            case ParseTradeResult.EResult.AcceptedWithoutItemLose:
                Logging.LogGenericInfo("Accepting trade: " + tradeOffer.TradeOfferID, Bot.BotName);
                await Bot.ArchiWebHandler.AcceptTradeOffer(tradeOffer.TradeOfferID).ConfigureAwait(false);

                break;

            case ParseTradeResult.EResult.RejectedPermanently:
            case ParseTradeResult.EResult.RejectedTemporarily:
                if (result.Result == ParseTradeResult.EResult.RejectedPermanently)
                {
                    if (Bot.BotConfig.IsBotAccount)
                    {
                        Logging.LogGenericInfo("Rejecting trade: " + tradeOffer.TradeOfferID, Bot.BotName);
                        Bot.ArchiWebHandler.DeclineTradeOffer(tradeOffer.TradeOfferID);
                        break;
                    }

                    IgnoredTrades.Add(tradeOffer.TradeOfferID);
                }

                Logging.LogGenericInfo("Ignoring trade: " + tradeOffer.TradeOfferID, Bot.BotName);
                break;
            }

            return(result);
        }
Example #7
0
        private void SortGamesToFarm()
        {
            IOrderedEnumerable <Game> gamesToFarm;

            switch (Bot.BotConfig.FarmingOrder)
            {
            case BotConfig.EFarmingOrder.Unordered:
                return;

            case BotConfig.EFarmingOrder.AppIDsAscending:
                gamesToFarm = GamesToFarm.OrderBy(game => game.AppID);
                break;

            case BotConfig.EFarmingOrder.AppIDsDescending:
                gamesToFarm = GamesToFarm.OrderByDescending(game => game.AppID);
                break;

            case BotConfig.EFarmingOrder.CardDropsAscending:
                gamesToFarm = GamesToFarm.OrderBy(game => game.CardsRemaining);
                break;

            case BotConfig.EFarmingOrder.CardDropsDescending:
                gamesToFarm = GamesToFarm.OrderByDescending(game => game.CardsRemaining);
                break;

            case BotConfig.EFarmingOrder.HoursAscending:
                gamesToFarm = GamesToFarm.OrderBy(game => game.HoursPlayed);
                break;

            case BotConfig.EFarmingOrder.HoursDescending:
                gamesToFarm = GamesToFarm.OrderByDescending(game => game.HoursPlayed);
                break;

            case BotConfig.EFarmingOrder.NamesAscending:
                gamesToFarm = GamesToFarm.OrderBy(game => game.GameName);
                break;

            case BotConfig.EFarmingOrder.NamesDescending:
                gamesToFarm = GamesToFarm.OrderByDescending(game => game.GameName);
                break;

            default:
                Logging.LogGenericError("Unhandled case: " + Bot.BotConfig.FarmingOrder, Bot.BotName);
                return;
            }

            GamesToFarm.ReplaceWith(gamesToFarm.ToList());             // We must call ToList() here as we can't enumerate during replacing
        }
Example #8
0
        private void OnConnected(SteamClient.ConnectedCallback callback)
        {
            if (callback == null)
            {
                return;
            }

            if (callback.Result != EResult.OK)
            {
                Logging.LogGenericError(BotName, "Unable to connect to Steam: " + callback.Result);
                return;
            }

            Logging.LogGenericInfo(BotName, "Connected to Steam!");

            byte[] sentryHash = null;
            if (File.Exists(SentryFile))
            {
                byte[] sentryFileContent = File.ReadAllBytes(SentryFile);
                sentryHash = CryptoHelper.SHAHash(sentryFileContent);
            }

            string steamLogin = SteamLogin;

            if (string.IsNullOrEmpty(steamLogin) || steamLogin.Equals("null"))
            {
                steamLogin           = Program.GetUserInput(BotName, Program.EUserInputType.Login);
                Config["SteamLogin"] = steamLogin;
            }

            string steamPassword = SteamPassword;

            if (string.IsNullOrEmpty(steamPassword) || steamPassword.Equals("null"))
            {
                steamPassword           = Program.GetUserInput(BotName, Program.EUserInputType.Password);
                Config["SteamPassword"] = steamPassword;
            }

            SteamUser.LogOn(new SteamUser.LogOnDetails {
                Username       = steamLogin,
                Password       = steamPassword,
                AuthCode       = AuthCode,
                TwoFactorCode  = TwoFactorAuth,
                SentryFileHash = sentryHash
            });
        }
Example #9
0
        private static void Main(string[] args)
        {
            Logging.LogGenericInfo("Main", "Archi's Steam Farm, version " + Version);

            Task.Run(async() => await CheckForUpdate().ConfigureAwait(false)).Wait();

            // Allow loading configs from source tree if it's a debug build
            if (Debugging.IsDebugBuild)
            {
                for (var i = 0; i < 4; i++)
                {
                    Directory.SetCurrentDirectory("..");
                    if (Directory.Exists(ConfigDirectoryPath))
                    {
                        break;
                    }
                }
            }

            if (!Directory.Exists(ConfigDirectoryPath))
            {
                Logging.LogGenericError("Main", "Config directory doesn't exist!");
                Console.ReadLine();
                Task.Run(async() => await Exit(1).ConfigureAwait(false)).Wait();
            }

            foreach (var configFile in Directory.EnumerateFiles(ConfigDirectoryPath, "*.xml"))
            {
                string botName = Path.GetFileNameWithoutExtension(configFile);
                Bot    bot     = new Bot(botName);
                if (!bot.Enabled)
                {
                    Logging.LogGenericInfo(botName, "Not starting this instance because it's disabled in config file");
                }
                Thread.Sleep(1000);                 // Try to avoid spamming steam
            }

            // Check if we got any bots running
            OnBotShutdown(null);

            ShutdownResetEvent.WaitOne();
        }
Example #10
0
        private static void InitServices()
        {
            GlobalConfig = GlobalConfig.Load();
            if (GlobalConfig == null)
            {
                Logging.LogGenericError("Global config could not be loaded, please make sure that ASF.json exists and is valid!");
                Thread.Sleep(5000);
                Exit(1);
            }

            GlobalDatabase = GlobalDatabase.Load();
            if (GlobalDatabase == null)
            {
                Logging.LogGenericError("Global database could not be loaded!");
                Thread.Sleep(5000);
                Exit(1);
            }

            ArchiWebHandler.Init();
            WebBrowser.Init();
            WCF.Init();
        }
Example #11
0
        private async Task <HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, IEnumerable <KeyValuePair <string, string> > data = null, string referer = null)
        {
            if (string.IsNullOrEmpty(request) || (httpMethod == null))
            {
                Logging.LogNullError(nameof(request) + " || " + nameof(httpMethod), Identifier);
                return(null);
            }

            if (request.StartsWith("https://", StringComparison.Ordinal) && Program.GlobalConfig.ForceHttp)
            {
                return(null);
            }

            HttpResponseMessage responseMessage;

            using (HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, request)) {
                if (data != null)
                {
                    try {
                        requestMessage.Content = new FormUrlEncodedContent(data);
                    } catch (UriFormatException e) {
                        Logging.LogGenericException(e, Identifier);
                        return(null);
                    }
                }

                if (!string.IsNullOrEmpty(referer))
                {
                    requestMessage.Headers.Referrer = new Uri(referer);
                }

                try {
                    responseMessage = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
                } catch (Exception e) {
                    // This exception is really common, don't bother with it unless debug mode is enabled
                    if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug)
                    {
                        Logging.LogGenericException(e, Identifier);
                    }

                    return(null);
                }
            }

            if (responseMessage == null)
            {
                return(null);
            }

            if (responseMessage.IsSuccessStatusCode)
            {
                return(responseMessage);
            }

            if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug)
            {
                Logging.LogGenericError("Request: " + request + " failed!", Identifier);
                Logging.LogGenericError("Status code: " + responseMessage.StatusCode, Identifier);
                Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false), Identifier);
            }

            responseMessage.Dispose();
            return(null);
        }
Example #12
0
        private static void Init(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
            TaskScheduler.UnobservedTaskException      += UnobservedTaskExceptionHandler;

            Logging.LogGenericInfo("Archi's Steam Farm, version " + Version);
            Directory.SetCurrentDirectory(ExecutableDirectory);
            InitServices();

            // 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 (var i = 0; i < 4; i++)
                {
                    Directory.SetCurrentDirectory("..");
                    if (Directory.Exists(ConfigDirectory))
                    {
                        break;
                    }
                }

                // If config directory doesn't exist after our adjustment, abort all of that
                if (!Directory.Exists(ConfigDirectory))
                {
                    Directory.SetCurrentDirectory(ExecutableDirectory);
                }
            }

            // If debugging is on, we prepare debug directory prior to running
            if (GlobalConfig.Debug)
            {
                if (Directory.Exists(DebugDirectory))
                {
                    Directory.Delete(DebugDirectory, true);
                    Thread.Sleep(1000);                     // Dirty workaround giving Windows some time to sync
                }
                Directory.CreateDirectory(DebugDirectory);

                SteamKit2.DebugLog.AddListener(new Debugging.DebugListener(Path.Combine(Program.DebugDirectory, "debug.txt")));
                SteamKit2.DebugLog.Enabled = true;
            }

            // Parse args
            ParseArgs(args);

            // If we ran ASF as a client, we're done by now
            if (Mode == EMode.Client)
            {
                return;
            }

            // From now on it's server mode
            Logging.Init();

            if (!Directory.Exists(ConfigDirectory))
            {
                Logging.LogGenericError("Config directory doesn't exist!");
                Thread.Sleep(5000);
                Environment.Exit(1);
            }

            CheckForUpdate().Wait();

            // Before attempting to connect, initialize our list of CMs
            Bot.RefreshCMs(GlobalDatabase.CellID).Wait();

            bool isRunning = false;

            foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.json"))
            {
                string botName = Path.GetFileNameWithoutExtension(configFile);
                if (botName.Equals(ASF))
                {
                    continue;
                }

                Bot bot = new Bot(botName);
                if (bot.BotConfig != null && bot.BotConfig.Enabled)
                {
                    isRunning = true;
                }
                else
                {
                    Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
                }
            }

            // CONVERSION START
            foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.xml"))
            {
                string botName = Path.GetFileNameWithoutExtension(configFile);
                Logging.LogGenericWarning("Found legacy " + botName + ".xml config file, it will now be converted to new ASF V2.0 format!");
                Bot bot = new Bot(botName);
                if (bot.BotConfig != null && bot.BotConfig.Enabled)
                {
                    isRunning = true;
                }
                else
                {
                    Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
                }
            }
            // CONVERSION END

            // Check if we got any bots running
            if (!isRunning)
            {
                OnBotShutdown();
            }
        }
Example #13
0
        private static async Task <HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary <string, string> data = null, Dictionary <string, string> cookies = null, string referer = null)
        {
            if (string.IsNullOrEmpty(request) || httpMethod == null)
            {
                return(null);
            }

            if (request.StartsWith("https://") && Program.GlobalConfig.ForceHttp)
            {
                return(null);
            }

            HttpResponseMessage responseMessage;

            using (HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, request)) {
                if (data != null && data.Count > 0)
                {
                    try {
                        requestMessage.Content = new FormUrlEncodedContent(data);
                    } catch (UriFormatException e) {
                        Logging.LogGenericException(e);
                        return(null);
                    }
                }

                if (cookies != null && cookies.Count > 0)
                {
                    StringBuilder cookieHeader = new StringBuilder();
                    foreach (KeyValuePair <string, string> cookie in cookies)
                    {
                        cookieHeader.Append(cookie.Key + "=" + cookie.Value + ";");
                    }
                    requestMessage.Headers.Add("Cookie", cookieHeader.ToString());
                }

                if (!string.IsNullOrEmpty(referer))
                {
                    requestMessage.Headers.Referrer = new Uri(referer);
                }

                try {
                    responseMessage = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
                } catch {                 // Request failed, we don't need to know the exact reason, swallow exception
                    return(null);
                }
            }

            if (responseMessage == null)
            {
                return(null);
            }

            if (!responseMessage.IsSuccessStatusCode)
            {
                if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug)
                {
                    Logging.LogGenericError("Request: " + request + " failed!");
                    Logging.LogGenericError("Status code: " + responseMessage.StatusCode);
                    Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false));
                }
                return(null);
            }

            return(responseMessage);
        }
Example #14
0
        private static void Init(IEnumerable <string> args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
            TaskScheduler.UnobservedTaskException      += UnobservedTaskExceptionHandler;

            Logging.LogGenericInfo("ASF V" + Version);
            Directory.SetCurrentDirectory(ExecutableDirectory);
            InitServices();

            // 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(ConfigDirectory))
                    {
                        break;
                    }
                }

                // If config directory doesn't exist after our adjustment, abort all of that
                if (!Directory.Exists(ConfigDirectory))
                {
                    Directory.SetCurrentDirectory(ExecutableDirectory);
                }
            }

            // If debugging is on, we prepare debug directory prior to running
            if (GlobalConfig.Debug)
            {
                if (Directory.Exists(DebugDirectory))
                {
                    Directory.Delete(DebugDirectory, true);
                    Thread.Sleep(1000);                     // Dirty workaround giving Windows some time to sync
                }
                Directory.CreateDirectory(DebugDirectory);

                SteamKit2.DebugLog.AddListener(new Debugging.DebugListener(Path.Combine(DebugDirectory, "debug.txt")));
                SteamKit2.DebugLog.Enabled = true;
            }

            // Parse args
            if (args != null)
            {
                ParseArgs(args);
            }

            // If we ran ASF as a client, we're done by now
            if (Mode == EMode.Client)
            {
                Exit();
            }

            // From now on it's server mode
            Logging.Init();

            if (!Directory.Exists(ConfigDirectory))
            {
                Logging.LogGenericError("Config directory doesn't exist!");
                Thread.Sleep(5000);
                Exit(1);
            }

            CheckForUpdate().Wait();

            // Before attempting to connect, initialize our list of CMs
            Bot.RefreshCMs(GlobalDatabase.CellID).Wait();

            bool isRunning = false;

            foreach (string botName in Directory.EnumerateFiles(ConfigDirectory, "*.json").Select(Path.GetFileNameWithoutExtension))
            {
                switch (botName)
                {
                case ASF:
                case "example":
                case "minimal":
                    continue;
                }

                Bot bot = new Bot(botName);
                if ((bot.BotConfig == null) || !bot.BotConfig.Enabled)
                {
                    continue;
                }

                if (bot.BotConfig.StartOnLaunch)
                {
                    isRunning = true;
                }
            }

            // Check if we got any bots running
            if (!isRunning)
            {
                OnBotShutdown();
            }
        }
Example #15
0
        internal async Task StartFarming()
        {
            await StopFarming().ConfigureAwait(false);

            await Semaphore.WaitAsync().ConfigureAwait(false);

            if (NowFarming)
            {
                Semaphore.Release();
                return;
            }

            Logging.LogGenericInfo(Bot.BotName, "Checking badges...");

            // Find the number of badge pages
            HtmlDocument badgesDocument = await Bot.ArchiWebHandler.GetBadgePage(1).ConfigureAwait(false);

            if (badgesDocument == null)
            {
                Logging.LogGenericWarning(Bot.BotName, "Could not get badges information, farming is stopped!");
                Semaphore.Release();
                return;
            }

            var maxPages = 1;
            HtmlNodeCollection badgesPagesNodeCollection = badgesDocument.DocumentNode.SelectNodes("//a[@class='pagelink']");

            if (badgesPagesNodeCollection != null)
            {
                maxPages = (badgesPagesNodeCollection.Count / 2) + 1;                 // Don't do this at home
            }

            // Find APPIDs we need to farm
            List <uint> appIDs = new List <uint>();

            for (var page = 1; page <= maxPages; page++)
            {
                Logging.LogGenericInfo(Bot.BotName, "Checking page: " + page + "/" + maxPages);

                if (page > 1)                   // Because we fetched page number 1 already
                {
                    badgesDocument = await Bot.ArchiWebHandler.GetBadgePage(page).ConfigureAwait(false);

                    if (badgesDocument == null)
                    {
                        break;
                    }
                }

                HtmlNodeCollection badgesPageNodes = badgesDocument.DocumentNode.SelectNodes("//a[@class='btn_green_white_innerfade btn_small_thin']");
                if (badgesPageNodes == null)
                {
                    continue;
                }

                foreach (HtmlNode badgesPageNode in badgesPageNodes)
                {
                    string steamLink = badgesPageNode.GetAttributeValue("href", null);
                    if (steamLink == null)
                    {
                        Logging.LogGenericError(Bot.BotName, "Couldn't get steamLink for one of the games: " + badgesPageNode.OuterHtml);
                        continue;
                    }

                    uint appID = (uint)Utilities.OnlyNumbers(steamLink);
                    if (appID == 0)
                    {
                        Logging.LogGenericError(Bot.BotName, "Couldn't get appID for one of the games: " + badgesPageNode.OuterHtml);
                        continue;
                    }

                    if (Bot.Blacklist.Contains(appID))
                    {
                        continue;
                    }

                    appIDs.Add(appID);
                }
            }

            // Start farming
            while (appIDs.Count > 0)
            {
                Logging.LogGenericInfo(Bot.BotName, "Farming in progress...");
                uint appID = appIDs[0];
                if (await Farm(appID).ConfigureAwait(false))
                {
                    appIDs.Remove(appID);
                }
                else
                {
                    return;
                }
            }

            Logging.LogGenericInfo(Bot.BotName, "Farming finished!");
            await Bot.OnFarmingFinished().ConfigureAwait(false);
        }
Example #16
0
        // TODO: This should be removed soon
        internal static BotConfig LoadOldFormat(string path)
        {
            if (!File.Exists(path))
            {
                return(null);
            }

            BotConfig botConfig = new BotConfig();

            try {
                using (XmlReader reader = XmlReader.Create(path)) {
                    while (reader.Read())
                    {
                        if (reader.NodeType != XmlNodeType.Element)
                        {
                            continue;
                        }

                        string key = reader.Name;
                        if (string.IsNullOrEmpty(key))
                        {
                            continue;
                        }

                        string value = reader.GetAttribute("value");
                        if (string.IsNullOrEmpty(value))
                        {
                            continue;
                        }

                        switch (key)
                        {
                        case "Enabled":
                            botConfig.Enabled = bool.Parse(value);
                            break;

                        case "SteamLogin":
                            botConfig.SteamLogin = value;
                            break;

                        case "SteamPassword":
                            botConfig.SteamPassword = value;
                            break;

                        case "SteamApiKey":
                            botConfig.SteamApiKey = value;
                            break;

                        case "SteamTradeToken":
                            botConfig.SteamTradeToken = value;
                            break;

                        case "SteamParentalPIN":
                            botConfig.SteamParentalPIN = value;
                            break;

                        case "SteamMasterID":
                            botConfig.SteamMasterID = ulong.Parse(value);
                            break;

                        case "SteamMasterClanID":
                            botConfig.SteamMasterClanID = ulong.Parse(value);
                            break;

                        case "StartOnLaunch":
                            botConfig.StartOnLaunch = bool.Parse(value);
                            break;

                        case "UseAsfAsMobileAuthenticator":
                            botConfig.UseAsfAsMobileAuthenticator = bool.Parse(value);
                            break;

                        case "CardDropsRestricted":
                            botConfig.CardDropsRestricted = bool.Parse(value);
                            break;

                        case "FarmOffline":
                            botConfig.FarmOffline = bool.Parse(value);
                            break;

                        case "HandleOfflineMessages":
                            botConfig.HandleOfflineMessages = bool.Parse(value);
                            break;

                        case "ForwardKeysToOtherBots":
                            botConfig.ForwardKeysToOtherBots = bool.Parse(value);
                            break;

                        case "DistributeKeys":
                            botConfig.DistributeKeys = bool.Parse(value);
                            break;

                        case "ShutdownOnFarmingFinished":
                            botConfig.ShutdownOnFarmingFinished = bool.Parse(value);
                            break;

                        case "SendOnFarmingFinished":
                            botConfig.SendOnFarmingFinished = bool.Parse(value);
                            break;

                        case "SendTradePeriod":
                            botConfig.SendTradePeriod = byte.Parse(value);
                            break;

                        case "GamesPlayedWhileIdle":
                            botConfig.GamesPlayedWhileIdle.Clear();
                            foreach (string appID in value.Split(','))
                            {
                                botConfig.GamesPlayedWhileIdle.Add(uint.Parse(appID));
                            }
                            break;

                        case "Statistics":
                        case "Blacklist":
                        case "SteamNickname":
                            break;

                        default:
                            Logging.LogGenericWarning("Unrecognized config value: " + key + "=" + value);
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                Logging.LogGenericException(e);
                Logging.LogGenericError("Your config for this bot instance is invalid, it won't run!");
                return(null);
            }

            // Fixups for new format
            if (botConfig.SteamLogin != null && botConfig.SteamLogin.Equals("null"))
            {
                botConfig.SteamLogin = null;
            }

            if (botConfig.SteamPassword != null && botConfig.SteamPassword.Equals("null"))
            {
                botConfig.SteamPassword = null;
            }

            if (botConfig.SteamApiKey != null && botConfig.SteamApiKey.Equals("null"))
            {
                botConfig.SteamApiKey = null;
            }

            if (botConfig.SteamParentalPIN != null && botConfig.SteamParentalPIN.Equals("null"))
            {
                botConfig.SteamParentalPIN = null;
            }

            if (botConfig.SteamTradeToken != null && botConfig.SteamTradeToken.Equals("null"))
            {
                botConfig.SteamTradeToken = null;
            }

            return(botConfig);
        }
Example #17
0
        private static void Init()
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
            TaskScheduler.UnobservedTaskException      += UnobservedTaskExceptionHandler;

            Logging.InitCoreLoggers();

            if (!Runtime.IsRuntimeSupported)
            {
                Logging.LogGenericError("ASF detected unsupported runtime version, program might NOT run correctly in current environment. You're running it at your own risk!");
            }

            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);
                    }
                }
            }

            InitServices();

            // 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
                }

                Directory.CreateDirectory(SharedInfo.DebugDirectory);

                SteamKit2.DebugLog.AddListener(new Debugging.DebugListener());
                SteamKit2.DebugLog.Enabled = true;
            }

            Logging.InitEnhancedLoggers();
        }
Example #18
0
        private static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;

            Logging.LogGenericInfo("Archi's Steam Farm, version " + Version);
            Directory.SetCurrentDirectory(ExecutableDirectory);
            InitServices();

            // 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 (var i = 0; i < 4; i++)
                {
                    Directory.SetCurrentDirectory("..");
                    if (Directory.Exists(ConfigDirectory))
                    {
                        break;
                    }
                }

                // If config directory doesn't exist after our adjustment, abort all of that
                if (!Directory.Exists(ConfigDirectory))
                {
                    Directory.SetCurrentDirectory(ExecutableDirectory);
                }
            }

            // By default we're operating on normal mode
            Mode = EMode.Normal;
            Logging.LogToFile = true;

            // But that can be overriden by arguments
            ParseArgs(args);

            // If we ran ASF as a client, we're done by now
            if (Mode == EMode.Client)
            {
                return;
            }

            Task.Run(async() => await CheckForUpdate().ConfigureAwait(false)).Wait();

            if (!Directory.Exists(ConfigDirectory))
            {
                Logging.LogGenericError("Config directory doesn't exist!");
                Thread.Sleep(5000);
                Exit(1);
            }

            // Before attempting to connect, initialize our list of CMs
            Bot.RefreshCMs().Wait();

            foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.xml"))
            {
                string botName = Path.GetFileNameWithoutExtension(configFile);
                Bot    bot     = new Bot(botName);
                if (!bot.Enabled)
                {
                    Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
                }
            }

            // Check if we got any bots running
            OnBotShutdown();

            // Wait for signal to shutdown
            ShutdownResetEvent.WaitOne();

            // We got a signal to shutdown, consider giving user some time to read the message
            Thread.Sleep(5000);

            // This is over, cleanup only now
            WCF.StopServer();
        }
Example #19
0
        private static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;

            Logging.LogGenericInfo("Archi's Steam Farm, version " + Version);
            Directory.SetCurrentDirectory(ExecutableDirectory);
            InitServices();

            // 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 (var i = 0; i < 4; i++)
                {
                    Directory.SetCurrentDirectory("..");
                    if (Directory.Exists(ConfigDirectory))
                    {
                        break;
                    }
                }

                // If config directory doesn't exist after our adjustment, abort all of that
                if (!Directory.Exists(ConfigDirectory))
                {
                    Directory.SetCurrentDirectory(ExecutableDirectory);
                }
            }

            // Parse args
            ParseArgs(args);

            // If we ran ASF as a client, we're done by now
            if (Mode == EMode.Client)
            {
                return;
            }

            // From now on it's server mode
            Logging.Init();

            if (!Directory.Exists(ConfigDirectory))
            {
                Logging.LogGenericError("Config directory doesn't exist!");
                Thread.Sleep(5000);
                Exit(1);
            }

            CheckForUpdate().Wait();

            // Before attempting to connect, initialize our list of CMs
            Bot.RefreshCMs(GlobalDatabase.CellID).Wait();

            foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.json"))
            {
                string botName = Path.GetFileNameWithoutExtension(configFile);
                if (botName.Equals(ASF))
                {
                    continue;
                }

                Bot bot = new Bot(botName);
                if (bot.BotConfig == null || !bot.BotConfig.Enabled)
                {
                    Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
                }
            }

            // CONVERSION START
            foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.xml"))
            {
                string botName = Path.GetFileNameWithoutExtension(configFile);
                Logging.LogGenericWarning("Found legacy " + botName + ".xml config file, it will now be converted to new ASF V2.0 format!");
                Bot bot = new Bot(botName);
                if (bot.BotConfig == null || !bot.BotConfig.Enabled)
                {
                    Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
                }
            }
            // CONVERSION END

            // Check if we got any bots running
            OnBotShutdown();

            // Wait for signal to shutdown
            ShutdownResetEvent.WaitOne();

            // We got a signal to shutdown, consider giving user some time to read the message
            Thread.Sleep(5000);

            // This is over, cleanup only now
            WCF.StopServer();
        }
Example #20
0
        internal static async Task CheckForUpdate(bool updateOverride = false)
        {
            string oldExeFile = ExecutableFile + ".old";

            // We booted successfully so we can now remove old exe file
            if (File.Exists(oldExeFile))
            {
                // It's entirely possible that old process is still running, allow at least a second before trying to remove the file
                await Utilities.SleepAsync(1000).ConfigureAwait(false);

                try {
                    File.Delete(oldExeFile);
                } catch (Exception e) {
                    Logging.LogGenericException(e);
                    Logging.LogGenericError("Could not remove old ASF binary, please remove " + oldExeFile + " manually in order for update function to work!");
                }
            }

            if (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Unknown)
            {
                return;
            }

            string releaseURL = GithubReleaseURL;

            if (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable)
            {
                releaseURL += "/latest";
            }

            Logging.LogGenericInfo("Checking new version...");

            string response = await WebBrowser.UrlGetToContentRetry(releaseURL).ConfigureAwait(false);

            if (string.IsNullOrEmpty(response))
            {
                Logging.LogGenericWarning("Could not check latest version!");
                return;
            }

            GitHub.ReleaseResponse releaseResponse;
            if (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable)
            {
                try {
                    releaseResponse = JsonConvert.DeserializeObject <GitHub.ReleaseResponse>(response);
                } catch (JsonException e) {
                    Logging.LogGenericException(e);
                    return;
                }
            }
            else
            {
                List <GitHub.ReleaseResponse> releases;
                try {
                    releases = JsonConvert.DeserializeObject <List <GitHub.ReleaseResponse> >(response);
                } catch (JsonException e) {
                    Logging.LogGenericException(e);
                    return;
                }

                if ((releases == null) || (releases.Count == 0))
                {
                    Logging.LogGenericWarning("Could not check latest version!");
                    return;
                }

                releaseResponse = releases[0];
            }

            if (string.IsNullOrEmpty(releaseResponse.Tag))
            {
                Logging.LogGenericWarning("Could not check latest version!");
                return;
            }

            Version newVersion = new Version(releaseResponse.Tag);

            Logging.LogGenericInfo("Local version: " + Version + " | Remote version: " + newVersion);

            if (Version.CompareTo(newVersion) >= 0)               // If local version is the same or newer than remote version
            {
                if ((AutoUpdatesTimer != null) || !GlobalConfig.AutoUpdates)
                {
                    return;
                }

                Logging.LogGenericInfo("ASF will automatically check for new versions every 24 hours");

                AutoUpdatesTimer = new Timer(
                    async e => await CheckForUpdate().ConfigureAwait(false),
                    null,
                    TimeSpan.FromDays(1),                    // Delay
                    TimeSpan.FromDays(1)                     // Period
                    );

                return;
            }

            if (!updateOverride && !GlobalConfig.AutoUpdates)
            {
                Logging.LogGenericInfo("New version is available!");
                Logging.LogGenericInfo("Consider updating yourself!");
                await Utilities.SleepAsync(5000).ConfigureAwait(false);

                return;
            }

            if (File.Exists(oldExeFile))
            {
                Logging.LogGenericWarning("Refusing to proceed with auto update as old " + oldExeFile + " binary could not be removed, please remove it manually");
                return;
            }

            // Auto update logic starts here
            if (releaseResponse.Assets == null)
            {
                Logging.LogGenericWarning("Could not proceed with update because that version doesn't include assets!");
                return;
            }

            GitHub.ReleaseResponse.Asset binaryAsset = releaseResponse.Assets.FirstOrDefault(asset => !string.IsNullOrEmpty(asset.Name) && asset.Name.Equals(ExecutableName, StringComparison.OrdinalIgnoreCase));

            if (binaryAsset == null)
            {
                Logging.LogGenericWarning("Could not proceed with update because there is no asset that relates to currently running binary!");
                return;
            }

            if (string.IsNullOrEmpty(binaryAsset.DownloadURL))
            {
                Logging.LogGenericWarning("Could not proceed with update because download URL is empty!");
                return;
            }

            byte[] result = await WebBrowser.UrlGetToBytesRetry(binaryAsset.DownloadURL).ConfigureAwait(false);

            if (result == null)
            {
                return;
            }

            string newExeFile = ExecutableFile + ".new";

            // Firstly we create new exec
            try {
                File.WriteAllBytes(newExeFile, result);
            } catch (Exception e) {
                Logging.LogGenericException(e);
                return;
            }

            // Now we move current -> old
            try {
                File.Move(ExecutableFile, oldExeFile);
            } catch (Exception e) {
                Logging.LogGenericException(e);
                try {
                    // Cleanup
                    File.Delete(newExeFile);
                } catch {
                    // Ignored
                }
                return;
            }

            // Now we move new -> current
            try {
                File.Move(newExeFile, ExecutableFile);
            } catch (Exception e) {
                Logging.LogGenericException(e);
                try {
                    // Cleanup
                    File.Move(oldExeFile, ExecutableFile);
                    File.Delete(newExeFile);
                } catch {
                    // Ignored
                }
                return;
            }

            Logging.LogGenericInfo("Update process finished!");

            if (GlobalConfig.AutoRestart)
            {
                Logging.LogGenericInfo("Restarting...");
                await Utilities.SleepAsync(5000).ConfigureAwait(false);

                Restart();
            }
            else
            {
                Logging.LogGenericInfo("Exiting...");
                await Utilities.SleepAsync(5000).ConfigureAwait(false);

                Exit();
            }
        }
Example #21
0
        private static void Init(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
            TaskScheduler.UnobservedTaskException      += UnobservedTaskExceptionHandler;

            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.ConfigDirectory))
                        {
                            break;
                        }
                    }

                    // If config directory doesn't exist after our adjustment, abort all of that
                    if (!Directory.Exists(SharedInfo.ConfigDirectory))
                    {
                        Directory.SetCurrentDirectory(homeDirectory);
                    }
                }
            }

            // Parse pre-init args
            if (args != null)
            {
                ParsePreInitArgs(args);
            }

            Logging.InitLoggers();
            Logging.LogGenericInfo("ASF V" + SharedInfo.Version);

            if (!Runtime.IsRuntimeSupported)
            {
                Logging.LogGenericError("ASF detected unsupported runtime version, program might NOT run correctly in current environment. You're running it at your own risk!");
                Thread.Sleep(10000);
            }

            InitServices();

            // 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
                }

                Directory.CreateDirectory(SharedInfo.DebugDirectory);

                SteamKit2.DebugLog.AddListener(new Debugging.DebugListener());
                SteamKit2.DebugLog.Enabled = true;
            }

            // Parse post-init args
            if (args != null)
            {
                ParsePostInitArgs(args);
            }

            // If we ran ASF as a client, we're done by now
            if (Mode == EMode.Client)
            {
                Exit();
            }

            // From now on it's server mode
            if (!Directory.Exists(SharedInfo.ConfigDirectory))
            {
                Logging.LogGenericError("Config directory doesn't exist!");
                Thread.Sleep(5000);
                Exit(1);
            }

            ASF.CheckForUpdate().Wait();

            // Before attempting to connect, initialize our list of CMs
            Bot.InitializeCMs(GlobalDatabase.CellID, GlobalDatabase.ServerListProvider);

            foreach (string botName in Directory.EnumerateFiles(SharedInfo.ConfigDirectory, "*.json").Select(Path.GetFileNameWithoutExtension))
            {
                switch (botName)
                {
                case SharedInfo.ASF:
                case "example":
                case "minimal":
                    continue;
                }

                new Bot(botName).Forget();
            }

            if (Bot.Bots.Count == 0)
            {
                Logging.LogGenericWarning("No bots are defined, did you forget to configure your ASF?");
            }

            ASF.InitFileWatcher();
        }
        internal HashSet <Steam.TradeOffer> GetActiveTradeOffers()
        {
            if (string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey))
            {
                Logging.LogNullError(nameof(Bot.BotConfig.SteamApiKey), Bot.BotName);
                return(null);
            }

            KeyValue response = null;

            for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++)
            {
                using (dynamic iEconService = WebAPI.GetInterface("IEconService", Bot.BotConfig.SteamApiKey)) {
                    iEconService.Timeout = Timeout;

                    try {
                        response = iEconService.GetTradeOffers(
                            get_received_offers: 1,
                            active_only: 1,
                            get_descriptions: 1,
                            secure: !Program.GlobalConfig.ForceHttp
                            );
                    } catch (Exception e) {
                        Logging.LogGenericException(e, Bot.BotName);
                    }
                }
            }

            if (response == null)
            {
                Logging.LogGenericWarning("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
                return(null);
            }

            Dictionary <ulong, Tuple <uint, Steam.Item.EType> > descriptions = new Dictionary <ulong, Tuple <uint, Steam.Item.EType> >();

            foreach (KeyValue description in response["descriptions"].Children)
            {
                ulong classID = description["classid"].AsUnsignedLong();
                if (classID == 0)
                {
                    Logging.LogNullError(nameof(classID), Bot.BotName);
                    return(null);
                }

                if (descriptions.ContainsKey(classID))
                {
                    continue;
                }

                uint appID = 0;

                string hashName = description["market_hash_name"].Value;
                if (!string.IsNullOrEmpty(hashName))
                {
                    appID = GetAppIDFromMarketHashName(hashName);
                }

                if (appID == 0)
                {
                    appID = description["appid"].AsUnsignedInteger();
                }

                Steam.Item.EType type = Steam.Item.EType.Unknown;

                string descriptionType = description["type"].Value;
                if (!string.IsNullOrEmpty(descriptionType))
                {
                    type = GetItemType(descriptionType);
                }

                descriptions[classID] = new Tuple <uint, Steam.Item.EType>(appID, type);
            }

            HashSet <Steam.TradeOffer> result = new HashSet <Steam.TradeOffer>();

            foreach (KeyValue trade in response["trade_offers_received"].Children)
            {
                Steam.TradeOffer.ETradeOfferState state = trade["trade_offer_state"].AsEnum <Steam.TradeOffer.ETradeOfferState>();
                if (state == Steam.TradeOffer.ETradeOfferState.Unknown)
                {
                    Logging.LogNullError(nameof(state));
                    return(null);
                }

                if (state != Steam.TradeOffer.ETradeOfferState.Active)
                {
                    continue;
                }

                ulong tradeOfferID = trade["tradeofferid"].AsUnsignedLong();
                if (tradeOfferID == 0)
                {
                    Logging.LogNullError(nameof(tradeOfferID));
                    return(null);
                }

                uint otherSteamID3 = trade["accountid_other"].AsUnsignedInteger();
                if (otherSteamID3 == 0)
                {
                    Logging.LogNullError(nameof(otherSteamID3));
                    return(null);
                }

                Steam.TradeOffer tradeOffer = new Steam.TradeOffer(tradeOfferID, otherSteamID3, state);

                List <KeyValue> itemsToGive = trade["items_to_give"].Children;
                if (itemsToGive.Count > 0)
                {
                    if (!ParseItems(descriptions, itemsToGive, tradeOffer.ItemsToGive))
                    {
                        Logging.LogGenericError("Parsing " + nameof(itemsToGive) + " failed!", Bot.BotName);
                        return(null);
                    }
                }

                List <KeyValue> itemsToReceive = trade["items_to_receive"].Children;
                if (itemsToReceive.Count > 0)
                {
                    if (!ParseItems(descriptions, itemsToReceive, tradeOffer.ItemsToReceive))
                    {
                        Logging.LogGenericError("Parsing " + nameof(itemsToReceive) + " failed!", Bot.BotName);
                        return(null);
                    }
                }

                result.Add(tradeOffer);
            }

            return(result);
        }
Example #23
0
        private static async void OnChanged(object sender, FileSystemEventArgs e)
        {
            if ((sender == null) || (e == null))
            {
                Logging.LogNullError(nameof(sender) + " || " + nameof(e));
                return;
            }

            string botName = Path.GetFileNameWithoutExtension(e.Name);

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

            if (botName.Equals(SharedInfo.ASF))
            {
                Logging.LogGenericError("Global config file has been changed, restarting...");
                Program.Restart();
                return;
            }

            Bot bot;

            if (!Bot.Bots.TryGetValue(botName, out bot))
            {
                return;
            }

            DateTime lastWriteTime = File.GetLastWriteTime(e.FullPath);

            DateTime savedLastWriteTime;

            if (LastWriteTimes.TryGetValue(bot, out savedLastWriteTime))
            {
                if (savedLastWriteTime >= lastWriteTime)
                {
                    return;
                }
            }

            LastWriteTimes[bot] = lastWriteTime;

            // It's entirely possible that some process is still accessing our file, allow at least a second before trying to read it
            await Task.Delay(1000).ConfigureAwait(false);

            // It's also possible that we got some other event in the meantime
            if (LastWriteTimes.TryGetValue(bot, out savedLastWriteTime))
            {
                if (lastWriteTime != savedLastWriteTime)
                {
                    return;
                }

                if (LastWriteTimes.TryRemove(bot, out savedLastWriteTime))
                {
                    if (lastWriteTime != savedLastWriteTime)
                    {
                        return;
                    }
                }
            }

            bot.OnNewConfigLoaded(new BotConfigEventArgs(BotConfig.Load(e.FullPath))).Forget();
        }