public async Task<MalMessageModel> GetMessageDetails(MalMessageModel msg)
        {
            try
            {
                var client = await MalHttpContextProvider.GetHttpContextAsync();
                var response = await client.GetAsync($"/mymessages.php?go=read&id={msg.Id}");
                var raw = await response.Content.ReadAsStringAsync();

                var doc = new HtmlDocument();
                doc.LoadHtml(raw);

                var msgNode = doc.FirstOfDescendantsWithClass("td", "dialog-text");
                var msgContent = msgNode.ChildNodes.Skip(3)
                    .Where(node => node.NodeType == HtmlNodeType.Text)
                    .Aggregate("", (current, textNode) => current + textNode.InnerText);

                msg.Content = WebUtility.HtmlDecode(msgContent.Trim());
                var ids =
                    doc.FirstOfDescendantsWithClass("input", "inputButton btn-middle flat").Attributes["onclick"].Value
                        .Split('=');
                msg.ThreadId = ids[4].Substring(0, ids[3].IndexOf('&'));
                msg.ReplyId = ids[3].Substring(0, ids[3].IndexOf('&'));
                return msg;
            }
            catch (WebException)
            {
                MalHttpContextProvider.ErrorMessage("Messages");
            }

            return new MalMessageModel();
        }
        /// <summary>
        ///     When we send new message we don't really know its id so we have to pull it.
        ///     Once we have that we will be able to pull thread id.
        /// </summary>
        public async Task<string> GetFirstSentMessageId()
        {
            try
            {
                var client = await MalHttpContextProvider.GetHttpContextAsync();
                var res = await client.GetAsync("/mymessages.php?go=sent");
                var body = await res.Content.ReadAsStringAsync();

                try
                {
                    var doc = new HtmlDocument();
                    doc.LoadHtml(body);
                    //?go=read&id=8473147&f=1
                    var id =
                        doc.FirstOfDescendantsWithClass("div", "message read spot2 clearfix")
                            .Descendants("a")
                            .Skip(1)
                            .First()
                            .Attributes["href"].Value.Split('=')[2];
                    return id.Substring(0, id.Length - 2);
                }
                catch (Exception)
                {
                    return "0";
                }
            }
            catch (WebException)
            {
                MalHttpContextProvider.ErrorMessage("Messages");
            }
            return "0";
        }
        public async Task<List<AnimeCharacter>> GetMangaCharacters(bool force) //html is malformed
        {
            if (_animeMode)
                throw new InvalidOperationException("You fed constructor with anime, remember?");

            var output = force
                ? new List<AnimeCharacter>()
                : await DataCache.RetrieveData<List<AnimeCharacter>>($"staff_{_animeId}", "MangaDetails", 7) ??
                  new List<AnimeCharacter>();

            var raw = await GetRequestResponse(false);
            if (string.IsNullOrEmpty(raw))
                return null;

            var doc = new HtmlDocument();
            doc.LoadHtml(raw);
            try
            {
                var mainContainer = doc.FirstOfDescendantsWithClass("div", "js-scrollfix-bottom-rel");
                var tables = mainContainer.ChildNodes.Where(node => node.Name == "table").ToList();

                foreach (var table in tables)
                {
                    try
                    {
                        var current = new AnimeCharacter();

                        var imgs = table.Descendants("img").ToList();
                        var infos = table.Descendants("td").ToList();

                        //character
                        var img = imgs[0].Attributes["data-src"].Value;
                        if (!img.Contains("questionmark"))
                        {
                            img = img.Replace("/r/46x64", "");
                            current.ImgUrl = img.Substring(0, img.IndexOf('?'));
                        }

                        current.FromAnime = _animeMode;
                        current.ShowId = _animeId.ToString();
                        current.Name = WebUtility.HtmlDecode(imgs[0].Attributes["alt"].Value.Replace(",", ""));
                        current.Id = infos[0].ChildNodes[1].ChildNodes[0].Attributes["href"].Value.Split('/')[2];
                        current.Notes = ""; //malformed html here TODO: Check if fixed 
                        //table.Descendants("small").First().InnerText;
                        output.Add(current);
                    }
                    catch (Exception)
                    {
                        //
                    }

                }
            }
            catch (Exception)
            {
                //html strikes again
            }
            return output;
        }
        public async Task<List<AnimeVideoData>> GetVideos(bool force)
        {

            var output = force
                ? new List<AnimeVideoData>()
                : await DataCache.RetrieveData<List<AnimeVideoData>>($"videos_{_id}", "AnimeDetails", 7) ??
                  new List<AnimeVideoData>();

            if (output.Any())
                return output;

            var raw = await GetRequestResponse(false);
            if (string.IsNullOrEmpty(raw))
                return output;

            var doc = new HtmlDocument();
            doc.LoadHtml(raw);

            try
            {
                foreach (
                    var video in
                    doc.FirstOfDescendantsWithClass("div", "video-block promotional-video mt16")
                        .WhereOfDescendantsWithClass("div", "video-list-outer po-r pv"))
                {
                    try
                    {
                        var current = new AnimeVideoData();
                        var img = video.Descendants("img").First();
                        current.Thumb = img.Attributes["data-src"].Value;
                        if (current.Thumb.Contains("banned"))
                            continue;
                        var href = video.Descendants("a").First().Attributes["href"].Value;
                        var pos = href.IndexOf('?');
                        href = href.Substring(0, pos);
                        current.YtLink = $"https://www.youtube.com/watch?v={href.Split('/').Last()}";

                        current.Name = WebUtility.HtmlDecode(img.Attributes["data-title"].Value);

                        output.Add(current);
                    }
                    catch (Exception)
                    {
                        //html
                    }

                }
            }
            catch (Exception)
            {
                //no videos
            }

            DataCache.SaveData(output, $"videos_{_id}", "AnimeDetails");

            return output;

        }
        public async Task<List<MalMessageModel>> GetMessagesInThread(MalMessageModel msg)
        {
            try
            {
                var client = await MalHttpContextProvider.GetHttpContextAsync();
                var response = await client.GetAsync($"/mymessages.php?go=read&id={msg.Id}&threadid={msg.ThreadId}");
                var raw = await response.Content.ReadAsStringAsync();

                var doc = new HtmlDocument();
                doc.LoadHtml(raw);

                var output = new List<MalMessageModel>();

                foreach (
                    var msgHistoryNode in
                        doc.FirstOfDescendantsWithClass("table", "pmessage-message-history").Descendants("tr"))
                {
                    var current = new MalMessageModel();
                    var tds = msgHistoryNode.Descendants("td").ToList();
                    current.Content = WebUtility.HtmlDecode(tds[2].InnerText.Trim());
                    if (string.IsNullOrEmpty(current.Content))
                        continue;


                    current.Subject = msg.Subject;
                    current.Date = tds[0].InnerText.Trim();
                    current.Sender = tds[1].InnerText.Trim();
                    output.Add(current);
                }


                return output;
            }
            catch (Exception)
            {
                MalHttpContextProvider.ErrorMessage("Messages");
            }

            return new List<MalMessageModel>();

        }
        public async Task<string> GetArticleHtml()
        {
            var possibleData = await DataCache.RetrieveArticleContentData(_title, _type);
            if (possibleData != null)
                return possibleData;
            var raw = await GetRequestResponse();
            if (string.IsNullOrEmpty(raw))
                return null;
            var doc = new HtmlDocument();
            doc.LoadHtml(raw);
            string htmlData;
            try
            {
                htmlData = doc.FirstOfDescendantsWithClass("div", "news-container").OuterHtml;
                DataCache.SaveArticleContentData(_title, htmlData, _type);
            }
            catch (Exception)
            {
                htmlData = "Something went wrong";
            }

            return htmlData;
        }
        public async Task<List<SeasonalAnimeData>> GetSeasonalAnime(bool force = false)
        {
            var output = force || DataCache.SeasonalUrls?.Count == 0 //either force or urls are empty after update
                ? new List<SeasonalAnimeData>()
                : await DataCache.RetrieveSeasonalData(_overriden ? _season.Name : "") ?? new List<SeasonalAnimeData>();
            //current season without suffix
            if (output.Count != 0) return output;
            var raw = await GetRequestResponse();
            if (string.IsNullOrEmpty(raw))
                return output;


            //Get season data - we are getting this only from current season
            try
            {
                var doc = new HtmlDocument();
                doc.LoadHtml(raw);
                var mainNode =
                    doc.DocumentNode.Descendants("div")
                        .First(
                            node =>
                                node.Attributes.Contains("class") &&
                                node.Attributes["class"].Value ==
                                HtmlClassMgr.ClassDefs["#Seasonal:mainNode:class"]);
                if (!_overriden)
                {
                    var seasonInfoNodes = doc.DocumentNode.Descendants("div").First(
                        node =>
                            node.Attributes.Contains("class") &&
                            node.Attributes["class"].Value ==
                            HtmlClassMgr.ClassDefs["#Seasonal:seasonInfo:class"]).Descendants("li").ToList();
                    var seasonData = new Dictionary<string, string>();
                    for (var j = 1; j <= 4; j++)
                    {
                        try
                        {
                            seasonData.Add(seasonInfoNodes[j].Descendants("a").First().InnerText.Trim(),
                                seasonInfoNodes[j].Descendants("a").First().Attributes["href"].Value);

                            if (seasonInfoNodes[j].Descendants("a").First().Attributes["class"].Value ==
                                HtmlClassMgr.ClassDefs["#Seasonal:seasonInfoCurrent:class"])
                                seasonData.Add("current", j.ToString());
                        }
                        catch (Exception)
                        {
                            //ignored
                        }
                    }
                    DataCache.SaveSeasonalUrls(seasonData);
                }

                //Get anime data
                var nodes = mainNode.ChildNodes.Where(node => node.Name == "div").Take(Settings.SeasonalToPull);
                try
                {
                    //add movies if any
                    nodes =
                        nodes.Concat(
                            doc.FirstOfDescendantsWithClass("div",
                                    "seasonal-anime-list js-seasonal-anime-list js-seasonal-anime-list-key-3 clearfix")
                                .ChildNodes.Where(node => node.Name == "div"));
                }
                catch (Exception e)
                {
                    //no movies or corrupt html
                }

                var i = 0;
                foreach (var htmlNode in nodes)
                {
                    try
                    {
                        var model = ParseFromHtml(htmlNode, i);
                        if(model == null)
                            continue;
                        output.Add(model);
                        i++;
                    }
                    catch (Exception e)
                    {

                    }
                }
            }
            catch (Exception e)
            {
                //sumthing
            }


            DataCache.SaveSeasonalData(output, _overriden ? _season.Name : "");

            //We are done.
            return output;
        }
        public async Task<AnimeStaffData> GetCharStaffData(bool force = false)
        {
            if (!_animeMode)
                throw new InvalidOperationException("Umm you said it's going to be manga...");
            var output = force
                ? new AnimeStaffData()
                : await DataCache.RetrieveData<AnimeStaffData>($"staff_{_animeId}", "AnimeDetails", 7) ??
                  new AnimeStaffData();
            if (output.AnimeCharacterPairs.Count > 0 || output.AnimeStaff.Count > 0) return output;

            var raw = await GetRequestResponse(false);
            if (string.IsNullOrEmpty(raw))
                return null;

            var doc = new HtmlDocument();
            doc.LoadHtml(raw);

            try
            {
                var mainContainer = doc.FirstOfDescendantsWithClass("div", "js-scrollfix-bottom-rel");
                var tables = mainContainer.ChildNodes.Where(node => node.Name == "table").ToList();
                int i = 0;
                foreach (var table in tables.Take(tables.Count - 1))
                {
                    try
                    {
                        var current = new AnimeCharacterStaffModel();

                        var imgs = table.Descendants("img").ToList();
                        var infos = table.Descendants("td").ToList(); //2nd is character 4th is person

                        //character
                        var img = imgs[0].Attributes["data-src"].Value;
                        if (!img.Contains("questionmark"))
                        {
                            img = img.Replace("/r/46x64", "");
                            current.AnimeCharacter.ImgUrl = img.Substring(0, img.IndexOf('?'));
                        }

                        current.AnimeCharacter.FromAnime = _animeMode;
                        current.AnimeCharacter.ShowId = _animeId.ToString();
                        current.AnimeCharacter.Name =
                            WebUtility.HtmlDecode(imgs[0].Attributes["alt"].Value.Replace(",", ""));
                        current.AnimeCharacter.Id = infos[1].ChildNodes[1].Attributes["href"].Value.Split('/')[2];
                        current.AnimeCharacter.Notes = infos[1].ChildNodes[3].InnerText;

                        //voiceactor
                        try
                        {
                            img = imgs[1].Attributes["data-src"].Value;
                            if (!img.Contains("questionmark"))
                            {
                                img = img.Replace("/r/46x64", "");
                                current.AnimeStaffPerson.ImgUrl = img.Substring(0, img.IndexOf('?'));
                            }
                            current.AnimeStaffPerson.Name = WebUtility.HtmlDecode(imgs[1].Attributes["alt"].Value.Replace(",", ""));
                            current.AnimeStaffPerson.Id = infos[3].ChildNodes[1].Attributes["href"].Value.Split('/')[2];
                            current.AnimeStaffPerson.Notes = infos[3].ChildNodes[4].InnerText;
                        }
                        catch (Exception)
                        {
                            //no voice actor
                            current.AnimeStaffPerson.Name = "Unknown";
                            current.AnimeStaffPerson.IsUnknown = true;
                        }


                        output.AnimeCharacterPairs.Add(current);
                        if (i++ > 30)
                            break;
                    }
                    catch (Exception)
                    {
                        //oddities
                    }

                }
                i = 0;
                foreach (var staffRow in tables.Last().Descendants("tr"))
                {
                    try
                    {
                        var current = new AnimeStaffPerson();
                        var imgs = staffRow.Descendants("img").ToList();
                        var info = staffRow.Descendants("td").Last(); //we want last

                        var img = imgs[0].Attributes["data-src"].Value;
                        if (!img.Contains("questionmark"))
                        {
                            img = img.Replace("/r/46x64", "");
                            current.ImgUrl = img.Substring(0, img.IndexOf('?'));
                        }
                        current.Name = WebUtility.HtmlDecode(imgs[0].Attributes["alt"].Value.Replace(",", ""));
                        current.Id = info.ChildNodes[0].Attributes["href"].Value.Split('/')[2];
                        current.Notes = info.ChildNodes[3].InnerText;

                        output.AnimeStaff.Add(current);
                        if (i++ > 30)
                            break;
                    }
                    catch (Exception)
                    {
                        //what can I say?
                    }
                }
            }
            catch (Exception)
            {
                //mysteries of html
            }


            DataCache.SaveData(output,$"staff_{_animeId}","AnimeDetails");

            return output;
        }
        public async Task<AnimeScrappedDetails> GetDetails(bool force)
        {
            var possibleData = force ? null :
                await DataCache.RetrieveData<AnimeScrappedDetails>(_id.ToString(), "anime_details_scrapped", 14);
            if (possibleData != null)
                return possibleData;

            var output = new AnimeScrappedDetails();
            var raw = await GetRequestResponse();
            if (string.IsNullOrEmpty(raw))
                return null;
            var doc = new HtmlDocument();
            doc.LoadHtml(raw);

            output.Id = _id;

            bool recording = false;
            string currentString = "";
            int currentStage = 0;
            try
            {
                foreach (var child in doc.FirstOfDescendantsWithClass("div", "js-scrollfix-bottom").ChildNodes)
                {

                    if (!recording)
                    {
                        if (child.Attributes.Contains("class") &&
                            child.Attributes["class"].Value.Contains("js-sns-icon-container"))
                            recording = true;
                        continue;
                    }
                    if (child.Name == "div" && child.Attributes.Contains("class") && child.Attributes["class"].Value.Contains("mauto"))
                        break;

                    if (child.Name == "h2")
                    {
                        currentStage++;
                        continue;
                    }
                    if (child.Name == "div")
                    {
                        currentString = Regex.Replace(WebUtility.HtmlDecode(child.InnerText.Replace('\n', ' ').Trim()), @"[ ]{2,}", " ");
                        switch (currentStage)
                        {
                            case 1:
                                output.AlternativeTitles.Add(currentString);
                                break;
                            case 2:
                                output.Information.Add(currentString);
                                break;
                            case 3:
                                output.Statistics.Add(currentString);
                                break;
                        }
                    }


                }

                if (_anime)
                {
                    foreach (var row in doc.FirstOfDescendantsWithClass("div", "theme-songs js-theme-songs ending").Descendants("span"))
                    {
                        output.Endings.Add(WebUtility.HtmlDecode(row.InnerText));
                    }
                    foreach (var row in doc.FirstOfDescendantsWithClass("div", "theme-songs js-theme-songs opnening").Descendants("span"))
                    {
                        output.Openings.Add(WebUtility.HtmlDecode(row.InnerText));
                    }
                }
            }
            catch (Exception)
            {
                //hatemeł
            }
            
            DataCache.SaveData(output,_id.ToString(), "anime_details_scrapped");
            return output;
        }
Exemple #10
0
        public async Task<List<MalComment>> GetComments()
        {
            var raw = await (await MalHttpContextProvider.GetHttpContextAsync()).GetAsync($"/profile/{_userName}");
            var doc = new HtmlDocument();
            doc.LoadHtml(await raw.Content.ReadAsStringAsync());
            var output = new List<MalComment>();
            try
            {
                var commentBox = doc.FirstOfDescendantsWithClass("div", "user-comments mt24 pt24");
                foreach (var comment in commentBox.WhereOfDescendantsWithClass("div", "comment clearfix"))
                {
                    var curr = new MalComment();
                    curr.User.ImgUrl = comment.Descendants("img").First().Attributes["src"].Value;
                    var textBlock = comment.Descendants("div").First();
                    var header = textBlock.Descendants("div").First();
                    curr.User.Name = header.ChildNodes[1].InnerText;
                    curr.Date = header.ChildNodes[3].InnerText;
                    curr.Content = WebUtility.HtmlDecode(textBlock.Descendants("div").Skip(1).First().InnerText.Trim());
                    var postActionNodes = comment.WhereOfDescendantsWithClass("a", "ml8");
                    var convNode = postActionNodes.FirstOrDefault(node => node.InnerText.Trim() == "Conversation");
                    if (convNode != null)
                    {
                        curr.ComToCom = WebUtility.HtmlDecode(convNode.Attributes["href"].Value.Split('?').Last());
                    }
                    var deleteNode = postActionNodes.FirstOrDefault(node => node.InnerText.Trim() == "Delete");
                    if(deleteNode != null)
                    {
                        curr.CanDelete = true;
                        curr.Id =
                            deleteNode.Attributes["onclick"].Value.Split(new char[] { '(', ')' },
                                StringSplitOptions.RemoveEmptyEntries).Last();
                    }
                    output.Add(curr);
                }
            }
            catch (Exception)
            {
                //no comments
            }

            await Task.Run( async () =>
            {
                var data = await DataCache.RetrieveProfileData(_userName);
                if (data != null)
                {
                    data.Comments = output;
                }
                DataCache.SaveProfileData(_userName, data);
            });

            return output;
        }
Exemple #11
0
        public async Task<ProfileData> GetProfileData(bool force = false, bool updateFavsOnly = false)
        {
            ProfileData possibleData = null;
            if (!force)
                possibleData = await DataCache.RetrieveProfileData(_userName);
            if (possibleData != null)
                return possibleData;
            var raw = !updateFavsOnly
                ? await (await (await MalHttpContextProvider.GetHttpContextAsync()).GetAsync($"/profile/{_userName}")).Content.ReadAsStringAsync()
                : await GetRequestResponse();
            var doc = new HtmlDocument();
            doc.LoadHtml(raw);
            var current = new ProfileData { User = { Name = _userName } };

            #region Recents
            try
            {
                var i = 1;
                foreach (
                    var recentNode in
                        doc.DocumentNode.Descendants("div")
                            .Where(
                                node =>
                                    node.Attributes.Contains("class") &&
                                    node.Attributes["class"].Value ==
                                    HtmlClassMgr.ClassDefs["#Profile:recentUpdateNode:class"]))
                {
                    if (i <= 3)
                    {
                        current.RecentAnime.Add(
                            int.Parse(
                                recentNode.Descendants("a").First().Attributes["href"].Value.Substring(8).Split('/')[2]));
                    }
                    else
                    {
                        current.RecentManga.Add(
                            int.Parse(
                                recentNode.Descendants("a").First().Attributes["href"].Value.Substring(8).Split('/')[2]));
                    }
                    i++;
                }
            }
            catch (Exception)
            {
                //no recents
            }

            #endregion

            #region FavChar

            try
            {
                foreach (
                    var favCharNode in
                        doc.DocumentNode.Descendants("ul")
                            .First(
                                node =>
                                    node.Attributes.Contains("class") &&
                                    node.Attributes["class"].Value ==
                                    HtmlClassMgr.ClassDefs["#Profile:favCharacterNode:class"])
                            .Descendants("li"))
                {
                    var curr = new AnimeCharacter();
                    var imgNode = favCharNode.Descendants("a").First();
                    var styleString = imgNode.Attributes["style"].Value.Substring(22);
                    curr.ImgUrl = styleString.Replace("/r/80x120", "");
                    curr.ImgUrl = curr.ImgUrl.Substring(0, curr.ImgUrl.IndexOf('?'));
                    var infoNode = favCharNode.Descendants("div").Skip(1).First();
                    var nameNode = infoNode.Descendants("a").First();
                    curr.Name = nameNode.InnerText.Trim();
                    curr.Id = nameNode.Attributes["href"].Value.Substring(9).Split('/')[2];
                    var originNode = infoNode.Descendants("a").Skip(1).First();
                    curr.Notes = originNode.InnerText.Trim();
                    curr.ShowId = originNode.Attributes["href"].Value.Split('/')[2];
                    curr.FromAnime = originNode.Attributes["href"].Value.Split('/')[1] == "anime";
                    current.FavouriteCharacters.Add(curr);
                }
            }
            catch (Exception)
            {
                //no favs
            }

            #endregion

            #region FavManga

            try
            {
                foreach (
                    var favMangaNode in
                        doc.DocumentNode.Descendants("ul")
                            .First(
                                node =>
                                    node.Attributes.Contains("class") &&
                                    node.Attributes["class"].Value ==
                                    HtmlClassMgr.ClassDefs["#Profile:favMangaNode:class"])
                            .Descendants("li"))
                {
                    current.FavouriteManga.Add(
                        int.Parse(
                            favMangaNode.Descendants("a").First().Attributes["href"].Value.Substring(9).Split('/')[2
                                ]));
                }
            }
            catch (Exception)
            {
                //no favs
            }

            #endregion

            #region FavAnime

            try
            {
                foreach (
                    var favAnimeNode in
                        doc.DocumentNode.Descendants("ul")
                            .First(
                                node =>
                                    node.Attributes.Contains("class") &&
                                    node.Attributes["class"].Value ==
                                    HtmlClassMgr.ClassDefs["#Profile:favAnimeNode:class"])
                            .Descendants("li"))
                {
                    current.FavouriteAnime.Add(
                        int.Parse(
                            favAnimeNode.Descendants("a").First().Attributes["href"].Value.Substring(9).Split('/')[2
                                ]));
                }
            }
            catch (Exception)
            {
                //no favs
            }

            #endregion

            #region FavPpl

            try
            {
                foreach (
                    var favPersonNode in
                        doc.DocumentNode.Descendants("ul")
                            .First(
                                node =>
                                    node.Attributes.Contains("class") &&
                                    node.Attributes["class"].Value ==
                                    HtmlClassMgr.ClassDefs["#Profile:favPeopleNode:class"])
                            .Descendants("li"))
                {
                    var curr = new AnimeStaffPerson();
                    var aElems = favPersonNode.Descendants("a");
                    var styleString = aElems.First().Attributes["style"].Value.Substring(22);
                    curr.ImgUrl = styleString.Replace("/r/80x120", "");
                    curr.ImgUrl = curr.ImgUrl.Substring(0, curr.ImgUrl.IndexOf('?'));

                    curr.Name = aElems.Skip(1).First().InnerText.Trim();
                    curr.Id = aElems.Skip(1).First().Attributes["href"].Value.Substring(9).Split('/')[2];

                    current.FavouritePeople.Add(curr);
                }
            }
            catch (Exception)
            {
                //no favs
            }

            #endregion

            #region Stats
            if (!updateFavsOnly)
                try
                {
                    var animeStats = doc.FirstOfDescendantsWithClass("div", "stats anime");
                    var generalStats = animeStats.Descendants("div").First().Descendants("div");
                    current.AnimeDays = float.Parse(generalStats.First().InnerText.Substring(5).Trim());
                    current.AnimeMean = float.Parse(generalStats.Last().InnerText.Substring(11).Trim());
                    var i = 0;

                    #region AnimeStats

                    foreach (
                        var htmlNode in
                            animeStats.FirstOfDescendantsWithClass("ul", "stats-status fl-l").Descendants("li"))
                    {
                        switch (i)
                        {
                            case 0:
                                current.AnimeWatching =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;

                            case 1:
                                current.AnimeCompleted =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                            case 2:
                                current.AnimeOnHold =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                            case 3:
                                current.AnimeDropped =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                            case 4:
                                current.AnimePlanned =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                        }
                        i++;
                    }
                    //left stats done now right
                    i = 0;
                    foreach (
                        var htmlNode in animeStats.FirstOfDescendantsWithClass("ul", "stats-data fl-r").Descendants("li"))
                    {
                        switch (i)
                        {
                            case 0:
                                current.AnimeTotal =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;

                            case 1:
                                current.AnimeRewatched =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;
                            case 2:
                                current.AnimeEpisodes =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;
                        }
                        i++;
                    }
                    //we are done with anime

                    #endregion

                    i = 0;
                    animeStats = doc.FirstOfDescendantsWithClass("div", "stats manga");
                    generalStats = animeStats.Descendants("div").First().Descendants("div");
                    current.MangaDays = float.Parse(generalStats.First().InnerText.Substring(5).Trim());
                    current.MangaMean = float.Parse(generalStats.Last().InnerText.Substring(11).Trim());

                    #region MangaStats

                    foreach (
                        var htmlNode in
                            animeStats.FirstOfDescendantsWithClass("ul", "stats-status fl-l").Descendants("li"))
                    {
                        switch (i)
                        {
                            case 0:
                                current.MangaReading =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;

                            case 1:
                                current.MangaCompleted =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                            case 2:
                                current.MangaOnHold =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                            case 3:
                                current.MangaDropped =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                            case 4:
                                current.MangaPlanned =
                                    int.Parse(htmlNode.Descendants("span").First().InnerText.Trim().Replace(",", ""));
                                break;
                        }
                        i++;
                    }
                    //left stats done now right
                    i = 0;
                    foreach (
                        var htmlNode in animeStats.FirstOfDescendantsWithClass("ul", "stats-data fl-r").Descendants("li"))
                    {
                        switch (i)
                        {
                            case 0:
                                current.MangaTotal =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;

                            case 1:
                                current.MangaReread =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;
                            case 2:
                                current.MangaChapters =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;
                            case 3:
                                current.MangaVolumes =
                                    int.Parse(htmlNode.Descendants("span").Last().InnerText.Trim().Replace(",", ""));
                                break;
                        }
                        i++;
                    }
                    //we are done with manga

                    #endregion
                }
                catch (Exception)
                {
                    //hatml
                }

            #endregion

            #region LeftSideBar
            if (!updateFavsOnly)
                try
                {
                    var sideInfo =
                        doc.FirstOfDescendantsWithClass("ul", "user-status border-top pb8 mb4").Descendants("li").ToList();
                    try
                    {
                        foreach (var htmlNode in sideInfo)
                        {
                            current.Details.Add(new Tuple<string, string>(htmlNode.FirstChild.InnerText, htmlNode.LastChild.InnerText));
                        }
                        //current.LastOnline = sideInfo[0].LastChild.InnerText;
                        //current.Gender = sideInfo[1].LastChild.InnerText;
                        //current.Birthday = sideInfo[2].LastChild.InnerText;
                        //current.Location = sideInfo[3].LastChild.InnerText;
                        //current.Joined = sideInfo[4].LastChild.InnerText;
                    }
                    catch (Exception)
                    {
                        //current.LastOnline = sideInfo[0].LastChild.InnerText;
                        //current.Joined = sideInfo[1].LastChild.InnerText;
                    }
                    current.User.ImgUrl =
                        doc.FirstOfDescendantsWithClass("div", "user-image mb8").Descendants("img").First().Attributes["src"
                            ]
                            .Value;

                }
                catch (Exception)
                {
                    //???
                }

            #endregion

            #region Friends
            if (!updateFavsOnly)
                try
                {
                    var friends = doc.FirstOfDescendantsWithClass("div", "user-friends pt4 pb12").Descendants("a");
                    foreach (var friend in friends)
                    {
                        var curr = new MalUser();
                        var styleString = friend.Attributes["style"].Value.Substring(22);
                        curr.ImgUrl = styleString.Replace("/r/76x120", "");
                        curr.ImgUrl = curr.ImgUrl.Substring(0, curr.ImgUrl.IndexOf('?'));

                        curr.Name = friend.InnerText;
                        current.Friends.Add(curr);
                    }
                }
                catch (Exception)
                {
                    //
                }

            #endregion

            #region Comments
            if (!updateFavsOnly)
                try
                {
                    var commentBox = doc.FirstOfDescendantsWithClass("div", "user-comments mt24 pt24");
                    foreach (var comment in commentBox.WhereOfDescendantsWithClass("div", "comment clearfix"))
                    {
                        var curr = new MalComment();
                        curr.User.ImgUrl = comment.Descendants("img").First().Attributes["src"].Value;
                        var textBlock = comment.Descendants("div").First();
                        var header = textBlock.Descendants("div").First();
                        curr.User.Name = header.ChildNodes[1].InnerText;
                        curr.Date = header.ChildNodes[3].InnerText;
                        curr.Content = WebUtility.HtmlDecode(textBlock.Descendants("div").Skip(1).First().InnerText.Trim());
                        var postActionNodes = comment.WhereOfDescendantsWithClass("a", "ml8");
                        var convNode = postActionNodes.FirstOrDefault(node => node.InnerText.Trim() == "Conversation");
                        if (convNode != null)
                        {
                            curr.ComToCom = WebUtility.HtmlDecode(convNode.Attributes["href"].Value.Split('?').Last());
                        }
                        var deleteNode = postActionNodes.FirstOrDefault(node => node.InnerText.Trim() == "Delete");
                        if(deleteNode != null)
                        {
                            curr.CanDelete = true;
                            curr.Id =
                                deleteNode.Attributes["onclick"].Value.Split(new char[] {'(', ')'},
                                    StringSplitOptions.RemoveEmptyEntries).Last();
                        }
                        current.Comments.Add(curr);
                    }
                }
                catch (Exception e)
                {
                    //no comments
                }

            #endregion

            try
            {
                current.ProfileMemId = doc.DocumentNode.Descendants("input")
                    .First(node => node.Attributes.Contains("name") && node.Attributes["name"].Value == "profileMemId")
                    .Attributes["value"].Value;
            }
            catch (Exception)
            {
                //restricted
            }

            try
            {
                current.HtmlContent = doc.FirstOfDescendantsWithClass("div", "word-break").OuterHtml;
            }
            catch (Exception)
            {
                //
            }


            if (_userName == Credentials.UserName) //umm why do we need someone's favs?
            {
                FavouritesManager.ForceNewSet(FavouriteType.Anime, current.FavouriteAnime.Select(i => i.ToString()).ToList());
                FavouritesManager.ForceNewSet(FavouriteType.Manga, current.FavouriteManga.Select(i => i.ToString()).ToList());
                FavouritesManager.ForceNewSet(FavouriteType.Character, current.FavouriteCharacters.Select(i => i.Id).ToList());
                FavouritesManager.ForceNewSet(FavouriteType.Person, current.FavouritePeople.Select(i => i.Id).ToList());
            }


            if (!updateFavsOnly)
                DataCache.SaveProfileData(_userName, current);

            return current;
        }
        public async Task<ForumBoardContent> GetTopicPosts(int? lastPage,bool force = false)
        {
            if(!force)
                try
                {
                    if (_animeId == 0)
                    {
                        if (_boardCache.ContainsKey(_board) && _boardCache[_board].ContainsKey(_page))
                            return _boardCache[_board][_page];
                    }
                    else
                    {
                        if (_animeBoardCache.ContainsKey(_animeId) && _animeBoardCache[_animeId].ContainsKey(_page))
                            return _animeBoardCache[_animeId][_page];
                    }
                }
                catch (Exception e)
                {
                    //
                }
            else //clear all pages
            {
                if (_animeId == 0)
                {
                    if(_boardCache.ContainsKey(_board))
                        _boardCache[_board] = new Dictionary<int, ForumBoardContent>();
                }
                else
                {
                    if (_animeBoardCache.ContainsKey(_animeId))
                        _animeBoardCache[_animeId] = new Dictionary<int, ForumBoardContent>();
                }
            }



            var output = new ForumBoardContent();
            var raw = await GetRequestResponse();
            if (string.IsNullOrEmpty(raw))
                return new ForumBoardContent();
            var doc = new HtmlDocument();
            doc.LoadHtml(raw);

            try
            {
                try
                {
                    output.Pages = lastPage ??
                                   int.Parse(
                                       doc.FirstOfDescendantsWithClass("span", "di-ib")
                                           .Descendants("a")
                                           .Last()
                                           .Attributes["href"]
                                           .Value.Split('=').Last())/50;
                }
                catch (Exception)
                {
                    output.Pages = 0;
                }


                var topicContainer =
                doc.DocumentNode.Descendants("table")
                    .First(node => node.Attributes.Contains("id") && node.Attributes["id"].Value == "forumTopics");

                foreach (var topicRow in topicContainer.Descendants("tr").Skip(1)) //skip forum table header
                {
                    try
                    {
                        output.ForumTopicEntries.Add(ParseHtmlToTopic(topicRow));
                    }
                    catch (Exception)
                    {
                        //hatml
                    }

                }
            }
            catch (Exception)
            {
                //
            }
            

            if (_animeId == 0)
            {
                if (!_boardCache.ContainsKey(_board))
                    _boardCache[_board] = new Dictionary<int, ForumBoardContent>();
                if (!_boardCache[_board].ContainsKey(_page))
                    _boardCache[_board].Add(_page, output);
                else
                    _boardCache[_board][_page] = output;
            }
            else
            {
                if (!_animeBoardCache.ContainsKey(_animeId))
                    _animeBoardCache[_animeId] = new Dictionary<int, ForumBoardContent>();
                if (!_animeBoardCache[_animeId].ContainsKey(_page))
                    _animeBoardCache[_animeId].Add(_page, output);
                else
                    _animeBoardCache[_animeId][_page] = output;
            }


            return output;
        }