From a589926bcf9083891c874e7d9df9c94509109353 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sun, 17 Jul 2022 09:14:11 +0000 Subject: [PATCH] Move download function outside Main struct --- src/download.rs | 1051 +++++++++++++++++++++++------------------------ 1 file changed, 524 insertions(+), 527 deletions(-) diff --git a/src/download.rs b/src/download.rs index 6b6a470..0558a18 100644 --- a/src/download.rs +++ b/src/download.rs @@ -60,7 +60,7 @@ impl Main { } } tasks - .add_task(Self::download_artwork(Arc::clone(&pw), id.clone())) + .add_task(download_artwork(Arc::clone(&pw), id.clone())) .await; if !download_multiple_posts { tasks.join().await; @@ -81,7 +81,7 @@ impl Main { } } tasks - .add_task(Self::download_fanbox_post(Arc::clone(&fc), id.clone())) + .add_task(download_fanbox_post(Arc::clone(&fc), id.clone())) .await; if !download_multiple_posts { tasks.join().await; @@ -111,562 +111,242 @@ impl Main { } re } +} - /// Download artwork link - /// * `link` - Link - /// * `np` - Number of page in artworks - /// * `progress_bars` - Multiple progress bars - /// * `datas` - The artwork's data - /// * `base` - The directory of the target - pub async fn download_artwork_link( - link: L, - np: u16, - progress_bars: Option>, - datas: Arc, - base: Arc, - ) -> Result<(), PixivDownloaderError> { - let file_name = get_file_name_from_url(link.clone()).try_err(format!( - "{} {}", - gettext("Failed to get file name from url:"), - link.as_str() - ))?; - let file_name = base.join(file_name); - let helper = get_helper(); - let downloader = Downloader::::new( - link, - json::object! {"referer": "https://www.pixiv.net/"}, - Some(&file_name), - helper.overwrite(), - )?; - match downloader { - DownloaderResult::Ok(d) => { - d.handle_options(&helper, progress_bars); - d.download(); - d.join().await?; - if d.is_downloaded() { - #[cfg(feature = "exif")] - { - if add_exifdata_to_image(&file_name, &datas, np).is_err() { - println!( - "{} {}", - gettext("Failed to add exif data to image:"), - file_name.to_str().unwrap_or("(null)") - ); - } - } - } else if d.is_panic() { - return Err(PixivDownloaderError::from( - d.get_panic() - .try_err(gettext("Failed to get error message."))?, - )); - } - } - DownloaderResult::Canceled => { +/// Download artwork link +/// * `link` - Link +/// * `np` - Number of page in artworks +/// * `progress_bars` - Multiple progress bars +/// * `datas` - The artwork's data +/// * `base` - The directory of the target +pub async fn download_artwork_link( + link: L, + np: u16, + progress_bars: Option>, + datas: Arc, + base: Arc, +) -> Result<(), PixivDownloaderError> { + let file_name = get_file_name_from_url(link.clone()).try_err(format!( + "{} {}", + gettext("Failed to get file name from url:"), + link.as_str() + ))?; + let file_name = base.join(file_name); + let helper = get_helper(); + let downloader = Downloader::::new( + link, + json::object! {"referer": "https://www.pixiv.net/"}, + Some(&file_name), + helper.overwrite(), + )?; + match downloader { + DownloaderResult::Ok(d) => { + d.handle_options(&helper, progress_bars); + d.download(); + d.join().await?; + if d.is_downloaded() { #[cfg(feature = "exif")] { - if helper.update_exif() && file_name.exists() { - if add_exifdata_to_image(&file_name, &datas, np).is_err() { - println!( - "{} {}", - gettext("Failed to add exif data to image:"), - file_name.to_str().unwrap_or("(null)") - ); - } - } - } - } - } - Ok(()) - } - - pub async fn download_artwork( - pw: Arc, - id: u64, - ) -> Result<(), PixivDownloaderError> { - let mut re = None; - let pages; - let mut ajax_ver = true; - let helper = get_helper(); - if helper.use_webpage() { - re = pw.get_artwork(id).await; - if re.is_some() { - ajax_ver = false; - } - } - if re.is_none() { - re = pw.get_artwork_ajax(id).await; - } - let re = re.try_err(gettext("Failed to get artwork's data."))?; - if ajax_ver { - pages = (&re["pageCount"]).as_u64(); - } else { - pages = (&re["illust"][format!("{}", id).as_str()]["pageCount"]).as_u64(); - } - let pages = pages.try_err(gettext("Failed to get page count."))?; - let mut pages_data: Option = None; - if pages > 1 { - pages_data = pw.get_illust_pages(id).await; - } - if pages > 1 && pages_data.is_none() { - return Err(PixivDownloaderError::from(gettext( - "Failed to get pages' data.", - ))); - } - let base = Arc::new(PathBuf::from(".")); - let json_file = base.join(format!("{}.json", id)); - let mut datas = PixivData::new(id).unwrap(); - if ajax_ver { - datas.from_web_page_ajax_data(&re, true); - } else { - datas.from_web_page_data(&re, true); - } - let datas = Arc::new(datas); - let json_data = JSONDataFile::from(Arc::clone(&datas)); - if !json_data.save(&json_file) { - return Err(PixivDownloaderError::from(gettext( - "Failed to save metadata to JSON file.", - ))); - } - let illust_type = if ajax_ver { - (&re["illustType"]).as_i64() - } else { - (&re["illust"][format!("{}", id).as_str()]["illustType"]).as_i64() - }; - if illust_type.is_some() { - let illust_type = illust_type.unwrap(); - match illust_type { - 0 => {} // Normal illust - 1 => {} // Manga illust - 2 => { - let ugoira_data = pw - .get_ugoira(id) - .await - .try_err(gettext("Failed to get ugoira's data."))?; - let src = (&ugoira_data["originalSrc"]) - .as_str() - .try_err(gettext("Can not find source link for ugoira."))?; - let dh = DownloaderHelper::builder(src)? - .headers(json::object! { "referer": "https://www.pixiv.net/" }) - .build(); - let tasks = TaskManager::default(); - tasks - .add_task(Self::download_file( - dh, - Some(get_progress_bar()), - Arc::clone(&base), - )) - .await; - tasks.join().await; - let mut tasks = tasks.take_finished_tasks(); - let task = tasks.get_mut(0).try_err(gettext("No finished task."))?; - let task = task.as_any_mut(); - let task = task - .downcast_mut::>>() - .try_err("Failed to downcast task.")?; - task.await??; - #[cfg(feature = "ugoira")] - { - let file_name = get_file_name_from_url(src).try_err(format!( - "{} {}", - gettext("Failed to get file name from url:"), - src - ))?; - let file_name = base.join(file_name); - let metadata = match get_video_metadata(Arc::clone(&datas).as_ref()) { - Ok(m) => m, - Err(e) => { - println!( - "{} {}", - gettext("Warning: Failed to generate video's metadata:"), - e - ); - AVDict::new() - } - }; - let options = AVDict::new(); - let frames = UgoiraFrames::from_json(&ugoira_data["frames"])?; - let output_file_name = base.join(format!("{}.mp4", id)); - convert_ugoira_to_mp4( - &file_name, - &output_file_name, - &frames, - 60f32, - &options, - &metadata, - )?; + if add_exifdata_to_image(&file_name, &datas, np).is_err() { println!( - "{}", - gettext("Converted -> ") - .replace("", file_name.to_str().unwrap_or("(null)")) - .replace("", output_file_name.to_str().unwrap_or("(null)")) - .as_str() + "{} {}", + gettext("Failed to add exif data to image:"), + file_name.to_str().unwrap_or("(null)") ); } - return Ok(()); - } - _ => { - println!( - "{} {}", - gettext("Warning: Unknown illust type:"), - illust_type - ) } + } else if d.is_panic() { + return Err(PixivDownloaderError::from( + d.get_panic() + .try_err(gettext("Failed to get error message."))?, + )); } - } else { - println!("{}", gettext("Warning: Failed to get illust's type.")); } - if pages_data.is_some() && helper.download_multiple_files() { - let mut np = 0u16; - let pages_data = pages_data.as_ref().unwrap(); - let progress_bars = get_progress_bar(); - let tasks = TaskManager::default(); - let mut re: Result<(), PixivDownloaderError> = Ok(()); - for page in pages_data.members() { - let url = page["urls"]["original"].as_str(); - if url.is_none() { - concat_pixiv_downloader_error!( - re, - Err::<(), &str>(gettext("Failed to get original picture's link.")) - ); - continue; - } - tasks - .add_task(Self::download_artwork_link( - url.unwrap().to_owned(), - np, - Some(Arc::clone(&progress_bars)), - Arc::clone(&datas), - Arc::clone(&base), - )) - .await; - np += 1; - } - tasks.join().await; - let tasks = tasks.take_finished_tasks(); - for mut task in tasks { - let t = task.as_any_mut(); - if let Some(task) = t.downcast_mut::>>() - { - let r = task.await; - let r = match r { - Ok(r) => r, - Err(e) => Err(PixivDownloaderError::from(e)), - }; - concat_pixiv_downloader_error!(re, r); + DownloaderResult::Canceled => { + #[cfg(feature = "exif")] + { + if helper.update_exif() && file_name.exists() { + if add_exifdata_to_image(&file_name, &datas, np).is_err() { + println!( + "{} {}", + gettext("Failed to add exif data to image:"), + file_name.to_str().unwrap_or("(null)") + ); + } } } - return re; - } else if pages_data.is_some() { - let mut np = 0u16; - let pages_data = pages_data.as_ref().unwrap(); - let tasks = TaskManager::default(); - for page in pages_data.members() { - let link = page["urls"]["original"] + } + } + Ok(()) +} + +pub async fn download_artwork( + pw: Arc, + id: u64, +) -> Result<(), PixivDownloaderError> { + let mut re = None; + let pages; + let mut ajax_ver = true; + let helper = get_helper(); + if helper.use_webpage() { + re = pw.get_artwork(id).await; + if re.is_some() { + ajax_ver = false; + } + } + if re.is_none() { + re = pw.get_artwork_ajax(id).await; + } + let re = re.try_err(gettext("Failed to get artwork's data."))?; + if ajax_ver { + pages = (&re["pageCount"]).as_u64(); + } else { + pages = (&re["illust"][format!("{}", id).as_str()]["pageCount"]).as_u64(); + } + let pages = pages.try_err(gettext("Failed to get page count."))?; + let mut pages_data: Option = None; + if pages > 1 { + pages_data = pw.get_illust_pages(id).await; + } + if pages > 1 && pages_data.is_none() { + return Err(PixivDownloaderError::from(gettext( + "Failed to get pages' data.", + ))); + } + let base = Arc::new(PathBuf::from(".")); + let json_file = base.join(format!("{}.json", id)); + let mut datas = PixivData::new(id).unwrap(); + if ajax_ver { + datas.from_web_page_ajax_data(&re, true); + } else { + datas.from_web_page_data(&re, true); + } + let datas = Arc::new(datas); + let json_data = JSONDataFile::from(Arc::clone(&datas)); + if !json_data.save(&json_file) { + return Err(PixivDownloaderError::from(gettext( + "Failed to save metadata to JSON file.", + ))); + } + let illust_type = if ajax_ver { + (&re["illustType"]).as_i64() + } else { + (&re["illust"][format!("{}", id).as_str()]["illustType"]).as_i64() + }; + if illust_type.is_some() { + let illust_type = illust_type.unwrap(); + match illust_type { + 0 => {} // Normal illust + 1 => {} // Manga illust + 2 => { + let ugoira_data = pw + .get_ugoira(id) + .await + .try_err(gettext("Failed to get ugoira's data."))?; + let src = (&ugoira_data["originalSrc"]) .as_str() - .try_err(gettext("Failed to get original picture's link."))?; + .try_err(gettext("Can not find source link for ugoira."))?; + let dh = DownloaderHelper::builder(src)? + .headers(json::object! { "referer": "https://www.pixiv.net/" }) + .build(); + let tasks = TaskManager::default(); tasks - .add_task(Self::download_artwork_link( - link.to_owned(), - np, + .add_task(download_file( + dh, Some(get_progress_bar()), - Arc::clone(&datas), Arc::clone(&base), )) .await; tasks.join().await; - np += 1; - } - let mut re = Ok(()); - let tasks = tasks.take_finished_tasks(); - for mut task in tasks { - let t = task.as_any_mut(); - if let Some(task) = t.downcast_mut::>>() + let mut tasks = tasks.take_finished_tasks(); + let task = tasks.get_mut(0).try_err(gettext("No finished task."))?; + let task = task.as_any_mut(); + let task = task + .downcast_mut::>>() + .try_err("Failed to downcast task.")?; + task.await??; + #[cfg(feature = "ugoira")] { - let r = task.await; - let r = match r { - Ok(r) => r, - Err(e) => Err(PixivDownloaderError::from(e)), + let file_name = get_file_name_from_url(src).try_err(format!( + "{} {}", + gettext("Failed to get file name from url:"), + src + ))?; + let file_name = base.join(file_name); + let metadata = match get_video_metadata(Arc::clone(&datas).as_ref()) { + Ok(m) => m, + Err(e) => { + println!( + "{} {}", + gettext("Warning: Failed to generate video's metadata:"), + e + ); + AVDict::new() + } }; - concat_pixiv_downloader_error!(re, r); + let options = AVDict::new(); + let frames = UgoiraFrames::from_json(&ugoira_data["frames"])?; + let output_file_name = base.join(format!("{}.mp4", id)); + convert_ugoira_to_mp4( + &file_name, + &output_file_name, + &frames, + 60f32, + &options, + &metadata, + )?; + println!( + "{}", + gettext("Converted -> ") + .replace("", file_name.to_str().unwrap_or("(null)")) + .replace("", output_file_name.to_str().unwrap_or("(null)")) + .as_str() + ); } + return Ok(()); } - return re; - } else { - let link = if ajax_ver { - (&re["urls"]["original"]).as_str() - } else { - (&re["illust"][format!("{}", id)]["urls"]["original"]).as_str() + _ => { + println!( + "{} {}", + gettext("Warning: Unknown illust type:"), + illust_type + ) + } + } + } else { + println!("{}", gettext("Warning: Failed to get illust's type.")); + } + if pages_data.is_some() && helper.download_multiple_files() { + let mut np = 0u16; + let pages_data = pages_data.as_ref().unwrap(); + let progress_bars = get_progress_bar(); + let tasks = TaskManager::default(); + let mut re: Result<(), PixivDownloaderError> = Ok(()); + for page in pages_data.members() { + let url = page["urls"]["original"].as_str(); + if url.is_none() { + concat_pixiv_downloader_error!( + re, + Err::<(), &str>(gettext("Failed to get original picture's link.")) + ); + continue; } - .try_err(gettext("Failed to get original picture's link."))?; - let tasks = TaskManager::default(); tasks - .add_task(Self::download_artwork_link( - link.to_owned(), - 0, - Some(get_progress_bar()), + .add_task(download_artwork_link( + url.unwrap().to_owned(), + np, + Some(Arc::clone(&progress_bars)), Arc::clone(&datas), Arc::clone(&base), )) .await; - tasks.join().await; - let mut tasks = tasks.take_finished_tasks(); - let task = tasks.get_mut(0).try_err(gettext("No tasks finished."))?; - let task = task.as_any_mut(); - let task = task - .downcast_mut::>>() - .try_err("Failed to downcast the result.")?; - task.await??; - } - Ok(()) - } - - /// Download a file link - /// * `dh` - Link and other informations - /// * `progress_bars` - Multiple progress bars - /// * `base` - The directory of the target - pub async fn download_file( - dh: DownloaderHelper, - progress_bars: Option>, - base: Arc, - ) -> Result<(), PixivDownloaderError> { - let helper = get_helper(); - match dh.download_local(helper.overwrite(), &*base)? { - DownloaderResult::Ok(d) => { - d.handle_options(&helper, progress_bars); - d.download(); - d.join().await?; - if d.is_panic() { - return Err(PixivDownloaderError::from( - d.get_panic() - .try_err(gettext("Failed to get error message."))?, - )); - } - } - DownloaderResult::Canceled => {} - } - Ok(()) - } - - /// Download a fanbox image link - /// * `dh` - Link and other informations - /// * `np` - Number of page - /// * `progress_bars` - Multiple progress bars - /// * `datas` - The artwork's data - /// * `base` - The directory of the target - pub async fn download_fanbox_image( - dh: DownloaderHelper, - np: u16, - progress_bars: Option>, - datas: Arc, - base: Arc, - ) -> Result<(), PixivDownloaderError> { - let helper = get_helper(); - let file_name = dh - .get_local_file_path(&*base) - .try_err(gettext("Failed to get file name from url."))?; - match dh.download_local(helper.overwrite(), &*base)? { - DownloaderResult::Ok(d) => { - d.handle_options(&helper, progress_bars); - d.download(); - d.join().await?; - if d.is_downloaded() { - #[cfg(feature = "exif")] - { - if add_exifdata_to_image(&file_name, &datas, np).is_err() { - println!( - "{} {}", - gettext("Failed to add exif data to image:"), - file_name.to_str().unwrap_or("(null)") - ); - } - } - } else if d.is_panic() { - return Err(PixivDownloaderError::from( - d.get_panic() - .try_err(gettext("Failed to get error message."))?, - )); - } - } - DownloaderResult::Canceled => { - #[cfg(feature = "exif")] - { - if helper.update_exif() && file_name.exists() { - if add_exifdata_to_image(&file_name, &datas, np).is_err() { - println!( - "{} {}", - gettext("Failed to add exif data to image:"), - file_name.to_str().unwrap_or("(null)") - ); - } - } - } - } - } - Ok(()) - } - - pub async fn download_fanbox_post( - fc: Arc, - id: FanboxPostID, - ) -> Result<(), PixivDownloaderError> { - let post = fc - .get_post_info(id.post_id) - .await - .try_err(gettext("Failed to get post info."))?; - let helper = get_helper(); - if helper.verbose() { - println!("{:#?}", post); - } - match post.check_unknown() { - Ok(_) => {} - Err(e) => { - println!( - "{} {}", - gettext("Warning: Post info contains unknown data:"), - e - ); - } - } - if post - .is_restricted() - .try_err(gettext("Failed to check the post is restricted or not."))? - { - println!("{}", gettext("Warning: This article is restricted.")); - // #TODO allow to continue - return Ok(()); - } - let base = Arc::new(PathBuf::from(format!("./{}/{}", id.creator_id, id.post_id))); - let json_file = base.join("data.json"); - let data = FanboxData::new(id, &post).try_err("Failed to create data file.")?; - let data_file = JSONDataFile::from(&data); - if !base.exists() { - match create_dir_all(&*base) { - Ok(_) => {} - Err(e) => { - if !base.exists() { - return Err(PixivDownloaderError::from(e)); - } - } - } - } - data_file - .save(&json_file) - .try_err(gettext("Failed to save post data to file."))?; - let tasks = TaskManager::default(); - let download_multiple_files = helper.download_multiple_files(); - match post { - FanboxPost::Article(article) => { - let article = Arc::new(article); - let body = article.body(); - let image_map = body - .image_map() - .try_err(gettext("Failed to get image map from article."))?; - let blocks = body - .blocks() - .try_err(gettext("Failed to get blocks from article."))?; - let mut np = 0; - let mut datas = data.clone(); - #[cfg(feature = "exif")] - datas.exif_data.replace(Box::new(Arc::clone(&article))); - let datas = Arc::new(datas); - for i in blocks { - match i { - FanboxArticleBlock::Image(img) => { - let img = image_map - .get_image( - img.image_id() - .try_err(gettext("Failed to get image id from block."))?, - ) - .try_err(gettext("Failed get image information from image map."))?; - let dh = img - .download_original_url()? - .try_err(gettext("Can not get original url for image"))?; - tasks - .add_task(Self::download_fanbox_image( - dh, - np, - Some(get_progress_bar()), - Arc::clone(&datas), - Arc::clone(&base), - )) - .await; - if !download_multiple_files { - tasks.join().await; - } - np += 1; - } - _ => {} - } - } - } - FanboxPost::File(file) => { - let body = file - .body() - .try_err(gettext("Failed to get the body of file post."))?; - let files = body - .files() - .try_err(gettext("Failed to get files from file post."))?; - for f in files.iter() { - let dh = f - .download_url()? - .try_err(gettext("Failed to get url of the file."))?; - tasks - .add_task(Self::download_file( - dh, - Some(get_progress_bar()), - Arc::clone(&base), - )) - .await; - if !download_multiple_files { - tasks.join().await; - } - } - } - FanboxPost::Image(img) => { - let img = Arc::new(img); - let body = img - .body() - .try_err(gettext("Failed to get the body of image post."))?; - let images = body - .images() - .try_err(gettext("Failed to get images from the image post."))?; - let mut np = 0; - let mut datas = data.clone(); - #[cfg(feature = "exif")] - datas.exif_data.replace(Box::new(Arc::clone(&img))); - let datas = Arc::new(datas); - for img in images.iter() { - let dh = img - .download_original_url()? - .try_err(gettext("Can not get original url for image"))?; - tasks - .add_task(Self::download_fanbox_image( - dh, - np, - Some(get_progress_bar()), - Arc::clone(&datas), - Arc::clone(&base), - )) - .await; - if !download_multiple_files { - tasks.join().await; - } - np += 1; - } - } - FanboxPost::Unknown(_) => { - return Err(PixivDownloaderError::from(gettext( - "Unrecognized post type.", - ))); - } + np += 1; } tasks.join().await; - let mut re = Ok(()); let tasks = tasks.take_finished_tasks(); for mut task in tasks { - let task = task.as_any_mut(); - if let Some(task) = task.downcast_mut::>>() - { + let t = task.as_any_mut(); + if let Some(task) = t.downcast_mut::>>() { let r = task.await; let r = match r { Ok(r) => r, @@ -675,6 +355,323 @@ impl Main { concat_pixiv_downloader_error!(re, r); } } - re + return re; + } else if pages_data.is_some() { + let mut np = 0u16; + let pages_data = pages_data.as_ref().unwrap(); + let tasks = TaskManager::default(); + for page in pages_data.members() { + let link = page["urls"]["original"] + .as_str() + .try_err(gettext("Failed to get original picture's link."))?; + tasks + .add_task(download_artwork_link( + link.to_owned(), + np, + Some(get_progress_bar()), + Arc::clone(&datas), + Arc::clone(&base), + )) + .await; + tasks.join().await; + np += 1; + } + let mut re = Ok(()); + let tasks = tasks.take_finished_tasks(); + for mut task in tasks { + let t = task.as_any_mut(); + if let Some(task) = t.downcast_mut::>>() { + let r = task.await; + let r = match r { + Ok(r) => r, + Err(e) => Err(PixivDownloaderError::from(e)), + }; + concat_pixiv_downloader_error!(re, r); + } + } + return re; + } else { + let link = if ajax_ver { + (&re["urls"]["original"]).as_str() + } else { + (&re["illust"][format!("{}", id)]["urls"]["original"]).as_str() + } + .try_err(gettext("Failed to get original picture's link."))?; + let tasks = TaskManager::default(); + tasks + .add_task(download_artwork_link( + link.to_owned(), + 0, + Some(get_progress_bar()), + Arc::clone(&datas), + Arc::clone(&base), + )) + .await; + tasks.join().await; + let mut tasks = tasks.take_finished_tasks(); + let task = tasks.get_mut(0).try_err(gettext("No tasks finished."))?; + let task = task.as_any_mut(); + let task = task + .downcast_mut::>>() + .try_err("Failed to downcast the result.")?; + task.await??; } + Ok(()) +} + +/// Download a file link +/// * `dh` - Link and other informations +/// * `progress_bars` - Multiple progress bars +/// * `base` - The directory of the target +pub async fn download_file( + dh: DownloaderHelper, + progress_bars: Option>, + base: Arc, +) -> Result<(), PixivDownloaderError> { + let helper = get_helper(); + match dh.download_local(helper.overwrite(), &*base)? { + DownloaderResult::Ok(d) => { + d.handle_options(&helper, progress_bars); + d.download(); + d.join().await?; + if d.is_panic() { + return Err(PixivDownloaderError::from( + d.get_panic() + .try_err(gettext("Failed to get error message."))?, + )); + } + } + DownloaderResult::Canceled => {} + } + Ok(()) +} + +/// Download a fanbox image link +/// * `dh` - Link and other informations +/// * `np` - Number of page +/// * `progress_bars` - Multiple progress bars +/// * `datas` - The artwork's data +/// * `base` - The directory of the target +pub async fn download_fanbox_image( + dh: DownloaderHelper, + np: u16, + progress_bars: Option>, + datas: Arc, + base: Arc, +) -> Result<(), PixivDownloaderError> { + let helper = get_helper(); + let file_name = dh + .get_local_file_path(&*base) + .try_err(gettext("Failed to get file name from url."))?; + match dh.download_local(helper.overwrite(), &*base)? { + DownloaderResult::Ok(d) => { + d.handle_options(&helper, progress_bars); + d.download(); + d.join().await?; + if d.is_downloaded() { + #[cfg(feature = "exif")] + { + if add_exifdata_to_image(&file_name, &datas, np).is_err() { + println!( + "{} {}", + gettext("Failed to add exif data to image:"), + file_name.to_str().unwrap_or("(null)") + ); + } + } + } else if d.is_panic() { + return Err(PixivDownloaderError::from( + d.get_panic() + .try_err(gettext("Failed to get error message."))?, + )); + } + } + DownloaderResult::Canceled => { + #[cfg(feature = "exif")] + { + if helper.update_exif() && file_name.exists() { + if add_exifdata_to_image(&file_name, &datas, np).is_err() { + println!( + "{} {}", + gettext("Failed to add exif data to image:"), + file_name.to_str().unwrap_or("(null)") + ); + } + } + } + } + } + Ok(()) +} + +pub async fn download_fanbox_post( + fc: Arc, + id: FanboxPostID, +) -> Result<(), PixivDownloaderError> { + let post = fc + .get_post_info(id.post_id) + .await + .try_err(gettext("Failed to get post info."))?; + let helper = get_helper(); + if helper.verbose() { + println!("{:#?}", post); + } + match post.check_unknown() { + Ok(_) => {} + Err(e) => { + println!( + "{} {}", + gettext("Warning: Post info contains unknown data:"), + e + ); + } + } + if post + .is_restricted() + .try_err(gettext("Failed to check the post is restricted or not."))? + { + println!("{}", gettext("Warning: This article is restricted.")); + // #TODO allow to continue + return Ok(()); + } + let base = Arc::new(PathBuf::from(format!("./{}/{}", id.creator_id, id.post_id))); + let json_file = base.join("data.json"); + let data = FanboxData::new(id, &post).try_err("Failed to create data file.")?; + let data_file = JSONDataFile::from(&data); + if !base.exists() { + match create_dir_all(&*base) { + Ok(_) => {} + Err(e) => { + if !base.exists() { + return Err(PixivDownloaderError::from(e)); + } + } + } + } + data_file + .save(&json_file) + .try_err(gettext("Failed to save post data to file."))?; + let tasks = TaskManager::default(); + let download_multiple_files = helper.download_multiple_files(); + match post { + FanboxPost::Article(article) => { + let article = Arc::new(article); + let body = article.body(); + let image_map = body + .image_map() + .try_err(gettext("Failed to get image map from article."))?; + let blocks = body + .blocks() + .try_err(gettext("Failed to get blocks from article."))?; + let mut np = 0; + let mut datas = data.clone(); + #[cfg(feature = "exif")] + datas.exif_data.replace(Box::new(Arc::clone(&article))); + let datas = Arc::new(datas); + for i in blocks { + match i { + FanboxArticleBlock::Image(img) => { + let img = image_map + .get_image( + img.image_id() + .try_err(gettext("Failed to get image id from block."))?, + ) + .try_err(gettext("Failed get image information from image map."))?; + let dh = img + .download_original_url()? + .try_err(gettext("Can not get original url for image"))?; + tasks + .add_task(download_fanbox_image( + dh, + np, + Some(get_progress_bar()), + Arc::clone(&datas), + Arc::clone(&base), + )) + .await; + if !download_multiple_files { + tasks.join().await; + } + np += 1; + } + _ => {} + } + } + } + FanboxPost::File(file) => { + let body = file + .body() + .try_err(gettext("Failed to get the body of file post."))?; + let files = body + .files() + .try_err(gettext("Failed to get files from file post."))?; + for f in files.iter() { + let dh = f + .download_url()? + .try_err(gettext("Failed to get url of the file."))?; + tasks + .add_task(download_file( + dh, + Some(get_progress_bar()), + Arc::clone(&base), + )) + .await; + if !download_multiple_files { + tasks.join().await; + } + } + } + FanboxPost::Image(img) => { + let img = Arc::new(img); + let body = img + .body() + .try_err(gettext("Failed to get the body of image post."))?; + let images = body + .images() + .try_err(gettext("Failed to get images from the image post."))?; + let mut np = 0; + let mut datas = data.clone(); + #[cfg(feature = "exif")] + datas.exif_data.replace(Box::new(Arc::clone(&img))); + let datas = Arc::new(datas); + for img in images.iter() { + let dh = img + .download_original_url()? + .try_err(gettext("Can not get original url for image"))?; + tasks + .add_task(download_fanbox_image( + dh, + np, + Some(get_progress_bar()), + Arc::clone(&datas), + Arc::clone(&base), + )) + .await; + if !download_multiple_files { + tasks.join().await; + } + np += 1; + } + } + FanboxPost::Unknown(_) => { + return Err(PixivDownloaderError::from(gettext( + "Unrecognized post type.", + ))); + } + } + tasks.join().await; + let mut re = Ok(()); + let tasks = tasks.take_finished_tasks(); + for mut task in tasks { + let task = task.as_any_mut(); + if let Some(task) = task.downcast_mut::>>() { + let r = task.await; + let r = match r { + Ok(r) => r, + Err(e) => Err(PixivDownloaderError::from(e)), + }; + concat_pixiv_downloader_error!(re, r); + } + } + re }