Inheritance: FavouriteBase
        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<AnimeCharacter>> GetSearchResults()
        {
            var output = new List<AnimeCharacter>();

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

            try
            {
                foreach (var row in doc.DocumentNode.Descendants("table").First().Descendants("tr").Skip(1))
                {
                    try
                    {
                        var character = new AnimeCharacter();
                        var tds = row.Descendants("td").ToList();
                        var link = tds[1].Descendants("a").First();
                        character.Id = link.Attributes["href"].Value.Split('/')[2];
                        character.Name = WebUtility.HtmlDecode(link.InnerText.Trim());
                        var smalls = tds[1].Descendants("small");
                        if (smalls.Any())
                            character.Notes = WebUtility.HtmlDecode(smalls.Last().InnerText);

                        var img = tds[0].Descendants("img").First().Attributes["src"].Value;
                        if (!img.Contains("questionmark"))
                        {
                            img = Regex.Replace(img, @"\/r\/\d+x\d+", "");
                            character.ImgUrl = img.Substring(0, img.IndexOf('?'));
                        }

                        output.Add(character);
                    }
                    catch (Exception)
                    {
                        //
                    }

                    
                }
            }
            catch (Exception)
            {
                //
            }

            return output;
        }
        public async Task<StaffDetailsData> GetStaffDetails(bool force)
        {
            var possibleData = force ? null : await DataCache.RetrieveData<StaffDetailsData>(_id.ToString(), "staff_details", 30);
            if (possibleData != null)
                return possibleData;

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

            output.Id = _id;
            try
            {
                var columns =
                    doc.DocumentNode.Descendants("table").First().ChildNodes[0].ChildNodes.Where(
                        node => node.Name == "td").ToList();
                var leftColumn = columns[0];
                var image = leftColumn.Descendants("img").FirstOrDefault();
                if (image != null && image.Attributes.Contains("alt"))
                    output.ImgUrl = image.Attributes["src"].Value;

                output.Name = WebUtility.HtmlDecode(doc.DocumentNode.Descendants("h1").First().InnerText.Trim());

                bool recording = false;
                var currentString = "";
                int i = 0;
                foreach (var child in leftColumn.ChildNodes)
                {
                    if (!recording)
                    {
                        if (child.Attributes.Contains("class") &&
                            child.Attributes["class"].Value.Trim() == "js-sns-icon-container icon-block")
                            recording = true;
                        else
                            continue;
                    }

                    if (child.Attributes.Contains("class") &&
                        child.Attributes["class"].Value == "spaceit_pad")
                    {
                        output.Details.Add(WebUtility.HtmlDecode(child.InnerText.Trim()));
                        currentString = "";
                        i = 0;
                    }
                    else if (!string.IsNullOrWhiteSpace(child.InnerText))
                    {
                        currentString += WebUtility.HtmlDecode(child.InnerText.Trim()) + " ";
                        i++;
                        if (i == 2)
                        {
                            output.Details.Add(currentString);
                            currentString = "";
                            i = 0;
                        }
                    }

                    if (child.Name == "div" && !child.Attributes.Contains("class"))
                        break;
                }

                foreach (var table in columns[1].Descendants("table").Take(2))
                    try
                    {
                        foreach (var row in table.Descendants("tr"))
                        {

                            var tds = row.Descendants("td").ToList();
                            if (tds.Count == 4)
                            {
                                var current = new ShowCharacterPair();
                                var show = new AnimeLightEntry();
                                var img = tds[0].Descendants("img").First().Attributes["data-src"].Value;
                                if (!img.Contains("questionmark"))
                                {
                                    img = Regex.Replace(img, @"\/r\/\d+x\d+", "");
                                    show.ImgUrl = img.Substring(0, img.IndexOf('?'));
                                }
                                var link = tds[1].Descendants("a").First();
                                show.IsAnime = true;
                                show.Id = int.Parse(link.Attributes["href"].Value.Split('/')[2]);
                                show.Title = WebUtility.HtmlDecode(link.InnerText.Trim());
                                current.AnimeLightEntry = show;

                                var character = new AnimeCharacter();
                                character.FromAnime = true;
                                character.ShowId = show.Id.ToString();
                                link = tds[2].Descendants("a").First();
                                character.Id = link.Attributes["href"].Value.Split('/')[2];
                                character.Name = WebUtility.HtmlDecode(link.InnerText.Trim());
                                character.Notes = WebUtility.HtmlDecode(tds[2].Descendants("div").Last().InnerText);

                                img = tds[3].Descendants("img").First().Attributes["data-src"].Value;
                                if (!img.Contains("questionmark"))
                                {
                                    img = Regex.Replace(img, @"\/r\/\d+x\d+", "");
                                    character.ImgUrl = img.Substring(0, img.IndexOf('?'));
                                }

                                current.AnimeCharacter = character;
                                output.ShowCharacterPairs.Add(current);
                            }
                            else
                            {
                                var show = new AnimeLightEntry();
                                var img = tds[0].Descendants("img").First().Attributes["data-src"].Value;
                                if (!img.Contains("questionmark"))
                                {
                                    img = Regex.Replace(img, @"\/r\/\d+x\d+", "");
                                    show.ImgUrl = img.Substring(0, img.IndexOf('?'));
                                }
                                var link = tds[1].Descendants("a").First();
                                show.IsAnime = !link.Attributes["href"].Value.Contains("/manga/");
                                show.Id = int.Parse(link.Attributes["href"].Value.Split('/')[2]);
                                show.Title = WebUtility.HtmlDecode(link.InnerText.Trim());
                                show.Notes =
                                    WebUtility.HtmlDecode(
                                        tds[1].Descendants("div").Last().InnerText.Replace("add", "").Trim());

                                output.StaffPositions.Add(show);

                            }
                        }
                    }
                    catch
                        (Exception e)
                    {
                        //htaml
                    }
            }
            catch (Exception)
            {
                //sorcery 
            }

            DataCache.SaveData(output, _id.ToString(), "staff_details");

            return output;
        }
Exemple #4
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;
        }
 private async void NavigateCharacterWebPage(AnimeCharacter character)
 {
     ResourceLocator.SystemControlsLauncherService.LaunchUri(new Uri($"https://myanimelist.net/character/{character.Id}"));
 }
 private void NavigateDetails(AnimeCharacter character)
 {
     ViewModelLocator.GeneralMain.Navigate(PageIndex.PageAnimeDetails,
         new AnimeDetailsPageNavigationArgs(int.Parse(character.ShowId), character.Notes, null,
             null)
         {
             Source = PageIndex.PageProfile,
             AnimeMode = character.FromAnime
         });
 }