use std::collections::HashMap;
use super::UA;
use crate::crypto::Crypto;
use serde::Serialize;
use serde_json::{json, Value};
#[derive(Serialize, Debug)]
pub struct ApiRequest {
method: Method,
url: String,
data: Option<H>,
option: RequestOption,
}
pub struct ApiRequestBuilder {
config: Config,
}
struct Config {
method: Method,
url: String,
data: Option<H>,
ua: UA,
cookies: Option<Hm>,
crypto: Crypto,
api_url: Option<String>,
real_ip: Option<String>,
}
type Pieces = (
Method,
String,
Option<H>,
UA,
Option<Hm>,
Crypto,
Option<String>,
Option<String>,
);
impl Default for ApiRequestBuilder {
fn default() -> Self {
ApiRequestBuilder::new(Method::Post, "")
}
}
impl ApiRequestBuilder {
pub fn new(method: Method, url: &str) -> Self {
Self {
config: Config {
method,
url: url.to_owned(),
data: None,
ua: UA::Chrome,
cookies: None,
crypto: Crypto::Weapi,
api_url: None,
real_ip: None,
},
}
}
pub fn build(self) -> ApiRequest {
let (method, url, data, ua, cookies, crypto, api_url, real_ip) = self.pieces();
ApiRequest {
method,
url,
data,
option: RequestOption {
ua,
cookies,
crypto,
api_url,
real_ip,
},
}
}
pub fn post(url: &str) -> Self {
Self::new(Method::Post, url)
}
pub fn pieces(self) -> Pieces {
let config = self.config;
(
config.method,
config.url,
config.data,
config.ua,
config.cookies,
config.crypto,
config.api_url,
config.real_ip,
)
}
pub fn set_data(mut self, data: H) -> Self {
self.config.data = Some(data);
self
}
pub fn insert(mut self, key: &str, val: Value) -> Self {
let mut data = self.config.data.unwrap_or_else(|| json!({}));
data.as_object_mut().unwrap().insert(key.to_owned(), val);
self.config.data = Some(data);
self
}
pub fn merge(mut self, val: Value) -> Self {
if !val.is_object() {
return self;
}
let mut data = self.config.data.unwrap_or_else(|| json!({}));
for (k, v) in val.as_object().unwrap() {
data.as_object_mut()
.unwrap()
.insert(k.to_owned(), v.to_owned());
}
self.config.data = Some(data);
self
}
pub fn set_ua(mut self, ua: UA) -> Self {
self.config.ua = ua;
self
}
#[allow(unused)]
pub fn set_cookies(mut self, cookies: Hm) -> Self {
self.config.cookies = Some(cookies);
self
}
pub fn add_cookie(mut self, name: &str, val: &str) -> Self {
let mut cookies = self.config.cookies.unwrap_or_default();
cookies.insert(name.to_owned(), val.to_owned());
self.config.cookies = Some(cookies);
self
}
pub fn set_crypto(mut self, crypto: Crypto) -> Self {
self.config.crypto = crypto;
self
}
pub fn set_api_url(mut self, u: &str) -> Self {
self.config.api_url = Some(String::from(u));
self
}
pub fn set_real_ip(mut self, real_ip: &str) -> Self {
self.config.real_ip = Some(String::from(real_ip));
self
}
}
impl Default for ApiRequest {
fn default() -> Self {
ApiRequest::new(Method::Post, "")
}
}
impl ApiRequest {
pub fn new(method: Method, url: &str) -> Self {
ApiRequestBuilder::new(method, url).build()
}
pub fn pieces(self) -> Pieces {
(
self.method,
self.url,
self.data,
self.option.ua,
self.option.cookies,
self.option.crypto,
self.option.api_url,
self.option.real_ip,
)
}
#[cfg(feature = "cache")]
fn serialize(&self) -> String {
serde_json::to_string(self).unwrap()
}
#[cfg(feature = "cache")]
pub fn id(&self) -> String {
let id = self.serialize();
crate::api::md5_hex(id.as_bytes())
}
}
#[derive(Serialize, Debug)]
pub struct RequestOption {
ua: UA,
cookies: Option<Hm>,
crypto: Crypto,
api_url: Option<String>,
real_ip: Option<String>,
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
#[allow(unused)]
pub enum Method {
Get,
Head,
Post,
Put,
Delete,
Connect,
Options,
Trace,
Patch,
}
pub(crate) type Hm = HashMap<String, String>;
pub(crate) type H = Value;
#[cfg(test)]
mod tests {
use serde_json::json;
use crate::client::api_request::Hm;
use crate::client::route::API_ROUTE;
use crate::client::ApiRequestBuilder;
use crate::client::UA;
type Rb = ApiRequestBuilder;
#[test]
fn test_request_builder() {
let r = Rb::post(API_ROUTE["search"])
.set_data(json!({
"name": "alex",
}))
.insert("age", json!(19))
.merge(json!({
"books": ["book1", "book2"]
}))
.set_api_url("/api/url")
.set_real_ip("real_ip")
.set_ua(UA::IPhone)
.set_cookies(Hm::new())
.add_cookie("sid", "f1h82fg191fh9")
.build();
assert_eq!(r.data.unwrap()["age"], 19);
}
#[cfg(feature = "cache")]
#[test]
fn test_serialize() {
let r = Rb::post(API_ROUTE["search"])
.set_data(json!({
"name": "alex",
}))
.build();
let a = r.serialize();
println!("{}", a)
}
}