private Manga ExtractMangaInfo(HtmlNode mangaFocus) { var mangaNode = mangaFocus.Descendants("span") .Where(p => (p.GetAttributeValue("class", "") == "manga") || (p.GetAttributeValue("class", "") == "manga easy-tooltip")) .FirstOrDefault().Descendants("a").FirstOrDefault(); string name = mangaNode.InnerText.Trim(); var uri = new Uri(mangaNode.GetAttributeValue("href", "")); var chapterNode = mangaFocus.Descendants("span") .Where(p => (p.GetAttributeValue("class", "") == "chapter")) .FirstOrDefault().Descendants("a").FirstOrDefault(); string latestChapter = chapterNode.InnerText.Trim(); var currentDateNode = mangaFocus.Descendants("span") .Where(p => (p.GetAttributeValue("class", "") == "current-date")) .FirstOrDefault(); string currentDate = currentDateNode.InnerText.Trim(); DateTime latestUpdatedDate = DateTime.Now; //DateTime.TryParse(currentDate, out latestUpdatedDate,); //System.Globalization.DateTimeStyles style = new System.Globalization.DateTimeStyles(); //style. var mangaInfo = new MangaInfo { MangaName = name, MangaUri = uri, LatestChapter = latestChapter, LatestUpdatedDate = latestUpdatedDate, }; var manga = new Manga(mangaInfo); return(manga); }
public void OpenZip() { var item = MangaInfo.Create("..\\TestContainerFolder.zip"); _viewModel.LoadContainer(item); Assert.AreEqual(7, _viewModel.TotalFiles); }
public ProviderSetViewModel(MangaInfo mangaInfo, IMangaIndex mangaIndex, SubscriptionViewModel.Factory factory) { _mangaIndex = mangaIndex; SubscriptionFactory = factory; Name = mangaInfo.Name; Providers = mangaInfo.Instances.Select(t => new ProviderData { Provider = t.provider, Url = t.url }).ToBindableCollection(); MetaData = mangaInfo.MetaData; var providerData = this .OnPropertyChanges(s => s.SelectedProvider).Do(_ => IsLoading = true) .SelectTask(a => GetProviderData(a.Provider, a.Url)).Do(_ => IsLoading = false) .ObserveOnDispatcher(); SelectedInstance = providerData .Select(vt => CreateInstanceViewModel(vt.coverUrl, new ChapterInstanceViewModel(vt.chapters))) .ToReactiveProperty(); Test = providerData .Select(vt => CreateInstanceViewModel(vt.coverUrl, SubscriptionFactory((Name, SelectedProvider), vt.chapters))) .ToReactiveProperty(); SelectedInstance .Subscribe(x => x?.ChapterInstanceViewModel.SelectedRows.Clear()); }
private async Task UpdateMangaChaptersAsync(MangaInfo manga) { _log.LogInformation($"Started loading new chapters for '{manga.Name}' title"); try { var newManga = await _mangaLoader.LoadMangaInfoAsync(manga); var chapters = await _chaptersRep.GetByAsync(chapter => chapter.MangaId == manga.Id); var currentChapters = manga.Chapters; var newChapters = new List <MangaChapterInfo>(); newManga.Chapters.ForEach(chapter => { if (currentChapters.Any(c => c.Name == chapter.Name)) { return; } newChapters.Add(chapter); _chaptersRep.Create(chapter); }); _log.LogInformation($"Found {newChapters.Count} new chapters for '{newManga.Name}' title"); if (newChapters.IsNotEmpty()) { _chaptersRep.Save(); CreateNewMangaNotifications(newChapters); } } catch (Exception ex) { _log.LogError($"Error while loading new info for '{manga.Name}' title. Error info: \n{ex.Message}\n{ex.StackTrace}"); } }
public static async Task <MangaInfo> Generate(InfoCacheAttribute cacheAttribute) { var info = new MangaInfo(); info.Uri = cacheAttribute.Uri; var manga = await Mangas.CreateFromWeb(new Uri(cacheAttribute.Uri)).ConfigureAwait(false); if (cacheAttribute.Downloadable) { await manga.Download().ConfigureAwait(false); var files = Directory.GetFiles(manga.GetAbsoluteFolderPath(), "*", SearchOption.AllDirectories); var fileInfos = files.Select(f => new FileInfo(f)).ToList(); info.FilesInFolder = fileInfos.Count; info.FolderSize = fileInfos.Sum(f => f.Length); info.AllFilesUnique = 1 == fileInfos.GroupBy(f => f.Length).Max(g => g.Count()); } info.Status = manga.Status; info.Description = manga.Description; return(info); }
private async Task LoadContainer(MangaInfo item) { if (item == null) { return; } await MainWindow.LoadContainer(item, true); }
public void RemoveTag(MangaInfo item, string tag) { var userGroup = TagGroups[1]; TagGroup thisNode = userGroup.Items.Cast <TagGroup>().First(node => node.Name.Equals(tag)); thisNode.Items.Remove(item); SetHeader(thisNode); //todo remove node if empty }
public MangaReader(DiscordSocketClient bot, MangaInfo manga, params ulong[] users) { if (users.Length == 0) { throw new ArgumentException("Please specify at least one user", nameof(users)); } _bot = bot; _manga = manga; _allowedUsers = new List <ulong>(users); }
private async void MangaDoubleClicked(object sender, MouseButtonEventArgs e) { var preItem = VisualUpwardSearch(e.OriginalSource as DependencyObject); MangaInfo item = preItem.DataContext as MangaInfo; if (item == null) { return; } await LoadContainer(item); }
public AboutMangaPageViewModel(INavigationService navigationService) { _navigationService = navigationService; if (!(_navigationService.NavigatedParametr is ICatalogTile)) { return; } _catalogTile = (ICatalogTile)_navigationService.NavigatedParametr; PagesInfo = new MangaInfo { Chapters = new ObservableCollection <IChapter>() }; MainViewVisible = false; }
private void SetupFavoriteTagMenuItem(ContextMenu contextMenu, MangaInfo item) { var addTagMenuItem = contextMenu.Items.Cast <MenuItem>().Single(mi => mi.Header.Equals("Add Tag to Favorites")); addTagMenuItem.Items.Clear(); foreach (var tag in item.AutoTags) { var tagMenuItem = new MenuItem { Header = tag.Tag, Tag = tag }; tagMenuItem.Click += (_, _) => StaticHelpers.LocalDatabase.AddFavoriteTag(tag.Tag); addTagMenuItem.Items.Add(tagMenuItem); } }
public void AddTag(MangaInfo item, string tag) { var userGroup = TagGroups[1]; TagGroup thisNode = userGroup.Items.Cast <TagGroup>().FirstOrDefault(node => node.Name.Equals(tag)); if (thisNode == null) { thisNode = new TagGroup { Name = tag }; userGroup.Items.Add(thisNode); } thisNode.Items.Add(item); SetHeader(thisNode); }
public JsonResult GetMangaMetadata(string mangaName) { var metadata = new MangaInfo { name = "Bleach", japaneseName = "ブリーチ", author = "Tite Kubo", publisher = "Shueisha", volumeCount = 74, chapterCount = 686, imageUri = "/images/MangaImages/bleach.jpg", website = "https://www.viz.com/bleach", fansite = "http://www.fanpop.com/clubs/bleach-anime" }; return(Json(metadata)); }
protected virtual MangaInfo FillMangaInfo(MangaInfo mangaInfo, MangaSource source, HtmlDocument document) { IMangaParser mangaParser = _parsersFactory.GetParser(source.Code); List <MangaChapterInfo> chaptersList = mangaParser.GetMangaChapters(document, source); chaptersList.Reverse(); chaptersList.ForEach(chapter => chapter.MangaId = mangaInfo.Id); string imageUrl = mangaParser.GetMangaImageUrl(document, source.ImageXpath); string name = mangaParser.GetMangaName(document, source.TitleXpath); var manga = new MangaInfo(); manga.Id = mangaInfo.Id; manga.ImageUrl = imageUrl; manga.Chapters = chaptersList; manga.Name = name; manga.Href = mangaInfo.Href; manga.Source = mangaInfo.Source; return(manga); }
private static EmbedBuilder FromMangaInfo(MangaInfo manga) { var embed = new EmbedBuilder { Title = manga.Title }; if (manga.Artists.Length >= 1) { embed.Author = new EmbedAuthorBuilder().WithName(manga.Artists[0]); } embed.Color = Color.Teal; if (manga.Tags.Length > 0) { embed.Fields.Add(new EmbedFieldBuilder { Name = "Tags", Value = string.Join(" ", manga.Tags) }); } if (manga.Categories.Length > 0) { embed.Fields.Add(new EmbedFieldBuilder { Name = "Categories", Value = string.Join(" ", manga.Categories) }); } if (manga.Languages.Length > 0) { embed.Fields.Add(new EmbedFieldBuilder { Name = "Languages", Value = string.Join(" ", manga.Languages) }); } return(embed); }
private void SetupSearchMenuItem(ContextMenu contextMenu, MangaInfo item) { var searchMenuItem = contextMenu.Items.Cast <MenuItem>().Single(mi => mi.Header.Equals("Search")); searchMenuItem.Items.Clear(); var nameMenuItem = new MenuItem { Header = item.Name, Tag = item.Name }; nameMenuItem.Click += SearchByDebugTagString; searchMenuItem.Items.Add(nameMenuItem); foreach (var tag in item.AutoTags) { var tagMenuItem = new MenuItem { Header = tag.Tag, Tag = tag }; tagMenuItem.Click += SearchByDebugTagString; searchMenuItem.Items.Add(tagMenuItem); } }
public RarContainer(MangaInfo item, Action <string> onPropertyChanged, MainViewModel.PageOrder pageOrder, bool extractFirstOnly = false, bool doNotExtract = false) : base(item, onPropertyChanged, pageOrder) { using var rarExtractor = new SevenZipExtractor(ContainerPath); OrderFiles(rarExtractor.ArchiveFileData); if (doNotExtract) { return; } if (extractFirstOnly) { ExtractFirst(); } else { var bg = new BackgroundWorker(); bg.DoWork += ExtractAllWork; bg.ProgressChanged += (_, _) => onPropertyChanged?.Invoke(nameof(Extracted)); bg.WorkerReportsProgress = true; bg.RunWorkerAsync(); } }
public async Task <MangaInfo> LoadMangaInfoAsync(MangaInfo mangaInfo) { mangaInfo.CheckArgumentNull(nameof(mangaInfo)); string mangaUrl = mangaInfo.Href; mangaUrl.CheckArgumentEmptyOrNull(nameof(mangaUrl)); Uri mangaUri = new Uri(mangaUrl); MangaSource mangaSource = GetSourceByUrl(mangaUri); mangaInfo.Source = mangaSource ?? throw new ArgumentException("Wrong url domain"); string sourceName = mangaSource.Name; ServiceConfigrationSection config = _configHelper.GetServiceConfig(sourceName); if (config == null) { throw new ArgumentException($"No handler for source {sourceName}"); } _htmlDocumentLoader.Cookies = config.Cookies; HtmlDocument document = await _htmlDocumentLoader.GetHtmlDoc(mangaInfo.Href); return(FillMangaInfo(mangaInfo, mangaSource, document)); }
public CoverData GetCoverImage(MangaInfo MangaInfo) { CoverData _Cover = new CoverData(); String PageHTML, FileLocation, CoverRegex = @"(?<File>http://s\d\.mangapanda\.com/cover/(?<Name>[\w-]+)/(?<FileName>[\w-]+l\d+?)(?<Extention>\.[\w]{3,4}))"; using (WebClient GWC = new WebClient()) { GWC.Encoding = Encoding.UTF8; PageHTML = GWC.DownloadString(MangaInfo.InfoPage); Match coverMatch = Regex.Match(PageHTML, CoverRegex); if (coverMatch.Success) { FileLocation = coverMatch.Groups["File"].Value; _Cover.CoverName = coverMatch.Groups["FileName"].Value; Stream tmpImage = new MemoryStream(GWC.DownloadData(FileLocation)); tmpImage.Position = 0; _Cover.CoverStream = new MemoryStream(); tmpImage.CopyTo(_Cover.CoverStream); tmpImage.Close(); } } return _Cover; }
protected override async Task <Manga> GetMangaAsync(Uri mangaUri, int count) { Manga manga = null; MangaInfo mangaInfo = null; HtmlNode nameNode; HtmlNode authorNode; IEnumerable <HtmlNode> genreNodes; try { string originalUrl = mangaUri.OriginalString; HttpClient httpClient = new HttpClient(); //var response = await httpClient.GetAsync(mangaUri); //string html = await response.Content.ReadAsStringAsync(); IBuffer buffer = await httpClient.GetBufferAsync(mangaUri); var html = Encoding.UTF8.GetString(buffer.ToArray(), 0, (int)buffer.Length - 1); HtmlDocument htmlDocument = new HtmlDocument(); htmlDocument.LoadHtml(html); nameNode = htmlDocument.DocumentNode.Descendants("h1").FirstOrDefault(p => p.GetAttributeValue("itemprop", "") == "name"); var coverUri = htmlDocument.GetElementbyId("infor-box").ChildNodes[1].Element("img").GetAttributeValue("src", ""); authorNode = htmlDocument.GetElementbyId("infor-box").Descendants("span").FirstOrDefault(p => p.GetAttributeValue("itemprop", "") == "name"); string[] latestChapterAndStatus = GetLatestChapterAndStatus(htmlDocument.GetElementbyId("infor-box")); genreNodes = htmlDocument.GetElementbyId("infor-box").Descendants("a"); HtmlNode mangaSummaryNode = htmlDocument.GetElementbyId("manga-summary"); HtmlNode nodeSummary = null; if (mangaSummaryNode != null) { try { nodeSummary = htmlDocument.GetElementbyId("manga-summary").ChildNodes[1]; } catch (IndexOutOfRangeException indexOutOfRangeException) { Debug.WriteLine("Catch IndexOutOfRangeException " + indexOutOfRangeException.Message); authorNode = htmlDocument.GetElementbyId("manga-summary").ChildNodes[0]; } } mangaInfo = new MangaInfo(); mangaInfo.MangaUri = mangaUri; mangaInfo.GenreListName = new List <string>(); if (genreNodes != null) { foreach (var nodeGenre in genreNodes) { if (nodeGenre.GetAttributeValue("itemprop", "") == "genre") { mangaInfo.GenreListName.Add(nodeGenre.InnerText.Trim()); } } } if (nodeSummary != null) { mangaInfo.Summary = nodeSummary.InnerText.Trim(); } if (nameNode != null) { mangaInfo.MangaName = nameNode.InnerText.Trim(); } if (authorNode != null) { mangaInfo.Author = authorNode.InnerText.Trim(); } if (!string.IsNullOrEmpty(coverUri)) { mangaInfo.CoverImage = new Uri(coverUri); } mangaInfo.LatestChapter = latestChapterAndStatus[0]; mangaInfo.Status = latestChapterAndStatus[1]; manga = new Manga(mangaInfo); } catch (HtmlWebException) { if (count == 0) { Debug.WriteLine("Reload: " + mangaUri.OriginalString); return(await GetMangaAsync(mangaUri, 1)); } } catch (ArgumentOutOfRangeException argumentEx) { Debug.WriteLine("ArgumentException_objectName: " + argumentEx.ParamName); } catch (NullReferenceException nullReferenceEx) { Debug.WriteLine("NullReferenceException_objectName: " + nullReferenceEx.Source); } catch (Exception ex) { Debug.WriteLine("Catch Exception: " + ex.Message); } return(manga); }
/// <summary> /// convert json string into mangaInfo object /// </summary> /// <param name="json">manga json</param> /// <returns>mangainfo</returns> public MangaInfo ConvertJson(string json) { MangaInfo mangaInfo = JsonConvert.DeserializeObject <MangaInfo>(json); return(mangaInfo); }
public FolderContainer(MangaInfo item, IEnumerable <FileInfo> files, MainViewModel.PageOrder pageOrder) : base(item, pageOrder) { CurrentIndex = 0; OrderFiles(files); }
public static async Task <MangaInfo?> GetMangaAsync(int id) { var request = (HttpWebRequest)WebRequest.Create(string.Format(GalleryUrl, id)); request.Method = "GET"; request.UserAgent = "AliceBot"; using var response = (HttpWebResponse) await request.GetResponseAsync(); await using var stream = response.GetResponseStream(); if (stream == null) { return(null); } using var reader = new StreamReader(stream); var manga = new MangaInfo { Url = $"http://hentaifox.com/gallery/{id}", IsNsfw = true }; string?imagesUrl = null; int? pages = null; // Get base url for all the pages string line; while (imagesUrl == null && (line = await reader.ReadLineAsync()) != null) { var index = line.IndexOf("<div class=\"cover\">", StringComparison.Ordinal); if (index >= 0) { line = await reader.ReadLineAsync(); const string imageRegex = @".+src=""\W*([a-z0-9-\.]+(?:\/\d+)+).*"".+"; var match = Regex.Match(line, imageRegex, RegexOptions.IgnoreCase); if (!match.Success) { return(null); } imagesUrl = "https://" + match.Groups[1].Value + "/{0}"; } } // Get Manga Name while (manga.Title == null && (line = await reader.ReadLineAsync()) != null) { var index = line.IndexOf("<h1>", StringComparison.Ordinal); if (index >= 0) { manga.Title = line.Substring(index + 4, line.Length - index - 4 - 5); } } // Get Tags while (manga.Tags == null && (line = await reader.ReadLineAsync()) != null) { var index = line.IndexOf("Tags: ", StringComparison.Ordinal); if (index >= 0) { const string tagsRegex = @"tag"">([\w\s-_]+?)<\/span"; var matches = Regex.Matches(line, tagsRegex, RegexOptions.IgnoreCase); manga.Tags = new string[matches.Count]; for (int i = 0; i < matches.Count; i++) { manga.Tags[i] = matches[i].Groups[1].Value; } } } // Get Artists while (manga.Artists == null && (line = await reader.ReadLineAsync()) != null) { var index = line.IndexOf("Artists: ", StringComparison.Ordinal); if (index >= 0) { const string artistsRegex = @"tag"">([\w\s-_]+?)<\/span"; var matches = Regex.Matches(line, artistsRegex, RegexOptions.IgnoreCase); manga.Artists = new string[matches.Count]; for (int i = 0; i < matches.Count; i++) { manga.Artists[i] = matches[i].Groups[1].Value; } } } // Get Languages while (manga.Languages == null && (line = await reader.ReadLineAsync()) != null) { var index = line.IndexOf("Language: ", StringComparison.Ordinal); if (index >= 0) { const string languagesRegex = @"tag"">([\w\s-_]+?)<\/span"; var matches = Regex.Matches(line, languagesRegex, RegexOptions.IgnoreCase); manga.Languages = new string[matches.Count]; for (int i = 0; i < matches.Count; i++) { manga.Languages[i] = matches[i].Groups[1].Value; } } } // Get Category while (manga.Categories == null && (line = await reader.ReadLineAsync()) != null) { var index = line.IndexOf("Category: ", StringComparison.Ordinal); if (index >= 0) { const string categoryRegex = @"tag"">([\w\s-_]+?)<\/span"; var matches = Regex.Matches(line, categoryRegex, RegexOptions.IgnoreCase); manga.Categories = new string[matches.Count]; for (int i = 0; i < matches.Count; i++) { manga.Categories[i] = matches[i].Groups[1].Value; } } } // Get number of pages while (pages == null && (line = await reader.ReadLineAsync()) != null) { int index = line.IndexOf("<span class=\"pages\">Pages: ", StringComparison.Ordinal); if (index >= 0) { int max = index + 27; for (; max < line.Length; max++) { if (!char.IsNumber(line[max])) { break; } } int.TryParse(line.Substring(index + 27, max - index - 27), out int pageCount); if (pageCount == 0) { return(null); } pages = pageCount; } } if (pages == null) { return(null); } manga.Cover = string.Format(imagesUrl, "cover.jpg"); manga.Pages = new string[pages.Value]; for (int i = 0; i < pages; i++) { manga.Pages[i] = string.Format(imagesUrl, i + 1 + ".jpg"); } return(manga); }
protected Container(MangaInfo item, MainViewModel.PageOrder pageOrder) : base(item, pageOrder) { }
public MangaInfo LoadMangaInformation(String InfoPage) { OnProgressChanged(1); MangaInfo MI = new MangaInfo() { Site = SiteName, InfoPage = InfoPage }; MI.Site = SiteName; OnProgressChanged(3); String PageHTML; Double Progress = 10, Step = 99D - (Double)Progress; OnProgressChanged((Int32)Math.Round(Progress)); using (WebClient GWC = new WebClient()) { GWC.Encoding = Encoding.UTF8; PageHTML = GWC.DownloadString(InfoPage); HtmlDocument _PageDoc = new HtmlDocument(); HtmlNode _PageElement; _PageDoc.LoadHtml(PageHTML); MI.Name = Regex.Match(PageHTML, InfoNameRegEx).Groups["Name"].Value; _PageElement = _PageDoc.GetElementbyId("mangaproperties"); List<Object> _MangaInfo = new List<Object>(); foreach (HtmlNode _TR in _PageElement.SelectNodes("//tr/td[2]")) { if (_MangaInfo.Count < 8) { _MangaInfo.Add(_TR.InnerText.Trim()); } else break; } _MangaInfo.TrimExcess(); MI.AltTitle = _MangaInfo[1] as String; MI.Released = _MangaInfo[2] as String; MI.Status = (_MangaInfo[3].Equals("Ongoing") ? MangaStatus.Ongoing : MangaStatus.Complete); MI.Author = _MangaInfo[4] as String; MI.Artist = _MangaInfo[5] as String; MI.ReadDirection = (_MangaInfo[6].Equals("Right to Left") ? ReadDirection.FromRight : ReadDirection.FromLeft); MI.Genre = _MangaInfo[7] as String; try { MI.ID = UInt32.Parse(Regex.Match(InfoPage, @"mangapanda\.com/(?<ID>\d+)/[\w-]*.html").Groups["ID"].Value); } catch { MI.ID = ChapterId(MI.InfoPage); } OnProgressChanged(7, MI as MangaData); MI.ChapterEntries.Clear(); MI.ChapterEntries = ChapterList(MI.ID); MI.ChapterEntries.TrimExcess(); OnProgressChanged(90); ChapterEntry _tmpCE = MI.ChapterEntries[0]; MI.Volume = _tmpCE.Volume; MI.Chapter = _tmpCE.Chapter; MI.SubChapter = _tmpCE.SubChapter; _tmpCE = null; } OnProgressChanged(100); GC.Collect(); return MI; }
protected ArchiveContainer(MangaInfo item, Action <string> onPropertyChanged, MainViewModel.PageOrder pageOrder) : base(item, pageOrder) { FileDirectory = Path.Combine(StaticHelpers.TempFolder, ContainerPath.GetHashCode().ToString()); Directory.CreateDirectory(FileDirectory); UpdateExtracted = onPropertyChanged; }
public ZipContainer(MangaInfo item, Action <string> onPropertyChanged, MainViewModel.PageOrder pageOrder) : base(item, onPropertyChanged, pageOrder) { using var archive = new ZipArchive(File.OpenRead(ContainerPath)); OrderFiles(archive.Entries); }
public MangaReader(DiscordSocketClient bot, MangaInfo manga, List <ulong> users) { _bot = bot; _manga = manga; _allowedUsers = users; }