private async Task <bool> UnlockParentalAccount(string parentalPin)
        {
            if (string.IsNullOrEmpty(parentalPin) || parentalPin.Equals("0"))
            {
                return(true);
            }

            Logging.LogGenericInfo("Unlocking parental account...", Bot.BotName);
            Dictionary <string, string> data = new Dictionary <string, string>(1)
            {
                { "pin", parentalPin }
            };

            string referer = SteamCommunityURL;
            string request = referer + "/parental/ajaxunlock";

            HttpResponseMessage response = null;

            for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++)
            {
                response = await WebBrowser.UrlPost(request, data, Cookie, referer).ConfigureAwait(false);
            }

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

            IEnumerable <string> setCookieValues;

            if (!response.Headers.TryGetValues("Set-Cookie", out setCookieValues))
            {
                Logging.LogNullError("setCookieValues", Bot.BotName);
                return(false);
            }

            foreach (string setCookieValue in setCookieValues)
            {
                if (!setCookieValue.Contains("steamparental="))
                {
                    continue;
                }

                string setCookie = setCookieValue.Substring(setCookieValue.IndexOf("steamparental=", StringComparison.Ordinal) + 14);

                int index = setCookie.IndexOf(';');
                if (index > 0)
                {
                    setCookie = setCookie.Substring(0, index);
                }

                Cookie["steamparental"] = setCookie;
                Logging.LogGenericInfo("Success!", Bot.BotName);
                return(true);
            }

            Logging.LogGenericWarning("Failed to unlock parental account!", Bot.BotName);
            return(false);
        }
        internal void DeclineTradeOffer(ulong tradeID)
        {
            if ((tradeID == 0) || string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey))
            {
                Logging.LogNullError(nameof(tradeID) + " || " + nameof(Bot.BotConfig.SteamApiKey), Bot.BotName);
                return;
            }

            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.DeclineTradeOffer(
                            tradeofferid: tradeID.ToString(),
                            method: WebRequestMethods.Http.Post,
                            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);
            }
        }
        internal static GlobalConfig Load()
        {
            string filePath = Path.Combine(Program.ConfigDirectory, Program.GlobalConfigFile);

            if (!File.Exists(filePath))
            {
                return(null);
            }

            GlobalConfig globalConfig;

            try {
                globalConfig = JsonConvert.DeserializeObject <GlobalConfig>(File.ReadAllText(filePath));
            } catch (Exception e) {
                Logging.LogGenericException(e);
                return(null);
            }

            // SK2 supports only TCP and UDP steam protocols
            // Make sure that user can't screw this up
            switch (globalConfig.SteamProtocol)
            {
            case ProtocolType.Tcp:
            case ProtocolType.Udp:
                break;

            default:
                Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ", default TCP protocol will be used instead");
                globalConfig.SteamProtocol = ProtocolType.Tcp;
                break;
            }

            return(globalConfig);
        }
Example #4
0
        internal async Task StopFarming()
        {
            if (!NowFarming)
            {
                return;
            }

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

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

            Logging.LogGenericInfo("Sending signal to stop farming", Bot.BotName);
            FarmResetEvent.Set();

            Logging.LogGenericInfo("Waiting for reaction...", Bot.BotName);
            for (byte i = 0; i < Program.GlobalConfig.HttpTimeout && NowFarming; i++)
            {
                await Utilities.SleepAsync(1000).ConfigureAwait(false);
            }

            if (NowFarming)
            {
                Logging.LogGenericWarning("Timed out!", Bot.BotName);
            }

            FarmResetEvent.Reset();
            Logging.LogGenericInfo("Farming stopped!", Bot.BotName);
            Semaphore.Release();
        }
        internal async Task StopFarming()
        {
            if (!NowFarming)
            {
                return;
            }

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

            if (!NowFarming)
            {
                FarmingSemaphore.Release();
                return;
            }

            Logging.LogGenericInfo("Sending signal to stop farming", Bot.BotName);
            KeepFarming = false;
            FarmResetEvent.Set();

            Logging.LogGenericInfo("Waiting for reaction...", Bot.BotName);
            for (byte i = 0; (i < 5) && NowFarming; i++)
            {
                await Utilities.SleepAsync(1000).ConfigureAwait(false);
            }

            if (NowFarming)
            {
                Logging.LogGenericWarning("Timed out!", Bot.BotName);
            }

            Logging.LogGenericInfo("Farming stopped!", Bot.BotName);
            Bot.OnFarmingStopped();
            FarmingSemaphore.Release();
        }
        internal uint GetServerTime()
        {
            KeyValue response = null;

            for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++)
            {
                using (dynamic iTwoFactorService = WebAPI.GetInterface("ITwoFactorService")) {
                    iTwoFactorService.Timeout = Timeout;

                    try {
                        response = iTwoFactorService.QueryTime(
                            method: WebRequestMethods.Http.Post,
                            secure: !Program.GlobalConfig.ForceHttp
                            );
                    } catch (Exception e) {
                        Logging.LogGenericException(e, Bot.BotName);
                    }
                }
            }

            if (response != null)
            {
                return(response["server_time"].AsUnsignedInteger());
            }

            Logging.LogGenericWarning("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
            return(0);
        }
Example #7
0
        private static void ParseArgs(IEnumerable <string> args)
        {
            if (args == null)
            {
                Logging.LogNullError(nameof(args));
                return;
            }

            foreach (string arg in args)
            {
                switch (arg)
                {
                case "":
                    break;

                case "--client":
                    Mode = EMode.Client;
                    break;

                case "--server":
                    Mode = EMode.Server;
                    WCF.StartServer();
                    break;

                default:
                    if (arg.StartsWith("--", StringComparison.Ordinal))
                    {
                        if (arg.StartsWith("--cryptkey=", StringComparison.Ordinal) && (arg.Length > 11))
                        {
                            CryptoHelper.SetEncryptionKey(arg.Substring(11));
                        }
                        else
                        {
                            Logging.LogGenericWarning("Unrecognized parameter: " + arg);
                        }

                        break;
                    }

                    if (Mode != EMode.Client)
                    {
                        Logging.LogGenericWarning("Ignoring command because --client wasn't specified: " + arg);
                        break;
                    }

                    Logging.LogGenericInfo("Command sent: " + arg);

                    // We intentionally execute this async block synchronously
                    Logging.LogGenericInfo("Response received: " + WCF.SendCommand(arg));

                    /*
                     * Task.Run(async () => {
                     *      Logging.LogGenericNotice("WCF", "Response received: " + await WCF.SendCommand(arg).ConfigureAwait(false));
                     * }).Wait();
                     */
                    break;
                }
            }
        }
Example #8
0
        private async Task <bool> IsAnythingToFarm()
        {
            Logging.LogGenericInfo("Checking badges...", Bot.BotName);

            // Find the number of badge pages
            Logging.LogGenericInfo("Checking first page...", Bot.BotName);
            HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetBadgePage(1).ConfigureAwait(false);

            if (htmlDocument == null)
            {
                Logging.LogGenericWarning("Could not get badges information, will try again later!", Bot.BotName);
                return(false);
            }

            byte maxPages = 1;

            HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("(//a[@class='pagelink'])[last()]");

            if (htmlNode != null)
            {
                string lastPage = htmlNode.InnerText;
                if (string.IsNullOrEmpty(lastPage))
                {
                    Logging.LogNullError(nameof(lastPage), Bot.BotName);
                    return(false);
                }

                if (!byte.TryParse(lastPage, out maxPages) || (maxPages == 0))
                {
                    Logging.LogNullError(nameof(maxPages), Bot.BotName);
                    return(false);
                }
            }

            GamesToFarm.ClearAndTrim();
            CheckPage(htmlDocument);

            if (maxPages == 1)
            {
                SortGamesToFarm();
                return(GamesToFarm.Count > 0);
            }

            Logging.LogGenericInfo("Checking other pages...", Bot.BotName);

            List <Task> tasks = new List <Task>(maxPages - 1);

            for (byte page = 2; page <= maxPages; page++)
            {
                byte currentPage = page;                 // We need a copy of variable being passed when in for loops, as loop will proceed before task is launched
                tasks.Add(CheckPage(currentPage));
            }

            await Task.WhenAll(tasks).ConfigureAwait(false);

            SortGamesToFarm();
            return(GamesToFarm.Count > 0);
        }
Example #9
0
        // TODO: This should be removed soon
        internal bool Convert(string path)
        {
            try {
                File.WriteAllText(path, JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented));
            } catch (Exception e) {
                Logging.LogGenericException(e);
                return(false);
            }

            Logging.LogGenericWarning("Your config was converted to new ASF V2.0 format");
            return(true);
        }
Example #10
0
        private async Task <bool> IsAnythingToFarm()
        {
            if (NowFarming)
            {
                return(true);
            }

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

            // Find the number of badge pages
            Logging.LogGenericInfo("Checking first page...", Bot.BotName);
            HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetBadgePage(1).ConfigureAwait(false);

            if (htmlDocument == null)
            {
                Logging.LogGenericWarning("Could not get badges information, will try again later!", Bot.BotName);
                return(false);
            }

            byte maxPages = 1;
            HtmlNodeCollection htmlNodeCollection = htmlDocument.DocumentNode.SelectNodes("//a[@class='pagelink']");

            if (htmlNodeCollection != null && htmlNodeCollection.Count > 0)
            {
                HtmlNode htmlNode = htmlNodeCollection[htmlNodeCollection.Count - 1];
                string   lastPage = htmlNode.InnerText;
                if (!string.IsNullOrEmpty(lastPage))
                {
                    if (!byte.TryParse(lastPage, out maxPages))
                    {
                        maxPages = 1;                         // Should never happen
                    }
                }
            }

            GamesToFarm.Clear();

            CheckPage(htmlDocument);

            if (maxPages > 1)
            {
                Logging.LogGenericInfo("Checking other pages...", Bot.BotName);
                List <Task> tasks = new List <Task>(maxPages - 1);
                for (byte page = 2; page <= maxPages; page++)
                {
                    byte currentPage = page;                     // We need a copy of variable being passed when in for loops, as loop will proceed before task is launched
                    tasks.Add(CheckPage(currentPage));
                }
                await Task.WhenAll(tasks).ConfigureAwait(false);
            }

            return(GamesToFarm.Count > 0);
        }
Example #11
0
        private static void ParseArgs(string[] args)
        {
            foreach (string arg in args)
            {
                switch (arg)
                {
                case "--client":
                    Mode = EMode.Client;
                    Logging.LogToFile = false;
                    break;

                case "--log":
                    Logging.LogToFile = true;
                    break;

                case "--no-log":
                    Logging.LogToFile = false;
                    break;

                case "--server":
                    Mode = EMode.Server;
                    WCF.StartServer();
                    break;

                default:
                    if (arg.StartsWith("--"))
                    {
                        Logging.LogGenericWarning("Unrecognized parameter: " + arg);
                        continue;
                    }

                    if (Mode != EMode.Client)
                    {
                        Logging.LogGenericWarning("Ignoring command because --client wasn't specified: " + arg);
                        continue;
                    }

                    Logging.LogGenericInfo("Command sent: \"" + arg + "\"");

                    // We intentionally execute this async block synchronously
                    Logging.LogGenericInfo("Response received: \"" + WCF.SendCommand(arg) + "\"");

                    /*
                     * Task.Run(async () => {
                     *      Logging.LogGenericNotice("WCF", "Response received: " + await WCF.SendCommand(arg).ConfigureAwait(false));
                     * }).Wait();
                     */
                    break;
                }
            }
        }
Example #12
0
        internal static BotConfig Load(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                Logging.LogNullError(nameof(filePath));
                return(null);
            }

            if (!File.Exists(filePath))
            {
                return(null);
            }

            BotConfig botConfig;

            try {
                botConfig = JsonConvert.DeserializeObject <BotConfig>(File.ReadAllText(filePath));
            } catch (Exception e) {
                Logging.LogGenericException(e);
                return(null);
            }

            if (botConfig == null)
            {
                Logging.LogNullError(nameof(botConfig));
                return(null);
            }

            // Support encrypted passwords
            if ((botConfig.PasswordFormat != CryptoHelper.ECryptoMethod.PlainText) && !string.IsNullOrEmpty(botConfig.SteamPassword))
            {
                // In worst case password will result in null, which will have to be corrected by user during runtime
                botConfig.SteamPassword = CryptoHelper.Decrypt(botConfig.PasswordFormat, botConfig.SteamPassword);
            }

            // User might not know what he's doing
            // Ensure that he can't screw core ASF variables
            if (botConfig.GamesPlayedWhileIdle.Count <= CardsFarmer.MaxGamesPlayedConcurrently)
            {
                return(botConfig);
            }

            Logging.LogGenericWarning("Playing more than " + CardsFarmer.MaxGamesPlayedConcurrently + " games concurrently is not possible, only first " + CardsFarmer.MaxGamesPlayedConcurrently + " entries from GamesPlayedWhileIdle will be used");

            HashSet <uint> validGames = new HashSet <uint>(botConfig.GamesPlayedWhileIdle.Take(CardsFarmer.MaxGamesPlayedConcurrently));

            botConfig.GamesPlayedWhileIdle.IntersectWith(validGames);
            botConfig.GamesPlayedWhileIdle.TrimExcess();

            return(botConfig);
        }
        internal Dictionary <uint, string> GetOwnedGames(ulong steamID)
        {
            if ((steamID == 0) || string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey))
            {
                Logging.LogNullError(nameof(steamID) + " || " + nameof(Bot.BotConfig.SteamApiKey), Bot.BotName);
                return(null);
            }

            KeyValue response = null;

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

                    try {
                        response = iPlayerService.GetOwnedGames(
                            steamid: steamID,
                            include_appinfo: 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 <uint, string> result = new Dictionary <uint, string>(response["games"].Children.Count);

            foreach (KeyValue game in response["games"].Children)
            {
                uint appID = game["appid"].AsUnsignedInteger();
                if (appID == 0)
                {
                    Logging.LogNullError(nameof(appID), Bot.BotName);
                    return(null);
                }

                result[appID] = game["name"].Value;
            }

            return(result);
        }
Example #14
0
        private async Task UnlockParentalAccount(string parentalPin)
        {
            if (string.IsNullOrEmpty(parentalPin) || parentalPin.Equals("0"))
            {
                return;
            }

            Logging.LogGenericInfo("Unlocking parental account...", Bot.BotName);
            Dictionary <string, string> data = new Dictionary <string, string>(1)
            {
                { "pin", parentalPin }
            };

            HttpResponseMessage response = null;

            for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++)
            {
                response = await WebBrowser.UrlPost("https://steamcommunity.com/parental/ajaxunlock", data, Cookie, "https://steamcommunity.com/").ConfigureAwait(false);
            }

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

            IEnumerable <string> setCookieValues;

            if (!response.Headers.TryGetValues("Set-Cookie", out setCookieValues))
            {
                Logging.LogNullError("setCookieValues", Bot.BotName);
                return;
            }

            foreach (string setCookieValue in setCookieValues)
            {
                if (setCookieValue.Contains("steamparental="))
                {
                    string setCookie = setCookieValue.Substring(setCookieValue.IndexOf("steamparental=") + 14);
                    setCookie = setCookie.Substring(0, setCookie.IndexOf(';'));
                    Cookie["steamparental"] = setCookie;
                    Logging.LogGenericInfo("Success!", Bot.BotName);
                    return;
                }
            }

            Logging.LogGenericWarning("Failed to unlock parental account!", Bot.BotName);
        }
Example #15
0
        private void OnDisconnected(SteamClient.DisconnectedCallback callback)
        {
            if (callback == null)
            {
                return;
            }

            if (SteamClient == null)
            {
                return;
            }

            Logging.LogGenericWarning(BotName, "Disconnected from Steam, reconnecting...");
            Thread.Sleep(TimeSpan.FromMilliseconds(CallbackSleep));
            SteamClient.Connect();
        }
Example #16
0
        private static void ParsePostInitArgs(IEnumerable <string> args)
        {
            if (args == null)
            {
                Logging.LogNullError(nameof(args));
                return;
            }

            foreach (string arg in args)
            {
                switch (arg)
                {
                case "":
                    break;

                case "--client":
                    Mode = EMode.Client;
                    break;

                case "--server":
                    Mode = EMode.Server;
                    WCF.StartServer();
                    break;

                default:
                    if (arg.StartsWith("--", StringComparison.Ordinal))
                    {
                        if (arg.StartsWith("--cryptkey=", StringComparison.Ordinal) && (arg.Length > 11))
                        {
                            CryptoHelper.SetEncryptionKey(arg.Substring(11));
                        }

                        break;
                    }

                    if (Mode != EMode.Client)
                    {
                        Logging.LogGenericWarning("Ignoring command because --client wasn't specified: " + arg);
                        break;
                    }

                    Logging.LogGenericInfo("Command sent: " + arg);
                    Logging.LogGenericInfo("Response received: " + WCF.SendCommand(arg));
                    break;
                }
            }
        }
        internal async Task <bool> AcceptTradeOffer(ulong tradeID)
        {
            if (tradeID == 0)
            {
                return(false);
            }

            string sessionID;

            if (!SteamCookieDictionary.TryGetValue("sessionid", out sessionID))
            {
                return(false);
            }

            string referer = "https://steamcommunity.com/tradeoffer/" + tradeID + "/";
            string request = referer + "accept";

            Dictionary <string, string> postData = new Dictionary <string, string>()
            {
                { "sessionid", sessionID },
                { "serverid", "1" },
                { "tradeofferid", tradeID.ToString() }
            };

            HttpResponseMessage result = await Utilities.UrlPostRequestWithResponse(request, postData, SteamCookieDictionary, referer).ConfigureAwait(false);

            bool success = result.IsSuccessStatusCode;

            if (!success)
            {
                Logging.LogGenericWarning(Bot.BotName, "Request failed, reason: " + result.ReasonPhrase);
                switch (result.StatusCode)
                {
                case HttpStatusCode.InternalServerError:
                    Logging.LogGenericWarning(Bot.BotName, "That might be caused by 7-days trade lock from new device");
                    Logging.LogGenericWarning(Bot.BotName, "Try again in 7 days, declining that offer for now");
                    DeclineTradeOffer(tradeID);
                    break;
                }
            }

            return(success);
        }
Example #18
0
        private async void OnDisconnected(SteamClient.DisconnectedCallback callback)
        {
            if (callback == null)
            {
                return;
            }

            if (!IsRunning)
            {
                return;
            }

            if (SteamClient == null)
            {
                return;
            }

            Logging.LogGenericWarning(BotName, "Disconnected from Steam, reconnecting...");
            await Utilities.SleepAsync(CallbackSleep).ConfigureAwait(false);

            SteamClient.Connect();
        }
Example #19
0
        internal async Task <Steam.ConfirmationDetails> GetConfirmationDetails(Confirmation confirmation)
        {
            if (confirmation == null)
            {
                Logging.LogNullError(nameof(confirmation), Bot.BotName);
                return(null);
            }

            if (!HasCorrectDeviceID)
            {
                Logging.LogGenericWarning("Can't execute properly due to invalid DeviceID!", Bot.BotName);
                return(null);
            }

            uint time = await GetSteamTime().ConfigureAwait(false);

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

            string confirmationHash = GenerateConfirmationKey(time, "conf");

            if (string.IsNullOrEmpty(confirmationHash))
            {
                Logging.LogNullError(nameof(confirmationHash), Bot.BotName);
                return(null);
            }

            Steam.ConfirmationDetails response = await Bot.ArchiWebHandler.GetConfirmationDetails(DeviceID, confirmationHash, time, confirmation).ConfigureAwait(false);

            if ((response == null) || !response.Success)
            {
                return(null);
            }

            return(response);
        }
Example #20
0
        internal async Task <byte[]> UrlGetToBytesRetry(string request, string referer = null)
        {
            if (string.IsNullOrEmpty(request))
            {
                Logging.LogNullError(nameof(request), Identifier);
                return(null);
            }

            byte[] result = null;
            for (byte i = 0; (i < MaxRetries) && (result == null); i++)
            {
                result = await UrlGetToBytes(request, referer).ConfigureAwait(false);
            }

            if (result != null)
            {
                return(result);
            }

            Logging.LogGenericWarning("Request failed even after " + MaxRetries + " tries", Identifier);
            return(null);
        }
Example #21
0
        private async Task <string> UrlPostToContentRetry(string request, ICollection <KeyValuePair <string, string> > data = null, string referer = null)
        {
            if (string.IsNullOrEmpty(request))
            {
                Logging.LogNullError(nameof(request), Identifier);
                return(null);
            }

            string result = null;

            for (byte i = 0; (i < MaxRetries) && string.IsNullOrEmpty(result); i++)
            {
                result = await UrlPostToContent(request, data, referer).ConfigureAwait(false);
            }

            if (!string.IsNullOrEmpty(result))
            {
                return(result);
            }

            Logging.LogGenericWarning("Request failed even after " + MaxRetries + " tries", Identifier);
            return(null);
        }
Example #22
0
        internal async Task <bool> UrlHeadRetry(string request, string referer = null)
        {
            if (string.IsNullOrEmpty(request))
            {
                Logging.LogNullError(nameof(request), Identifier);
                return(false);
            }

            bool result = false;

            for (byte i = 0; (i < MaxRetries) && !result; i++)
            {
                result = await UrlHead(request, referer).ConfigureAwait(false);
            }

            if (result)
            {
                return(true);
            }

            Logging.LogGenericWarning("Request failed even after " + MaxRetries + " tries", Identifier);
            return(false);
        }
Example #23
0
        internal void StartServer()
        {
            if (ServiceHost != null)
            {
                return;
            }

            Logging.LogGenericInfo("Starting WCF server...");
            ServiceHost = new ServiceHost(typeof(WCF));
            ServiceHost.AddServiceEndpoint(typeof(IWCF), new BasicHttpBinding(), URL);

            try {
                ServiceHost.Open();
            } catch (AddressAccessDeniedException) {
                Logging.LogGenericWarning("WCF service could not be started because of AddressAccessDeniedException");
                Logging.LogGenericWarning("If you want to use WCF service provided by ASF, consider starting ASF as administrator, or giving proper permissions");
                return;
            } catch (Exception e) {
                Logging.LogGenericException(e);
                return;
            }

            Logging.LogGenericInfo("WCF server ready!");
        }
Example #24
0
        internal async Task <bool> HandleConfirmations(HashSet <Confirmation> confirmations, bool accept)
        {
            if ((confirmations == null) || (confirmations.Count == 0))
            {
                Logging.LogNullError(nameof(confirmations), Bot.BotName);
                return(false);
            }

            if (!HasCorrectDeviceID)
            {
                Logging.LogGenericWarning("Can't execute properly due to invalid DeviceID!", Bot.BotName);
                return(false);
            }

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

            try {
                uint time = await GetSteamTime().ConfigureAwait(false);

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

                string confirmationHash = GenerateConfirmationKey(time, "conf");
                if (string.IsNullOrEmpty(confirmationHash))
                {
                    Logging.LogNullError(nameof(confirmationHash), Bot.BotName);
                    return(false);
                }

                bool?result = await Bot.ArchiWebHandler.HandleConfirmations(DeviceID, confirmationHash, time, confirmations, accept).ConfigureAwait(false);

                if (!result.HasValue)                   // Request timed out
                {
                    return(false);
                }

                if (result.Value)                   // Request succeeded
                {
                    return(true);
                }

                // Our multi request failed, this is almost always Steam fuckup that happens randomly
                // In this case, we'll accept all pending confirmations one-by-one, synchronously (as Steam can't handle them in parallel)
                // We totally ignore actual result returned by those calls, abort only if request timed out

                foreach (Confirmation confirmation in confirmations)
                {
                    bool?confirmationResult = await Bot.ArchiWebHandler.HandleConfirmation(DeviceID, confirmationHash, time, confirmation.ID, confirmation.Key, accept).ConfigureAwait(false);

                    if (!confirmationResult.HasValue)
                    {
                        return(false);
                    }
                }

                return(true);
            } finally {
                ConfirmationsSemaphore.Release();
            }
        }
        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 #26
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 #27
0
        internal static string GetUserInput(EUserInputType userInputType, string botName = "Main", string extraInformation = null)
        {
            if (userInputType == EUserInputType.Unknown)
            {
                return(null);
            }

            if (GlobalConfig.Headless)
            {
                Logging.LogGenericWarning("Received a request for user input, but process is running in headless mode!");
                return(null);
            }

            string result;

            lock (ConsoleLock) {
                ConsoleIsBusy = true;
                switch (userInputType)
                {
                case EUserInputType.DeviceID:
                    Console.Write("<" + botName + "> Please enter your Device ID (including \"android:\"): ");
                    break;

                case EUserInputType.Login:
                    Console.Write("<" + botName + "> Please enter your login: "******"<" + botName + "> Please enter your password: "******"<" + botName + "> Please enter your full phone number (e.g. +1234567890): ");
                    break;

                case EUserInputType.SMS:
                    Console.Write("<" + botName + "> Please enter SMS code sent on your mobile: ");
                    break;

                case EUserInputType.SteamGuard:
                    Console.Write("<" + botName + "> Please enter the auth code sent to your email: ");
                    break;

                case EUserInputType.SteamParentalPIN:
                    Console.Write("<" + botName + "> Please enter steam parental PIN: ");
                    break;

                case EUserInputType.RevocationCode:
                    Console.WriteLine("<" + botName + "> PLEASE WRITE DOWN YOUR REVOCATION CODE: " + extraInformation);
                    Console.Write("<" + botName + "> Hit enter once ready...");
                    break;

                case EUserInputType.TwoFactorAuthentication:
                    Console.Write("<" + botName + "> Please enter your 2 factor auth code from your authenticator app: ");
                    break;

                case EUserInputType.WCFHostname:
                    Console.Write("<" + botName + "> Please enter your WCF hostname: ");
                    break;

                default:
                    Console.Write("<" + botName + "> Please enter not documented yet value of \"" + userInputType + "\": ");
                    break;
                }

                result = Console.ReadLine();

                if (!Console.IsOutputRedirected)
                {
                    Console.Clear();                     // For security purposes
                }

                ConsoleIsBusy = false;
            }

            return(!string.IsNullOrEmpty(result) ? result.Trim() : null);
        }
Example #28
0
        internal async Task <HashSet <Confirmation> > GetConfirmations()
        {
            if (!HasCorrectDeviceID)
            {
                Logging.LogGenericWarning("Can't execute properly due to invalid DeviceID!", Bot.BotName);
                return(null);
            }

            uint time = await GetSteamTime().ConfigureAwait(false);

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

            string confirmationHash = GenerateConfirmationKey(time, "conf");

            if (string.IsNullOrEmpty(confirmationHash))
            {
                Logging.LogNullError(nameof(confirmationHash), Bot.BotName);
                return(null);
            }

            HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetConfirmations(DeviceID, confirmationHash, time).ConfigureAwait(false);

            HtmlNodeCollection confirmationNodes = htmlDocument?.DocumentNode.SelectNodes("//div[@class='mobileconf_list_entry']");

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

            HashSet <Confirmation> result = new HashSet <Confirmation>();

            foreach (HtmlNode confirmationNode in confirmationNodes)
            {
                string idString = confirmationNode.GetAttributeValue("data-confid", null);
                if (string.IsNullOrEmpty(idString))
                {
                    Logging.LogNullError(nameof(idString), Bot.BotName);
                    return(null);
                }

                uint id;
                if (!uint.TryParse(idString, out id) || (id == 0))
                {
                    Logging.LogNullError(nameof(id), Bot.BotName);
                    return(null);
                }

                string keyString = confirmationNode.GetAttributeValue("data-key", null);
                if (string.IsNullOrEmpty(keyString))
                {
                    Logging.LogNullError(nameof(keyString), Bot.BotName);
                    return(null);
                }

                ulong key;
                if (!ulong.TryParse(keyString, out key) || (key == 0))
                {
                    Logging.LogNullError(nameof(key), Bot.BotName);
                    return(null);
                }

                HtmlNode descriptionNode = confirmationNode.SelectSingleNode(".//div[@class='mobileconf_list_entry_description']/div");
                if (descriptionNode == null)
                {
                    Logging.LogNullError(nameof(descriptionNode), Bot.BotName);
                    return(null);
                }

                Steam.ConfirmationDetails.EType type;

                string description = descriptionNode.InnerText;
                if (description.Equals("Sell - Market Listing"))
                {
                    type = Steam.ConfirmationDetails.EType.Market;
                }
                else if (description.StartsWith("Trade with ", StringComparison.Ordinal))
                {
                    type = Steam.ConfirmationDetails.EType.Trade;
                }
                else
                {
                    Logging.LogGenericWarning("Received unknown confirmation type, please report this: " + description, Bot.BotName);
                    type = Steam.ConfirmationDetails.EType.Other;
                }

                result.Add(new Confirmation(id, key, type));
            }

            return(result);
        }
Example #29
0
        private async Task <bool> IsAnythingToFarm()
        {
            if (NowFarming)
            {
                return(false);
            }

            if (await Bot.ArchiWebHandler.ReconnectIfNeeded().ConfigureAwait(false))
            {
                return(false);
            }

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

            // Find the number of badge pages
            Logging.LogGenericInfo("Checking first page...", Bot.BotName);
            HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetBadgePage(1).ConfigureAwait(false);

            if (htmlDocument == null)
            {
                Logging.LogGenericWarning("Could not get badges information, will try again later!", Bot.BotName);
                return(false);
            }

            byte maxPages = 1;
            HtmlNodeCollection htmlNodeCollection = htmlDocument.DocumentNode.SelectNodes("//a[@class='pagelink']");

            if (htmlNodeCollection != null && htmlNodeCollection.Count > 0)
            {
                HtmlNode htmlNode = htmlNodeCollection[htmlNodeCollection.Count - 1];
                if (!byte.TryParse(htmlNode.InnerText, out maxPages))
                {
                    maxPages = 1;                     // Should never happen
                }
            }

            GamesToFarm.Clear();

            // Find APPIDs we need to farm
            Logging.LogGenericInfo("Checking other pages...", Bot.BotName);

            List <Task> tasks = new List <Task>(maxPages - 1);

            for (byte page = 1; page <= maxPages; page++)
            {
                if (page == 1)
                {
                    CheckPage(htmlDocument);                     // Because we fetched page number 1 already
                }
                else
                {
                    byte currentPage = page;                     // We need a copy of variable being passed when in for loops
                    tasks.Add(Task.Run(async() => await CheckPage(currentPage).ConfigureAwait(false)));
                }
            }
            await Task.WhenAll(tasks).ConfigureAwait(false);

            if (GamesToFarm.Count == 0)
            {
                return(true);
            }

            // If we have restricted card drops, actually do check hours of all games that are left to farm
            if (Bot.CardDropsRestricted)
            {
                tasks = new List <Task>(GamesToFarm.Keys.Count);
                Logging.LogGenericInfo("Checking hours...", Bot.BotName);
                foreach (uint appID in GamesToFarm.Keys)
                {
                    tasks.Add(Task.Run(async() => await CheckHours(appID).ConfigureAwait(false)));
                }
                await Task.WhenAll(tasks).ConfigureAwait(false);
            }

            return(true);
        }
Example #30
0
        internal static async Task CheckForUpdate()
        {
            string oldExeFile = ExecutableFile + ".old";

            // We booted successfully so we can now remove old exe file
            if (File.Exists(oldExeFile))
            {
                try {
                    File.Delete(oldExeFile);
                } catch (Exception e) {
                    Logging.LogGenericException(e);
                    return;
                }
            }

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

            string releaseURL = GithubReleaseURL;

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

            string response = null;

            Logging.LogGenericInfo("Checking new version...");
            for (byte i = 0; i < WebBrowser.MaxRetries && string.IsNullOrEmpty(response); i++)
            {
                response = await WebBrowser.UrlGetToContent(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)
                {
                    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 (!GlobalConfig.AutoUpdates)
            {
                Logging.LogGenericInfo("New version is available!");
                Logging.LogGenericInfo("Consider updating yourself!");
                await Utilities.SleepAsync(5000).ConfigureAwait(false);

                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.Asset binaryAsset = null;
            foreach (var asset in releaseResponse.Assets)
            {
                if (string.IsNullOrEmpty(asset.Name) || !asset.Name.Equals(ExecutableName))
                {
                    continue;
                }

                binaryAsset = asset;
                break;
            }

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

            Logging.LogGenericInfo("Downloading new version...");
            Stream newExe = await WebBrowser.UrlGetToStream(binaryAsset.DownloadURL).ConfigureAwait(false);

            if (newExe == null)
            {
                Logging.LogGenericWarning("Could not download new version!");
                return;
            }

            // We start deep update logic here
            string newExeFile = ExecutableFile + ".new";

            // Firstly we create new exec
            try {
                using (FileStream fileStream = File.Open(newExeFile, FileMode.Create)) {
                    await newExe.CopyToAsync(fileStream).ConfigureAwait(false);
                }
            } 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 { }
                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 { }
                return;
            }

            Logging.LogGenericInfo("Update process is finished! ASF will now restart itself...");
            await Utilities.SleepAsync(5000);

            Restart();
        }