public override void RunAsync() { if (BackgroundWorker.IsBusy) { MessageBox.Show("Program is busy", "Download in progress", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } OnPagesDownloadStarted(new PagesDownloadStartedEventArgs(PageIndices, GalleryId)); DownloadPagesRunArg runArg = new DownloadPagesRunArg(GalleryId, PageIndices, HttpClient, PathFormatter, SearchResultCache, CacheFileSystem); BackgroundWorker.RunWorkerAsync(runArg); }
private static void DownloadPagesBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker backgroundWorker = sender as BackgroundWorker; DownloadPagesRunArg runArg = e.Argument as DownloadPagesRunArg; Metadata metadata = runArg.SearchResultCache.Find(runArg.Id); if (metadata == null) { string metadataFilePath; if (runArg.PathFormatter.IsEnabled) { metadataFilePath = runArg.PathFormatter.GetMetadata(runArg.Id); } else { // NOTE: must be an absolute path for the webbrowser to display the images correctly. metadataFilePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", runArg.PathFormatter.GetCacheDirectory(), runArg.Id, ".json"); } metadata = JsonUtility.LoadFromFile <Metadata>(metadataFilePath); if (metadata == null) { // TODO? redownload it instead of aborting? e.Result = runArg.Id; //e.Cancel = true; return; } } int maxCount = (runArg.PageIndices != null && runArg.PageIndices.Length > 0) ? runArg.PageIndices.Count() : metadata.Images.Pages.Count; int loadCount = 0; int[] cachedPageIndices = runArg.CacheFileSystem.GetCachedPageIndices(metadata.Id); int cacheCount = cachedPageIndices.Length; for (int i = 0; i < metadata.Images.Pages.Count; ++i) { if (backgroundWorker.CancellationPending) { PageDownloadCompletedArg cancelledArg = new PageDownloadCompletedArg(loadCount, maxCount, cacheCount, metadata); e.Result = cancelledArg; //e.Cancel = true; return; } string error = ""; string pageCachedFilePath; if (runArg.PathFormatter.IsEnabled) { pageCachedFilePath = runArg.PathFormatter.GetPage(metadata, i); } else { string paddedIndex = (i + 1).ToString(CultureInfo.InvariantCulture).PadLeft(global::NHxD.Frontend.Winforms.PathFormatter.GetBaseCount(metadata.Images.Pages.Count), '0'); pageCachedFilePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}/{2}{3}", runArg.PathFormatter.GetCacheDirectory(), metadata.Id, paddedIndex, metadata.Images.Pages[i].GetFileExtension()).Replace('\\', '/'); } bool shouldFilter = (runArg.PageIndices != null && runArg.PageIndices.Length > 0) ? ShouldFilterPage(metadata, i, runArg.PageIndices) : false; if (shouldFilter) { pageCachedFilePath = ""; error = "SKIP"; } else { ++loadCount; if (!File.Exists(pageCachedFilePath)) { try { var mediaServerId = -1; { var url = $"https://nhentai.net/g/{metadata.Id}/{i + 1}/"; Program.Logger.LogLine($"Downloading gallery webpage {url}..."); using (var response = Task.Run(() => runArg.HttpClient?.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)).GetAwaiter().GetResult()) { if (!response.IsSuccessStatusCode) { Program.Logger.ErrorLine($"{response.ReasonPhrase} ({response.StatusCode})"); response.EnsureSuccessStatusCode(); } else { var html = Task.Run(() => response.Content.ReadAsStringAsync()).GetAwaiter().GetResult(); var mediaServerIdRegExp = new Regex(@"media_server:\s*(\d+),"); var mediaServerIdMatch = mediaServerIdRegExp.Match(html); if (!mediaServerIdMatch.Success) { throw new Exception("Could not find media server id."); } else { mediaServerId = int.Parse(mediaServerIdMatch.Groups[1].Value); } } } } string uri = string.Format(CultureInfo.InvariantCulture, "https://i{3}.nhentai.net/galleries/{0}/{1}{2}", metadata.MediaId, i + 1, metadata.Images.Pages[i].GetFileExtension(), mediaServerId); Program.Logger.LogLine($"Downloading gallery page {uri}..."); using (HttpResponseMessage response = Task.Run(() => runArg.HttpClient?.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead)).GetAwaiter().GetResult()) { if (!response.IsSuccessStatusCode) { Program.Logger.ErrorLine($"{response.ReasonPhrase} ({response.StatusCode})"); response.EnsureSuccessStatusCode(); } else { byte[] imageData = Task.Run(() => response.Content.ReadAsByteArrayAsync()).GetAwaiter().GetResult(); // TODO: the issue is that I have designed things to be immutable so metadatas can't change. // but even if I do change the metadata and replace it in the searchResult, // it won't affect other cached searchResults with the same metadata. (because searchresults embed metadatas directly instead of storing indices to them) // so I might be able to save the changes to the metadata (file), one searchResult, but not everything (without greatly impacting performances) /* * //if (runArg.FixFileExtension) * { * ImageType pageImageType = metadata.Images.Pages[i].Type; * ImageType? realPageImageType = null; * * if (imageData.Length >= 8 * && imageData.Match(0, 8, PngFileSignature)) * { * realPageImageType = ImageType.Png; * } * else if (imageData.Length >= 8 * && imageData.Match(0, 2, JfifStartOfImageSegmentHeader) * && imageData.Match(2, 2, JfifStartOfImageSegmentHeader) * && imageData.Match(6, 5, JfifApp0SegmentSegmentIdentifier)) * { * realPageImageType = ImageType.Jpeg; * } * else if (imageData.Length >= 8 * && imageData.Match(0, 8, GifFileSignature)) * { * realPageImageType = ImageType.Gif; * } * else * { * // unknown format. * } * * if (pageImageType != realPageImageType) * { * * } * } */ Directory.CreateDirectory(Path.GetDirectoryName(pageCachedFilePath)); File.WriteAllBytes(pageCachedFilePath, imageData); ++cacheCount; } } } catch (Exception ex) { //pageCachedFilePath = ""; error = ex.Message; Program.Logger.ErrorLine(ex.ToString()); } } } PageDownloadProgressArg progressArg = new PageDownloadProgressArg(loadCount, maxCount, cacheCount, i, metadata, pageCachedFilePath, 0, 0, error); backgroundWorker.ReportProgress((int)(loadCount / (float)maxCount * 100), progressArg); } PageDownloadCompletedArg completedArg = new PageDownloadCompletedArg(loadCount, maxCount, cacheCount, metadata); e.Result = completedArg; }