Пример #1
0
        void OnProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            if (callback.ResponsePending)
            {
                return;
            }

            var req = GetRequest(r => r.JobID == callback.JobID);

            if (req == null)
            {
                return;
            }

            bool isUnknownPackage = callback.UnknownPackages.Contains(req.PackageID) || !callback.Packages.ContainsKey(req.PackageID);

            if (isUnknownPackage)
            {
                IRC.Instance.Send(req.Channel, "{0}: Unable to request package info for {1}: unknown PackageID", req.Requester.Nickname, req.PackageID);
                return;
            }

            var packageInfo = callback.Packages[req.PackageID];
            var kv          = packageInfo.KeyValues.Children
                              .FirstOrDefault(); // sigh, inconsistencies

            var path   = Path.Combine("packageinfo", string.Format("{0}.vdf", req.PackageID));
            var fsPath = Path.Combine(Settings.Current.WebPath, path);


            var webUri = new Uri(new Uri(Settings.Current.WebURL), path);

            try
            {
                kv.SaveToFile(fsPath, false);
            }
            catch (IOException ex)
            {
                IRC.Instance.Send(req.Channel, "{0}: Unable to save package info for {1} to web path!", req.Requester.Nickname, req.PackageID);
                Log.WriteError("PackageInfoCommand", "Unable to save package info for {0} to web path: {1}", req.PackageID, ex);

                return;
            }

            IRC.Instance.Send(req.Channel, "{0}: {1} {2}", req.Requester.Nickname, webUri, packageInfo.MissingToken ? "(requires token)" : "");
        }
Пример #2
0
        public static async Task HandleMetadataInfo(SteamApps.PICSProductInfoCallback callback)
        {
            var apps = new List <uint>();
            var subs = new List <uint>();

            await using var db = await Database.GetConnectionAsync();

            if (callback.Apps.Any())
            {
                Log.WriteDebug(nameof(FullUpdateProcessor), $"Received metadata only product info for {callback.Apps.Count} apps ({callback.Apps.First().Key}...{callback.Apps.Last().Key}), job: {callback.JobID}");

                var currentChangeNumbers = (await db.QueryAsync <(uint, uint)>(
                                                "SELECT `AppID`, `Value` FROM `AppsInfo` WHERE `Key` = @ChangeNumberKey AND `AppID` IN @Apps",
                                                new
                {
                    ChangeNumberKey = KeyNameCache.GetAppKeyID("root_changenumber"),
                    Apps = callback.Apps.Keys
                }
                                                )).ToDictionary(x => x.Item1, x => x.Item2);

                foreach (var app in callback.Apps.Values)
                {
                    currentChangeNumbers.TryGetValue(app.ID, out var currentChangeNumber);

                    if (currentChangeNumber == app.ChangeNumber)
                    {
                        continue;
                    }

                    Log.WriteInfo(nameof(FullUpdateProcessor), $"App {app.ID} - Change: {currentChangeNumber} -> {app.ChangeNumber}");
                    apps.Add(app.ID);

                    if (!Settings.IsFullRun)
                    {
                        await db.ExecuteAsync("INSERT INTO `Changelists` (`ChangeID`) VALUES (@ChangeNumber) ON DUPLICATE KEY UPDATE `Date` = `Date`", new { app.ChangeNumber });

                        await db.ExecuteAsync("INSERT INTO `ChangelistsApps` (`ChangeID`, `AppID`) VALUES (@ChangeNumber, @AppID) ON DUPLICATE KEY UPDATE `AppID` = `AppID`", new { AppID = app.ID, app.ChangeNumber });
                    }
                }
            }

            if (callback.Packages.Any())
            {
                Log.WriteDebug(nameof(FullUpdateProcessor), $"Received metadata only product info for {callback.Packages.Count} packages ({callback.Packages.First().Key}...{callback.Packages.Last().Key}), job: {callback.JobID}");

                var currentChangeNumbers = (await db.QueryAsync <(uint, uint)>(
                                                "SELECT `SubID`, `Value` FROM `SubsInfo` WHERE `Key` = @ChangeNumberKey AND `SubID` IN @Subs",
                                                new
                {
                    ChangeNumberKey = KeyNameCache.GetSubKeyID("root_changenumber"),
                    Subs = callback.Packages.Keys
                }
                                                )).ToDictionary(x => x.Item1, x => x.Item2);

                foreach (var sub in callback.Packages.Values)
                {
                    currentChangeNumbers.TryGetValue(sub.ID, out var currentChangeNumber);

                    if (currentChangeNumber == sub.ChangeNumber)
                    {
                        continue;
                    }

                    Log.WriteInfo(nameof(FullUpdateProcessor), $"Package {sub.ID} - Change: {currentChangeNumber} -> {sub.ChangeNumber}");
                    subs.Add(sub.ID);

                    if (!Settings.IsFullRun)
                    {
                        await db.ExecuteAsync("INSERT INTO `Changelists` (`ChangeID`) VALUES (@ChangeNumber) ON DUPLICATE KEY UPDATE `Date` = `Date`", new { sub.ChangeNumber });

                        await db.ExecuteAsync("INSERT INTO `ChangelistsSubs` (`ChangeID`, `SubID`) VALUES (@ChangeNumber, @SubID) ON DUPLICATE KEY UPDATE `SubID` = `SubID`", new { SubID = sub.ID, sub.ChangeNumber });
                    }
                }
            }

            if (apps.Any() || subs.Any())
            {
                JobManager.AddJob(
                    () => Steam.Instance.Apps.PICSGetAccessTokens(apps, subs),
                    new PICSTokens.RequestedTokens
                {
                    Apps     = apps,
                    Packages = subs,
                });
            }
        }
Пример #3
0
        private static void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            JobManager.TryRemoveJob(callback.JobID);

            var processors = new List <BaseProcessor>(
                callback.Apps.Count +
                callback.Packages.Count +
                callback.UnknownApps.Count +
                callback.UnknownPackages.Count
                );

            processors.AddRange(callback.Apps.Select(app => new AppProcessor(app.Key, app.Value)));
            processors.AddRange(callback.Packages.Select(package => new SubProcessor(package.Key, package.Value)));
            processors.AddRange(callback.UnknownApps.Select(app => new AppProcessor(app, null)));
            processors.AddRange(callback.UnknownPackages.Select(package => new SubProcessor(package, null)));

            foreach (var workaround in processors)
            {
                var processor = workaround;

                Task mostRecentItem;

                lock (CurrentlyProcessing)
                {
                    CurrentlyProcessing.TryGetValue(processor.Id, out mostRecentItem);
                }

                var workerItem = TaskManager.Run(async() =>
                {
                    try
                    {
                        await Semaphore.WaitAsync(TaskManager.TaskCancellationToken.Token).ConfigureAwait(false);

                        if (mostRecentItem?.IsCompleted == false)
                        {
                            Log.WriteDebug(processor.ToString(), $"Waiting for previous task to finish processing ({CurrentlyProcessing.Count})");

                            await mostRecentItem.ConfigureAwait(false);

#if DEBUG
                            Log.WriteDebug(processor.ToString(), "Previous task lock ended");
#endif
                        }

                        await processor.Process().ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        ErrorReporter.Notify(processor.ToString(), e);
                    }
                    finally
                    {
                        Semaphore.Release();

                        processor.Dispose();
                    }

                    return(processor);
                }).Unwrap();

                lock (CurrentlyProcessing)
                {
                    CurrentlyProcessing[processor.Id] = workerItem;
                }

                // Register error handler on inner task and the continuation
                TaskManager.RegisterErrorHandler(workerItem);
                TaskManager.RegisterErrorHandler(workerItem.ContinueWith(RemoveProcessorLock, TaskManager.TaskCancellationToken.Token));
            }
        }
Пример #4
0
        private async void OnLoggedOn(SteamUser.LoggedOnCallback callback)
        {
            if (callback.Result != EResult.OK)
            {
                if (callback.Result == EResult.AccountLogonDenied)
                {
                    // if we recieve AccountLogonDenied or one of it's flavors (AccountLogonDeniedNoMailSent, etc)
                    // then the account we're logging into is SteamGuard protected
                    // see sample 5 for how SteamGuard can be handled

                    _logger.LogWarning("Unable to logon to Steam: This account is SteamGuard protected.");
                    return;
                }

                _logger.LogError("Unable to logon to Steam: {0} / {1}", callback.Result, callback.ExtendedResult);

                return;
            }

            // in this sample, we'll simply do a few async requests to acquire information about appid 440 (Team Fortress 2)

            // first, we'll request a depot decryption key for TF2's client/server shared depot (441)
            var depotJob = steamApps.GetDepotDecryptionKey(depotid: 441, appid: 440);

            // at this point, this request is now in-flight to the steam server, so we'll use te async/await pattern to wait for a response
            // the await pattern allows this code to resume once the Steam servers have replied to the request.
            // if Steam does not reply to the request in a timely fashion (controlled by the `Timeout` field on the AsyncJob object), the underlying
            // task for this job will be cancelled, and TaskCanceledException will be thrown.
            // additionally, if Steam encounters a remote failure and is unable to process your request, the job will be faulted and an AsyncJobFailedException
            // will be thrown.
            SteamApps.DepotKeyCallback depotKey = await depotJob;

            if (depotKey.Result == EResult.OK)
            {
                _logger.LogDebug($"Got our depot key: {BitConverter.ToString(depotKey.DepotKey)}");
            }
            else
            {
                _logger.LogDebug("Unable to request depot key!");
            }

            // now request some product info for TF2
            var productJob = steamApps.PICSGetProductInfo(440, package: null);

            // note that with some requests, Steam can return multiple results, so these jobs don't return the callback object directly, but rather
            // a result set that could contain multiple callback objects if Steam gives us multiple results
            AsyncJobMultiple <SteamApps.PICSProductInfoCallback> .ResultSet resultSet = await productJob;

            if (resultSet.Complete)
            {
                // the request fully completed, we can handle the data
                SteamApps.PICSProductInfoCallback productInfo = resultSet.Results.First();

                // ... do something with our product info
            }
            else if (resultSet.Failed)
            {
                // the request partially completed, and then Steam encountered a remote failure. for async jobs with only a single result (such as
                // GetDepotDecryptionKey), this would normally throw an AsyncJobFailedException. but since Steam had given us a partial set of callbacks
                // we get to decide what to do with the data

                // keep in mind that if Steam immediately fails to provide any data, or times out while waiting for the first result, an
                // AsyncJobFailedException or TaskCanceledException will be thrown

                // the result set might not have our data, so we need to test to see if we have results for our request
                SteamApps.PICSProductInfoCallback productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(440));

                if (productInfo != null)
                {
                    // we were lucky and Steam gave us the info we requested before failing
                }
                else
                {
                    // bad luck
                }
            }
            else
            {
                // the request partially completed, but then we timed out. essentially the same as the previous case, but Steam didn't explicitly fail.

                // we still need to check our result set to see if we have our data
                SteamApps.PICSProductInfoCallback productInfo = resultSet.Results.FirstOrDefault(prodCallback => prodCallback.Apps.ContainsKey(440));

                if (productInfo != null)
                {
                    // we were lucky and Steam gave us the info we requested before timing out
                }
                else
                {
                    // bad luck
                }
            }

            // lastly, if you're unable to use the async/await pattern (older VS/compiler, etc) you can still directly access the TPL Task associated
            // with the async job by calling `ToTask()`
            var depotTask = steamApps.GetDepotDecryptionKey(depotid: 441, appid: 440).ToTask();

            // set up a continuation for when this task completes
            var ignored = depotTask.ContinueWith(task =>
            {
                depotKey = task.Result;

                // do something with the depot key

                // we're finished with this sample, drop out of the callback loop
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
        }
Пример #5
0
        public void OnProductInfo(IRCRequest request, SteamApps.PICSProductInfoCallback callback)
        {
            if (request.Type == SteamProxy.IRCRequestType.TYPE_SUB)
            {
                if (!callback.Packages.ContainsKey(request.Target))
                {
                    CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Unknown SubID: {3}{4}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, Colors.OLIVE, request.Target);

                    return;
                }

                var    info = callback.Packages[request.Target];
                var    kv   = info.KeyValues.Children.FirstOrDefault(); // Blame VoiDeD
                string name = string.Format("SubID {0}", info.ID);

                if (kv["name"].Value != null)
                {
                    name = kv["name"].AsString();
                }

                try
                {
                    kv.SaveToFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sub", string.Format("{0}.vdf", info.ID)), false);
                }
                catch (Exception e)
                {
                    CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Unable to save file for {3}: {4}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, name, e.Message);

                    return;
                }

                CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Dump for {3}{4}{5} -{6} {7}{8}{9}",
                                              Colors.OLIVE, request.Command.Nickname, Colors.NORMAL,
                                              Colors.OLIVE, name, Colors.NORMAL,
                                              Colors.DARK_BLUE, SteamDB.GetRawPackageURL(info.ID), Colors.NORMAL,
                                              info.MissingToken ? " (missing token)" : string.Empty
                                              );
            }
            else if (request.Type == SteamProxy.IRCRequestType.TYPE_APP)
            {
                if (!callback.Apps.ContainsKey(request.Target))
                {
                    CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Unknown AppID: {3}{4}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, Colors.OLIVE, request.Target);

                    return;
                }

                var    info = callback.Apps[request.Target];
                string name = string.Format("AppID {0}", info.ID);

                if (info.KeyValues["common"]["name"].Value != null)
                {
                    name = info.KeyValues["common"]["name"].AsString();
                }

                try
                {
                    info.KeyValues.SaveToFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "app", string.Format("{0}.vdf", info.ID)), false);
                }
                catch (Exception e)
                {
                    CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Unable to save file for {3}: {4}", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL, name, e.Message);

                    return;
                }

                CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: Dump for {3}{4}{5} -{6} {7}{8}{9}",
                                              Colors.OLIVE, request.Command.Nickname, Colors.NORMAL,
                                              Colors.OLIVE, name, Colors.NORMAL,
                                              Colors.DARK_BLUE, SteamDB.GetRawAppURL(info.ID), Colors.NORMAL,
                                              info.MissingToken ? " (missing token)" : string.Empty
                                              );
            }
            else
            {
                CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2}: I have no idea what happened here!", Colors.OLIVE, request.Command.Nickname, Colors.NORMAL);
            }
        }
Пример #6
0
        private static void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            var apps     = callback.Apps.Concat(callback.UnknownApps.ToDictionary(x => x, x => (SteamApps.PICSProductInfoCallback.PICSProductInfo)null));
            var packages = callback.Packages.Concat(callback.UnknownPackages.ToDictionary(x => x, x => (SteamApps.PICSProductInfoCallback.PICSProductInfo)null));

            foreach (var workaround in apps)
            {
                var app = workaround;

                Log.WriteInfo("PICSProductInfo", "{0}AppID: {1}", app.Value == null ? "Unknown " : "", app.Key);

                Task mostRecentItem;

                lock (ProcessedApps)
                {
                    ProcessedApps.TryGetValue(app.Key, out mostRecentItem);
                }

                var workerItem = TaskManager.Run(async delegate
                {
                    if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                    {
                        Log.WriteDebug("PICSProductInfo", "Waiting for app {0} to finish processing", app.Key);

                        await mostRecentItem;
                    }

                    using (var processor = new AppProcessor(app.Key))
                    {
                        if (app.Value == null)
                        {
                            processor.ProcessUnknown();
                        }
                        else
                        {
                            processor.Process(app.Value);
                        }
                    }
                });

                if (Settings.IsFullRun)
                {
                    continue;
                }


                lock (ProcessedApps)
                {
                    ProcessedApps[app.Key] = workerItem;
                }

                workerItem.ContinueWith(task =>
                {
                    lock (ProcessedApps)
                    {
                        if (ProcessedApps.TryGetValue(app.Key, out mostRecentItem) && mostRecentItem.IsCompleted)
                        {
                            ProcessedApps.Remove(app.Key);
                        }
                    }
                });
            }

            foreach (var workaround in packages)
            {
                var package = workaround;

                Log.WriteInfo("PICSProductInfo", "{0}SubID: {1}", package.Value == null ? "Unknown " : "", package.Key);

                Task mostRecentItem;

                lock (ProcessedSubs)
                {
                    ProcessedSubs.TryGetValue(package.Key, out mostRecentItem);
                }

                var workerItem = TaskManager.Run(async delegate
                {
                    if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                    {
                        Log.WriteDebug("PICSProductInfo", "Waiting for package {0} to finish processing", package.Key);

                        await mostRecentItem;
                    }

                    using (var processor = new SubProcessor(package.Key))
                    {
                        if (package.Value == null)
                        {
                            processor.ProcessUnknown();
                        }
                        else
                        {
                            processor.Process(package.Value);
                        }
                    }
                });

                if (Settings.IsFullRun)
                {
                    continue;
                }

                lock (ProcessedSubs)
                {
                    ProcessedSubs[package.Key] = workerItem;
                }

                workerItem.ContinueWith(task =>
                {
                    lock (ProcessedSubs)
                    {
                        if (ProcessedSubs.TryGetValue(package.Key, out mostRecentItem) && mostRecentItem.IsCompleted)
                        {
                            ProcessedSubs.Remove(package.Key);
                        }
                    }
                });
            }
        }
Пример #7
0
        private static void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            JobManager.TryRemoveJob(callback.JobID);

            var processors = new List <BaseProcessor>(
                callback.Apps.Count +
                callback.Packages.Count +
                callback.UnknownApps.Count +
                callback.UnknownPackages.Count
                );

            processors.AddRange(callback.Apps.Select(app => new AppProcessor(app.Key, app.Value)));
            processors.AddRange(callback.Packages.Select(package => new SubProcessor(package.Key, package.Value)));
            processors.AddRange(callback.UnknownApps.Select(app => new AppProcessor(app, null)));
            processors.AddRange(callback.UnknownPackages.Select(package => new SubProcessor(package, null)));

            foreach (var workaround in processors)
            {
                var processor = workaround;

                Task mostRecentItem;

                lock (CurrentlyProcessing)
                {
                    CurrentlyProcessing.TryGetValue(processor.Id, out mostRecentItem);
                }

                var workerItem = TaskManager.Run(async() =>
                {
                    await Semaphore.WaitAsync(TaskManager.TaskCancellationToken.Token).ConfigureAwait(false);

                    try
                    {
                        if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                        {
                            Log.WriteDebug("PICSProductInfo", "Waiting for {0} to finish processing", processor.ToString());

                            await mostRecentItem.ConfigureAwait(false);
                        }

                        await processor.Process().ConfigureAwait(false);
                    }
                    finally
                    {
                        Semaphore.Release();

                        processor.Dispose();
                    }
                }).Unwrap();

                lock (CurrentlyProcessing)
                {
                    CurrentlyProcessing[processor.Id] = workerItem;
                }

                workerItem.ContinueWith(task =>
                {
                    lock (CurrentlyProcessing)
                    {
                        if (CurrentlyProcessing.TryGetValue(processor.Id, out mostRecentItem) && mostRecentItem.IsCompleted)
                        {
                            CurrentlyProcessing.Remove(processor.Id);
                        }
                    }
                }, TaskManager.TaskCancellationToken.Token);
            }
        }
Пример #8
0
        private static void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            JobManager.TryRemoveJob(callback.JobID);

            var apps     = callback.Apps.Concat(callback.UnknownApps.ToDictionary(x => x, x => (SteamApps.PICSProductInfoCallback.PICSProductInfo)null));
            var packages = callback.Packages.Concat(callback.UnknownPackages.ToDictionary(x => x, x => (SteamApps.PICSProductInfoCallback.PICSProductInfo)null));

            foreach (var workaround in apps)
            {
                var app = workaround;

                Log.WriteInfo("PICSProductInfo", "{0}AppID: {1}", app.Value == null ? "Unknown " : "", app.Key);

                IWorkItemResult mostRecentItem;

                lock (ProcessedApps)
                {
                    ProcessedApps.TryGetValue(app.Key, out mostRecentItem);
                }

                var workerItem = ProcessorThreadPool.QueueWorkItem(delegate
                {
                    try
                    {
                        if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                        {
                            Log.WriteDebug("PICSProductInfo", "Waiting for app {0} to finish processing", app.Key);

                            SmartThreadPool.WaitAll(new IWaitableResult[] { mostRecentItem });
                        }

                        using (var processor = new AppProcessor(app.Key))
                        {
                            if (app.Value == null)
                            {
                                processor.ProcessUnknown();
                            }
                            else
                            {
                                processor.Process(app.Value);
                            }
                        }
                    }
                    catch (MySqlException e)
                    {
                        Log.WriteError("PICSProductInfo", "App {0} faulted: {1}", app.Key, e);

                        JobManager.AddJob(() => Steam.Instance.Apps.PICSGetAccessTokens(app.Key, null));
                    }
                    catch (Exception e)
                    {
                        Log.WriteError("PICSProductInfo", "App {0} faulted: {1}", app.Key, e);
                    }
                    finally
                    {
                        lock (ProcessedApps)
                        {
                            if (ProcessedApps.TryGetValue(app.Key, out mostRecentItem) && mostRecentItem.IsCompleted)
                            {
                                ProcessedApps.Remove(app.Key);
                            }
                        }
                    }
                });

                if (Settings.IsFullRun)
                {
                    continue;
                }

                lock (ProcessedApps)
                {
                    ProcessedApps[app.Key] = workerItem;
                }
            }

            foreach (var workaround in packages)
            {
                var package = workaround;

                Log.WriteInfo("PICSProductInfo", "{0}SubID: {1}", package.Value == null ? "Unknown " : "", package.Key);

                IWorkItemResult mostRecentItem;

                lock (ProcessedSubs)
                {
                    ProcessedSubs.TryGetValue(package.Key, out mostRecentItem);
                }

                var workerItem = ProcessorThreadPool.QueueWorkItem(delegate
                {
                    try
                    {
                        if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                        {
                            Log.WriteDebug("PICSProductInfo", "Waiting for package {0} to finish processing", package.Key);

                            SmartThreadPool.WaitAll(new IWaitableResult[] { mostRecentItem });
                        }

                        using (var processor = new SubProcessor(package.Key))
                        {
                            if (package.Value == null)
                            {
                                processor.ProcessUnknown();
                            }
                            else
                            {
                                processor.Process(package.Value);
                            }
                        }
                    }
                    catch (MySqlException e)
                    {
                        Log.WriteError("PICSProductInfo", "Package {0} faulted: {1}", package.Key, e);

                        JobManager.AddJob(() => Steam.Instance.Apps.PICSGetProductInfo(null, package.Key, false, false));
                    }
                    catch (Exception e)
                    {
                        Log.WriteError("PICSProductInfo", "Package {0} faulted: {1}", package.Key, e);
                    }
                    finally
                    {
                        lock (ProcessedSubs)
                        {
                            if (ProcessedSubs.TryGetValue(package.Key, out mostRecentItem) && mostRecentItem.IsCompleted)
                            {
                                ProcessedSubs.Remove(package.Key);
                            }
                        }
                    }
                });

                if (Settings.IsFullRun)
                {
                    continue;
                }

                lock (ProcessedSubs)
                {
                    ProcessedSubs[package.Key] = workerItem;
                }
            }
        }
Пример #9
0
        private static void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            JobManager.TryRemoveJob(callback.JobID);

            var apps     = callback.Apps.Concat(callback.UnknownApps.ToDictionary(x => x, x => (SteamApps.PICSProductInfoCallback.PICSProductInfo)null));
            var packages = callback.Packages.Concat(callback.UnknownPackages.ToDictionary(x => x, x => (SteamApps.PICSProductInfoCallback.PICSProductInfo)null));

            foreach (var workaround in apps)
            {
                var app = workaround;

                Log.WriteInfo("PICSProductInfo", "{0}AppID: {1}", app.Value == null ? "Unknown " : "", app.Key);

                Task mostRecentItem;

                lock (ProcessedApps)
                {
                    ProcessedApps.TryGetValue(app.Key, out mostRecentItem);
                }

                var workerItem = TaskManager.Run(async() =>
                {
                    try
                    {
                        await ProcessorSemaphore.WaitAsync().ConfigureAwait(false);

                        if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                        {
                            Log.WriteDebug("PICSProductInfo", "Waiting for app {0} to finish processing", app.Key);

                            await mostRecentItem.ConfigureAwait(false);
                        }

                        using (var processor = new AppProcessor(app.Key))
                        {
                            if (app.Value == null)
                            {
                                processor.ProcessUnknown();
                            }
                            else
                            {
                                processor.Process(app.Value);
                            }
                        }
                    }
                    catch (MySqlException e)
                    {
                        ErrorReporter.Notify($"App {app.Key}", e);

                        JobManager.AddJob(() => Steam.Instance.Apps.PICSGetAccessTokens(app.Key, null));
                    }
                    catch (Exception e)
                    {
                        ErrorReporter.Notify($"App {app.Key}", e);
                    }
                    finally
                    {
                        lock (ProcessedApps)
                        {
                            if (ProcessedApps.TryGetValue(app.Key, out mostRecentItem) && mostRecentItem.IsCompleted)
                            {
                                ProcessedApps.Remove(app.Key);
                            }
                        }

                        ProcessorSemaphore.Release();
                    }
                });

                if (Settings.IsFullRun)
                {
                    continue;
                }

                lock (ProcessedApps)
                {
                    ProcessedApps[app.Key] = workerItem;
                }
            }

            foreach (var workaround in packages)
            {
                var package = workaround;

                Log.WriteInfo("PICSProductInfo", "{0}SubID: {1}", package.Value == null ? "Unknown " : "", package.Key);

                Task mostRecentItem;

                lock (ProcessedSubs)
                {
                    ProcessedSubs.TryGetValue(package.Key, out mostRecentItem);
                }

                var workerItem = TaskManager.Run(async() =>
                {
                    try
                    {
                        await ProcessorSemaphore.WaitAsync().ConfigureAwait(false);

                        if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                        {
                            Log.WriteDebug("PICSProductInfo", "Waiting for package {0} to finish processing", package.Key);

                            await mostRecentItem.ConfigureAwait(false);
                        }

                        using (var processor = new SubProcessor(package.Key))
                        {
                            if (package.Value == null)
                            {
                                processor.ProcessUnknown();
                            }
                            else
                            {
                                processor.Process(package.Value);
                            }
                        }
                    }
                    catch (MySqlException e)
                    {
                        ErrorReporter.Notify($"Package {package.Key}", e);

                        JobManager.AddJob(() => Steam.Instance.Apps.PICSGetProductInfo(null, package.Key, false, false));
                    }
                    catch (Exception e)
                    {
                        ErrorReporter.Notify($"Package {package.Key}", e);
                    }
                    finally
                    {
                        lock (ProcessedSubs)
                        {
                            if (ProcessedSubs.TryGetValue(package.Key, out mostRecentItem) && mostRecentItem.IsCompleted)
                            {
                                ProcessedSubs.Remove(package.Key);
                            }
                        }

                        ProcessorSemaphore.Release();
                    }
                });

                if (Settings.IsFullRun)
                {
                    continue;
                }

                lock (ProcessedSubs)
                {
                    ProcessedSubs[package.Key] = workerItem;
                }
            }
        }
Пример #10
0
        private void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback, JobID jobID)
        {
            var request = SteamProxy.Instance.IRCRequests.Find(r => r.JobID == jobID);

            if (request != null)
            {
                SteamProxy.Instance.IRCRequests.Remove(request);

                SecondaryPool.QueueWorkItem(SteamProxy.Instance.OnProductInfo, request, callback);

                return;
            }

            foreach (var app in callback.Apps)
            {
                Log.WriteInfo("Steam", "AppID: {0}", app.Key);

                var workaround = app;

                IWorkItemResult mostRecentItem;
                ProcessedApps.TryGetValue(workaround.Key, out mostRecentItem);

                var workerItem = ProcessorPool.QueueWorkItem(delegate
                {
                    if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                    {
                        Log.WriteDebug("Steam", "Waiting for app {0} to finish processing", workaround.Key);

                        SmartThreadPool.WaitAll(new IWaitableResult[] { mostRecentItem });
                    }

                    new AppProcessor(workaround.Key).Process(workaround.Value);
                });

                ProcessedApps.AddOrUpdate(app.Key, workerItem, (key, oldValue) => workerItem);
            }

            foreach (var package in callback.Packages)
            {
                Log.WriteInfo("Steam", "SubID: {0}", package.Key);

                var workaround = package;

                IWorkItemResult mostRecentItem;
                ProcessedSubs.TryGetValue(workaround.Key, out mostRecentItem);

                var workerItem = ProcessorPool.QueueWorkItem(delegate
                {
                    if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                    {
                        Log.WriteDebug("Steam", "Waiting for package {0} to finish processing", workaround.Key);

                        SmartThreadPool.WaitAll(new IWaitableResult[] { mostRecentItem });
                    }

                    new SubProcessor(workaround.Key).Process(workaround.Value);
                });

                ProcessedSubs.AddOrUpdate(package.Key, workerItem, (key, oldValue) => workerItem);
            }

            foreach (uint app in callback.UnknownApps)
            {
                Log.WriteInfo("Steam", "Unknown AppID: {0}", app);

                uint workaround = app;

                IWorkItemResult mostRecentItem;
                ProcessedApps.TryGetValue(workaround, out mostRecentItem);

                var workerItem = ProcessorPool.QueueWorkItem(delegate
                {
                    if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                    {
                        Log.WriteDebug("Steam", "Waiting for app {0} to finish processing (unknown)", workaround);

                        SmartThreadPool.WaitAll(new IWaitableResult[] { mostRecentItem });
                    }

                    new AppProcessor(workaround).ProcessUnknown();
                });

                ProcessedApps.AddOrUpdate(app, workerItem, (key, oldValue) => workerItem);
            }

            foreach (uint package in callback.UnknownPackages)
            {
                Log.WriteInfo("Steam", "Unknown SubID: {0}", package);

                uint workaround = package;

                IWorkItemResult mostRecentItem;
                ProcessedSubs.TryGetValue(workaround, out mostRecentItem);

                var workerItem = ProcessorPool.QueueWorkItem(delegate
                {
                    if (mostRecentItem != null && !mostRecentItem.IsCompleted)
                    {
                        Log.WriteDebug("Steam", "Waiting for package {0} to finish processing (unknown)", workaround);

                        SmartThreadPool.WaitAll(new IWaitableResult[] { mostRecentItem });
                    }

                    new SubProcessor(workaround).ProcessUnknown();
                });

                ProcessedSubs.AddOrUpdate(package, workerItem, (key, oldValue) => workerItem);
            }
        }
Пример #11
0
        private static void OnPICSProductInfo(SteamApps.PICSProductInfoCallback callback)
        {
            JobAction job;

            if (!JobManager.TryRemoveJob(callback.JobID, out job) || !job.IsCommand)
            {
                return;
            }

            var request = job.CommandRequest;

            if (request.Type == JobManager.IRCRequestType.TYPE_SUB)
            {
                if (!callback.Packages.ContainsKey(request.Target))
                {
                    CommandHandler.ReplyToCommand(request.Command, "Unknown SubID: {0}{1}{2}", Colors.BLUE, request.Target, LicenseList.OwnedSubs.ContainsKey(request.Target) ? SteamDB.StringCheckmark : string.Empty);

                    return;
                }

                var    info = callback.Packages[request.Target];
                var    kv   = info.KeyValues.Children.FirstOrDefault();
                string name;

                if (kv["name"].Value != null)
                {
                    name = Utils.RemoveControlCharacters(kv["name"].AsString());
                }
                else
                {
                    name = Steam.GetPackageName(info.ID);
                }

                try
                {
                    kv.SaveToFile(Path.Combine(Application.Path, "sub", string.Format("{0}.vdf", info.ID)), false);
                }
                catch (Exception e)
                {
                    CommandHandler.ReplyToCommand(request.Command, "Unable to save file for {0}: {1}", name, e.Message);

                    return;
                }

                CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2} -{3} {4}{5} - Dump:{6} {7}{8}{9}{10}",
                                              Colors.BLUE, name, Colors.NORMAL,
                                              Colors.DARKBLUE, SteamDB.GetPackageURL(info.ID), Colors.NORMAL,
                                              Colors.DARKBLUE, SteamDB.GetRawPackageURL(info.ID), Colors.NORMAL,
                                              info.MissingToken ? SteamDB.StringNeedToken : string.Empty,
                                              LicenseList.OwnedSubs.ContainsKey(info.ID) ? SteamDB.StringCheckmark : string.Empty
                                              );
            }
            else if (request.Type == JobManager.IRCRequestType.TYPE_APP)
            {
                if (!callback.Apps.ContainsKey(request.Target))
                {
                    CommandHandler.ReplyToCommand(request.Command, "Unknown AppID: {0}{1}{2}", Colors.BLUE, request.Target, LicenseList.OwnedApps.ContainsKey(request.Target) ? SteamDB.StringCheckmark : string.Empty);

                    return;
                }

                var    info = callback.Apps[request.Target];
                string name;

                if (info.KeyValues["common"]["name"].Value != null)
                {
                    name = Utils.RemoveControlCharacters(info.KeyValues["common"]["name"].AsString());
                }
                else
                {
                    name = Steam.GetAppName(info.ID);
                }

                try
                {
                    info.KeyValues.SaveToFile(Path.Combine(Application.Path, "app", string.Format("{0}.vdf", info.ID)), false);
                }
                catch (Exception e)
                {
                    CommandHandler.ReplyToCommand(request.Command, "Unable to save file for {0}: {1}", name, e.Message);

                    return;
                }

                CommandHandler.ReplyToCommand(request.Command, "{0}{1}{2} -{3} {4}{5} - Dump:{6} {7}{8}{9}{10}",
                                              Colors.BLUE, name, Colors.NORMAL,
                                              Colors.DARKBLUE, SteamDB.GetAppURL(info.ID), Colors.NORMAL,
                                              Colors.DARKBLUE, SteamDB.GetRawAppURL(info.ID), Colors.NORMAL,
                                              info.MissingToken ? SteamDB.StringNeedToken : string.Empty,
                                              LicenseList.OwnedApps.ContainsKey(info.ID) ? SteamDB.StringCheckmark : string.Empty
                                              );
            }
            else
            {
                CommandHandler.ReplyToCommand(request.Command, "I have no idea what happened here!");
            }
        }