public static void Cleanup()
        {
            Log.WriteInfo(nameof(Application), "Exiting...");

            try
            {
                Steam.Instance.IsRunning = false;
                Steam.Instance.Client.Disconnect();
                Steam.Instance.Dispose();
            }
            catch (Exception e)
            {
                ErrorReporter.Notify(nameof(Application), e);
            }

            if (Settings.Current.IRC.Enabled)
            {
                Log.WriteInfo(nameof(Application), "Closing IRC connection...");

                RssReader.Timer.Stop();
                RssReader.Dispose();

                IRC.Instance.Close();

                IrcThread.Join(TimeSpan.FromSeconds(5));
            }

            TaskManager.CancelAllTasks();

            if (!Settings.IsFullRun)
            {
                LocalConfig.Update("backend.changenumber", Steam.Instance.PICSChanges.PreviousChangeNumber.ToString())
                .GetAwaiter().GetResult();
            }
        }
示例#2
0
        private static async void Tick(object sender, ElapsedEventArgs e)
        {
            DateTime lastPostDate;

            await using (var db = await Database.GetConnectionAsync())
            {
                lastPostDate = db.ExecuteScalar <DateTime>("SELECT `Value` FROM `LocalConfig` WHERE `ConfigKey` = @Key", new { Key = "backend.lastrsspost" });
            }

            var tasks = Settings.Current.RssFeeds.Select(uri => ProcessFeed(uri, lastPostDate));

            var dates = await Task.WhenAll(tasks);

            var maxDate = dates.Max();

            if (maxDate > lastPostDate)
            {
                await LocalConfig.Update("backend.lastrsspost", maxDate.ToString(CultureInfo.InvariantCulture));
            }
        }
示例#3
0
 private Task Save()
 {
     return(LocalConfig.Update("backend.freelicense.requests", JsonConvert.SerializeObject(FreeLicensesToRequest)));
 }
示例#4
0
        private void OnPICSChanges(SteamApps.PICSChangesCallback callback)
        {
            if (PreviousChangeNumber == callback.CurrentChangeNumber)
            {
                return;
            }

            Log.WriteInfo(nameof(PICSChanges), $"Changelist {callback.LastChangeNumber} -> {callback.CurrentChangeNumber} ({callback.AppChanges.Count} apps, {callback.PackageChanges.Count} packages)");

            PreviousChangeNumber = callback.CurrentChangeNumber;

            TaskManager.Run(async() => await HandleChangeNumbers(callback));

            if (callback.RequiresFullAppUpdate || callback.RequiresFullPackageUpdate)
            {
                TaskManager.Run(async() =>
                {
                    if (callback.RequiresFullAppUpdate)
                    {
                        IRC.Instance.SendOps($"Changelist {callback.CurrentChangeNumber} has forced a full app update");

                        // When full update flag is set, presumably Steam client start hammering the servers
                        // and the PICS service just does not return any data for a while until it clears up
                        await FullUpdateProcessor.FullUpdateAppsMetadata(true);
                    }

                    if (callback.RequiresFullPackageUpdate)
                    {
                        IRC.Instance.SendOps($"Changelist {callback.CurrentChangeNumber} has forced a full package update");

                        await FullUpdateProcessor.FullUpdatePackagesMetadata();
                    }

                    IRC.Instance.SendOps($"Changelist {callback.CurrentChangeNumber} full update has finished");
                });
            }

            if (callback.AppChanges.Count == 0 && callback.PackageChanges.Count == 0)
            {
                return;
            }

            const int appsPerJob = 50;

            if (callback.AppChanges.Count > appsPerJob)
            {
                foreach (var list in callback.AppChanges.Keys.Split(appsPerJob))
                {
                    JobManager.AddJob(
                        () => Steam.Instance.Apps.PICSGetAccessTokens(list, Enumerable.Empty <uint>()),
                        new PICSTokens.RequestedTokens
                    {
                        Apps = list.ToList()
                    });
                }
            }
            else if (callback.AppChanges.Count > 0)
            {
                JobManager.AddJob(
                    () => Steam.Instance.Apps.PICSGetAccessTokens(callback.AppChanges.Keys, Enumerable.Empty <uint>()),
                    new PICSTokens.RequestedTokens
                {
                    Apps = callback.AppChanges.Keys.ToList()
                });
            }

            if (callback.PackageChanges.Count > appsPerJob)
            {
                foreach (var list in callback.PackageChanges.Keys.Split(appsPerJob))
                {
                    JobManager.AddJob(
                        () => Steam.Instance.Apps.PICSGetAccessTokens(Enumerable.Empty <uint>(), list),
                        new PICSTokens.RequestedTokens
                    {
                        Packages = list.ToList()
                    });
                }
            }
            else if (callback.PackageChanges.Count > 0)
            {
                JobManager.AddJob(
                    () => Steam.Instance.Apps.PICSGetAccessTokens(Enumerable.Empty <uint>(), callback.PackageChanges.Keys),
                    new PICSTokens.RequestedTokens
                {
                    Packages = callback.PackageChanges.Keys.ToList()
                });
            }

            if (callback.AppChanges.Count > 0)
            {
                _ = TaskManager.Run(async() => await HandleApps(callback));
            }

            if (callback.PackageChanges.Count > 0)
            {
                _ = TaskManager.Run(async() => await HandlePackages(callback));
                _ = TaskManager.Run(async() => await HandlePackagesChangelists(callback));
            }

            if (PreviousChangeNumber - LastStoredChangeNumber >= 1000)
            {
                LastStoredChangeNumber = PreviousChangeNumber;

                _ = TaskManager.Run(async() => await LocalConfig.Update("backend.changenumber", LastStoredChangeNumber.ToString()));
            }

            PrintImportants(callback);
        }
示例#5
0
 private Task SaveBetas()
 {
     return(LocalConfig.Update("backend.beta.requests", JsonConvert.SerializeObject(BetasToRequest)));
 }
        /*
         * Here be dragons.
         */
        public static async Task <EResult> DownloadFilesFromDepot(DepotProcessor.ManifestJob job, DepotManifest depotManifest)
        {
            var filesRegex    = Files[job.DepotID];
            var files         = depotManifest.Files.Where(x => filesRegex.IsMatch(x.FileName.Replace('\\', '/'))).ToList();
            var downloadState = EResult.Fail;

            ConcurrentDictionary <string, ExistingFileData> existingFileData;

            await using (var db = await Database.GetConnectionAsync())
            {
                var data = db.ExecuteScalar <string>("SELECT `Value` FROM `LocalConfig` WHERE `ConfigKey` = @Key", new { Key = $"depot.{job.DepotID}" });

                if (data != null)
                {
                    existingFileData = JsonConvert.DeserializeObject <ConcurrentDictionary <string, ExistingFileData> >(data);
                }
                else
                {
                    existingFileData = new ConcurrentDictionary <string, ExistingFileData>();
                }
            }

            foreach (var file in existingFileData.Keys.Except(files.Select(x => x.FileName)))
            {
                Log.WriteWarn(nameof(FileDownloader), $"\"{file}\" no longer exists in manifest");
            }

            Log.WriteInfo($"FileDownloader {job.DepotID}", $"Will download {files.Count} files");

            var downloadedFiles = 0;
            var fileTasks       = new Task[files.Count];

            for (var i = 0; i < fileTasks.Length; i++)
            {
                var file = files[i];
                fileTasks[i] = TaskManager.Run(async() =>
                {
                    var existingFile = existingFileData.GetOrAdd(file.FileName, _ => new ExistingFileData());
                    EResult fileState;

                    try
                    {
                        await ChunkDownloadingSemaphore.WaitAsync().ConfigureAwait(false);

                        fileState = await DownloadFile(job, file, existingFile);
                    }
                    finally
                    {
                        ChunkDownloadingSemaphore.Release();
                    }

                    if (fileState == EResult.OK || fileState == EResult.SameAsPreviousValue)
                    {
                        existingFile.FileHash = file.FileHash;

                        downloadedFiles++;
                    }

                    if (fileState != EResult.SameAsPreviousValue)
                    {
                        // Do not write progress info to log file
                        Console.WriteLine($"{job.DepotName} [{downloadedFiles / (float) files.Count * 100.0f,6:#00.00}%] {files.Count - downloadedFiles} files left to download");
                    }

                    if (downloadState == EResult.DataCorruption)
                    {
                        return;
                    }

                    if (fileState == EResult.OK || fileState == EResult.DataCorruption)
                    {
                        downloadState = fileState;
                    }
                });
            }

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

            await LocalConfig.Update($"depot.{job.DepotID}", JsonConvert.SerializeObject(existingFileData));

            job.Result = downloadState switch
            {
                EResult.OK => EResult.OK,
                EResult.DataCorruption => EResult.DataCorruption,
                _ => EResult.Ignored
            };

            return(job.Result);
        }