Skip to main content

facebook_api_rs/graph/batch/
request.rs

1use crate::prelude::errors::{ClientErr, FacebookAPiError};
2use crate::prelude::HttpConnection;
3use serde::de::DeserializeOwned;
4use serde::Deserialize;
5use serde_json::{json, Value};
6use std::fmt::Debug;
7
8pub struct BatchApi {
9    pub base_url: String,
10    pub page_access_token: String,
11    pub page_id: String,
12}
13
14impl BatchApi {
15    pub fn new(base_url: String, page_access_token: String, page_id: String) -> Self {
16        BatchApi {
17            base_url,
18            page_access_token,
19            page_id,
20        }
21    }
22
23    pub async fn request(
24        self,
25        batch_items: BatchItems,
26    ) -> Result<Vec<BatchResponseBody>, ClientErr> {
27        let batch = serde_json::to_string(&batch_items.data).unwrap();
28
29        let url = self.base_url
30            + "?batch="
31            + &batch
32            + "&access_token="
33            + &self.page_access_token
34            + "&include_headers=false";
35
36        let resp =
37            HttpConnection::batch_post::<Vec<BatchResponseBody>, String>(url, "".to_string())
38                .await?;
39        Ok(resp)
40    }
41
42    pub async fn request_with_type<T>(
43        self,
44        batch_items: BatchItems,
45    ) -> Result<Vec<BatchResponseBodyWithType<T>>, ClientErr>
46    where
47        T: DeserializeOwned,
48    {
49        let batch = serde_json::to_string(&batch_items.data).unwrap();
50
51        let url = self.base_url
52            + "?batch="
53            + &batch
54            + "&access_token="
55            + &self.page_access_token
56            + "&include_headers=false";
57
58        let resp: Vec<BatchResponseBody> =
59            HttpConnection::batch_post::<Vec<BatchResponseBody>, String>(url, "".to_string())
60                .await?;
61
62        let mut resp_body: Vec<BatchResponseBodyWithType<T>> = Vec::new();
63
64        for body in resp {
65            if let Some(data) = body.body {
66                if body.code == 200 {
67                    let data: T = serde_json::from_str(&data.as_str())?;
68
69                    resp_body.push(BatchResponseBodyWithType {
70                        code: body.code,
71                        body: Some(data),
72                        error: None,
73                    })
74                } else {
75                    let data: FacebookAPiError = serde_json::from_str(&data.as_str())?;
76
77                    resp_body.push(BatchResponseBodyWithType {
78                        code: body.code,
79                        body: None,
80                        error: Some(data),
81                    })
82                }
83            } else {
84                resp_body.push(BatchResponseBodyWithType {
85                    code: body.code,
86                    body: None,
87                    error: None,
88                })
89            }
90        }
91        Ok(resp_body)
92    }
93}
94
95#[derive(Deserialize, Debug, Clone, Default)]
96pub struct BatchItems {
97    pub data: Vec<Value>,
98}
99
100impl BatchItems {
101    pub fn add_batch_item_with_body(
102        mut self,
103        method: &str,
104        body: String,
105        relative_url: &str,
106    ) -> Self {
107        let data = json!(
108            {
109                "method": method.to_uppercase(),
110               "relative_url":relative_url,
111                "body": body
112            }
113        );
114
115        self.data.push(data);
116        self
117    }
118
119    pub fn add_batch_item_with_body_access_token(
120        mut self,
121        method: &str,
122        body: String,
123        relative_url: &str,
124        access_token: String,
125    ) -> Self {
126        let data = json!(
127            {
128                "method": method.to_uppercase(),
129               "relative_url":relative_url.to_owned() + "?access_token=" + &access_token,
130                "body": body
131            }
132        );
133        self.data.push(data);
134        self
135    }
136
137    pub fn add_batch_item_without_body(mut self, method: &str, relative_url: &str) -> Self {
138        let data = json!(
139            {
140                "method": method.to_uppercase(),
141               "relative_url":relative_url,
142            }
143        );
144        self.data.push(data);
145        self
146    }
147
148    pub fn add_batch_item_with_access_token(
149        mut self,
150        method: &str,
151        relative_url: &str,
152        access_token: String,
153    ) -> Self {
154        let data = json!(
155            {
156                "method": method.to_uppercase(),
157               "relative_url":relative_url.to_owned() + "?access_token=" + &access_token,
158            }
159        );
160        self.data.push(data);
161        self
162    }
163}
164
165#[derive(Deserialize, Debug, Clone)]
166pub struct BatchResponseBody {
167    pub code: u64,
168    pub body: Option<String>,
169}
170
171#[derive(Deserialize, Debug, Clone)]
172pub struct BatchResponseBodyWithType<T> {
173    pub code: u64,
174    pub body: Option<T>,
175    pub error: Option<FacebookAPiError>,
176}