Update OptHelper, current only an instance in whole programs

This commit is contained in:
2022-05-30 10:44:33 +00:00
committed by GitHub
parent 3f2a9d6ff6
commit c00fbfde9c
7 changed files with 130 additions and 94 deletions

View File

@@ -1,6 +1,6 @@
use crate::author_name_filter::AuthorFiler;
use crate::gettext;
use crate::opthelper::OptHelper;
use crate::opthelper::get_helper;
use crate::pixiv_link::ToPixivID;
use crate::pixiv_link::PixivID;
use json::JsonValue;
@@ -16,11 +16,10 @@ pub struct PixivData {
/// The author
pub author: Option<String>,
pub description: Option<String>,
helper: OptHelper,
}
impl PixivData {
pub fn new<T: ToPixivID>(id: T, helper: OptHelper) -> Option<Self> {
pub fn new<T: ToPixivID>(id: T) -> Option<Self> {
let i = id.to_pixiv_id();
if i.is_none() {
return None;
@@ -30,7 +29,6 @@ impl PixivData {
title: None,
author: None,
description: None,
helper: helper,
})
}
@@ -59,7 +57,7 @@ impl PixivData {
let author = value["userName"].as_str();
if author.is_some() {
let au = author.unwrap();
match self.helper.author_name_filters() {
match get_helper().author_name_filters() {
Some(l) => { self.author = Some(l.filter(au)) }
None => { self.author = Some(String::from(author.unwrap())); }
}

View File

@@ -9,7 +9,7 @@ use crate::data::video::get_video_metadata;
use crate::downloader::pd_file::enums::PdFileResult;
use crate::downloader::pd_file::PdFile;
use crate::gettext;
use crate::opthelper::OptHelper;
use crate::opthelper::get_helper;
use crate::pixiv_link::PixivID;
use crate::pixiv_web::PixivWebClient;
#[cfg(feature = "ugoira")]
@@ -26,7 +26,7 @@ use std::sync::Arc;
impl Main {
pub fn download(&mut self) -> i32 {
let pw = Arc::new(PixivWebClient::new(&self));
let pw = Arc::new(PixivWebClient::new());
if !pw.init() {
println!("{}", gettext("Failed to initialize pixiv web api client."));
return 1;
@@ -53,7 +53,7 @@ impl Main {
0
}
pub async fn download_artwork_page(pw: Arc<PixivWebClient>, page: JsonValue, np: u16, progress_bars: Arc<MultiProgress>, datas: Arc<PixivData>, base: Arc<PathBuf>, helper: Arc<OptHelper>) -> i32 {
pub async fn download_artwork_page(pw: Arc<PixivWebClient>, page: JsonValue, np: u16, progress_bars: Arc<MultiProgress>, datas: Arc<PixivData>, base: Arc<PathBuf>) -> i32 {
let link = &page["urls"]["original"];
if !link.is_string() {
println!("{}", gettext("Failed to get original picture's link."));
@@ -67,6 +67,7 @@ impl Main {
}
let file_name = file_name.unwrap();
let file_name = base.join(file_name);
let helper = get_helper();
let pdf = match PdFile::open(&file_name) {
Ok(f) => {
match f {
@@ -152,7 +153,7 @@ impl Main {
}
}
let r = r.unwrap();
let re = WebClient::adownload_stream(&file_name, r, &helper, Some(progress_bars)).await;
let re = WebClient::adownload_stream(&file_name, r, Some(progress_bars)).await;
if re.is_err() {
println!("{} {}", gettext("Failed to download image:"), link);
return 1;
@@ -174,7 +175,7 @@ impl Main {
let mut re = None;
let pages;
let mut ajax_ver = true;
let helper = Arc::new(pw.helper.clone());
let helper = get_helper();
if helper.use_webpage() {
re = pw.get_artwork(id);
if re.is_some() {
@@ -208,7 +209,7 @@ impl Main {
}
let base = Arc::new(PathBuf::from("."));
let json_file = base.join(format!("{}.json", id));
let mut datas = PixivData::new(id, (*helper).clone()).unwrap();
let mut datas = PixivData::new(id).unwrap();
if ajax_ver {
datas.from_web_page_ajax_data(&re, true);
} else {
@@ -264,7 +265,7 @@ impl Main {
return 1;
}
let r = r.unwrap();
let re = WebClient::download_stream(&file_name, r, &helper);
let re = WebClient::download_stream(&file_name, r);
if re.is_err() {
println!("{} {}", gettext("Failed to download ugoira:"), src);
return 1;
@@ -315,7 +316,7 @@ impl Main {
let progress_bars = Arc::new(MultiProgress::new());
let mut tasks = Vec::new();
for page in pages_data.members() {
let f = tokio::spawn(Self::download_artwork_page(Arc::clone(&pw), page.clone(), np, Arc::clone(&progress_bars), Arc::clone(&datas), Arc::clone(&base), Arc::clone(&helper)));
let f = tokio::spawn(Self::download_artwork_page(Arc::clone(&pw), page.clone(), np, Arc::clone(&progress_bars), Arc::clone(&datas), Arc::clone(&base)));
tasks.push(f);
np += 1;
}
@@ -377,7 +378,7 @@ impl Main {
return 1;
}
let r = r.unwrap();
let re = WebClient::download_stream(&file_name, r, &helper);
let re = WebClient::download_stream(&file_name, r);
if re.is_err() {
println!("{} {}", gettext("Failed to download image:"), link);
return 1;
@@ -447,7 +448,7 @@ impl Main {
return 1;
}
let r = r.unwrap();
let re = WebClient::download_stream(&file_name, r, &helper);
let re = WebClient::download_stream(&file_name, r);
if re.is_err() {
println!("{} {}", gettext("Failed to download image:"), link);
return 1;

View File

@@ -61,11 +61,12 @@ mod ugoira;
mod utils;
mod webclient;
use i18n::gettext;
use opts::Command;
use opts::CommandOpts;
use opts::ConfigCommand;
use settings::SettingStore;
use crate::i18n::gettext;
use crate::opthelper::get_helper;
use crate::opts::Command;
use crate::opts::CommandOpts;
use crate::opts::ConfigCommand;
use crate::settings::SettingStore;
pub struct Main {
pub cmd: Option<CommandOpts>,
@@ -135,6 +136,7 @@ impl Main {
}
None => {}
}
get_helper().update(cmd.clone(), self.settings.as_ref().unwrap().clone());
match cmd.cmd {
Command::Config => {
self.deal_config_cmd();

View File

@@ -1,5 +1,7 @@
use crate::author_name_filter::AuthorNameFilter;
use crate::ext::json::FromJson;
use crate::ext::replace::ReplaceWith2;
use crate::ext::rw_lock::GetRwLock;
use crate::ext::use_or_not::ToBool;
use crate::ext::use_or_not::UseOrNot;
use crate::opt::use_progress_bar::UseProgressBar;
@@ -7,34 +9,37 @@ use crate::opts::CommandOpts;
use crate::list::NonTailList;
use crate::retry_interval::parse_retry_interval_from_json;
use crate::settings::SettingStore;
use std::sync::Arc;
use std::sync::RwLock;
use std::sync::RwLockReadGuard;
use std::time::Duration;
/// An sturct to access all available settings/command line switches
#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct OptHelper {
/// Command Line Options
opt: CommandOpts,
opt: RwLock<CommandOpts>,
/// Settings
settings: SettingStore,
default_retry_interval: NonTailList<Duration>,
_author_name_filters: Option<Vec<AuthorNameFilter>>,
_use_progress_bar: Option<UseProgressBar>,
settings: RwLock<SettingStore>,
default_retry_interval: RwLock<NonTailList<Duration>>,
_author_name_filters: RwLock<Vec<AuthorNameFilter>>,
_use_progress_bar: RwLock<Option<UseProgressBar>>,
}
impl OptHelper {
pub fn author_name_filters(&self) -> Option<&Vec<AuthorNameFilter>> {
if self.settings.have("author-name-filters") {
return self._author_name_filters.as_ref();
pub fn author_name_filters<'a>(&'a self) -> Option<RwLockReadGuard<'a, Vec<AuthorNameFilter>>> {
if self.settings.get_ref().have("author-name-filters") {
return Some(self._author_name_filters.get_ref());
}
None
}
/// return cookies location, no any check
pub fn cookies(&self) -> Option<String> {
if self.opt.cookies.is_some() {
self.opt.cookies.clone()
} else if self.settings.have_str("cookies") {
self.settings.get_str("cookies")
if self.opt.get_ref().cookies.is_some() {
self.opt.get_ref().cookies.clone()
} else if self.settings.get_ref().have_str("cookies") {
self.settings.get_ref().get_str("cookies")
} else {
None
}
@@ -42,53 +47,47 @@ impl OptHelper {
/// return language
pub fn language(&self) -> Option<String> {
if self.opt.language.is_some() {
self.opt.language.clone()
} else if self.settings.have_str("language") {
self.settings.get_str("language")
if self.opt.get_ref().language.is_some() {
self.opt.get_ref().language.clone()
} else if self.settings.get_ref().have_str("language") {
self.settings.get_ref().get_str("language")
} else {
None
}
}
pub fn new(opt: CommandOpts, settings: SettingStore) -> Self {
pub fn update(&self, opt: CommandOpts, settings: SettingStore) {
let mut l = NonTailList::default();
l += Duration::new(3, 0);
let _author_name_filters = if settings.have("author-name-filters") {
Some(AuthorNameFilter::from_json(settings.get("author-name-filters").unwrap()).unwrap())
} else {
None
};
let _use_progress_bar = if opt.use_progress_bar.is_some() {
self.default_retry_interval.replace_with2(l);
if settings.have("author-name-filters") {
self._author_name_filters.replace_with2(AuthorNameFilter::from_json(settings.get("author-name-filters").unwrap()).unwrap());
}
self._use_progress_bar.replace_with2(if opt.use_progress_bar.is_some() {
Some(UseProgressBar::from(opt.use_progress_bar.unwrap()))
} else if settings.have("use-progress-bar") {
Some(UseProgressBar::from(UseOrNot::from_json(settings.get("use-progress-bar").unwrap()).unwrap()))
} else {
None
};
Self {
opt,
settings,
default_retry_interval: l,
_author_name_filters: _author_name_filters,
_use_progress_bar: _use_progress_bar,
}
});
self.opt.replace_with2(opt);
self.settings.replace_with2(settings);
}
pub fn overwrite(&self) -> Option<bool> {
self.opt.overwrite
self.opt.get_ref().overwrite
}
pub fn verbose(&self) -> bool {
self.opt.verbose
self.opt.get_ref().verbose
}
/// Return retry count
pub fn retry(&self) -> Option<u64> {
if self.opt.retry.is_some() {
return Some(self.opt.retry.unwrap());
if self.opt.get_ref().retry.is_some() {
return Some(self.opt.get_ref().retry.unwrap());
}
let re = self.settings.get("retry");
let re = self.settings.get_ref().get("retry");
if re.is_some() {
return Some(re.unwrap().as_u64().unwrap());
}
@@ -97,23 +96,23 @@ impl OptHelper {
/// Return retry interval
pub fn retry_interval(&self) -> NonTailList<Duration> {
if self.opt.retry_interval.is_some() {
return self.opt.retry_interval.as_ref().unwrap().clone();
if self.opt.get_ref().retry_interval.is_some() {
return self.opt.get_ref().retry_interval.as_ref().unwrap().clone();
}
if self.settings.have("retry-interval") {
let v = self.settings.get("retry-interval").unwrap();
if self.settings.get_ref().have("retry-interval") {
let v = self.settings.get_ref().get("retry-interval").unwrap();
return parse_retry_interval_from_json(v).unwrap();
}
self.default_retry_interval.clone()
self.default_retry_interval.get_ref().clone()
}
/// Return whether to use data from webpage first.
pub fn use_webpage(&self) -> bool {
if self.opt.use_webpage {
if self.opt.get_ref().use_webpage {
return true;
}
if self.settings.have_bool("use-webpage") {
return self.settings.get_bool("use-webpage").unwrap();
if self.settings.get_ref().have_bool("use-webpage") {
return self.settings.get_ref().get_bool("use-webpage").unwrap();
}
false
}
@@ -122,40 +121,62 @@ impl OptHelper {
/// Return whether to add/update exif information to image files even
/// when overwrite are disabled.
pub fn update_exif(&self) -> bool {
if self.opt.update_exif {
if self.opt.get_ref().update_exif {
return true;
}
if self.settings.have_bool("update-exif") {
return self.settings.get_bool("update-exif").unwrap();
if self.settings.get_ref().have_bool("update-exif") {
return self.settings.get_ref().get_bool("update-exif").unwrap();
}
false
}
/// Return whether to use progress bar.
pub fn use_progress_bar(&self) -> bool {
if self._use_progress_bar.is_some() {
return self._use_progress_bar.as_ref().unwrap().to_bool();
if self._use_progress_bar.get_ref().is_some() {
return self._use_progress_bar.get_ref().as_ref().unwrap().to_bool();
}
atty::is(atty::Stream::Stdout)
}
/// Return progress bar's template
pub fn progress_bar_template(&self) -> String {
if self.settings.have("progress-bar-template") {
return self.settings.get_str("progress-bar-template").unwrap()
if self.settings.get_ref().have("progress-bar-template") {
return self.settings.get_ref().get_str("progress-bar-template").unwrap()
}
String::from("[{elapsed_precise}] [{wide_bar:.green/yellow}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta}) {msg:40}")
}
/// Return whether to download multiple images at the same time.
pub fn download_multiple_images(&self) -> bool {
match self.opt.download_multiple_images {
match self.opt.get_ref().download_multiple_images {
Some(r) => { return r; }
None => {}
}
if self.settings.have_bool("download-multiple-images") {
return self.settings.get_bool("download-multiple-images").unwrap();
if self.settings.get_ref().have_bool("download-multiple-images") {
return self.settings.get_ref().get_bool("download-multiple-images").unwrap();
}
false
}
}
impl Default for OptHelper {
fn default() -> Self {
Self {
opt: RwLock::new(CommandOpts::default()),
settings: RwLock::new(SettingStore::default()),
default_retry_interval: RwLock::new(NonTailList::default()),
_author_name_filters: RwLock::new(Vec::new()),
_use_progress_bar: RwLock::new(None),
}
}
}
lazy_static!{
#[doc(hidden)]
pub static ref HELPER: Arc<OptHelper> = Arc::new(OptHelper::default());
}
/// Get a [OptHelper] interface.
pub fn get_helper() -> Arc<OptHelper> {
Arc::clone(&HELPER)
}

View File

@@ -366,3 +366,9 @@ pub fn parse_cmd() -> Option<CommandOpts> {
}
re
}
impl Default for CommandOpts {
fn default() -> Self {
Self::new(Command::None)
}
}

View File

@@ -1,10 +1,9 @@
use crate::downloader::pd_file::PdFile;
use crate::ext::rw_lock::GetRwLock;
use crate::gettext;
use crate::opthelper::OptHelper;
use crate::opthelper::get_helper;
use crate::parser::metadata::MetaDataParser;
use crate::webclient::WebClient;
use crate::Main;
use json::JsonValue;
use reqwest::IntoUrl;
use reqwest::Response;
@@ -20,7 +19,6 @@ use std::time::Duration;
/// A client which use Pixiv's web API
pub struct PixivWebClient {
client: WebClient,
pub helper: OptHelper,
/// true if in is initialized
inited: Arc<AtomicBool>,
/// pixiv global data
@@ -30,10 +28,9 @@ pub struct PixivWebClient {
}
impl PixivWebClient {
pub fn new(m: &Main) -> Self {
pub fn new() -> Self {
Self {
client: WebClient::new(),
helper: OptHelper::new(m.cmd.as_ref().unwrap().clone(), m.settings.as_ref().unwrap().clone()),
inited: Arc::new(AtomicBool::new(false)),
data: RwLock::new(None),
params: RwLock::new(None),
@@ -75,14 +72,15 @@ impl PixivWebClient {
}
pub fn init(&self) -> bool {
let c = self.helper.cookies();
let helper = get_helper();
let c = helper.cookies();
if c.is_some() {
if !self.client.read_cookies(c.as_ref().unwrap()) {
return false;
}
}
self.client.set_header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36");
let l = self.helper.language();
let l = helper.language();
if l.is_some() {
self.client.set_header("Accept-Language", l.as_ref().unwrap());
self.params.get_mut().replace(json::object! { "lang": l.as_ref().unwrap().replace("-", "_").as_str() });
@@ -90,12 +88,12 @@ impl PixivWebClient {
self.client.set_header("Accept-Language", "ja");
self.params.get_mut().replace(json::object! { "lang": "ja" });
}
self.client.set_verbose(self.helper.verbose());
let retry = self.helper.retry();
self.client.set_verbose(helper.verbose());
let retry = helper.retry();
if retry.is_some() {
self.client.set_retry(retry.unwrap());
}
self.client.get_retry_interval_as_mut().replace(self.helper.retry_interval());
self.client.get_retry_interval_as_mut().replace(helper.retry_interval());
self.inited.store(true, Ordering::Relaxed);
true
}
@@ -133,7 +131,7 @@ impl PixivWebClient {
println!("{}", gettext("Failed to parse main page."));
return false;
}
if self.helper.verbose() {
if get_helper().verbose() {
println!("{}\n{}", gettext("Main page's data:"), p.value.as_ref().unwrap().pretty(2).as_str());
}
self.get_data_as_mut().replace(p.value.unwrap());
@@ -229,7 +227,7 @@ impl PixivWebClient {
}
let r = r.unwrap();
let v = self.deal_json(r);
if self.helper.verbose() && v.is_some() {
if get_helper().verbose() && v.is_some() {
println!("{} {}", gettext("Artwork's data:"), v.as_ref().unwrap().pretty(2));
}
v
@@ -259,7 +257,7 @@ impl PixivWebClient {
println!("{}", gettext("Failed to parse artwork page."));
return None;
}
if self.helper.verbose() {
if get_helper().verbose() {
println!("{} {}", gettext("Artwork's data:"), p.value.as_ref().unwrap().pretty(2));
}
Some(p.value.unwrap())
@@ -273,7 +271,7 @@ impl PixivWebClient {
}
let r = r.unwrap();
let v = self.deal_json(r);
if self.helper.verbose() && v.is_some() {
if get_helper().verbose() && v.is_some() {
println!("{} {}", gettext("Artwork's page data:"), v.as_ref().unwrap().pretty(2));
}
v
@@ -287,7 +285,7 @@ impl PixivWebClient {
}
let r = r.unwrap();
let v = self.deal_json(r);
if self.helper.verbose() && v.is_some() {
if get_helper().verbose() && v.is_some() {
println!("{} {}", gettext("Ugoira's data:"), v.as_ref().unwrap().pretty(2));
}
v
@@ -310,7 +308,7 @@ impl PixivWebClient {
impl Drop for PixivWebClient {
fn drop(&mut self) {
if self.is_inited() {
let c = self.helper.cookies();
let c = get_helper().cookies();
if c.is_some() {
if !self.client.save_cookies(c.as_ref().unwrap()) {
println!("{} {}", gettext("Warning: Failed to save cookies file:"), c.as_ref().unwrap());

View File

@@ -5,7 +5,7 @@ use crate::cookies::CookieJar;
use crate::ext::json::ToJson;
use crate::gettext;
use crate::list::NonTailList;
use crate::opthelper::OptHelper;
use crate::opthelper::get_helper;
use futures_util::StreamExt;
use indicatif::MultiProgress;
use indicatif::ProgressBar;
@@ -15,6 +15,7 @@ use reqwest::{Client, IntoUrl, RequestBuilder, Response};
use spin_on::spin_on;
use std::collections::HashMap;
use std::convert::TryInto;
use std::default::Default;
use std::ffi::OsStr;
use std::fs::File;
use std::fs::remove_file;
@@ -474,8 +475,9 @@ impl WebClient {
/// * `progess_bars` - Multiple progress bars
///
/// Note: If file already exists, will remove existing file first.
pub async fn adownload_stream<S: AsRef<OsStr> + ?Sized>(file_name: &S, r: Response, opt: &OptHelper, progress_bars: Option<Arc<MultiProgress>>) -> Result<(), ()> {
pub async fn adownload_stream<S: AsRef<OsStr> + ?Sized>(file_name: &S, r: Response, progress_bars: Option<Arc<MultiProgress>>) -> Result<(), ()> {
let content_length = r.content_length();
let opt = get_helper();
let use_progress_bar = match &content_length {
Some(_) => { opt.use_progress_bar() }
None => { false }
@@ -558,8 +560,9 @@ impl WebClient {
/// * `opt` - Options
///
/// Note: If file already exists, will remove existing file first.
pub fn download_stream<S: AsRef<OsStr> + ?Sized>(file_name: &S, r: Response, opt: &OptHelper) -> Result<(), ()> {
pub fn download_stream<S: AsRef<OsStr> + ?Sized>(file_name: &S, r: Response) -> Result<(), ()> {
let content_length = r.content_length();
let opt = get_helper();
let use_progress_bar = match &content_length {
Some(_) => { opt.use_progress_bar() }
None => { false }
@@ -613,3 +616,10 @@ impl WebClient {
Ok(())
}
}
impl Default for WebClient {
fn default() -> Self {
let c = Self::new();
c
}
}