use std::collections::BTreeMap;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use bytes::Bytes;
use serde::{Serialize, Deserialize};
use serde_json::Value;
use crate::{session::SessionStore, LabradorResult, RequestBody, RequestType, WechatCpClient, WechatRequest, WechatCommonResponse, request, get_nonce_str};
use crate::wechat::cp::constants::{ATTACHMENT_TYPE, MEDIA_TYPE};
use crate::wechat::cp::method::{CpMediaMethod, WechatCpMethod};
#[derive(Debug, Clone)]
pub struct WechatCpMedia<'a, T: SessionStore> {
client: &'a WechatCpClient<T>,
}
#[allow(unused)]
impl<'a, T: SessionStore> WechatCpMedia<'a, T> {
#[inline]
pub fn new(client: &WechatCpClient<T>) -> WechatCpMedia<T> {
WechatCpMedia {
client,
}
}
pub async fn upload_media(&self, media_type: &str, file_name: Option<&str>, data: Vec<u8>) -> LabradorResult<WechatCpMediaResponse> {
let default_file_name = format!("{}.png", get_nonce_str());
let req = WechatCpMediaRequest {
media_type: media_type.to_string(),
file_name: file_name.map(|v| v.to_string()).unwrap_or(default_file_name),
media_data: data
};
let v = self.client.execute::<WechatCpMediaRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpMediaResponse>(v)
}
pub async fn upload_img(&self, media_type: &str, file_name: &str, data: Vec<u8>) -> LabradorResult<WechatCpMediaResponse> {
let req = WechatCpMediaRequest {
media_type: media_type.to_string(),
file_name: file_name.to_string(),
media_data: data
};
let v= self.client.execute::<WechatCpMediaRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpMediaResponse>(v)
}
pub async fn upload_media_with_file(&self, media_type: &str, file_path: &str) -> LabradorResult<WechatCpMediaResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
self.upload_media(media_type, file_name.into(),content).await
}
pub async fn upload_media_with_url(&self, media_type: &str, url: &str) -> LabradorResult<WechatCpMediaResponse> {
let result = request(|client| client.get(url)).await?;
let content = result.bytes()?;
self.upload_media(media_type, None,content.to_vec()).await
}
pub async fn get_media(&self, media_id: &str) -> LabradorResult<Bytes> {
let response = self.client.post(WechatCpMethod::Media(CpMediaMethod::GetMedia), vec![("media_id".to_string(), media_id.to_string())], serde_json::Value::Null, RequestType::Json).await?;
response.bytes()
}
pub async fn upload_attachment_with_file(&self, media_type: &str, attachment_type: &str, file_path: &str) -> LabradorResult<WechatCpMediaResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
self.upload_attachment(media_type, attachment_type, file_name.into(), content).await
}
pub async fn upload_attachment_with_url(&self, media_type: &str, attachment_type: &str, url: &str) -> LabradorResult<WechatCpMediaResponse> {
let result = request(|client| client.get(url)).await?;
let content = result.bytes()?;
self.upload_attachment(media_type, attachment_type,None, content.to_vec()).await
}
pub async fn upload_attachment(&self, media_type: &str, attachment_type: &str, file_name: Option<&str>, data: Vec<u8>) -> LabradorResult<WechatCpMediaResponse> {
let default_file_name = format!("{}.png", get_nonce_str());
let req = WechatCpAttachmentRequest {
media_type: media_type.to_string(),
attachment_type: attachment_type.to_string(),
file_name: file_name.map(|v| v.to_string()).unwrap_or(default_file_name),
media_data: data
};
let v = self.client.execute::<WechatCpAttachmentRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatCpMediaResponse>(v)
}
pub async fn get_media_jssdk(&self, media_id: &str) -> LabradorResult<Bytes> {
let response = self.client.post(WechatCpMethod::Media(CpMediaMethod::GetMediaJssdk), vec![("media_id".to_string(), media_id.to_string())], serde_json::Value::Null, RequestType::Json).await?;
response.bytes()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatCpMediaRequest {
pub media_type: String,
pub file_name: String,
pub media_data: Vec<u8>
}
impl WechatRequest for WechatCpMediaRequest {
fn get_api_method_name(&self) -> String {
CpMediaMethod::UploadMedia(self.media_type.to_string()).get_method()
}
fn get_request_body<T: Serialize>(&self) -> RequestBody<T> {
let form = reqwest::multipart::Form::new().part("media", reqwest::multipart::Part::stream(self.media_data.to_owned()).file_name(self.file_name.to_string()));
form.into()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatCpMediaResponse {
pub url: Option<String>,
pub media_id: Option<String>,
#[serde(rename="type")]
pub r#type: Option<String>,
pub thumb_media_id: Option<String>,
pub created_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatCpAttachmentRequest {
pub media_type: String,
pub attachment_type: String,
pub file_name: String,
pub media_data: Vec<u8>
}
impl WechatRequest for WechatCpAttachmentRequest {
fn get_api_method_name(&self) -> String {
CpMediaMethod::UploadAttachment.get_method()
}
fn get_query_params(&self) -> BTreeMap<String, String> {
BTreeMap::from([(MEDIA_TYPE.to_string(), self.media_type.to_string()), (ATTACHMENT_TYPE.to_string(), self.attachment_type.to_string())])
}
fn get_request_body<T: Serialize>(&self) -> RequestBody<T> {
let form = reqwest::multipart::Form::new().part("file", reqwest::multipart::Part::stream(self.media_data.to_owned()).file_name(self.file_name.to_string()));
form.into()
}
}