diff --git a/Tranga/MangaConnectors/ChromiumDownloadClient.cs b/Tranga/MangaConnectors/ChromiumDownloadClient.cs new file mode 100644 index 0000000..bbb5949 --- /dev/null +++ b/Tranga/MangaConnectors/ChromiumDownloadClient.cs @@ -0,0 +1,95 @@ +using System.Net; +using System.Text; +using HtmlAgilityPack; +using PuppeteerSharp; + +namespace Tranga.MangaConnectors; + +internal class ChromiumDownloadClient : DownloadClient +{ + private IBrowser browser { get; set; } + private const string ChromiumVersion = "1154303"; + + private async Task DownloadBrowser() + { + BrowserFetcher browserFetcher = new BrowserFetcher(); + foreach(string rev in browserFetcher.LocalRevisions().Where(rev => rev != ChromiumVersion)) + browserFetcher.Remove(rev); + if (!browserFetcher.LocalRevisions().Contains(ChromiumVersion)) + { + Log("Downloading headless browser"); + DateTime last = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)); + browserFetcher.DownloadProgressChanged += (_, args) => + { + double currentBytes = Convert.ToDouble(args.BytesReceived) / Convert.ToDouble(args.TotalBytesToReceive); + if (args.TotalBytesToReceive == args.BytesReceived) + Log("Browser downloaded."); + else if (DateTime.Now > last.AddSeconds(1)) + { + Log($"Browser download progress: {currentBytes:P2}"); + last = DateTime.Now; + } + + }; + if (!browserFetcher.CanDownloadAsync(ChromiumVersion).Result) + { + Log($"Can't download browser version {ChromiumVersion}"); + throw new Exception(); + } + await browserFetcher.DownloadAsync(ChromiumVersion); + } + + Log("Starting Browser."); + return await Puppeteer.LaunchAsync(new LaunchOptions + { + Headless = true, + ExecutablePath = browserFetcher.GetExecutablePath(ChromiumVersion), + Args = new [] { + "--disable-gpu", + "--disable-dev-shm-usage", + "--disable-setuid-sandbox", + "--no-sandbox"} + }); + } + + public ChromiumDownloadClient(GlobalBase clone, Dictionary rateLimitRequestsPerMinute) : base(clone, rateLimitRequestsPerMinute) + { + this.browser = DownloadBrowser().Result; + } + + protected override RequestResult MakeRequestInternal(string url, string? referrer = null) + { + IPage page = this.browser!.NewPageAsync().Result; + IResponse response = page.GoToAsync(url, WaitUntilNavigation.DOMContentLoaded).Result; + + Stream stream = Stream.Null; + HtmlDocument? document = null; + + if (response.Headers.TryGetValue("Content-Type", out string? content)) + { + if (content.Contains("text/html")) + { + string htmlString = page.GetContentAsync().Result; + stream = new MemoryStream(Encoding.Default.GetBytes(htmlString)); + document = new (); + document.LoadHtml(htmlString); + }else if (content.Contains("image")) + { + stream = new MemoryStream(response.BufferAsync().Result); + } + } + else + { + page.CloseAsync(); + return new RequestResult(HttpStatusCode.InternalServerError, null, Stream.Null); + } + + page.CloseAsync(); + return new RequestResult(response.Status, document, stream, false, ""); + } + + public override void Close() + { + this.browser.CloseAsync(); + } +} \ No newline at end of file diff --git a/Tranga/MangaConnectors/DownloadClient.cs b/Tranga/MangaConnectors/DownloadClient.cs index efdc9ac..1b87413 100644 --- a/Tranga/MangaConnectors/DownloadClient.cs +++ b/Tranga/MangaConnectors/DownloadClient.cs @@ -1,107 +1,66 @@ using System.Net; -using System.Net.Http.Headers; +using HtmlAgilityPack; namespace Tranga.MangaConnectors; -internal class DownloadClient : GlobalBase +internal abstract class DownloadClient : GlobalBase +{ + private readonly Dictionary _lastExecutedRateLimit; + private readonly Dictionary _rateLimit; + + protected DownloadClient(GlobalBase clone, Dictionary rateLimitRequestsPerMinute) : base(clone) { - private static readonly HttpClient Client = new() + this._lastExecutedRateLimit = new(); + _rateLimit = new(); + foreach (KeyValuePair limit in rateLimitRequestsPerMinute) + _rateLimit.Add(limit.Key, TimeSpan.FromMinutes(1).Divide(limit.Value)); + } + + public RequestResult MakeRequest(string url, byte requestType, string? referrer = null) + { + if (_rateLimit.TryGetValue(requestType, out TimeSpan value)) + _lastExecutedRateLimit.TryAdd(requestType, DateTime.Now.Subtract(value)); + else { - Timeout = TimeSpan.FromSeconds(60), - DefaultRequestHeaders = - { - UserAgent = - { - new ProductInfoHeaderValue("Tranga", "0.1") - } - } - }; - - private readonly Dictionary _lastExecutedRateLimit; - private readonly Dictionary _rateLimit; - - public DownloadClient(GlobalBase clone, Dictionary rateLimitRequestsPerMinute) : base(clone) - { - _lastExecutedRateLimit = new(); - _rateLimit = new(); - foreach(KeyValuePair limit in rateLimitRequestsPerMinute) - _rateLimit.Add(limit.Key, TimeSpan.FromMinutes(1).Divide(limit.Value)); + Log("RequestType not configured for rate-limit."); + return new RequestResult(HttpStatusCode.NotAcceptable, null, Stream.Null); } - /// - /// Request Webpage - /// - /// - /// For RateLimits: Same Endpoints use same type - /// Used in http request header - /// RequestResult with StatusCode and Stream of received data - public RequestResult MakeRequest(string url, byte requestType, string? referrer = null) + TimeSpan rateLimitTimeout = _rateLimit[requestType] + .Subtract(DateTime.Now.Subtract(_lastExecutedRateLimit[requestType])); + + if (rateLimitTimeout > TimeSpan.Zero) + Thread.Sleep(rateLimitTimeout); + + RequestResult result = MakeRequestInternal(url, referrer); + _lastExecutedRateLimit[requestType] = DateTime.Now; + return result; + } + + protected abstract RequestResult MakeRequestInternal(string url, string? referrer = null); + public abstract void Close(); + + public struct RequestResult + { + public HttpStatusCode statusCode { get; } + public Stream result { get; } + public bool hasBeenRedirected { get; } + public string? redirectedToUrl { get; } + public HtmlDocument? htmlDocument { get; } + + public RequestResult(HttpStatusCode statusCode, HtmlDocument? htmlDocument, Stream result) { - if (_rateLimit.TryGetValue(requestType, out TimeSpan value)) - _lastExecutedRateLimit.TryAdd(requestType, DateTime.Now.Subtract(value)); - else - { - Log("RequestType not configured for rate-limit."); - return new RequestResult(HttpStatusCode.NotAcceptable, Stream.Null); - } - - TimeSpan rateLimitTimeout = _rateLimit[requestType] - .Subtract(DateTime.Now.Subtract(_lastExecutedRateLimit[requestType])); - - if(rateLimitTimeout > TimeSpan.Zero) - Thread.Sleep(rateLimitTimeout); - - HttpResponseMessage? response = null; - while (response is null) - { - try - { - HttpRequestMessage requestMessage = new(HttpMethod.Get, url); - if(referrer is not null) - requestMessage.Headers.Referrer = new Uri(referrer); - _lastExecutedRateLimit[requestType] = DateTime.Now; - //Log($"Requesting {requestType} {url}"); - response = Client.Send(requestMessage); - } - catch (HttpRequestException e) - { - Log("Exception:\n\t{0}\n\tWaiting {1} before retrying.", e.Message, _rateLimit[requestType] * 2); - Thread.Sleep(_rateLimit[requestType] * 2); - } - } - if (!response.IsSuccessStatusCode) - { - Log($"Request-Error {response.StatusCode}: {response.ReasonPhrase}"); - return new RequestResult(response.StatusCode, Stream.Null); - } - - // Request has been redirected to another page. For example, it redirects directly to the results when there is only 1 result - if(response.RequestMessage is not null && response.RequestMessage.RequestUri is not null) - { - return new RequestResult(response.StatusCode, response.Content.ReadAsStream(), true, response.RequestMessage.RequestUri.AbsoluteUri); - } - - return new RequestResult(response.StatusCode, response.Content.ReadAsStream()); + this.statusCode = statusCode; + this.htmlDocument = htmlDocument; + this.result = result; } - public struct RequestResult + public RequestResult(HttpStatusCode statusCode, HtmlDocument? htmlDocument, Stream result, bool hasBeenRedirected, string redirectedTo) + : this(statusCode, htmlDocument, result) { - public HttpStatusCode statusCode { get; } - public Stream result { get; } - public bool hasBeenRedirected { get; } - public string? redirectedToUrl { get; } - - public RequestResult(HttpStatusCode statusCode, Stream result) - { - this.statusCode = statusCode; - this.result = result; - } - - public RequestResult(HttpStatusCode statusCode, Stream result, bool hasBeenRedirected, string redirectedTo) - : this(statusCode, result) - { - this.hasBeenRedirected = hasBeenRedirected; - redirectedToUrl = redirectedTo; - } + this.hasBeenRedirected = hasBeenRedirected; + redirectedToUrl = redirectedTo; } - } \ No newline at end of file + } + +} \ No newline at end of file diff --git a/Tranga/MangaConnectors/HttpDownloadClient.cs b/Tranga/MangaConnectors/HttpDownloadClient.cs new file mode 100644 index 0000000..da5b795 --- /dev/null +++ b/Tranga/MangaConnectors/HttpDownloadClient.cs @@ -0,0 +1,70 @@ +using System.Net.Http.Headers; +using HtmlAgilityPack; + +namespace Tranga.MangaConnectors; + +internal class HttpDownloadClient : DownloadClient +{ + private static readonly HttpClient Client = new() + { + Timeout = TimeSpan.FromSeconds(60), + DefaultRequestHeaders = + { + UserAgent = + { + new ProductInfoHeaderValue("Tranga", "0.1") + } + } + }; + + + public HttpDownloadClient(GlobalBase clone, Dictionary rateLimitRequestsPerMinute) : base(clone, rateLimitRequestsPerMinute) + { + + } + + protected override RequestResult MakeRequestInternal(string url, string? referrer = null) + { + HttpResponseMessage? response = null; + while (response is null) + { + HttpRequestMessage requestMessage = new(HttpMethod.Get, url); + if (referrer is not null) + requestMessage.Headers.Referrer = new Uri(referrer); + //Log($"Requesting {requestType} {url}"); + response = Client.Send(requestMessage); + } + + if (!response.IsSuccessStatusCode) + { + Log($"Request-Error {response.StatusCode}: {response.ReasonPhrase}"); + return new RequestResult(response.StatusCode, null, Stream.Null); + } + + Stream stream = response.Content.ReadAsStream(); + + HtmlDocument? document = null; + + if (response.Content.Headers.ContentType?.MediaType == "text/html") + { + StreamReader reader = new (stream); + document = new (); + document.LoadHtml(reader.ReadToEnd()); + stream.Position = 0; + } + + // Request has been redirected to another page. For example, it redirects directly to the results when there is only 1 result + if (response.RequestMessage is not null && response.RequestMessage.RequestUri is not null) + { + return new RequestResult(response.StatusCode, document, stream, true, + response.RequestMessage.RequestUri.AbsoluteUri); + } + + return new RequestResult(response.StatusCode, document, stream); + } + + public override void Close() + { + Log("Closing."); + } +} \ No newline at end of file diff --git a/Tranga/MangaConnectors/MangaConnector.cs b/Tranga/MangaConnectors/MangaConnector.cs index 927dd03..cc4c97f 100644 --- a/Tranga/MangaConnectors/MangaConnector.cs +++ b/Tranga/MangaConnectors/MangaConnector.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.IO.Compression; +using System.IO.Compression; using System.Net; using System.Runtime.InteropServices; using System.Text.RegularExpressions; @@ -16,12 +15,18 @@ public abstract class MangaConnector : GlobalBase { internal DownloadClient downloadClient { get; init; } = null!; - protected MangaConnector(GlobalBase clone) : base(clone) + public void StopDownloadClient() { + downloadClient.Close(); + } + + protected MangaConnector(GlobalBase clone, string name) : base(clone) + { + this.name = name; Directory.CreateDirectory(settings.coverImageCache); } - public abstract string name { get; } //Name of the Connector (e.g. Website) + public string name { get; } //Name of the Connector (e.g. Website) /// /// Returns all Publications with the given string. diff --git a/Tranga/MangaConnectors/MangaDex.cs b/Tranga/MangaConnectors/MangaDex.cs index 92ac155..f0203bd 100644 --- a/Tranga/MangaConnectors/MangaDex.cs +++ b/Tranga/MangaConnectors/MangaDex.cs @@ -8,8 +8,6 @@ using JsonSerializer = System.Text.Json.JsonSerializer; namespace Tranga.MangaConnectors; public class MangaDex : MangaConnector { - public override string name { get; } - private enum RequestType : byte { Manga, @@ -19,10 +17,9 @@ public class MangaDex : MangaConnector Author, } - public MangaDex(GlobalBase clone) : base(clone) + public MangaDex(GlobalBase clone) : base(clone, "MangaDex") { - name = "MangaDex"; - this.downloadClient = new DownloadClient(clone, new Dictionary() + this.downloadClient = new HttpDownloadClient(clone, new Dictionary() { {(byte)RequestType.Manga, 250}, {(byte)RequestType.Feed, 250}, diff --git a/Tranga/MangaConnectors/MangaKatana.cs b/Tranga/MangaConnectors/MangaKatana.cs index 992fb2f..12f15cd 100644 --- a/Tranga/MangaConnectors/MangaKatana.cs +++ b/Tranga/MangaConnectors/MangaKatana.cs @@ -8,12 +8,9 @@ namespace Tranga.MangaConnectors; public class MangaKatana : MangaConnector { - public override string name { get; } - - public MangaKatana(GlobalBase clone) : base(clone) + public MangaKatana(GlobalBase clone) : base(clone, "MangaKatana") { - this.name = "MangaKatana"; - this.downloadClient = new DownloadClient(clone, new Dictionary() + this.downloadClient = new HttpDownloadClient(clone, new Dictionary() { {1, 60} }); diff --git a/Tranga/MangaConnectors/Manganato.cs b/Tranga/MangaConnectors/Manganato.cs index 38ec2b4..3f9b818 100644 --- a/Tranga/MangaConnectors/Manganato.cs +++ b/Tranga/MangaConnectors/Manganato.cs @@ -8,12 +8,9 @@ namespace Tranga.MangaConnectors; public class Manganato : MangaConnector { - public override string name { get; } - - public Manganato(GlobalBase clone) : base(clone) + public Manganato(GlobalBase clone) : base(clone, "Manganato") { - this.name = "Manganato"; - this.downloadClient = new DownloadClient(clone, new Dictionary() + this.downloadClient = new HttpDownloadClient(clone, new Dictionary() { {1, 60} }); @@ -22,24 +19,22 @@ public class Manganato : MangaConnector public override Manga[] GetManga(string publicationTitle = "") { Log($"Searching Publications. Term=\"{publicationTitle}\""); - string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*")).ToLower(); + string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(str => str.Length > 0)).ToLower(); string requestUrl = $"https://manganato.com/search/story/{sanitizedTitle}"; DownloadClient.RequestResult requestResult = downloadClient.MakeRequest(requestUrl, 1); if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) return Array.Empty(); - Manga[] publications = ParsePublicationsFromHtml(requestResult.result); + if (requestResult.htmlDocument is null) + return Array.Empty(); + Manga[] publications = ParsePublicationsFromHtml(requestResult.htmlDocument); Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\""); return publications; } - private Manga[] ParsePublicationsFromHtml(Stream html) + private Manga[] ParsePublicationsFromHtml(HtmlDocument document) { - StreamReader reader = new (html); - string htmlString = reader.ReadToEnd(); - HtmlDocument document = new (); - document.LoadHtml(htmlString); IEnumerable searchResults = document.DocumentNode.Descendants("div").Where(n => n.HasClass("search-story-item")); List urls = new(); foreach (HtmlNode mangaResult in searchResults) @@ -65,16 +60,14 @@ public class Manganato : MangaConnector downloadClient.MakeRequest(url, 1); if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) return null; - - return ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]); + + if (requestResult.htmlDocument is null) + return null; + return ParseSinglePublicationFromHtml(requestResult.htmlDocument, url.Split('/')[^1]); } - private Manga ParseSinglePublicationFromHtml(Stream html, string publicationId) + private Manga ParseSinglePublicationFromHtml(HtmlDocument document, string publicationId) { - StreamReader reader = new (html); - string htmlString = reader.ReadToEnd(); - HtmlDocument document = new (); - document.LoadHtml(htmlString); string status = ""; Dictionary altTitles = new(); Dictionary? links = null; @@ -144,17 +137,15 @@ public class Manganato : MangaConnector return Array.Empty(); //Return Chapters ordered by Chapter-Number - List chapters = ParseChaptersFromHtml(manga, requestResult.result); + if (requestResult.htmlDocument is null) + return Array.Empty(); + List chapters = ParseChaptersFromHtml(manga, requestResult.htmlDocument); Log($"Got {chapters.Count} chapters. {manga}"); return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, numberFormatDecimalPoint)).ToArray(); } - private List ParseChaptersFromHtml(Manga manga, Stream html) + private List ParseChaptersFromHtml(Manga manga, HtmlDocument document) { - StreamReader reader = new (html); - string htmlString = reader.ReadToEnd(); - HtmlDocument document = new (); - document.LoadHtml(htmlString); List ret = new(); HtmlNode chapterList = document.DocumentNode.Descendants("ul").First(l => l.HasClass("row-content-chapter")); @@ -186,7 +177,7 @@ public class Manganato : MangaConnector if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) return requestResult.statusCode; - string[] imageUrls = ParseImageUrlsFromHtml(requestResult.result); + string[] imageUrls = ParseImageUrlsFromHtml(requestResult.htmlDocument); string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); @@ -194,12 +185,8 @@ public class Manganato : MangaConnector return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken); } - private string[] ParseImageUrlsFromHtml(Stream html) + private string[] ParseImageUrlsFromHtml(HtmlDocument document) { - StreamReader reader = new (html); - string htmlString = reader.ReadToEnd(); - HtmlDocument document = new (); - document.LoadHtml(htmlString); List ret = new(); HtmlNode imageContainer = diff --git a/Tranga/MangaConnectors/Mangasee.cs b/Tranga/MangaConnectors/Mangasee.cs index 4bbbcae..aeae553 100644 --- a/Tranga/MangaConnectors/Mangasee.cs +++ b/Tranga/MangaConnectors/Mangasee.cs @@ -1,72 +1,20 @@ -using System.Globalization; -using System.Net; +using System.Net; using System.Text.RegularExpressions; using System.Xml.Linq; using HtmlAgilityPack; using Newtonsoft.Json; -using PuppeteerSharp; using Tranga.Jobs; namespace Tranga.MangaConnectors; public class Mangasee : MangaConnector { - public override string name { get; } - private IBrowser? _browser; - private const string ChromiumVersion = "1154303"; - - public Mangasee(GlobalBase clone) : base(clone) + public Mangasee(GlobalBase clone) : base(clone, "Mangasee") { - this.name = "Mangasee"; - this.downloadClient = new DownloadClient(clone, new Dictionary() + this.downloadClient = new ChromiumDownloadClient(clone, new Dictionary() { { 1, 60 } }); - - Task d = new Task(DownloadBrowser); - d.Start(); - } - - private async void DownloadBrowser() - { - BrowserFetcher browserFetcher = new BrowserFetcher(); - foreach(string rev in browserFetcher.LocalRevisions().Where(rev => rev != ChromiumVersion)) - browserFetcher.Remove(rev); - if (!browserFetcher.LocalRevisions().Contains(ChromiumVersion)) - { - Log("Downloading headless browser"); - DateTime last = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)); - browserFetcher.DownloadProgressChanged += (_, args) => - { - double currentBytes = Convert.ToDouble(args.BytesReceived) / Convert.ToDouble(args.TotalBytesToReceive); - if (args.TotalBytesToReceive == args.BytesReceived) - Log("Browser downloaded."); - else if (DateTime.Now > last.AddSeconds(1)) - { - Log($"Browser download progress: {currentBytes:P2}"); - last = DateTime.Now; - } - - }; - if (!browserFetcher.CanDownloadAsync(ChromiumVersion).Result) - { - Log($"Can't download browser version {ChromiumVersion}"); - throw new Exception(); - } - await browserFetcher.DownloadAsync(ChromiumVersion); - } - - Log("Starting Browser."); - this._browser = await Puppeteer.LaunchAsync(new LaunchOptions - { - Headless = true, - ExecutablePath = browserFetcher.GetExecutablePath(ChromiumVersion), - Args = new [] { - "--disable-gpu", - "--disable-dev-shm-usage", - "--disable-setuid-sandbox", - "--no-sandbox"} - }); } public override Manga[] GetManga(string publicationTitle = "") @@ -78,38 +26,27 @@ public class Mangasee : MangaConnector if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) return Array.Empty(); - Manga[] publications = ParsePublicationsFromHtml(requestResult.result, publicationTitle); + if (requestResult.htmlDocument is null) + return Array.Empty(); + Manga[] publications = ParsePublicationsFromHtml(requestResult.htmlDocument, publicationTitle); Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\""); return publications; } public override Manga? GetMangaFromUrl(string url) { - while (this._browser is null) - { - Log("Waiting for headless browser to download..."); - Thread.Sleep(1000); - } - Regex publicationIdRex = new(@"https:\/\/mangasee123.com\/manga\/(.*)(\/.*)*"); string publicationId = publicationIdRex.Match(url).Groups[1].Value; - IPage page = _browser!.NewPageAsync().Result; - IResponse response = page.GoToAsync(url, WaitUntilNavigation.DOMContentLoaded).Result; - if (response.Ok) - { - HtmlDocument document = new(); - document.LoadHtml(page.GetContentAsync().Result); - page.CloseAsync(); - return ParseSinglePublicationFromHtml(document, publicationId); - } - page.CloseAsync(); + DownloadClient.RequestResult requestResult = this.downloadClient.MakeRequest(url, 1); + if(requestResult.htmlDocument is not null) + return ParseSinglePublicationFromHtml(requestResult.htmlDocument, publicationId); return null; } - private Manga[] ParsePublicationsFromHtml(Stream html, string publicationTitle) + private Manga[] ParsePublicationsFromHtml(HtmlDocument document, string publicationTitle) { - string jsonString = new StreamReader(html).ReadToEnd(); + string jsonString = document.DocumentNode.SelectSingleNode("//body").InnerText; List result = JsonConvert.DeserializeObject>(jsonString)!; Dictionary queryFiltered = new(); foreach (SearchResultItem resultItem in result) @@ -244,36 +181,25 @@ public class Mangasee : MangaConnector if (progressToken?.cancellationRequested ?? false) return HttpStatusCode.RequestTimeout; Manga chapterParentManga = chapter.parentManga; - while (this._browser is null && !(progressToken?.cancellationRequested??false)) - { - Log("Waiting for headless browser to download..."); - Thread.Sleep(1000); - } if (progressToken?.cancellationRequested??false) return HttpStatusCode.RequestTimeout; Log($"Retrieving chapter-info {chapter} {chapterParentManga}"); - IPage page = _browser!.NewPageAsync().Result; - IResponse response = page.GoToAsync(chapter.url).Result; - if (response.Ok) - { - HtmlDocument document = new (); - document.LoadHtml(page.GetContentAsync().Result); - page.CloseAsync(); - HtmlNode gallery = document.DocumentNode.Descendants("div").First(div => div.HasClass("ImageGallery")); - HtmlNode[] images = gallery.Descendants("img").Where(img => img.HasClass("img-fluid")).ToArray(); - List urls = new(); - foreach(HtmlNode galleryImage in images) - urls.Add(galleryImage.GetAttributeValue("src", "")); - - string comicInfoPath = Path.GetTempFileName(); - File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); + DownloadClient.RequestResult requestResult = this.downloadClient.MakeRequest(chapter.url, 1); + if(requestResult.htmlDocument is null) + return HttpStatusCode.RequestTimeout; + HtmlDocument document = requestResult.htmlDocument; - return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, progressToken:progressToken); - } - - page.CloseAsync(); - return response.Status; + HtmlNode gallery = document.DocumentNode.Descendants("div").First(div => div.HasClass("ImageGallery")); + HtmlNode[] images = gallery.Descendants("img").Where(img => img.HasClass("img-fluid")).ToArray(); + List urls = new(); + foreach(HtmlNode galleryImage in images) + urls.Add(galleryImage.GetAttributeValue("src", "")); + + string comicInfoPath = Path.GetTempFileName(); + File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); + + return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, progressToken:progressToken); } } \ No newline at end of file diff --git a/Tranga/Tranga.cs b/Tranga/Tranga.cs index 44c697f..458c5e2 100644 --- a/Tranga/Tranga.cs +++ b/Tranga/Tranga.cs @@ -67,6 +67,11 @@ public partial class Tranga : GlobalBase jobBoss.CheckJobs(); Thread.Sleep(100); } + + foreach (MangaConnector connector in _connectors) + { + + } }); t.Start(); }