private static async Task UpdateMissingGames()
        {
            var tickCount = Environment.TickCount;

            MissingUpdaterEventSource.Log.UpdateMissingGamesStart();

            var allSteamAppsTask = GetAllSteamApps(s_client);
            var allKnownAppsTask = StorageHelper.GetAllApps(null, StorageRetries);

            await Task.WhenAll(allSteamAppsTask, allKnownAppsTask).ConfigureAwait(false);

            var allSteamApps = allSteamAppsTask.Result;
            var allKnownApps = allKnownAppsTask.Result;

            var knownSteamIdsHash = new HashSet <int>(allKnownApps.Select(ae => ae.SteamAppId));
            var missingApps       = allSteamApps.Where(a => !knownSteamIdsHash.Contains(a.appid)).Take(UpdateLimit).ToArray();

            MissingUpdaterEventSource.Log.MissingAppsDetermined(missingApps);

            var updates = new ConcurrentBag <AppEntity>();
            InvalidOperationException ioe = null;

            try
            {
                await SteamStoreHelper
                .GetStoreInformationUpdates(missingApps.Select(a => new BasicStoreInfo(a.appid, a.name, null)).ToArray(), s_client, updates)
                .ConfigureAwait(false);
            }
            catch (Exception e)
            {
                ioe = new InvalidOperationException("Could not retrieve store information for all games", e);
            }

            var measuredUpdates = updates.Where(a => a.Measured).ToArray();

            if (measuredUpdates.Length > 0)
            {
                await HltbScraper.ScrapeHltb(measuredUpdates).ConfigureAwait(false);

                //re-impute for measured updates
                await Imputer.Impute(allKnownApps.Where(a => a.Measured).Concat(measuredUpdates).ToArray()).ConfigureAwait(false);
            }

            //we're inserting new entries, no fear of collisions (even if two jobs overlap the next one will fix it)
            await StorageHelper.Insert(updates, "updating missing games", StorageHelper.SteamToHltbTableName, StorageRetries).ConfigureAwait(false);

            if (ioe != null)
            {
                throw ioe; //fail job
            }

            await SiteUtil.SendSuccessMail("Missing updater", updates.Count + " app(s) added", tickCount).ConfigureAwait(false);

            MissingUpdaterEventSource.Log.UpdateMissingGamesStop();
        }
Example #2
0
        private static async Task UpdateUnknownApps()
        {
            var ticks = Environment.TickCount;

            UnknownUpdaterEventSource.Log.UpdateUnknownAppsStart();

            var allUnknownApps = (await StorageHelper.GetAllApps(AppEntity.UnknownFilter, StorageRetries).ConfigureAwait(false)).Take(UpdateLimit).ToArray();

            var updates = new ConcurrentBag <AppEntity>();
            InvalidOperationException ioe = null;

            try
            {
                await SteamStoreHelper.GetStoreInformationUpdates(
                    allUnknownApps.Select(ae => new BasicStoreInfo(ae.SteamAppId, ae.SteamName, ae.AppType)).ToArray(), Client, updates).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                ioe = new InvalidOperationException("Could not retrieve store information for all apps", e);
            }

            UnknownUpdaterEventSource.Log.UpdateNewlyCategorizedApps(updates);

            var measuredUpdates = updates.Where(a => a.Measured).ToArray();

            if (measuredUpdates.Length > 0)
            {
                await HltbScraper.ScrapeHltb(measuredUpdates).ConfigureAwait(false);

                //re-impute with new scraped values for updated games (Enumberable.Union() guarantees measuredUpdates will be enumerated before allApps!)
                var allMeasuredApps = await StorageHelper.GetAllApps(AppEntity.MeasuredFilter).ConfigureAwait(false);

                await Imputer.Impute(measuredUpdates.Union(allMeasuredApps, new AppEntitySteamIdComparer()).ToArray()).ConfigureAwait(false);
            }

            var unknownAppsMap = allUnknownApps.ToDictionary(ae => ae.SteamAppId);
            await StorageHelper.ExecuteOperations(updates,
                                                  ae => new[] { TableOperation.Delete(unknownAppsMap[ae.SteamAppId]), TableOperation.Insert(ae) },
                                                  StorageHelper.SteamToHltbTableName, "updating previously unknown games", StorageRetries).ConfigureAwait(false);

            if (ioe != null)
            {
                throw ioe; //fail job
            }

            await SiteUtil.SendSuccessMail("Unknown updater",
                                           updates.Count + " previously unknown game(s) updated", ticks).ConfigureAwait(false);

            UnknownUpdaterEventSource.Log.UpdateUnknownAppsStop();
        }
        public void TestStoreApi()
        {
            var updates = new ConcurrentBag <AppEntity>();

            using (var client = new HttpRetryClient(200))
            {
                var steamApps = MissingUpdater.GetAllSteamApps(client).Result;
                var portalApp = steamApps.FirstOrDefault(app => app.appid == 400 && String.Equals(app.name, "Portal", StringComparison.Ordinal));
                Assert.IsNotNull(portalApp, "Could not find Portal in the steam library: {0}",
                                 String.Join(", ", steamApps.Select(a => String.Format(CultureInfo.InvariantCulture, "{0}/{1}", a.appid, a.name))));

                SteamStoreHelper.GetStoreInformationUpdates(new[] { new BasicStoreInfo(portalApp.appid, portalApp.name, null) }, client, updates).Wait();
            }

            Assert.AreEqual(1, updates.Count, "Expected exactly one update for requested app (Portal)");
            var portal = updates.First();

            Assert.IsTrue(portal.IsGame, "Portal is not classified as a game");
            Assert.IsFalse(portal.IsDlc, "Portal is classified as a DLC");
            Assert.IsFalse(portal.IsMod, "Portal is classified as a mod");

            Assert.IsTrue(portal.Categories.Contains("Single-player", StringComparer.OrdinalIgnoreCase),
                          "Portal is not classified as single-player: {0}", portal.CategoriesFlat);

            Assert.AreEqual("Valve", portal.Developers.SingleOrDefault(),
                            "Valve are not listed as the sole developers of Portal: {0}", portal.DevelopersFlat);

            Assert.AreEqual("Valve", portal.Publishers.SingleOrDefault(),
                            "Valve are not listed as the sole publishers of Portal: {0}", portal.PublishersFlat);

            Assert.IsTrue(portal.Genres.Contains("Action", StringComparer.OrdinalIgnoreCase),
                          "Portal is not classified as an action game: {0}", portal.GenresFlat);

            Assert.IsTrue(portal.MetacriticScore > 85, "Portal is scored too low on Metacritic: {0}", portal.MetacriticScore);

            Assert.IsTrue(portal.Platforms.HasFlag(Common.Entities.Platforms.Windows) &&
                          portal.Platforms.HasFlag(Common.Entities.Platforms.Linux) &&
                          portal.Platforms.HasFlag(Common.Entities.Platforms.Mac),
                          "Portal is not listed as supported on Windows, Mac, and Linux: {0}", portal.Platforms);

            Assert.AreEqual(new DateTime(2007, 10, 10), portal.ReleaseDate, "Portal release date is incorrect");
        }