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; }
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; }
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; }