use std::collections::HashMap;
use crate::{auth::Auth, endpoint::*, errors::KdlError};
use derive_builder::Builder;
use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize};
pub struct Client {
auth: Auth,
}
impl Client {
pub fn new(auth: Auth) -> Self {
Self { auth }
}
pub async fn get_order_expire_time(&self) -> KdlResult<GetOrderExpireTimeRets> {
Ok(self
.make_request(GET_ORDER_EXPIRE_TIME, GetOrderExpireTimeArgs)
.await?)
}
pub async fn get_proxy_authorization(&self) -> KdlResult<GetProxyAuthorizationRets> {
Ok(self
.make_request(
GET_PROXY_AUTHORIZATION,
GetProxyAuthorizationArgsBuilder::default()
.build()
.map_err(|_| KdlError::BuidlerError)?,
)
.await?)
}
pub async fn get_account_balance(&self) -> KdlResult<GetAccountBalanceRets> {
Ok(self
.make_request(GET_ACCOUNT_BALANCE, GetAccountBalanceArgs)
.await?)
}
pub async fn get_ua(&self, args: GetUAArgs) -> KdlResult<GetUARets> {
Ok(self.make_request(GET_UA, args).await?)
}
pub async fn get_area_code(&self, args: GetAreaCodeArgs) -> KdlResult<GetAreaCodeRets> {
Ok(self.make_request(GET_AREA_CODE, args).await?)
}
pub async fn check_ops_valid(&self, args: CheckOpsValidArgs) -> KdlResult<CheckOpsValidRets> {
Ok(self.make_request(CHECK_OPS_VALID, args).await?)
}
pub async fn get_ip_balance(&self) -> KdlResult<GetIpBalanceRets> {
Ok(self.make_request(GET_IP_BALANCE, GetIpBalanceArgs).await?)
}
pub async fn get_ip_whitelist(&self) -> KdlResult<GetIpWhitelistRets> {
Ok(self
.make_request(GET_IP_WHITELIST, GetIpWhitelistArgs)
.await?)
}
pub async fn check_dps_valid(&self, args: CheckDpsValidArgs) -> KdlResult<CheckDpsValidRets> {
Ok(self.make_request(CHECK_DPS_VALID, args).await?)
}
pub async fn set_ip_whitelist(
&self,
args: SetIpWhitelistArgs,
) -> KdlResult<SetIpWhitelistRets> {
Ok(self.make_request(SET_IP_WHITELIST, args).await?)
}
pub async fn tps_current_ip(&self) -> KdlResult<TpsCurrentIpRets> {
Ok(self.make_request(TPS_CURRENT_IP, TpsCurrentIpArgs).await?)
}
pub async fn change_tps_ip(&self) -> KdlResult<ChangeTpsIpRets> {
Ok(self.make_request(CHANGE_TPS_IP, ChangeTpsIpArgs).await?)
}
pub async fn get_tps(&self, args: GetTpsArgs) -> KdlResult<GetTpsRets> {
Ok(self.make_request(GET_TPS, args).await?)
}
pub async fn get_dps_valid_time(
&self,
args: GetDpsValidTimeArgs,
) -> KdlResult<GetDpsValidTimeRets> {
Ok(self.make_request(GET_DPS_VALID_TIME, args).await?)
}
pub async fn get_dps(&self, args: GetDpsArgs) -> KdlResult<GetDpsRets> {
Ok(self.make_request(GET_DPS_PROXY, args).await?)
}
pub async fn get_kps(&self, args: GetKpsArgs) -> KdlResult<GetKpsRets> {
Ok(self.make_request(GET_KPS_PROXY, args).await?)
}
pub async fn get_proxy(&self, args: GetProxyArgs) -> KdlResult<GetProxyRets> {
Ok(self.make_request(GET_OPS_PROXY_NORMAL_OR_VIP, args).await?)
}
async fn make_request<A, R>(&self, endpoint: Endpoint, args: A) -> Result<R, KdlError>
where
A: Serialize,
R: DeserializeOwned,
{
let url = format!(
"https://{endpoint}?orderid={order_id}&signature={api_key}&{query_string}",
endpoint = endpoint.to_string(),
order_id = self.auth.get_order_id(),
api_key = self.auth.get_api_key(),
query_string = serde_qs::to_string(&args)?
);
let res = reqwest::get(url).await?.text().await?;
let res = serde_json::from_str::<KdlRet<R>>(&res)?;
match res.code {
0 => Ok(res.data),
c => Err(KdlError::CodeError {
code: c,
message: res.message,
}),
}
}
}
#[derive(Debug, Deserialize)]
struct KdlRet<Data> {
#[serde(rename = "msg")]
message: String,
code: i32,
data: Data,
}
pub type KdlResult<T> = Result<T, KdlError>;
#[derive(Builder, Debug, Serialize)]
pub struct SetIpWhitelistArgs {
#[serde(rename = "iplist")]
ip_list: String,
}
pub type SetIpWhitelistRets = String;
#[derive(Debug, Serialize)]
pub struct TpsCurrentIpArgs;
#[derive(Debug, Deserialize)]
pub struct TpsCurrentIpRets {
current_ip: String,
}
#[derive(Debug, Serialize)]
pub struct ChangeTpsIpArgs;
#[derive(Debug, Deserialize)]
pub struct ChangeTpsIpRets {
current_ip: String,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetTpsArgs {
#[builder(default = "1")]
num: u32,
#[builder(default = "1")]
pt: u32,
#[builder(default = "\"json\".to_string()")]
format: String,
#[builder(default = "\"\n\".to_string()")]
sep: String,
}
#[derive(Debug, Deserialize)]
pub struct GetTpsRets {
count: u32,
proxy_list: Vec<String>,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetDpsValidTimeArgs {
proxy: String,
}
pub type GetDpsValidTimeRets = HashMap<String, u32>;
#[derive(Builder, Debug, Serialize)]
pub struct GetDpsArgs {
num: u32,
#[builder(default = "\"json\".to_string()")]
format: String,
#[builder(default = "\"\n\".to_string()")]
sep: String,
}
#[derive(Debug, Deserialize)]
pub struct GetDpsRets {
count: u32,
dedup_count: u32,
order_left_count: u32,
today_left_count: u32,
proxy_list: Vec<String>,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetKpsArgs {
num: u32,
#[builder(default = "\"json\".to_string()")]
format: String,
#[builder(default = "\"\n\".to_string()")]
sep: String,
}
#[derive(Debug, Deserialize)]
pub struct GetKpsRets {
count: u32,
proxy_list: Vec<String>,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetProxyArgs {
num: u32,
#[builder(default = "\"json\".to_string()")]
format: String,
#[builder(default = "\"\n\".to_string()")]
sep: String,
}
#[derive(Debug, Deserialize)]
pub struct GetProxyRets {
count: u32,
proxy_list: Vec<String>,
}
#[derive(Debug, Serialize)]
pub struct CheckDpsValidArgs {
proxy: String,
}
pub type CheckDpsValidRets = HashMap<String, bool>;
#[derive(Debug, Serialize)]
pub struct GetIpWhitelistArgs;
#[derive(Debug, Deserialize)]
pub struct GetIpWhitelistRets {
count: u32,
#[serde(rename = "ipwhitelist")]
ip_whitelist: Vec<String>,
limit: u32,
}
#[derive(Debug, Serialize)]
pub struct GetOrderExpireTimeArgs;
#[derive(Debug, Deserialize)]
pub struct GetOrderExpireTimeRets {
expire_time: String,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetProxyAuthorizationArgs {
#[builder(default = "1")]
plain_text: u8,
}
#[derive(Debug, Deserialize)]
pub struct GetProxyAuthorizationRets {
r#type: String,
credentials: String,
username: String,
password: String,
}
#[derive(Debug, Serialize)]
pub struct GetAccountBalanceArgs;
#[derive(Debug, Deserialize)]
pub struct GetAccountBalanceRets {
#[serde(deserialize_with = "deserialize_string_to_f32")]
balance: f32,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetUAArgs {
#[builder(default = "1")]
num: u32,
#[builder(default = "vec![UADeviceType::All]")]
dt: Vec<UADeviceType>,
#[builder(default = "vec![UAPlatform::All]")]
platform: Vec<UAPlatform>,
#[builder(default = "vec![UABrowser::All]")]
browser: Vec<UABrowser>,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum UADeviceType {
All,
Pc,
Mobile,
Pad,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum UAPlatform {
All,
Win,
Macos,
Linux,
Ios,
Android,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum UABrowser {
All,
Chrome,
Firefox,
Ie,
Weixin,
}
#[derive(Debug, Deserialize)]
pub struct GetUARets {
count: u32,
ua_list: Vec<String>,
}
#[derive(Builder, Debug, Serialize)]
pub struct GetAreaCodeArgs {
area: String,
}
#[derive(Debug, Deserialize)]
pub struct GetAreaCodeRets {
#[serde(rename = "are_anme")]
area_name: String,
#[serde(rename = "are_code")]
area_code: String,
}
#[derive(Builder, Debug, Serialize)]
pub struct CheckOpsValidArgs {
proxy: String,
}
pub type CheckOpsValidRets = HashMap<String, bool>;
#[derive(Debug, Serialize)]
pub struct GetIpBalanceArgs;
#[derive(Debug, Deserialize)]
pub struct GetIpBalanceRets {
balance: u32,
}
fn deserialize_string_to_f32<'de, D>(d: D) -> Result<f32, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(d)?;
s.parse::<f32>()
.map_err(|e| serde::de::Error::custom(format!("{:?}", e)))
}