ArchiSteamFarm.CardsFarmer.CheckPage C# (CSharp) Метод

CheckPage() приватный Метод

private CheckPage ( HtmlAgilityPack.HtmlDocument htmlDocument ) : Task
htmlDocument HtmlAgilityPack.HtmlDocument
Результат Task
		private async Task CheckPage(HtmlDocument htmlDocument) {
			if (htmlDocument == null) {
				Bot.ArchiLogger.LogNullError(nameof(htmlDocument));
				return;
			}

			HtmlNodeCollection htmlNodes = htmlDocument.DocumentNode.SelectNodes("//div[@class='badge_title_stats_content']");
			if (htmlNodes == null) {
				// No eligible badges whatsoever
				return;
			}

			HashSet<Task> extraTasks = new HashSet<Task>();

			foreach (HtmlNode htmlNode in htmlNodes) {
				HtmlNode appIDNode = htmlNode.SelectSingleNode(".//div[@class='card_drop_info_dialog']");
				if (appIDNode == null) {
					// It's just a badge, nothing more
					continue;
				}

				string appIDString = appIDNode.GetAttributeValue("id", null);
				if (string.IsNullOrEmpty(appIDString)) {
					Bot.ArchiLogger.LogNullError(nameof(appIDString));
					continue;
				}

				string[] appIDSplitted = appIDString.Split('_');
				if (appIDSplitted.Length < 5) {
					Bot.ArchiLogger.LogNullError(nameof(appIDSplitted));
					continue;
				}

				appIDString = appIDSplitted[4];

				uint appID;
				if (!uint.TryParse(appIDString, out appID) || (appID == 0)) {
					Bot.ArchiLogger.LogNullError(nameof(appID));
					continue;
				}

				if (GlobalConfig.GlobalBlacklist.Contains(appID) || Program.GlobalConfig.Blacklist.Contains(appID)) {
					// We have this appID blacklisted, so skip it
					continue;
				}

				// Cards
				HtmlNode progressNode = htmlNode.SelectSingleNode(".//span[@class='progress_info_bold']");
				if (progressNode == null) {
					Bot.ArchiLogger.LogNullError(nameof(progressNode));
					continue;
				}

				string progressText = progressNode.InnerText;
				if (string.IsNullOrEmpty(progressText)) {
					Bot.ArchiLogger.LogNullError(nameof(progressText));
					continue;
				}

				ushort cardsRemaining = 0;
				Match progressMatch = Regex.Match(progressText, @"\d+");

				// This might fail if we have no card drops remaining, that's fine
				if (progressMatch.Success) {
					if (!ushort.TryParse(progressMatch.Value, out cardsRemaining)) {
						Bot.ArchiLogger.LogNullError(nameof(cardsRemaining));
						continue;
					}
				}

				if (cardsRemaining == 0) {
					// Normally we'd trust this information and simply skip the rest
					// However, Steam is so fucked up that we can't simply assume that it's correct
					// It's entirely possible that actual game page has different info, and badge page lied to us
					// We can't check every single game though, as this will literally kill people with cards from games they don't own
					if (!UntrustedAppIDs.Contains(appID)) {
						continue;
					}

					// To save us on extra work, check cards earned so far first
					HtmlNode cardsEarnedNode = htmlNode.SelectSingleNode(".//div[@class='card_drop_info_header']");
					string cardsEarnedText = cardsEarnedNode.InnerText;
					if (string.IsNullOrEmpty(cardsEarnedText)) {
						Bot.ArchiLogger.LogNullError(nameof(cardsEarnedText));
						continue;
					}

					Match cardsEarnedMatch = Regex.Match(cardsEarnedText, @"\d+");
					if (!cardsEarnedMatch.Success) {
						Bot.ArchiLogger.LogNullError(nameof(cardsEarnedMatch));
						continue;
					}

					ushort cardsEarned;
					if (!ushort.TryParse(cardsEarnedMatch.Value, out cardsEarned)) {
						Bot.ArchiLogger.LogNullError(nameof(cardsEarned));
						continue;
					}

					if (cardsEarned > 0) {
						// If we already earned some cards for this game, it's very likely that it's done
						// Let's hope that trusting cardsRemaining AND cardsEarned is enough
						// If I ever hear that it's not, I'll most likely need a doctor
						continue;
					}

					// If we have no cardsRemaining and no cardsEarned, it's either:
					// - A game we don't own physically, but we have cards from it in inventory
					// - F2P game that we didn't spend any money in, but we have cards from it in inventory
					// - Steam fuckup
					// As you can guess, we must follow the rest of the logic in case of Steam fuckup
					// Please kill me ;_;
				}

				// Hours
				HtmlNode timeNode = htmlNode.SelectSingleNode(".//div[@class='badge_title_stats_playtime']");
				if (timeNode == null) {
					Bot.ArchiLogger.LogNullError(nameof(timeNode));
					continue;
				}

				string hoursString = timeNode.InnerText;
				if (string.IsNullOrEmpty(hoursString)) {
					Bot.ArchiLogger.LogNullError(nameof(hoursString));
					continue;
				}

				float hours = 0;
				Match hoursMatch = Regex.Match(hoursString, @"[0-9\.,]+");

				// This might fail if we have exactly 0.0 hours played, that's fine
				if (hoursMatch.Success) {
					if (!float.TryParse(hoursMatch.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out hours)) {
						Bot.ArchiLogger.LogNullError(nameof(hours));
						continue;
					}
				}

				// Names
				HtmlNode nameNode = htmlNode.SelectSingleNode("(.//div[@class='card_drop_info_body'])[last()]");
				if (nameNode == null) {
					Bot.ArchiLogger.LogNullError(nameof(nameNode));
					continue;
				}

				string name = nameNode.InnerText;
				if (string.IsNullOrEmpty(name)) {
					Bot.ArchiLogger.LogNullError(nameof(name));
					continue;
				}

				// We handle two cases here - normal one, and no card drops remaining
				int nameStartIndex = name.IndexOf(" by playing ", StringComparison.Ordinal);
				if (nameStartIndex <= 0) {
					nameStartIndex = name.IndexOf("You don't have any more drops remaining for ", StringComparison.Ordinal);
					if (nameStartIndex <= 0) {
						Bot.ArchiLogger.LogNullError(nameof(nameStartIndex));
						continue;
					}

					nameStartIndex += 32; // + 12 below
				}

				nameStartIndex += 12;

				int nameEndIndex = name.LastIndexOf('.');
				if (nameEndIndex <= nameStartIndex) {
					Bot.ArchiLogger.LogNullError(nameof(nameEndIndex));
					continue;
				}

				name = name.Substring(nameStartIndex, nameEndIndex - nameStartIndex);

				// We have two possible cases here
				// Either we have decent info about appID, name, hours and cardsRemaining (cardsRemaining > 0)
				// OR we strongly believe that Steam lied to us, in this case we will need to check game invidually (cardsRemaining == 0)

				if (cardsRemaining > 0) {
					GamesToFarm.Add(new Game(appID, name, hours, cardsRemaining));
				} else {
					extraTasks.Add(CheckGame(appID, name, hours));
				}
			}

			// If we have any pending tasks, wait for them
			await Task.WhenAll(extraTasks).ConfigureAwait(false);
		}

Same methods

CardsFarmer::CheckPage ( byte page ) : Task