Example #1
0
        public void IsEnabledReturnsTrueForAllLevelsTest(LogLevel logLevel)
        {
            var name = Guid.NewGuid().ToString();

            var client = Substitute.For <IRavenClient>();

            var sut = new SentryLogger(name, client);

            var actual = sut.IsEnabled(logLevel);

            actual.Should().BeTrue();
        }
Example #2
0
        /// <summary>
        ///     Shows the form and ends the program after an exception makes it to the top level.
        /// </summary>
        /// <param name="e">The unhandled exception.</param>
        private static void HandleUnhandledException(Exception e)
        {
            Logger.Exception("Fatal Error: ", e);
            SentryLogger.Log(e);

            using (FatalErrorDialog dialog = new FatalErrorDialog(e))
            {
                dialog.ShowDialog();
            }

            Application.Exit();
        }
Example #3
0
        public void LogSendsTypeReflectionLoadExceptionWithAdditionalContentTest()
        {
            var name     = Guid.NewGuid().ToString();
            var sentryId = Guid.NewGuid().ToString();
            var eventId  = new EventId(Environment.TickCount);
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString("N")
            };
            var first          = Model.Ignoring <ValueTypeException>(x => x.Data).Create <ValueTypeException>();
            var second         = Model.Ignoring <WithNestedClassException>(x => x.Data).Create <WithNestedClassException>();
            var innerException = new ReflectionTypeLoadException(
                new[]
            {
                typeof(string),
                typeof(int)
            },
                new Exception[]
            {
                first,
                second
            });
            var exception = new AggregateException(Guid.NewGuid().ToString(), innerException);

            exception.AddContextData(state.Address);

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.Log(LogLevel.Critical, eventId, state, exception, (logState, ex) => ex.ToString());

            client.Received().Capture(
                Arg.Is <SentryEvent>(
                    x => x.Exception.Data["ReflectionTypeLoadException.Types"].As <string>()
                    .Contains(innerException.Types[0].AssemblyQualifiedName)));
            client.Received().Capture(
                Arg.Is <SentryEvent>(
                    x => x.Exception.Data["ReflectionTypeLoadException.Types"].As <string>()
                    .Contains(innerException.Types[1].AssemblyQualifiedName)));
            client.Received().Capture(
                Arg.Is <SentryEvent>(
                    x => x.Exception.Data["ReflectionTypeLoadException.LoaderExceptions"].As <string>()
                    .Contains(innerException.LoaderExceptions[0].GetType().Name)));
            client.Received().Capture(
                Arg.Is <SentryEvent>(
                    x => x.Exception.Data["ReflectionTypeLoadException.LoaderExceptions"].As <string>()
                    .Contains(innerException.LoaderExceptions[1].GetType().Name)));
        }
Example #4
0
        public static Dictionary <int, AppInfo> LoadApps(string path)
        {
            Dictionary <int, AppInfo>      appInfos = new Dictionary <int, AppInfo>();
            Dictionary <uint, AppInfoNode> appInfoNodes;

            try
            {
                /*
                 * string currentHash = Utility.CalculateMD5(path);
                 *
                 * if (!File.Exists(Location.File.AppInfoCache) || !File.Exists(Location.File.AppInfoHash) || (File.ReadAllText(Location.File.AppInfoHash) != currentHash))
                 * {
                 */
                appInfoNodes = new AppInfoReader(path).Items;

                /*
                 *      File.WriteAllText(Location.File.AppInfoCache, JsonConvert.SerializeObject(appInfoNodes));
                 *      File.WriteAllText(Location.File.AppInfoHash, currentHash);
                 * }
                 * else
                 * {
                 *      appInfoNodes = JsonConvert.DeserializeObject<Dictionary<uint, AppInfoNode>>(File.ReadAllText(Location.File.AppInfoCache));
                 * }
                 */
            }
            catch (Exception e)
            {
                SentryLogger.Log(e);
                throw;
            }

            try
            {
                foreach (AppInfoNode appInfoNode in appInfoNodes.Values)
                {
                    AppInfo appInfo = FromNode(appInfoNode);
                    if (appInfo != null)
                    {
                        appInfos.Add(appInfo.AppId, appInfo);
                    }
                }
            }
            catch (Exception e)
            {
                SentryLogger.Log(e);
                throw;
            }

            return(appInfos);
        }
Example #5
0
        public void LogDoesNotSendEntryToSentryWhenExceptionIsNullTest()
        {
            var name    = Guid.NewGuid().ToString();
            var eventId = new EventId(Environment.TickCount);
            var state   = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };

            var client = Substitute.For <IRavenClient>();

            var sut = new SentryLogger(name, client);

            sut.Log(LogLevel.Critical, eventId, state, null, (logState, ex) => ex.ToString());

            client.DidNotReceive().Capture(Arg.Any <SentryEvent>());
        }
Example #6
0
        public void BeginScopeReturnsInstanceTest()
        {
            var state = DateTimeOffset.UtcNow;
            var name  = Guid.NewGuid().ToString();

            var client = Substitute.For <IRavenClient>();

            var sut = new SentryLogger(name, client);

            var actual = sut.BeginScope(state);

            actual.Should().NotBeNull();

            Action action = () => actual.Dispose();

            action.Should().NotThrow();
        }
        private async Task <bool> upload(List <Model.HttpDataModel.ClippingItemRequest> clippingItemRequests)
        {
            if (clippingItemRequests.Count == 0)
            {
                return(true);
            }

            var clippingsAPI = new Repository.Clippings();

            try {
                clippingsAPI.UplodClippings(clippingItemRequests);
                return(true);
            } catch (Exception err) {
                SentryLogger.Log(err);
                return(false);
            }
        }
Example #8
0
        public void LogSendsExceptionToSentryTest(LogLevel logLevel)
        {
            var name     = Guid.NewGuid().ToString();
            var sentryId = Guid.NewGuid().ToString();
            var eventId  = new EventId(Environment.TickCount);
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };
            var exception     = new TimeoutException(Guid.NewGuid().ToString());
            var expectedLevel = ErrorLevel.Debug;

            if (logLevel == LogLevel.Critical)
            {
                expectedLevel = ErrorLevel.Fatal;
            }
            else if (logLevel == LogLevel.Information)
            {
                expectedLevel = ErrorLevel.Info;
            }
            else if (Enum.IsDefined(typeof(ErrorLevel), logLevel.ToString()))
            {
                expectedLevel = (ErrorLevel)Enum.Parse(typeof(ErrorLevel), logLevel.ToString());
            }

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.Log(logLevel, eventId, state, exception, (logState, ex) => ex.ToString());

            client.Received(1).Capture(Arg.Any <SentryEvent>());
            client.Received().Capture(Arg.Is <SentryEvent>(x => x.Level == expectedLevel));
            client.Received().Capture(Arg.Is <SentryEvent>(x => x.Exception == exception));
            client.Received().Capture(Arg.Is <SentryEvent>(x => x.Message == exception.Message));
            client.Logger.Should().Be(name);
            client.Received().Capture(Arg.Is <SentryEvent>(x => x.Exception.Data["ContextData"] == null));
            client.Received().Capture(Arg.Is <SentryEvent>(x => x.Exception.Data["AsyncException"] == null));
            client.Received().Capture(Arg.Is <SentryEvent>(x => x.Exception.Data["StorageException"] == null));
        }
Example #9
0
        public XmlDocument FetchAppListFromWeb()
        {
            XmlDocument document = new XmlDocument();

            lock (Games)
            {
                Logger.Instance.Info("Downloading Steam app list");

                Stream responseStream = null;
                try
                {
                    WebRequest req = WebRequest.Create(@"http://api.steampowered.com/ISteamApps/GetAppList/v0002/?format=xml");
                    using (WebResponse resp = req.GetResponse())
                    {
                        responseStream = resp.GetResponseStream();
                        if (responseStream == null)
                        {
                            return(document);
                        }

                        document.Load(responseStream);
                    }
                }
                catch (Exception e)
                {
                    SentryLogger.Log(e);
                    throw;
                }
                finally
                {
                    if (responseStream != null)
                    {
                        responseStream.Dispose();
                    }
                }

                Logger.Instance.Info("XML App list downloaded");
            }

            return(document);
        }
Example #10
0
        private void Load(Storage storage)
        {
            _dependencies.Cache(BeatmapManager = new BeatmapManager());
            _dependencies.Cache(UserManager    = new UserManager());

            _dependencies.Cache(BeatmapMirrorAccess = new BeatmapMirrorAccess());

            _dependencies.Cache(QsorDbContextFactory = new QsorDbContextFactory(storage));
            _dependencies.Cache(ConfigManager        = new QsorConfigManager(storage));

            _dependencies.Cache(NotificationOverlay = new NotificationOverlay());

            _dependencies.Cache(SentryLogger = new SentryLogger(this));

            _dependencies.Cache(DiscordManager = new DiscordManager());

            _dependencies.CacheAs(this);
            _dependencies.CacheAs(Host);

            AddInternal(DiscordManager);

            Resources.AddStore(new NamespacedResourceStore <byte[]>(new DllResourceStore(typeof(QsorGame).Assembly), @"Resources"));

            QsorDbContextFactory.Get().Migrate();

            AddInternal(BeatmapManager);
            AddInternal(NotificationOverlay);

            Updater ??= new DummyUpdater();

            UpdaterOverlay = new UpdaterOverlay();

            _dependencies.Cache(UpdaterOverlay);
            _dependencies.CacheAs(Updater);

            LoadComponent(Updater);

            ConfigManager.Save();

            AddInternal(SettingsOverlay = new SettingsOverlay());
        }
Example #11
0
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();

            //CreateHostBuilder(args).Build().Run();
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var context = services.GetRequiredService <DataContext>();
                    context.Database.Migrate();
                }
                catch (Exception ex)
                {
                    var Logger = services.GetRequiredService <ILogger <Program> >();
                    Logger.LogError(ex, "Error!!! An error occured during Migration- Please Look into DB Contexts` ");
                    SentryLogger.LogtoSentry("Test event for Information", LogEventLevel.Error, ex);
                }
                host.Run();
            }
        }
Example #12
0
        public void LogDoesNotIncludeNullNestedTypeInExceptionDataTest()
        {
            var name     = Guid.NewGuid().ToString();
            var sentryId = Guid.NewGuid().ToString();
            var eventId  = new EventId(Environment.TickCount);
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };
            var exception = Model.Ignoring <WithNestedClassException>(x => x.Data).Create <WithNestedClassException>()
                            .Set(x => x.State = null);

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.Log(LogLevel.Critical, eventId, state, exception, (logState, ex) => ex.ToString());

            client.Received().Capture(
                Arg.Is <SentryEvent>(x => x.Exception.Data.Contains("WithNestedClassException.State") == false));
        }
Example #13
0
        public void LogSendsSkipsNullPropertyWhenExtractingAdditionalDataTest()
        {
            var name     = Guid.NewGuid().ToString();
            var sentryId = Guid.NewGuid().ToString();
            var eventId  = new EventId(Environment.TickCount);
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };
            var exception = new EmptyException();

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.Log(LogLevel.Critical, eventId, state, exception, (logState, ex) => ex.ToString());

            client.Received(1).Capture(Arg.Any <SentryEvent>());
            client.Received().Capture(
                Arg.Is <SentryEvent>(x => x.Exception.Data.Contains("EmptyException.Company") == false));
        }
Example #14
0
        public void LogDoesNotIncludeCustomStringDataWithoutValueTest(string value)
        {
            var sentryId = Guid.NewGuid().ToString();
            var name     = Guid.NewGuid().ToString();
            var eventId  = new EventId(Environment.TickCount);
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };
            var exception = Model.Ignoring <ValueTypeException>(x => x.Data).Create <ValueTypeException>()
                            .Set(x => x.Id = value);

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.Log(LogLevel.Critical, eventId, state, exception, (logState, ex) => ex.ToString());

            client.Received().Capture(
                Arg.Is <SentryEvent>(x => x.Exception.Data.Contains("ValueTypeException.Id") == false));
        }
Example #15
0
        public void LogSendsExceptionToSentryOnlyIfNotAlreadySentTest()
        {
            var sentryId = Guid.NewGuid().ToString();
            var name     = Guid.NewGuid().ToString();
            var eventId  = new EventId(Environment.TickCount);
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };
            var exception = new TimeoutException(Guid.NewGuid().ToString());

            exception.AddContextData(state.Address);

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.Log(LogLevel.Critical, eventId, state, exception, (logState, ex) => ex.ToString());
            sut.Log(LogLevel.Critical, eventId, state, exception, (logState, ex) => ex.ToString());

            client.Received(1).Capture(Arg.Any <SentryEvent>());
        }
Example #16
0
        public void LogSendsToSentryWithoutNullFormattedMessageTest()
        {
            var name     = Guid.NewGuid().ToString();
            var sentryId = Guid.NewGuid().ToString();
            var state    = new AddressState
            {
                Address = Guid.NewGuid().ToString()
            };
            var exception = new TimeoutException(Guid.NewGuid().ToString());

            exception.AddContextData(state.Address);

            var client = Substitute.For <IRavenClient>();

            client.Capture(Arg.Any <SentryEvent>()).Returns(sentryId);

            var sut = new SentryLogger(name, client);

            sut.LogError(exception, null);

            client.Received(1).Capture(Arg.Any <SentryEvent>());
            client.Received().Capture(
                Arg.Is <SentryEvent>(x => x.Exception.Data.Contains("FormattedMessage") == false));
        }
Example #17
0
        public static AppInfo FromNode(AppInfoNode node)
        {
            if (node == null)
            {
                return(null);
            }

            if (!node.Items.ContainsKey("appinfo") || !node["appinfo"].Items.ContainsKey("common") || !node["appinfo"]["common"].Items.ContainsKey("gameid"))
            {
                return(null);
            }

            AppInfoNode dataNode = node["appinfo"]["common"];

            string gameIdNode = dataNode["gameid"].Value;

            if (!int.TryParse(gameIdNode, out int appId))
            {
                return(null);
            }

            AppInfo appInfo = new AppInfo(appId);

            if (dataNode.Items.ContainsKey("name"))
            {
                appInfo.Name = dataNode["name"].Value;
            }

            if (dataNode.Items.ContainsKey("type"))
            {
                string typeData = dataNode["type"].Value;
                if (Enum.TryParse(typeData, true, out AppType type))
                {
                    appInfo.AppType = type;
                }
                else
                {
                    SentryLogger.Log(new DataException(string.Format(CultureInfo.InvariantCulture, "New AppType '{0}'", typeData)));
                }
            }

            if (dataNode.Items.ContainsKey("oslist"))
            {
                string osList = dataNode["oslist"].Value;
                if (osList.IndexOf("windows", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    appInfo.Platforms |= AppPlatforms.Windows;
                }

                if (osList.IndexOf("mac", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    appInfo.Platforms |= AppPlatforms.Mac;
                }

                if (osList.IndexOf("linux", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    appInfo.Platforms |= AppPlatforms.Linux;
                }
            }

            if (!dataNode.Items.ContainsKey("parent"))
            {
                return(appInfo);
            }

            string parentNode = dataNode["parent"].Value;

            if (int.TryParse(parentNode, out int parentId))
            {
                appInfo.ParentId = parentId;
            }

            return(appInfo);
        }
Example #18
0
        private bool Save(string path)
        {
            lock (Games)
            {
                Logger.Instance.Info("Database: Saving current instance to '{0}'", path);

                XmlWriter writer = null;
                Stream    stream = null;
                try
                {
                    stream = new FileStream(path, FileMode.Create);
                    stream = new GZipStream(stream, CompressionMode.Compress);

                    XmlWriterSettings settings = new XmlWriterSettings
                    {
                        Indent      = true,
                        CloseOutput = true
                    };

                    writer = XmlWriter.Create(stream, settings);

                    writer.WriteStartDocument();
                    writer.WriteStartElement(XmlName_RootNode);

                    writer.WriteElementString(XmlName_LastHltbUpdate, LastHLTBUpdate.ToString(CultureInfo.InvariantCulture));
                    writer.WriteElementString(XmlName_dbLanguage, Enum.GetName(typeof(StoreLanguage), Language));

                    writer.WriteStartElement(XmlName_Games);
                    XmlSerializer           xmlSerializer = new XmlSerializer(typeof(DatabaseEntry));
                    XmlSerializerNamespaces nameSpace     = new XmlSerializerNamespaces();
                    nameSpace.Add("", "");
                    foreach (DatabaseEntry entry in Games.Values)
                    {
                        xmlSerializer.Serialize(writer, entry, nameSpace);
                    }

                    writer.WriteEndElement();

                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }
                catch (Exception e)
                {
                    Logger.Instance.Error("Database: Error while trying to save current instance to '{0}'", path);
                    SentryLogger.Log(e);
                    throw;
                }
                finally
                {
                    if (writer != null)
                    {
                        writer.Dispose();
                    }

                    if (stream != null)
                    {
                        stream.Dispose();
                    }
                }

                Logger.Instance.Info("Database: Saved current instance to '{0}'", path);
            }

            return(true);
        }
Example #19
0
        private void Load(string path)
        {
            lock (Games)
            {
                if (!File.Exists(path))
                {
                    return;
                }

                Logger.Instance.Info("Database: Loading a database instance from '{0}'", path);

                XmlDocument document = new XmlDocument();

                Stream stream = null;
                try
                {
                    stream = new FileStream(path, FileMode.Open);
                    stream = new GZipStream(stream, CompressionMode.Decompress);
                    document.Load(stream);
                }
                catch (Exception e)
                {
                    Logger.Instance.Error("Database: Error while reading database file from '{0}'", path);
                    SentryLogger.Log(e);
                    throw;
                }
                finally
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }
                }

                try
                {
                    Games.Clear();

                    XmlNode gameListNode = document.SelectSingleNode("/" + XmlName_RootNode);
                    if (gameListNode == null)
                    {
                        throw new InvalidDataException();
                    }

                    Language       = (StoreLanguage)Enum.Parse(typeof(StoreLanguage), XmlUtil.GetStringFromNode(gameListNode[XmlName_dbLanguage], "english"), true);
                    LastHLTBUpdate = XmlUtil.GetIntFromNode(gameListNode[XmlName_LastHltbUpdate], 0);

                    XmlNode dictonaryNode = gameListNode.SelectSingleNode(XmlName_Games);
                    if (dictonaryNode == null)
                    {
                        throw new InvalidDataException();
                    }

                    XmlSerializer xmlSerializer = new XmlSerializer(typeof(DatabaseEntry));
                    foreach (XmlNode appNode in dictonaryNode.ChildNodes)
                    {
                        using (XmlReader reader = new XmlNodeReader(appNode))
                        {
                            DatabaseEntry entry = (DatabaseEntry)xmlSerializer.Deserialize(reader);
                            AddOrUpdate(entry);
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Instance.Error("Database: Error while parsing database file from '{0}'", path);
                    SentryLogger.Log(e);
                    throw;
                }

                Logger.Instance.Info("Database: Loaded current instance from '{0}'", path);
            }
        }
Example #20
0
        public void ScrapeStore()
        {
            Logger.Instance.Verbose("Scraping {0}: Initializing store scraping for Id: {0}", Id);

            string page;
            int    redirectTarget = -1;

            HttpWebResponse resp           = null;
            Stream          responseStream = null;

            try
            {
                string storePage = string.Format(CultureInfo.InvariantCulture, "http://store.steampowered.com/app/{0}/?l={1}", Id, Settings.Instance.StoreLanguage).ToLowerInvariant();

                HttpWebRequest req = GetSteamRequest(storePage);
                resp = (HttpWebResponse)req.GetResponse();

                int count = 0;
                while ((resp.StatusCode == HttpStatusCode.Found) && (count < 5))
                {
                    resp.Close();

                    // Check if we were redirected to the Steam Store front page
                    if (resp.Headers[HttpResponseHeader.Location] == @"http://store.steampowered.com/")
                    {
                        Logger.Instance.Verbose("Scraping {0}: Redirected to main store page, aborting scraping", Id);
                        return;
                    }

                    // Check if we were redirected to the same page
                    if (resp.ResponseUri.ToString() == resp.Headers[HttpResponseHeader.Location])
                    {
                        Logger.Instance.Verbose("Scraping {0}: Store page redirected to itself, aborting scraping", Id);
                        return;
                    }

                    req  = GetSteamRequest(resp.Headers[HttpResponseHeader.Location]);
                    resp = (HttpWebResponse)req.GetResponse();
                    count++;
                }

                // Check if we were redirected too many times
                if ((count == 5) && (resp.StatusCode == HttpStatusCode.Found))
                {
                    Logger.Instance.Verbose("Scraping {0}: Too many redirects, aborting scraping", Id);
                    return;
                }

                // Check if we were redirected to the Steam Store front page
                if (resp.ResponseUri.Segments.Length < 2)
                {
                    Logger.Instance.Verbose("Scraping {0}: Redirected to main store page, aborting scraping", Id);
                    return;
                }

                // Check if we were redirected outside of the app route
                if (resp.ResponseUri.Segments[1] != "app/")
                {
                    Logger.Instance.Verbose("Scraping {0}: Redirected outside the app (app/) route, aborting scraping", Id);
                    return;
                }

                // The URI ends with "/app/" ?
                if (resp.ResponseUri.Segments.Length < 3)
                {
                    Logger.Instance.Verbose("Scraping {0}: Response URI ends with 'app' thus missing ID found, aborting scraping", Id);
                    return;
                }

                // Check if we encountered an age gate, cookies should bypass this, but sometimes they don't seem to
                if (resp.ResponseUri.Segments[1] == "agecheck/")
                {
                    // Encountered an age check with no redirect
                    if ((resp.ResponseUri.Segments.Length < 4) || (resp.ResponseUri.Segments[3].TrimEnd('/') == Id.ToString(CultureInfo.InvariantCulture)))
                    {
                        Logger.Instance.Verbose("Scraping {0}: Encounterd an age check without redirect, aborting scraping", Id);
                        return;
                    }

                    // Age check + redirect
                    Logger.Instance.Verbose("Scraping {0}: Hit age check for Id: {1}", Id, resp.ResponseUri.Segments[3].TrimEnd('/'));

                    // Check if we encountered an age gate without a numeric id
                    if (!int.TryParse(resp.ResponseUri.Segments[3].TrimEnd('/'), out redirectTarget))
                    {
                        return;
                    }
                }

                // Check if we were redirected to a different Id
                else if (resp.ResponseUri.Segments[2].TrimEnd('/') != Id.ToString(CultureInfo.InvariantCulture))
                {
                    // if new app id is an actual number
                    if (!int.TryParse(resp.ResponseUri.Segments[2].TrimEnd('/'), out redirectTarget))
                    {
                        Logger.Instance.Verbose("Scraping {0}: Redirected to an unknown Id ({1}), aborting scraping", Id, resp.ResponseUri.Segments[2].TrimEnd('/'));
                        return;
                    }

                    Logger.Instance.Verbose("Scraping {0}: Redirected to another app Id ({1})", Id, resp.ResponseUri.Segments[2].TrimEnd('/'));
                }

                responseStream = resp.GetResponseStream();
                if (responseStream == null)
                {
                    Logger.Instance.Verbose("Scraping {0}: The response stream was null, aborting scraping", Id);
                    return;
                }

                using (StreamReader streamReader = new StreamReader(responseStream))
                {
                    page = streamReader.ReadToEnd();
                    Logger.Instance.Verbose("Scraping {0}: Page read", Id);
                }
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.Timeout)
                {
                    return;
                }

                throw;
            }
            catch (Exception e)
            {
                SentryLogger.Log(e);
                throw;
            }
            finally
            {
                if (resp != null)
                {
                    resp.Dispose();
                }

                if (responseStream != null)
                {
                    responseStream.Dispose();
                }
            }

            // Check for server-sided errors
            if (page.Contains("<title>Site Error</title>"))
            {
                Logger.Instance.Verbose("Scraping {0}: Received Site Error, aborting scraping", Id);
                return;
            }

            // Double checking if this is an app (Game or Application)
            if (!RegGamecheck.IsMatch(page) && !RegSoftwarecheck.IsMatch(page))
            {
                Logger.Instance.Verbose("Scraping {0}: Could not parse info from page, aborting scraping", Id);
                return;
            }

            LastStoreScrape = Utility.CurrentUnixTime();
            GetAllDataFromPage(page);

            // Set or Update ParentId if we got a redirect target
            if (redirectTarget != -1)
            {
                ParentId = redirectTarget;
            }

            // Check whether it's DLC and return appropriately
            if (RegDlCcheck.IsMatch(page))
            {
                Logger.Instance.Verbose("Scraping {0}: Parsed. DLC. Genre: {1}", Id, string.Join(",", Genres));
                AppType = AppType.DLC;
                return;
            }

            Logger.Instance.Verbose("Scraping {0}: Parsed. Genre: {1}", Id, string.Join(",", Genres));

            if (RegSoftwarecheck.IsMatch(page))
            {
                AppType = AppType.Application;
            }

            if (RegGamecheck.IsMatch(page))
            {
                AppType = AppType.Game;
            }
        }