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); }
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); }
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; } } }
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); }
// 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); }
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); }
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; } } }
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); }
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); }
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(); }
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); }
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(); }
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); }
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); }
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); }
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); }
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!"); }
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); }
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(); } }
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); }
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); }
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); }
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(); }