whatsapp_cloud_api/
whatspapp_client.rs1use crate::{
2 models::{MediaResponse, Message, MessageResponse, MessageStatus, MessageStatusResponse},
3 WhatsappError,
4};
5
6const FACEBOOK_GRAPH_API_BASE_URL: &str = "https://graph.facebook.com/v17.0";
7
8pub struct WhatasppClient {
9 access_token: String,
10 phone_number_id: String,
11}
12
13impl WhatasppClient {
14 pub fn new(access_token: &str, phone_number_id: &str) -> Self {
15 Self {
16 access_token: access_token.into(),
17 phone_number_id: phone_number_id.into(),
18 }
19 }
20
21 pub async fn send_message(&self, message: &Message) -> Result<MessageResponse, WhatsappError> {
22 http_client::post(&self.messages_api_url(), &self.access_token, message).await
23 }
24
25 pub async fn mark_message_as_read(
26 &self,
27 message_id: &str,
28 ) -> Result<MessageStatusResponse, WhatsappError> {
29 let message_status = MessageStatus::for_read(message_id);
30 http_client::post(
31 &self.messages_api_url(),
32 &self.access_token,
33 &message_status,
34 )
35 .await
36 }
37
38 pub async fn get_media(&self, media_id: &str) -> Result<MediaResponse, WhatsappError> {
39 http_client::get(&self.media_api_url(media_id), &self.access_token).await
40 }
41
42 fn messages_api_url(&self) -> String {
43 format!(
44 "{FACEBOOK_GRAPH_API_BASE_URL}/{}/messages",
45 self.phone_number_id
46 )
47 }
48
49 fn media_api_url(&self, media_id: &str) -> String {
50 format!("{FACEBOOK_GRAPH_API_BASE_URL}/{media_id}")
51 }
52}
53
54mod http_client {
55 use reqwest::StatusCode;
56 use serde::{de::DeserializeOwned, Serialize};
57
58 use crate::WhatsappError;
59
60 pub async fn get<U>(url: &str, bearer_token: &str) -> Result<U, WhatsappError>
61 where
62 U: DeserializeOwned,
63 {
64 let client = reqwest::Client::new();
65 let resp = client.get(url).bearer_auth(bearer_token).send().await?;
66
67 match resp.status() {
68 StatusCode::OK => {
69 let json = resp.json::<U>().await?;
70 Ok(json)
71 }
72 _ => {
73 log::warn!("{:?}", &resp);
74 let error_text = &resp.text().await?;
75 log::warn!("{:?}", &error_text);
76 Err(WhatsappError::UnexpectedError(error_text.to_string()))
77 }
78 }
79 }
80
81 pub async fn post<T, U>(url: &str, bearer_token: &str, data: &T) -> Result<U, WhatsappError>
82 where
83 T: Serialize + ?Sized,
84 U: DeserializeOwned,
85 {
86 let client = reqwest::Client::new();
87 let resp = client
88 .post(url)
89 .bearer_auth(bearer_token)
90 .json(&data)
91 .send()
92 .await?;
93
94 match resp.status() {
95 StatusCode::OK | StatusCode::CREATED => {
96 let json = resp.json::<U>().await?;
97 Ok(json)
98 }
99 _ => {
100 log::warn!("{:?}", &resp);
101 let error_text = &resp.text().await?;
102 log::warn!("{:?}", &error_text);
103 Err(WhatsappError::UnexpectedError(error_text.to_string()))
104 }
105 }
106 }
107}