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 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(); }
private async Task <bool> UnlockParentalAccount(string parentalPin) { if (string.IsNullOrEmpty(parentalPin)) { Logging.LogNullError(nameof(parentalPin), Bot.BotName); return(false); } Logging.LogGenericInfo("Unlocking parental account...", Bot.BotName); string request = SteamCommunityURL + "/parental/ajaxunlock"; Dictionary <string, string> data = new Dictionary <string, string>(1) { { "pin", parentalPin } }; bool result = await WebBrowser.UrlPostRetry(request, data, SteamCommunityURL).ConfigureAwait(false); if (!result) { Logging.LogGenericInfo("Failed!", Bot.BotName); return(false); } Logging.LogGenericInfo("Success!", Bot.BotName); return(true); }
private async Task ParseTrade(Steam.TradeOffer tradeOffer) { if (tradeOffer == null) { Logging.LogNullError(nameof(tradeOffer), Bot.BotName); return; } if (tradeOffer.State != Steam.TradeOffer.ETradeOfferState.Active) { return; } if (await ShouldAcceptTrade(tradeOffer).ConfigureAwait(false)) { Logging.LogGenericInfo("Accepting trade: " + tradeOffer.TradeOfferID, Bot.BotName); await Bot.ArchiWebHandler.AcceptTradeOffer(tradeOffer.TradeOfferID).ConfigureAwait(false); } else if (Bot.BotConfig.IsBotAccount) { Logging.LogGenericInfo("Rejecting trade: " + tradeOffer.TradeOfferID, Bot.BotName); Bot.ArchiWebHandler.DeclineTradeOffer(tradeOffer.TradeOfferID); } else { Logging.LogGenericInfo("Ignoring trade: " + tradeOffer.TradeOfferID, Bot.BotName); } }
private async Task <bool> FarmSolo(Game game) { if (game == null) { Logging.LogNullError(nameof(game), Bot.BotName); return(true); } CurrentGamesFarming.Add(game); Logging.LogGenericInfo("Now farming: " + game.AppID + " (" + game.GameName + ")", Bot.BotName); bool result = await Farm(game).ConfigureAwait(false); CurrentGamesFarming.ClearAndTrim(); if (!result) { return(false); } GamesToFarm.Remove(game); TimeSpan timeSpan = TimeSpan.FromHours(game.HoursPlayed); Logging.LogGenericInfo("Done farming: " + game.AppID + " (" + game.GameName + ") after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!", Bot.BotName); return(true); }
public string HandleCommand(string input) { if (string.IsNullOrEmpty(input)) { Logging.LogNullError(nameof(input)); return(null); } if (Program.GlobalConfig.SteamOwnerID == 0) { return("Refusing to handle request because SteamOwnerID is not set!"); } Bot bot = Bot.Bots.Values.FirstOrDefault(); if (bot == null) { return("ERROR: No bots are enabled!"); } string command = "!" + input; string output = bot.Response(Program.GlobalConfig.SteamOwnerID, command).Result; // TODO: This should be asynchronous Logging.LogGenericInfo("Answered to command: " + input + " with: " + output); return(output); }
private async Task <bool> FarmSolo(uint appID) { if (appID == 0) { return(true); } CurrentGamesFarming.Add(appID); Logging.LogGenericInfo("Now farming: " + appID, Bot.BotName); if (await Farm(appID).ConfigureAwait(false)) { CurrentGamesFarming.Clear(); CurrentGamesFarming.TrimExcess(); float hours; if (GamesToFarm.TryRemove(appID, out hours)) { TimeSpan timeSpan = TimeSpan.FromHours(hours); Logging.LogGenericInfo("Done farming: " + appID + " after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!", Bot.BotName); } return(true); } else { CurrentGamesFarming.Clear(); CurrentGamesFarming.TrimExcess(); return(false); } }
private bool FarmMultiple() { if (GamesToFarm.Count == 0) { return(true); } float maxHour = 0; foreach (KeyValuePair <uint, float> game in GamesToFarm) { CurrentGamesFarming.Add(game.Key); if (game.Value > maxHour) { maxHour = game.Value; } } if (maxHour >= 2) { CurrentGamesFarming.ClearAndTrim(); return(true); } Logging.LogGenericInfo("Now farming: " + string.Join(", ", CurrentGamesFarming), Bot.BotName); bool result = FarmHours(maxHour, CurrentGamesFarming); CurrentGamesFarming.ClearAndTrim(); return(result); }
private async Task <bool> FarmSolo(uint appID) { if (appID == 0) { Logging.LogNullError(nameof(appID), Bot.BotName); return(true); } CurrentGamesFarming.Add(appID); Logging.LogGenericInfo("Now farming: " + appID, Bot.BotName); bool result = await Farm(appID).ConfigureAwait(false); CurrentGamesFarming.ClearAndTrim(); if (!result) { return(false); } float hours; if (!GamesToFarm.TryRemove(appID, out hours)) { return(false); } TimeSpan timeSpan = TimeSpan.FromHours(hours); Logging.LogGenericInfo("Done farming: " + appID + " after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!", Bot.BotName); return(true); }
internal void StartServer() { if (ServiceHost != null) { return; } Logging.LogGenericInfo("Starting WCF server..."); try { ServiceHost = new ServiceHost(typeof(WCF), new Uri(URL)); ServiceHost.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); ServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); ServiceHost.AddServiceEndpoint(typeof(IWCF), new BasicHttpBinding(), string.Empty); ServiceHost.Open(); } catch (Exception e) { Logging.LogGenericException(e); return; } Logging.LogGenericInfo("WCF server ready!"); }
private static void Main(string[] args) { Logging.LogGenericInfo("Main", "Archi's Steam Farm, version " + Version); Task.Run(async() => await CheckForUpdate().ConfigureAwait(false)).Wait(); // Config directory may not be in the same directory as the .exe, check maximum of 3 levels lower for (var i = 0; i < 4 && !Directory.Exists(ConfigDirectoryPath); i++) { Directory.SetCurrentDirectory(".."); } if (!Directory.Exists(ConfigDirectoryPath)) { Logging.LogGenericError("Main", "Config directory doesn't exist!"); Console.ReadLine(); Exit(1); } lock (Bots) { foreach (var configFile in Directory.EnumerateFiles(ConfigDirectoryPath, "*.xml")) { string botName = Path.GetFileNameWithoutExtension(configFile); Bot bot = new Bot(botName); Bots.Add(bot); if (!bot.Enabled) { Logging.LogGenericInfo(botName, "Not starting this instance because it's disabled in config file"); } } } Thread.Sleep(Timeout.Infinite); }
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(); }
private async Task <bool> RefreshSessionIfNeeded() { if (DateTime.Now.Subtract(LastSessionRefreshCheck).TotalSeconds < MinSessionTTL) { return(true); } await SessionSemaphore.WaitAsync().ConfigureAwait(false); if (DateTime.Now.Subtract(LastSessionRefreshCheck).TotalSeconds < MinSessionTTL) { SessionSemaphore.Release(); return(true); } bool result; bool?isLoggedIn = await IsLoggedIn().ConfigureAwait(false); if (isLoggedIn.GetValueOrDefault(true)) { result = true; LastSessionRefreshCheck = DateTime.Now; } else { Logging.LogGenericInfo("Refreshing our session!", Bot.BotName); result = await Bot.RefreshSession().ConfigureAwait(false); } SessionSemaphore.Release(); return(result); }
private static async Task CheckForUpdate() { JObject response = await WebBrowser.UrlGetToJObject(LatestGithubReleaseURL).ConfigureAwait(false); if (response == null) { return; } string remoteVersion = response["tag_name"].ToString(); if (string.IsNullOrEmpty(remoteVersion)) { return; } string localVersion = Version; Logging.LogGenericInfo("Local version: " + localVersion); Logging.LogGenericInfo("Remote version: " + remoteVersion); int comparisonResult = localVersion.CompareTo(remoteVersion); if (comparisonResult < 0) { Logging.LogGenericInfo("New version is available!"); Logging.LogGenericInfo("Consider updating yourself!"); await Utilities.SleepAsync(5000).ConfigureAwait(false); } else if (comparisonResult > 0) { Logging.LogGenericInfo("You're currently using pre-release version!"); Logging.LogGenericInfo("Be careful!"); } }
private async Task <bool> UnlockParentalAccount(string parentalPin) { if (string.IsNullOrEmpty(parentalPin) || parentalPin.Equals("0")) { return(true); } Logging.LogGenericInfo("Unlocking parental account...", Bot.BotName); string request = SteamCommunityURL + "/parental/ajaxunlock"; Dictionary <string, string> data = new Dictionary <string, string>(1) { { "pin", parentalPin } }; bool result = false; for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) { result = await WebBrowser.UrlPost(request, data, SteamCommunityURL).ConfigureAwait(false); } if (!result) { Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName); return(false); } Logging.LogGenericInfo("Success!", Bot.BotName); return(true); }
private async Task <bool> Farm(ulong appID) { if (NowFarming) { AutoResetEvent.Set(); Thread.Sleep(1000); AutoResetEvent.Reset(); } bool success = true; bool?keepFarming = await ShouldFarm(appID).ConfigureAwait(false); while (keepFarming == null || keepFarming.Value) { if (!NowFarming) { NowFarming = true; Logging.LogGenericInfo(Bot.BotName, "Now farming: " + appID); Bot.PlayGame(appID); } if (AutoResetEvent.WaitOne(1000 * 60 * StatusCheckSleep)) { success = false; break; } keepFarming = await ShouldFarm(appID).ConfigureAwait(false); } Logging.LogGenericInfo(Bot.BotName, "Stopped farming: " + appID); Bot.PlayGame(0); NowFarming = false; return(success); }
private async Task <bool> Farm(uint appID) { if (appID == 0) { return(false); } Bot.ArchiHandler.PlayGames(appID); bool success = true; bool?keepFarming = await ShouldFarm(appID).ConfigureAwait(false); for (ushort farmingTime = 0; farmingTime <= 60 * Program.GlobalConfig.MaxFarmingTime && keepFarming.GetValueOrDefault(true); farmingTime += Program.GlobalConfig.FarmingDelay) { if (FarmResetEvent.WaitOne(60 * 1000 * Program.GlobalConfig.FarmingDelay)) { success = false; break; } // Don't forget to update our GamesToFarm hours float timePlayed = Program.GlobalConfig.FarmingDelay / 60.0F; GamesToFarm[appID] += timePlayed; keepFarming = await ShouldFarm(appID).ConfigureAwait(false); Logging.LogGenericInfo("Still farming: " + appID, Bot.BotName); } Bot.ResetGamesPlayed(); Logging.LogGenericInfo("Stopped farming: " + appID, Bot.BotName); return(success); }
private async Task <bool> Farm(ulong appID) { bool success = true; bool?keepFarming = await ShouldFarm(appID).ConfigureAwait(false); while (keepFarming == null || keepFarming.Value) { if (!NowFarming) { NowFarming = true; Logging.LogGenericInfo(Bot.BotName, "Now farming: " + appID); Bot.PlayGame(appID); Semaphore.Release(); // We're farming, allow other tasks to shut us down } else { Logging.LogGenericInfo(Bot.BotName, "Still farming: " + appID); } if (FarmResetEvent.WaitOne(1000 * 60 * StatusCheckSleep)) { success = false; break; } keepFarming = await ShouldFarm(appID).ConfigureAwait(false); } Bot.PlayGame(0); NowFarming = false; Logging.LogGenericInfo(Bot.BotName, "Stopped farming: " + appID); return(success); }
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); }
private void OnLoggedOff(SteamUser.LoggedOffCallback callback) { if (callback == null) { return; } Logging.LogGenericInfo(BotName, "Logged off of Steam: " + callback.Result); }
internal static async void OnBotShutdown(Bot bot) { if (Bot.GetRunningBotsCount() == 0) { Logging.LogGenericInfo("Main", "No bots are running, exiting"); await Utilities.SleepAsync(5000).ConfigureAwait(false); // This might be the only message user gets, consider giving him some time ShutdownResetEvent.Set(); } }
private bool FarmHours(ConcurrentHashSet <Game> games) { if ((games == null) || (games.Count == 0)) { Logging.LogNullError(nameof(games), Bot.BotName); return(false); } float maxHour = games.Max(game => game.HoursPlayed); if (maxHour < 0) { Logging.LogNullError(nameof(maxHour), Bot.BotName); return(false); } if (maxHour >= 2) { Logging.LogGenericError("Received request for past-2h games!", Bot.BotName); return(true); } Bot.ArchiHandler.PlayGames(games.Select(game => game.AppID), Bot.BotConfig.CustomGamePlayedWhileFarming); bool success = true; while (maxHour < 2) { Logging.LogGenericInfo("Still farming: " + string.Join(", ", games.Select(game => game.AppID)), Bot.BotName); DateTime startFarmingPeriod = DateTime.Now; if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay)) { FarmResetEvent.Reset(); success = KeepFarming; } // Don't forget to update our GamesToFarm hours float timePlayed = (float)DateTime.Now.Subtract(startFarmingPeriod).TotalHours; foreach (Game game in games) { game.HoursPlayed += timePlayed; } if (!success) { break; } maxHour += timePlayed; } Logging.LogGenericInfo("Stopped farming: " + string.Join(", ", games.Select(game => game.AppID)), Bot.BotName); return(success); }
internal static void OnBotShutdown() { if (Program.ShutdownSequenceInitialized || Program.WCF.IsServerRunning() || Bot.Bots.Values.Any(bot => bot.KeepRunning)) { return; } Logging.LogGenericInfo("No bots are running, exiting"); Task.Delay(5000).Wait(); Program.Shutdown(); }
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); }
internal async Task <bool> ReconnectIfNeeded() { bool?isLoggedIn = await IsLoggedIn().ConfigureAwait(false); if (isLoggedIn.HasValue && !isLoggedIn.Value) { Logging.LogGenericInfo("Reconnecting because our sessionID expired!", Bot.BotName); Task.Run(async() => await Bot.Restart().ConfigureAwait(false)).Forget(); return(true); } return(false); }
private async Task <ParseTradeResult> ParseTrade(Steam.TradeOffer tradeOffer) { if (tradeOffer == null) { Logging.LogNullError(nameof(tradeOffer), Bot.BotName); return(null); } if (tradeOffer.State != Steam.TradeOffer.ETradeOfferState.Active) { Logging.LogGenericError("Ignoring trade in non-active state!", Bot.BotName); return(null); } ParseTradeResult result = await ShouldAcceptTrade(tradeOffer).ConfigureAwait(false); if (result == null) { Logging.LogNullError(nameof(result), Bot.BotName); return(null); } switch (result.Result) { case ParseTradeResult.EResult.AcceptedWithItemLose: case ParseTradeResult.EResult.AcceptedWithoutItemLose: Logging.LogGenericInfo("Accepting trade: " + tradeOffer.TradeOfferID, Bot.BotName); await Bot.ArchiWebHandler.AcceptTradeOffer(tradeOffer.TradeOfferID).ConfigureAwait(false); break; case ParseTradeResult.EResult.RejectedPermanently: case ParseTradeResult.EResult.RejectedTemporarily: if (result.Result == ParseTradeResult.EResult.RejectedPermanently) { if (Bot.BotConfig.IsBotAccount) { Logging.LogGenericInfo("Rejecting trade: " + tradeOffer.TradeOfferID, Bot.BotName); Bot.ArchiWebHandler.DeclineTradeOffer(tradeOffer.TradeOfferID); break; } IgnoredTrades.Add(tradeOffer.TradeOfferID); } Logging.LogGenericInfo("Ignoring trade: " + tradeOffer.TradeOfferID, Bot.BotName); break; } return(result); }
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; } } }
private async Task <bool?> ShouldFarm(Game game) { if (game == null) { Logging.LogNullError(nameof(game), Bot.BotName); return(false); } HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetGameCardsPage(game.AppID).ConfigureAwait(false); if (htmlDocument == null) { return(null); } HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//span[@class='progress_info_bold']"); if (htmlNode == null) { Logging.LogNullError(nameof(htmlNode), Bot.BotName); return(null); } string progress = htmlNode.InnerText; if (string.IsNullOrEmpty(progress)) { Logging.LogNullError(nameof(progress), Bot.BotName); return(null); } ushort cardsRemaining = 0; Match match = Regex.Match(progress, @"\d+"); if (match.Success) { if (!ushort.TryParse(match.Value, out cardsRemaining)) { Logging.LogNullError(nameof(cardsRemaining), Bot.BotName); return(null); } } game.CardsRemaining = cardsRemaining; Logging.LogGenericInfo("Status for " + game.AppID + " (" + game.GameName + "): " + cardsRemaining + " cards remaining", Bot.BotName); return(cardsRemaining > 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); }