use super::{MinappEnvVersion, Qr, QrCode, Rgb};
use crate::utils::{RequestBuilder, ResponseExt};
use crate::{
Result, constants,
error::Error,
new_type::{NonQueryPagePath, SceneString},
};
use http::header::CONTENT_TYPE;
use serde::{Deserialize, Serialize};
use tracing::debug;
#[derive(Debug, Deserialize, Serialize)]
pub struct UnlimitedQrCodeArgs {
page: String,
scene: String,
#[serde(skip_serializing_if = "Option::is_none")]
width: Option<i16>,
#[serde(skip_serializing_if = "Option::is_none")]
check_path: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
auto_color: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
line_color: Option<Rgb>,
#[serde(skip_serializing_if = "Option::is_none")]
is_hyaline: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
env_version: Option<MinappEnvVersion>,
}
#[derive(Debug, Deserialize)]
pub struct UnlimitedQrCodeArgsBuilder {
page: Option<String>,
scene: Option<String>,
width: Option<i16>,
check_path: Option<bool>,
auto_color: Option<bool>,
line_color: Option<Rgb>,
is_hyaline: Option<bool>,
env_version: Option<MinappEnvVersion>,
}
impl UnlimitedQrCodeArgs {
pub fn builder() -> UnlimitedQrCodeArgsBuilder {
UnlimitedQrCodeArgsBuilder::new()
}
pub fn page(&self) -> String {
self.page.clone()
}
pub fn width(&self) -> Option<i16> {
self.width
}
pub fn auto_color(&self) -> Option<bool> {
self.auto_color
}
pub fn line_color(&self) -> Option<Rgb> {
self.line_color.clone()
}
pub fn is_hyaline(&self) -> Option<bool> {
self.is_hyaline
}
pub fn env_version(&self) -> Option<MinappEnvVersion> {
self.env_version.clone()
}
}
impl Default for UnlimitedQrCodeArgsBuilder {
fn default() -> Self {
Self::new()
}
}
impl UnlimitedQrCodeArgsBuilder {
pub fn new() -> Self {
UnlimitedQrCodeArgsBuilder {
page: None,
scene: None,
check_path: None,
width: None,
auto_color: None,
line_color: None,
is_hyaline: None,
env_version: None,
}
}
pub fn page(mut self, page: impl Into<String>) -> Self {
self.page = Some(page.into());
self
}
pub fn scene(mut self, scene: impl Into<String>) -> Self {
self.scene = Some(scene.into());
self
}
pub fn width(mut self, width: i16) -> Self {
self.width = Some(width);
self
}
pub fn with_auto_color(mut self) -> Self {
self.auto_color = Some(true);
self
}
pub fn line_color(mut self, color: Rgb) -> Self {
self.line_color = Some(color);
self
}
pub fn with_is_hyaline(mut self) -> Self {
self.is_hyaline = Some(true);
self
}
pub fn env_version(mut self, version: MinappEnvVersion) -> Self {
self.env_version = Some(version);
self
}
pub fn build(self) -> Result<UnlimitedQrCodeArgs> {
let page = self.page.map_or_else(
|| {
Err(Error::InvalidParameter(
"小程序页面路径不能为空".to_string(),
))
},
|v| {
let path = NonQueryPagePath::try_from(v)?;
Ok(path.to_string())
},
)?;
let scene = self.scene.map_or_else(
|| Err(Error::InvalidParameter("scene 不能为空".to_string())),
|v| {
let valid_scene = SceneString::try_from(v)?;
Ok(valid_scene.to_string())
},
)?;
if self.auto_color.is_some() && self.line_color.is_some() {
return Err(Error::InvalidParameter(
"auto_color 为 true 时,line_color 不能设置".to_string(),
));
}
Ok(UnlimitedQrCodeArgs {
page,
scene,
check_path: self.check_path,
width: self.width,
auto_color: self.auto_color,
line_color: self.line_color,
is_hyaline: self.is_hyaline,
env_version: self.env_version,
})
}
}
impl Qr {
pub async fn unlimited_qr_code(&self, args: UnlimitedQrCodeArgs) -> Result<QrCode> {
debug!("get unlimited qr code args {:?}", &args);
let query = serde_json::json!({
"access_token":self.client.token().await?
});
let headers = serde_json::json!({
"encoding":"null",
CONTENT_TYPE.to_string():"application/json"
});
let body = serde_json::to_value(UnlimitedQrCodeArgs {
page: args.page,
scene: args.scene,
check_path: args.check_path,
width: args.width,
auto_color: args.auto_color,
line_color: args.line_color,
is_hyaline: args.is_hyaline,
env_version: args.env_version,
})?;
let request = RequestBuilder::new(constants::UNLIMITIED_QR_CODE_ENDPOINT)
.headers(headers)
.query(query)
.body(body)
.build()?;
let client = &self.client.client;
let response = client.execute(request).await?;
debug!("get unlimited qr code response: {:#?}", response);
let buffer = response.to_raw()?;
if buffer.len() > 2048 {
return Ok(QrCode { buffer });
}
Err(Error::InternalServer(
String::from_utf8_lossy(&buffer).to_string(),
))
}
}