diff --git a/src/main.rs b/src/main.rs index 42061fb..9dfd041 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ mod opts; mod parser; mod pixiv_link; mod pixiv_web; +mod push; mod retry_interval; #[cfg(feature = "server")] mod server; diff --git a/src/push/every_push.rs b/src/push/every_push.rs new file mode 100644 index 0000000..773d4c2 --- /dev/null +++ b/src/push/every_push.rs @@ -0,0 +1,91 @@ +use crate::webclient::WebClient; +use std::collections::HashMap; + +pub struct EveryPushClient { + client: WebClient, + server: String, +} + +impl EveryPushClient { + pub fn new(server: String) -> Self { + Self { + client: WebClient::default(), + server, + } + } + + pub async fn push_message( + &self, + push_token: String, + text: String, + title: Option, + typ: Option, + ) -> Result<(), String> { + let mut params: HashMap = HashMap::new(); + params.insert(String::from("pushToken"), push_token); + params.insert(String::from("text"), text); + match title { + Some(t) => params.insert(String::from("title"), t), + None => None, + }; + match typ { + Some(t) => params.insert(String::from("type"), t), + None => None, + }; + let re = self + .client + .post(format!("{}/message/push", self.server), None, Some(params)) + .await + .ok_or("Failed to send push message.")?; + let status = re.status(); + if status.is_success() { + Ok(()) + } else { + match re.text().await { + Ok(t) => match json::parse(t.as_str()) { + Ok(v) => { + let msg = v["message"].as_str(); + match msg { + Some(m) => Err(m.to_owned()), + None => Err(format!("HTTP ERROR {}", status)), + } + } + Err(e) => Err(format!("HTTP ERROR {}: {}", status, e)), + }, + Err(e) => Err(format!("HTTP ERROR {}: {}", status, e)), + } + } + } +} + +#[proc_macros::async_timeout_test(120s)] +#[tokio::test(flavor = "multi_thread")] +async fn test_every_push_push() { + match std::env::var("EVERY_PUSH_SERVER") { + Ok(server) => match std::env::var("EVERY_PUSH_TOKEN") { + Ok(token) => { + let client = EveryPushClient::new(server); + match client + .push_message( + token, + String::from("Push Test"), + Some(String::from("Push")), + None, + ) + .await + { + Ok(_) => {} + Err(e) => { + panic!("{}", e); + } + } + } + Err(_) => { + println!("No every push token specified, skip test.") + } + }, + Err(_) => { + println!("No every push server specified, skip test.") + } + } +} diff --git a/src/push/mod.rs b/src/push/mod.rs new file mode 100644 index 0000000..f937820 --- /dev/null +++ b/src/push/mod.rs @@ -0,0 +1 @@ +pub mod every_push; diff --git a/src/webclient.rs b/src/webclient.rs index ee5ad57..cba5299 100644 --- a/src/webclient.rs +++ b/src/webclient.rs @@ -361,6 +361,103 @@ impl WebClient { } r } + + pub async fn post( + &self, + url: U, + headers: H, + form: Option>, + ) -> Option { + let mut count = 0i64; + let retry = self.get_retry(); + while retry < 0 || count <= retry { + let r = self + ._apost2(url.clone(), headers.clone(), form.clone()) + .await; + if r.is_some() { + return r; + } + count += 1; + if retry < 0 || count <= retry { + let t = + self.get_retry_interval().as_ref().unwrap()[(count - 1).try_into().unwrap()]; + if !t.is_zero() { + println!( + "{}", + gettext("Retry after seconds.") + .replace("", format!("{}", t.as_secs_f64()).as_str()) + .as_str() + ); + tokio::time::sleep(t).await; + } + } + println!( + "{}", + gettext("Retry times now.") + .replace("", format!("{}", count).as_str()) + .as_str() + ); + } + None + } + + pub async fn _apost2( + &self, + url: U, + headers: H, + form: Option>, + ) -> Option { + let r = self._apost(url, headers, form); + let r = r.send().await; + match r { + Ok(_) => {} + Err(e) => { + println!("{} {}", gettext("Error when request:"), e); + return None; + } + } + let r = r.unwrap(); + self.handle_set_cookie(&r); + if self.get_verbose() { + println!("{}", r.status()); + } + Some(r) + } + + /// Generate a POST request + pub fn _apost( + &self, + url: U, + headers: H, + form: Option>, + ) -> RequestBuilder { + let s = url.as_str(); + if self.get_verbose() { + println!("POST {}", s); + } + let mut r = self.client.post(s); + for (k, v) in self.get_headers().iter() { + r = r.header(k, v); + } + let headers = headers.to_headers(); + if headers.is_some() { + let h = headers.unwrap(); + for (k, v) in h.iter() { + r = r.header(k, v); + } + } + let c = gen_cookie_header(&self, s); + if c.len() > 0 { + r = r.header("Cookie", c.as_str()); + } + match form { + Some(f) => { + r = r.form(&f); + } + None => {} + } + r + } } impl Default for WebClient {