use super::Link;
use crate::{
Result, constants,
error::Error::{self, InternalServer},
};
use http::header::{CONTENT_TYPE, HeaderValue};
use http::{Method, Request};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tracing::debug;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ShortLink {
link: String,
}
#[derive(Debug, Deserialize)]
pub struct ShortLinkArgs {
path: String,
page_title: Option<String>,
is_permanent: bool,
}
#[derive(Debug, Deserialize)]
pub struct ShortLinkArgsBuilder {
path: Option<String>,
page_title: Option<String>,
is_permanent: Option<bool>,
}
impl ShortLinkArgs {
pub fn builder() -> ShortLinkArgsBuilder {
ShortLinkArgsBuilder::new()
}
pub fn path(&self) -> String {
self.path.clone()
}
pub fn page_title(&self) -> Option<String> {
self.page_title.clone()
}
pub fn is_permanent(&self) -> bool {
self.is_permanent
}
}
impl ShortLinkArgsBuilder {
pub fn new() -> Self {
ShortLinkArgsBuilder {
path: None,
page_title: None,
is_permanent: None,
}
}
pub fn path(mut self, path: impl Into<String>) -> Self {
self.path = Some(path.into());
self
}
pub fn page_title(mut self, title: impl Into<String>) -> Self {
self.page_title = Some(title.into());
self
}
pub fn with_permanent(mut self) -> Self {
self.is_permanent = Some(true);
self
}
pub fn build(self) -> Result<ShortLinkArgs> {
let path = self.path.map_or_else(
|| {
Err(Error::InvalidParameter(
"小程序页面路径不能为空".to_string(),
))
},
|v| {
if v.len() > 1024 {
return Err(Error::InvalidParameter(
"页面路径最大长度 1024 个字符".to_string(),
));
}
Ok(v)
},
)?;
Ok(ShortLinkArgs {
path,
page_title: self.page_title,
is_permanent: self.is_permanent.unwrap_or(false),
})
}
}
impl Default for ShortLinkArgsBuilder {
fn default() -> Self {
Self::new()
}
}
impl Link {
pub async fn short_link(&self, args: ShortLinkArgs) -> Result<ShortLink> {
debug!("get qr code args {:?}", &args);
let token = format!("access_token={}", self.client.token().await?);
let mut url = url::Url::parse(constants::SHORT_LINK_END_POINT)?;
url.set_query(Some(&token));
let mut body = HashMap::new();
body.insert("page_url", args.path);
if let Some(page_title) = args.page_title {
body.insert("page_title", page_title.to_string());
}
if args.is_permanent {
body.insert("is_permanent", args.is_permanent.to_string());
}
let client = &self.client.client;
let req_body = serde_json::to_vec(&body)?;
let request = Request::builder()
.uri(url.as_str())
.method(Method::POST)
.header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
.header(
"User-Agent",
HeaderValue::from_static(constants::HTTP_CLIENT_USER_AGENT),
)
.body(req_body)?;
let response = client.execute(request).await?;
debug!("response: {:#?}", response);
if response.status().is_success() {
let (_parts, body) = response.into_parts();
debug!("short link response body: {:?}", &body);
eprintln!(
"short link response body: {:?}",
String::from_utf8_lossy(&body)
);
let json = serde_json::from_slice::<ShortLink>(&body)?;
debug!("short link: {:#?}", &json);
Ok(json)
} else {
let (_parts, body) = response.into_parts();
let message = String::from_utf8_lossy(&body).to_string();
Err(InternalServer(message))
}
}
}