labrador/wechat/miniapp/api/
media.rs

1use std::fs::File;
2use std::io::Read;
3use std::path::Path;
4use bytes::Bytes;
5use serde::{Serialize, Deserialize};
6use serde_json::Value;
7
8use crate::{session::SessionStore, LabradorResult, RequestBody, RequestType, WechatCommonResponse, request, get_nonce_str};
9use crate::wechat::miniapp::method::{MaMediaMethod, WechatMaMethod};
10use crate::wechat::miniapp::{WechatMaClient, WechatRequest};
11
12
13#[derive(Debug, Clone)]
14pub struct WechatMaMedia<'a, T: SessionStore> {
15    client: &'a WechatMaClient<T>,
16}
17
18#[allow(unused)]
19impl<'a, T: SessionStore> WechatMaMedia<'a, T> {
20
21    #[inline]
22    pub fn new(client: &WechatMaClient<T>) -> WechatMaMedia<T> {
23        WechatMaMedia {
24            client,
25        }
26    }
27
28    /// <pre>
29    /// 新增临时素材
30    /// 小程序可以使用本接口把媒体文件(目前仅支持图片)上传到微信服务器,用户发送客服消息或被动回复用户消息。
31    /// 详情请见: <a href="https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/material.html#新增临时素材">新增临时素材</a>
32    /// 接口url格式:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
33    /// </pre>
34    pub async fn upload_media(&self, media_type: &str, file_name: Option<&str>, data: Vec<u8>) -> LabradorResult<WechatMaMediaResponse> {
35        let default_file_name = format!("{}.png", get_nonce_str());
36        let req = WechatMaMediaRequest {
37            media_type: media_type.to_string(),
38            file_name: file_name.map(|v| v.to_string()).unwrap_or(default_file_name),
39            media_data: data
40        };
41        let v= self.client.execute::<WechatMaMediaRequest, String>(req).await?.json::<Value>()?;
42        WechatCommonResponse::parse::<WechatMaMediaResponse>(v)
43    }
44
45    /// <pre>
46    /// 新增临时素材
47    /// 小程序可以使用本接口把媒体文件(目前仅支持图片)上传到微信服务器,用户发送客服消息或被动回复用户消息。
48    ///
49    /// 详情请见: <a href="https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/material.html#新增临时素材">新增临时素材</a>
50    /// 接口url格式:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
51    /// </pre>
52    pub async fn upload_media_with_file(&self, media_type: &str, file_path: &str) -> LabradorResult<WechatMaMediaResponse> {
53        let path = Path::new(file_path);
54        let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
55        let mut f = File::open(path)?;
56        let mut content: Vec<u8> = Vec::new();
57        let _ = f.read_to_end(&mut content)?;
58        self.upload_media(media_type, file_name.into(),content).await
59    }
60
61    /// <pre>
62    /// 新增临时素材
63    /// 小程序可以使用本接口把媒体文件(目前仅支持图片)上传到微信服务器,用户发送客服消息或被动回复用户消息。
64    ///
65    /// 详情请见: <a href="https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/material.html#新增临时素材">新增临时素材</a>
66    /// 接口url格式:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
67    /// </pre>
68    pub async fn upload_media_with_url(&self, media_type: &str, url: &str) -> LabradorResult<WechatMaMediaResponse> {
69        let result = request(|client| client.get(url)).await?;
70        let content = result.bytes()?;
71        self.upload_media(media_type, None,content.to_vec()).await
72    }
73
74    /// <pre>
75    /// 获取临时素材
76    /// 小程序可以使用本接口获取客服消息内的临时素材(即下载临时的多媒体文件)。目前小程序仅支持下载图片文件。
77    ///
78    /// 详情请见: <a href="https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/material.html#获取临时素材">获取临时素材</a>
79    /// 接口url格式:https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
80    /// </pre>
81    pub async fn get_media(&self, media_id: &str) -> LabradorResult<Bytes> {
82        let response = self.client.post(WechatMaMethod::Media(MaMediaMethod::GetMedia), vec![("media_id".to_string(), media_id.to_string())], serde_json::Value::Null, RequestType::Json).await?;
83        response.bytes()
84    }
85}
86
87//----------------------------------------------------------------------------------------------------------------------------
88
89
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct WechatMaMediaRequest {
93    pub media_type: String,
94    pub file_name: String,
95    pub media_data: Vec<u8>
96}
97
98impl WechatRequest for WechatMaMediaRequest {
99    fn get_api_method_name(&self) -> String {
100        MaMediaMethod::UploadMedia(self.media_type.to_string()).get_method()
101    }
102
103    fn get_request_body<T: Serialize>(&self) -> RequestBody<T> {
104        let form = reqwest::multipart::Form::new().part("media", reqwest::multipart::Part::stream(self.media_data.to_owned()).file_name(self.file_name.to_string()));
105        form.into()
106    }
107}
108
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct WechatMaMediaResponse {
112    pub url: Option<String>,
113    pub media_id: Option<String>,
114    #[serde(rename="type")]
115    pub r#type: Option<String>,
116    pub thumb_media_id: Option<String>,
117    pub created_at: Option<i64>,
118}