Esempio n. 1
0
        public MangaObject ParseMangaObject(string Content)
        {
            HtmlDocument MangaObjectDocument = new HtmlDocument();

            MangaObjectDocument.LoadHtml(Content);

            HtmlNode MangaNode = MangaObjectDocument.DocumentNode.SelectSingleNode(".//section[contains(@class, 'manga')]");
            String   Name      = HtmlEntity.DeEntitize(MangaNode.SelectSingleNode(".//div/div[1]/h1/a").InnerText);

            Name = Name.Substring(0, Name.LastIndexOf(' '));
            HtmlNode      AlternateNamesNode = MangaNode.SelectSingleNode(".//div/table/tr/td[2]/table/tr[4]/td");
            List <String> AlternateNames     = (from AltName in HtmlEntity.DeEntitize(AlternateNamesNode.InnerText).Split(';')
                                                select AltName.Trim()).ToList();
            List <String> Authors = (from Node in MangaNode.SelectNodes(".//div/table/tr/td[2]/table/tr[5]/td/a")
                                     select HtmlEntity.DeEntitize(Node.InnerText)).ToList();
            List <String> Artists = (from Node in MangaNode.SelectNodes(".//div/table/tr/td[2]/table/tr[6]/td/a")
                                     select HtmlEntity.DeEntitize(Node.InnerText)).ToList();
            List <String> Genres = (from Node in MangaNode.SelectNodes(".//div/table/tr/td[2]/table/tr[7]/td/a")
                                    select HtmlEntity.DeEntitize(Node.InnerText)).ToList();

            // Detect type
            MangaObjectType MangaType = MangaObjectType.Unknown;
            String          mType     = MangaNode.SelectSingleNode(".//div/table/tr/td[2]/table/tr[8]/td").InnerText.ToLower();

            if (mType.Contains("japanese manga"))
            {
                MangaType = MangaObjectType.Manga;
            }
            else if (mType.Contains("korean manhwa"))
            {
                MangaType = MangaObjectType.Manhwa;
            }

            // Get description
            String Description = HtmlEntity.DeEntitize(MangaNode.SelectSingleNode(".//div/p").InnerText);

            // Chapters
            List <ChapterObject> Chapters = new List <ChapterObject>();

            foreach (HtmlNode ChapterVersionNode in MangaNode.SelectNodes(".//*[@id='list']/div[starts-with(@id, 'stream_')]"))
            {
                foreach (HtmlNode VolumeNode in ChapterVersionNode.SelectNodes(".//div[contains(@class, 'volume')]"))
                {
                    UInt32   Volume         = 0;
                    HtmlNode VolumeNameNode = VolumeNode.SelectSingleNode(".//h4");
                    if (!Equals(VolumeNameNode, null))
                    {
                        String[] idParts = VolumeNameNode.GetAttributeValue("id", "v-1-").Split('-');
                        UInt32.TryParse(idParts[2], out Volume);
                    }

                    foreach (HtmlNode ChapterNode in ChapterVersionNode.SelectNodes(".//div/ul/li"))
                    {
                        HtmlNode InfoNode = ChapterNode.SelectSingleNode(".//a");
                        String   ChapterName = HtmlEntity.DeEntitize(InfoNode.InnerText),
                                 Url = InfoNode.GetAttributeValue("href", null);
                        UInt32 Chapter = 0, SubChapter = 0;

                        Match match = Regex.Match(ChapterName, @"(vol\.(?<Volume>\d+)\s)?ch\.(?<Chapter>\d+)(\.(?<SubChapter>\d+))?");
                        if (match.Success)
                        {
                            if (match.Groups["Volume"].Success)
                            {
                                UInt32.TryParse(match.Groups["Volume"].Value, out Volume);
                            }
                            if (match.Groups["Chapter"].Success)
                            {
                                UInt32.TryParse(match.Groups["Chapter"].Value, out Chapter);
                            }
                            if (match.Groups["SubChapter"].Success)
                            {
                                UInt32.TryParse(match.Groups["SubChapter"].Value, out SubChapter);
                            }
                        }

                        if (Equals(Url, null))
                        {
                            continue;
                        }
                        Url = String.Format("{0}{1}", ExtensionDescriptionAttribute.RootUrl, Url);

                        ChapterObject NewChapterObject = new ChapterObject()
                        {
                            Name       = ChapterName,
                            Volume     = Volume,
                            Chapter    = Chapter,
                            SubChapter = SubChapter,
                            Locations  =
                            {
                                new LocationObject()
                                {
                                    Enabled           = true,
                                    ExtensionName     = ExtensionDescriptionAttribute.Name,
                                    ExtensionLanguage = ExtensionDescriptionAttribute.Language,
                                    Url = Url
                                }
                            }
                        };
                        ChapterObject ExistingChapterObject = Chapters.FirstOrDefault(o =>
                        {
                            if (!Int32.Equals(o.Chapter, NewChapterObject.Chapter))
                            {
                                return(false);
                            }
                            if (!Int32.Equals(o.SubChapter, NewChapterObject.SubChapter))
                            {
                                return(false);
                            }
                            return(true);
                        });
                        if (Equals(ExistingChapterObject, null))
                        {
                            Chapters.Add(NewChapterObject);
                        }
                        else
                        {
                            ExistingChapterObject.Merge(NewChapterObject);
                        }
                    }
                }
            }
            Chapters = Chapters.OrderBy(c => c.Chapter).ThenBy(c => c.SubChapter).ThenBy(c => c.Volume).ToList();

            return(new MangaObject()
            {
                Name = Name,
                AlternateNames = AlternateNames,
                Description = Description,
                Authors = Authors,
                Artists = Artists,
                Genres = Genres,
                MangaType = MangaType,
                Chapters = Chapters
            });
        }
        private async Task <ChapterObject> LoadChapterObjectAsync(MangaObject MangaObject, ChapterObject ChapterObject, CancellationToken ct, IProgress <Int32> progress)
        {
            try
            {
                await TaskConcurrencySemaphore.WaitAsync(ct);

                ct.ThrowIfCancellationRequested();

                // Store valid ISiteExtension
                IEnumerable <ISiteExtension> ValidSiteExtensions = ValidExtensions(CORE.SiteExtensions, CORE.UserConfiguration.EnabledExtensions).Cast <ISiteExtension>();

                // Re-Order the Chapter's LocationObjects to the EnabledExtensions order.
                IEnumerable <LocationObject> OrderedChapterObjectLocations = from EnExt in CORE.UserConfiguration.EnabledExtensions
                                                                             where ChapterObject.Locations.Exists(LocObj => EnExt.EqualsLocationObject(LocObj))
                                                                             select ChapterObject.Locations.FirstOrDefault(LocObj => EnExt.EqualsLocationObject(LocObj));

                foreach (LocationObject LocationObject in OrderedChapterObjectLocations)
                {
                    ct.ThrowIfCancellationRequested();
                    ISiteExtension SiteExtension = ValidSiteExtensions.FirstOrDefault(_ => LocationObjectExtension(_, LocationObject));
                    if (Equals(SiteExtension, null))
                    {
                        continue;                               // Continue with the foreach loop
                    }
                    ct.ThrowIfCancellationRequested();
                    using (WebDownloader WebDownloader = new WebDownloader(SiteExtension.Cookies))
                    {
                        WebDownloader.Encoding = System.Text.Encoding.UTF8;
                        WebDownloader.Referer  = SiteExtension.ExtensionDescriptionAttribute.RefererHeader;
                        DownloadProgressChangedEventHandler ProgressEventHandler = (s, e) =>
                        {
                            if (!Equals(progress, null))
                            {
                                progress.Report((Int32)Math.Round((Double)e.ProgressPercentage * 0.9));
                            }
                            ct.ThrowIfCancellationRequested();
                        };
                        WebDownloader.DownloadProgressChanged += ProgressEventHandler;

                        String ChapterWebContent = await WebDownloader.DownloadStringTaskAsync(LocationObject.Url).Retry(DOWNLOAD_TIMEOUT);

                        ChapterObject DownloadedChapterObject = SiteExtension.ParseChapterObject(ChapterWebContent);

                        WebDownloader.DownloadProgressChanged -= ProgressEventHandler;
                        ct.ThrowIfCancellationRequested();
                        if (!Equals(DownloadedChapterObject, null))
                        {
                            ChapterObject.Merge(DownloadedChapterObject);
                            ChapterObject.Pages = DownloadedChapterObject.Pages;
                            break;  // Break free of the foreach loop
                        }
                    }
                }
                if (!Equals(progress, null))
                {
                    progress.Report(100);
                }
                ct.ThrowIfCancellationRequested();
                return(ChapterObject);
            }
            finally { TaskConcurrencySemaphore.Release(); }
        }