public override void UpdateNameAndStatus(IManga manga) { var localizedName = new MangaName(); try { var document = new HtmlDocument(); document.LoadHtml(Page.GetPage(manga.Uri).Content); var enName = Regex.Match(document.DocumentNode.InnerHtml, @"title>(.*?) »", RegexOptions.IgnoreCase); if (enName.Success) { localizedName.English = WebUtility.HtmlDecode(enName.Groups[1].Value); var regexed = Regex.Escape(localizedName.English); var node = document.DocumentNode.SelectSingleNode("//a[@class='title_top_a']"); var ruName = Regex.Match(node.InnerHtml, $"{regexed} \\((.*?)\\)", RegexOptions.IgnoreCase); if (ruName.Success) { localizedName.Russian = WebUtility.HtmlDecode(ruName.Groups[1].Value); } } } catch (NullReferenceException ex) { Log.Exception(ex); } UpdateName(manga, localizedName.ToString()); }
/// <summary> /// Method for gets chapter information for manga /// </summary> /// <param name="htmlManga">Html manga representation</param> /// <param name="parsedManga">Object manga representation</param> private void GetChapters(IElement htmlManga, IManga parsedManga) { var chapters = new List <IChapter>(); var htmlChapters = htmlManga.QuerySelectorAll(".expandable.chapters-link tbody tr"); foreach (var htmlChapter in htmlChapters) { var htmlChapterInfo = htmlChapter.QuerySelectorAll("td"); if (htmlChapterInfo.Any()) { var chapterUrl = htmlChapterInfo[0].QuerySelector("a")?.GetAttribute("href"); _mangaChaptersRegex.Match(chapterUrl.EmptyStringIfNull()) .GetGroupValue(2, out var volume) .GetGroupValue(3, out var chapter); chapters.Add( new Chapter { Id = chapter, Volume = volume, Name = Regex.Replace(htmlChapterInfo[0].QuerySelector("a")?.TextContent ?? string.Empty, @"\s{2,}", " ").Trim(), Url = $@"{BaseUrl}{chapterUrl}", Date = htmlChapterInfo[1].TextContent.Replace("\n", string.Empty).Replace(" ", string.Empty) }); } } parsedManga.Chapters = chapters; }
/// <summary> /// Method for getting manga volume information /// </summary> /// <param name="htmlManga">Html manga representation</param> /// <param name="parsedManga">Object manga representation</param> private void GetVolume(IElement htmlManga, IManga parsedManga) { if (htmlManga == null) { parsedManga.Volumes = null; return; } var chapter = htmlManga.QuerySelector(".title3"); var textLastVolume = chapter?.TextContent; if (string.IsNullOrEmpty(textLastVolume)) { parsedManga.Volumes = "N/A"; return; } if (textLastVolume.Contains("TBD")) { textLastVolume = "TBD"; } _mangaVolumeRegex.Match(textLastVolume.EmptyStringIfNull()) .GetGroupValue(1, out var lastVolume); parsedManga.Volumes = lastVolume; }
public override async Task UpdateNameAndStatus(IManga manga) { var client = await MangachanPlugin.Instance.GetCookieClient(true).ConfigureAwait(false); var page = await client.GetPage(manga.Uri).ConfigureAwait(false); var localizedName = new MangaName(); try { var document = new HtmlDocument(); document.LoadHtml(page.Content); var enName = Regex.Match(document.DocumentNode.InnerHtml, @"title>(.*?) »", RegexOptions.IgnoreCase); if (enName.Success) { localizedName.English = WebUtility.HtmlDecode(enName.Groups[1].Value); var regexed = Regex.Escape(localizedName.English); var node = document.DocumentNode.SelectSingleNode("//a[@class='title_top_a']"); var ruName = Regex.Match(node.InnerHtml, $"{regexed} \\((.*?)\\)", RegexOptions.IgnoreCase); if (ruName.Success) { localizedName.Russian = WebUtility.HtmlDecode(ruName.Groups[1].Value); } } } catch (NullReferenceException ex) { Log.Exception(ex); } UpdateName(manga, localizedName.ToString()); var status = string.Empty; try { var document = new HtmlDocument(); document.LoadHtml(page.Content); var nodes = document.DocumentNode.SelectNodes("//table[@class=\"mangatitle\"]//tr"); if (nodes != null) { status = nodes.Aggregate(status, (current, node) => current + Regex.Replace(WebUtility.HtmlDecode(node.InnerText).Trim(), @"\s+", " ").Replace("\n", "") + Environment.NewLine); } } catch (NullReferenceException ex) { Log.Exception(ex); } manga.Status = status; var description = string.Empty; try { var document = new HtmlDocument(); document.LoadHtml(page.Content); var node = document.DocumentNode.SelectSingleNode("//div[@id=\"description\"]"); if (node != null) { description = WebUtility.HtmlDecode(node.InnerText).Trim().Replace("Прислать описание", "").TrimEnd(); } } catch (Exception e) { Log.Exception(e); } manga.Description = description; }
/// <summary> /// Создать мангу по ссылке. /// </summary> /// <param name="uri">Ссылка на мангу.</param> /// <returns>Манга.</returns> /// <remarks>Не сохранена в базе, требует заполнения полей.</remarks> public static IManga Create(Uri uri) { IManga manga = null; MangaSetting setting; using (var context = Repository.GetEntityContext()) { setting = context.Get <MangaSetting>().ToList().SingleOrDefault(s => s.MangaSettingUris.Any(u => u.Host == uri.Host)); if (setting != null) { var plugin = ConfigStorage.Plugins.SingleOrDefault(p => Equals(p.GetSettings(), setting)); if (plugin != null) { manga = Activator.CreateInstance(plugin.MangaType) as IManga; if (manga != null) { manga.Created = DateTime.Now; } if (manga is Mangas mangas) { mangas.Setting = setting; } } } } if (manga != null) { var parseResult = manga.Parser.ParseUri(uri); manga.Uri = parseResult.CanBeParsed ? parseResult.MangaUri : uri; } return(manga); }
public void UpdateProperties(IManga manga) { if (manga == null) { return; } this.Id = manga.Id; this.Name = manga.LocalName; this.OriginalName = manga.ServerName; this.Folder = manga.Folder; this.CanChangeName = manga.IsNameChanged; this.NeedCompress = manga.NeedCompress; this.CompressionModes = new List <Compression.CompressionMode>(manga.AllowedCompressionModes); this.CompressionMode = manga.CompressionMode; if (manga.Downloaded > Downloaded) { this.Downloaded = manga.Downloaded; } SetCompletedIcon(manga.IsCompleted); SetType(manga); SetNeedUpdate(manga.NeedUpdate); this.Status = manga.Status; this.SettingsId = manga.Setting.Id; this.Created = manga.Created; this.DownloadedAt = manga.DownloadedAt; }
/// <summary> /// Method for gets published year information for manga /// </summary> /// <param name="informationLine">Html manga information line representation</param> /// <param name="parsedManga">Object manga representation</param> private void GetPublishedYear(IElement informationLine, IManga parsedManga) { if (informationLine.QuerySelector(".elem_year") != null) { parsedManga.Published = int.Parse(informationLine.QuerySelector(".elem_year a")?.TextContent); } }
public static void CreateMangaHistory(IManga manga) { var history = new MangaReader.Core.Manga.MangaHistory(Url); manga.Histories.Add(new MangaReader.Core.Manga.MangaHistory(history.Uri)); manga.Save(); }
public async Task AddMangaToFavorite(IManga manga) { var favoriteList = await BlobCache.UserAccount.GetOrCreateObject("favoriteList", () => new FavoriteHistoryModel() { Favorites = new List <MangaHistoryViewModel>() }); var inFavoriteManga = favoriteList.Favorites.FirstOrDefault(x => x.Url == manga.Url); if (inFavoriteManga != null) { return; } favoriteList.Favorites.Add(new MangaHistoryViewModel() { Url = manga.Url, MangaName = manga.MangaName, ImageUrl = manga.ImageUrl, CountOfChapters = manga.CountOfChapters, Chapters = manga.Chapters.Select(x => new ChapterViewModel() { Url = x.Url, ChapterName = x.ChapterName }) .ToList() }); await BlobCache.UserAccount.InsertObject("favoriteList", favoriteList); }
/// <summary> /// Method for gets translator information for manga /// </summary> /// <param name="informationLine">Html manga information line representation</param> /// <param name="parsedManga">Object manga representation</param> /// <returns>Returns <value>true</value> if action was succeed; otherwise returns <value>false</value>.</returns> private bool GetTranslators(IElement informationLine, IManga parsedManga) { if (informationLine.QuerySelector(".elem_translator") != null) { parsedManga.Translators = informationLine.QuerySelectorAll(".elem_translator a") .Where(x => !string.IsNullOrEmpty(x.TextContent)) .Select(x => { var url = x.GetAttribute("href"); _mangaAuthorTranslatorRegex.Match(url.EmptyStringIfNull()) .GetGroupValue(1, out var id); return(new Translator { Id = id, Name = x.TextContent, Url = $@"{BaseUrl}{url}" }); }); return(true); } return(false); }
/// <summary> /// Method for getting manga chapters information /// </summary> /// <param name="htmlManga">Html manga representation</param> /// <param name="parsedManga">Object manga representation</param> private void GetChapters(IEnumerable <IElement> htmlManga, IManga parsedManga) { if (htmlManga == null) { return; } parsedManga.Chapters = htmlManga .Select(x => { var chapterUrl = x.GetAttribute("href"); _chapterIdRegex.Match(chapterUrl).GetValue(out var id); _chapterVolumeRegex.Match(chapterUrl).GetValue(out var volume); return(new Chapter() { Id = id, Volume = volume, Name = x.GetAttribute("title"), Url = chapterUrl, Date = x.QuerySelector(".title2")?.TextContent }); }); }
private async Task SaveManga(IManga manga) { await _historyService.AddMangaToHistory(manga); // var history = await historyService.GetListOfLastManga(); // Console.WriteLine("kek"); }
/// <summary> /// Получить содержание манги - главы. /// </summary> /// <param name="manga">Манга.</param> public override async Task UpdateContent(IManga manga) { var chapters = new List <ChapterDto>(); try { var document = new HtmlDocument(); document.LoadHtml((await Page.GetPageAsync(manga.Uri).ConfigureAwait(false)).Content); var chapterNodes = document.DocumentNode.SelectNodes("//a[@class=\"pull-left font-w600\"]").Reverse(); foreach (var chapterNode in chapterNodes) { var uri = chapterNode.Attributes.Single(a => a.Name == "href").Value; var text = WebUtility.HtmlDecode(chapterNode.FirstChild.InnerText.Trim()); var number = Regex.Match(text, "^[0-9\\.]+", RegexOptions.Compiled).Value; var parsedNumber = double.Parse(number, NumberStyles.Float, CultureInfo.InvariantCulture); chapters.Add(new ChapterDto(uri, text) { Number = parsedNumber }); } } catch (NullReferenceException ex) { Log.Exception(ex); } FillMangaChapters(manga, chapters); }
/// <summary> /// Обновить название и статус манги. /// </summary> /// <param name="manga">Манга.</param> public override void UpdateNameAndStatus(IManga manga) { try { var document = new HtmlDocument(); document.LoadHtml(Page.GetPage(new Uri(manga.Uri.OriginalString + @"/about"), this.GetAdultClient()).Content); var nameNode = document.DocumentNode.SelectSingleNode("//head//meta[@property=\"og:title\"]"); if (nameNode != null && nameNode.Attributes.Any(a => Equals(a.Name, "content"))) { var name = WebUtility.HtmlDecode(nameNode.Attributes.Single(a => Equals(a.Name, "content")).Value); UpdateName(manga, name); } var content = document.GetElementbyId("contentMargin"); if (content != null) { var summary = string.Empty; var status = WebUtility.HtmlDecode(content.SelectSingleNode(".//h2").InnerText).ToLowerInvariant().Contains("(закончен)"); manga.IsCompleted = status; var nodes = content.SelectNodes(".//div[@class=\"about-summary\"]//p"); summary = nodes.Aggregate(summary, (current, node) => current + Regex.Replace(node.InnerText.Trim(), @"\s+", " ").Replace("\n", "") + Environment.NewLine); summary = WebUtility.HtmlDecode(summary); manga.Status = summary; } } catch (NullReferenceException ex) { Log.Exception(ex); } }
public override void UpdateNameAndStatus(IManga manga) { var name = string.Empty; try { var document = new HtmlDocument(); var page = Page.GetPage(manga.Uri); document.LoadHtml(page.Content); var nameNode = document.DocumentNode.SelectSingleNode("//head/title"); var splitter = "»"; if (nameNode != null && nameNode.InnerText.Contains(splitter)) { var index = nameNode.InnerText.IndexOf(splitter, StringComparison.InvariantCultureIgnoreCase); name = nameNode.InnerText.Substring(0, index); index = name.LastIndexOf('-'); if (index > 0) { var rightPart = name.Substring(index).ToLowerInvariant(); if (rightPart.Contains("глава") || rightPart.Contains("часть")) { name = name.Substring(0, index); } } name = name.Trim(); } } catch (NullReferenceException ex) { Log.Exception(ex); } name = WebUtility.HtmlDecode(name); UpdateName(manga, name); }
public override async Task <IEnumerable <byte[]> > GetPreviews(IManga manga) { byte[] result = null; try { var document = new HtmlDocument(); var client = this.GetClient(); document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/banner"), client).ConfigureAwait(false)).Content); var banners = document.DocumentNode.SelectSingleNode("//div[@class='serial-content']"); var image = banners.ChildNodes.SkipWhile(n => n.InnerText != "160x90").Skip(1).FirstOrDefault(); var src = image.ChildNodes[0].Attributes.Single(a => a.Name == "src").Value; Uri link; if (Uri.IsWellFormedUriString(src, UriKind.Relative)) { link = new Uri(manga.Setting.MainUri, src); } else { link = new Uri(src); } result = client.DownloadData(link); } catch (Exception ex) { Log.Exception(ex); } return(new[] { result }); }
/// <summary> /// Method for gets volume information for manga /// </summary> /// <param name="information">Html manga information representation</param> /// <param name="parsedManga">Object manga representation</param> private void GetVolume(IHtmlCollection <IElement> information, IManga parsedManga) { _mangaVolumeRegex.Match(information[0].TextContent.EmptyStringIfNull()) .GetGroupValue(1, out var textVolumes); parsedManga.Volumes = textVolumes; }
/// <summary> /// Method for get genre information for manga /// </summary> /// <param name="informationLine">Html manga information line representation</param> /// <param name="parsedManga">Object manga representation</param> /// <returns>Returns <value>true</value> if action was succeed; otherwise returns <value>false</value>.</returns> private bool GetGenres(IElement informationLine, IManga parsedManga) { if (informationLine.QuerySelector(".elem_genre") != null) { parsedManga.Genres = informationLine .QuerySelectorAll(".elem_genre a") .Select(x => { var url = x.GetAttribute("href"); _mangaGenreRegex.Match(url.EmptyStringIfNull()) .GetGroupValue(1, out var id); return(new Genre { Id = id, Title = x.TextContent, Url = $@"{BaseUrl}{url}" }); }); return(true); } return(false); }
public LibraryViewModelArgs(double?percent, IManga manga, MangaOperation mangaOperation, LibraryOperation libraryOperation) { this.Percent = percent; this.Manga = manga; this.MangaOperation = mangaOperation; this.LibraryOperation = libraryOperation; }
public static StrategyCache Lock(IManga manga) { mangaCache.GetOrAdd(manga, GetNamingStrategy); return(new StrategyCache() { manga = manga }); }
public static async Task DeleteMangaHistory(IManga manga) { using (var context = Repository.GetEntityContext()) { manga.ClearHistory(); await context.Save(manga).ConfigureAwait(false); } }
public static async Task CreateMangaHistory(IManga manga) { using (var context = Repository.GetEntityContext()) { var history = new MangaReader.Core.Manga.MangaHistory(Url); manga.Histories.Add(new MangaReader.Core.Manga.MangaHistory(history.Uri)); await context.Save(manga).ConfigureAwait(false); } }
public async Task <HistoryChapterModel> GetChapterListOfManga(IManga manga) { var chapters = await BlobCache.UserAccount.GetOrCreateObject($"MangaChapterHistory_{manga.Url}", () => new HistoryChapterModel { ChapterHistoryViewModels = new List <ChapterViewModel>() }); chapters.ChapterHistoryViewModels ??= new List <ChapterViewModel>(); return(chapters); }
public ChapterSelectorViewModel(IManga manga, List <IChapter> selectedMangaChapters) { Manga = manga; Chapters.Clear(); foreach (var chapter in selectedMangaChapters) { Chapters.Add(chapter); } }
public override async Task UpdateContent(IManga manga) { var chapters = new List <ChapterDto>(); try { var document = new HtmlDocument(); var page = await GetPageWithRedirect(manga.Uri).ConfigureAwait(false); var content = page.Item1.Content; var uri = page.Item2; if (content.Contains(AdultOnly)) { throw new GetSiteInfoException(AdultOnly, manga); } if (content.Contains(NeedRegister)) { throw new GetSiteInfoException("Требуется регистрация.", manga); } document.LoadHtml(content); var headerNode = document.GetElementbyId("right"); if (!headerNode.InnerText.Contains("Похожая манга")) { var chapterNodes = headerNode.SelectNodes(".//option"); if (chapterNodes != null) { foreach (var node in chapterNodes) { var chapterUri = new Uri(uri, node.Attributes.Single(a => a.Name == "value").Value); chapters.Add(new ChapterDto(chapterUri, WebUtility.HtmlDecode((node.NextSibling ?? node).InnerText)) { Number = HentaichanChapter.GetChapterNumber(chapterUri) }); } } } else { // Это манга из одной главы. chapters.Add(new ChapterDto(uri, manga.ServerName) { Number = 0 }); } } catch (NullReferenceException ex) { Log.Exception(ex, $"Возможно, требуется регистрация для доступа к {manga.Uri}"); } catch (GetSiteInfoException ex) { Log.Exception(ex); } FillMangaChapters(manga, chapters); }
internal static async Task <IEnumerable <byte[]> > GetPreviewsImpl(IManga manga) { var links = new List <Uri>(); var client = GetClient(); try { var document = new HtmlDocument(); var content = (await Page.GetPageAsync(manga.Uri, client).ConfigureAwait(false)).Content; document.LoadHtml(content); var chapterNodes = document.DocumentNode.SelectNodes("//img[@id='cover']"); if (chapterNodes != null) { foreach (var node in chapterNodes.SelectMany(n => n.Attributes).Where(a => a.Name == "src" && !string.IsNullOrWhiteSpace(a.Value))) { var src = node.Value; Uri link; if (Uri.IsWellFormedUriString(src, UriKind.Relative)) { link = new Uri(manga.Setting.MainUri, src); } else { link = new Uri(src); } links.Add(link); } } } catch (NullReferenceException ex) { Log.Exception(ex, $"Возможно, требуется регистрация для доступа к {manga.Uri}"); } var images = new List <byte[]>(); foreach (var link in links) { byte[] image = null; try { image = client.DownloadData(link); } catch (Exception e) { Log.Exception(e); } if (image != null) { images.Add(image); } } return(images); }
public async Task <bool> IsMangaFavorite(IManga manga) { var favoriteList = await BlobCache.UserAccount.GetOrCreateObject("favoriteList", () => new FavoriteHistoryModel() { Favorites = new List <MangaHistoryViewModel>() }); return(favoriteList.Favorites.FirstOrDefault(x => x.Url == manga.Url) != null); }
public Chapter(string chapterName, string url, IManga manga) { ChapterName = chapterName; var index = url.IndexOf("#page", StringComparison.Ordinal); var sub = url;//url.Replace("res", ""); Url = index > 0 ? sub.Remove(index) : sub; Manga = manga; Id = _currentId++; }
public override async Task UpdateContentType(IManga manga) { try { var document = new HtmlDocument(); document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/content"), this.GetClient()).ConfigureAwait(false)).Content); manga.HasVolumes = document.DocumentNode.SelectNodes(VolumeXPath) != null; manga.HasChapters = document.DocumentNode.SelectNodes(ChapterXPath) != null; } catch (System.Exception) { } }
public override void UpdateContentType(IManga manga) { try { var document = new HtmlDocument(); document.LoadHtml(Page.GetPage(new Uri(manga.Uri.OriginalString + @"/content"), this.GetAdultClient()).Content); manga.HasVolumes = document.DocumentNode.SelectNodes(VolumeXPath) != null; manga.HasChapters = document.DocumentNode.SelectNodes(ChapterXPath) != null; } catch (System.Exception) { } }
public static async Task<MangaViewModel> Create(IManga manga) { var view = new MangaViewModel(manga); var ch = await manga.Chapters(); view.Chapters = ch.ToList(); return view; }
private MangaViewModel(IManga manga) { _manga = manga; //UrlsList = _manga.Chapters.Select(c => _manga.Name + " " + c.Number).ToList(); //Name = "test"; }