1use reqwest::{Client, ClientBuilder, header::HeaderMap};
2
3pub use errors::ApiError;
4pub use bot::{Bot};
5use serde_json::{ Value};
6use std::{collections::HashMap};
7use std::fs::File;
8use std::io::BufReader;
9
10mod errors;
11mod utils;
12mod api;
13mod bot;
14mod test;
15
16use crate::api::SarufiApiError;
17
18
19
20pub struct SarufiAPI {
23 client: Client,
24}
25
26
27impl SarufiAPI {
28 pub fn new<S: Into<String>>(api_key: S) -> Result<SarufiAPI, ApiError> {
31 let owned_key = api_key.into();
32
33 utils::validate_keys(&owned_key)?;
34
35 let mut default_headers = HeaderMap::new();
36 default_headers.insert("Authorization", format!("Bearer {}", owned_key).parse().unwrap());
37 default_headers.insert("Content-Type", "application/json".parse().unwrap());
38
39
40 let client = ClientBuilder::new().default_headers(default_headers).build()?;
41
42 Ok(SarufiAPI { client })
43 }
44
45
46 pub async fn get_bot(&self, id: usize) -> Result<Bot, ApiError> {
47 let url = utils::api_url(&format!("/chatbot/{}", id));
48
49 let response = self.client.get(&url).send().await?;
50
51 if response.status().is_success() {
52 let result = response.json::<Bot>().await?;
53 Ok(result)
54 } else {
55 let error = response.json::<SarufiApiError>().await?;
56 Err(ApiError::GenericError(error.message()))
57 }
58
59 }
60
61 pub async fn get_all_bots(&self) -> Result<Vec<Bot>, ApiError> {
62 let url = utils::api_url("/chatbots");
63 let response = self.client.get(&url).send().await?;
64
65 if response.status().is_success() {
66 let result = response.json::<Vec<Bot>>().await?;
67 Ok(result)
68 } else {
69 let error = response.json::<SarufiApiError>().await?;
70 Err(ApiError::GenericError(error.message()))
71 }
72
73 }
74
75 pub async fn _fetch_response(&self, bot_id: usize, chat_id: &str, message: &str, message_type: &str, channel: &str) -> Result<String, ApiError> {
76 let _url = utils::api_url("/conversation");
77
78 if channel == "whatsapp" {
79 let _url = utils::api_url("/conversation/whatsapp");
80 }
81
82 let mut data = HashMap::new();
83 data.insert("bot_id".to_owned(), Value::Number(serde_json::Number::from(bot_id)));
84 data.insert("chat_id".to_owned(), Value::String(chat_id.to_owned()));
85 data.insert("message".to_owned(), Value::String(message.to_owned()));
86 data.insert("message_type".to_owned(), Value::String(message_type.to_owned()));
87 data.insert("channel".to_owned(), Value::String(channel.to_owned()));
88
89 let response = self.client.post(&_url).json(&Value::Object(data.into_iter().collect())).send().await?;
90
91 if response.status().is_success() {
92
93 let json_string = response.text().await.unwrap();
94 let json_value: Value = serde_json::from_str(&json_string).unwrap();
95 let result = & json_value["message"][0];
96
97 Ok(result.to_string())
98 } else {
99 let error = response.json::<SarufiApiError>().await?;
100 Err(ApiError::GenericError(error.message()))
101 }
102 }
103
104 pub async fn chat(&self, bot_id: usize) -> Result<String, ApiError> {
105 let chat_id = utils::generate_uuid().to_string();
106 println!("Chat ID: {:?}", chat_id);
107 let message = "Hello";
108 let message_type = "text";
109 let channel = "general";
110
111 let response = self._fetch_response(bot_id, &chat_id, message, message_type, channel).await.unwrap();
112
113 Ok(response)
114 }
115
116 pub async fn chat_status(&self, bot_id: usize, chat_id: &str) -> Result<String, ApiError> {
117 let url = utils::api_url("/allchannels/status");
118
119 let mut data = HashMap::new();
120 data.insert("bot_id".to_owned(), Value::Number(serde_json::Number::from(bot_id)));
121 data.insert("chat_id".to_owned(), Value::String(chat_id.to_owned()));
122
123 let response = self.client.post(&url).json(&Value::Object(data.into_iter().collect())).send().await?;
124
125 if response.status().is_success() {
126 let json_string = response.text().await.unwrap();
127 Ok(json_string)
128 } else {
129 let error = response.json::<SarufiApiError>().await?;
130 Err(ApiError::GenericError(error.message()))
131 }
132 }
133
134 pub async fn update_conversation_state(&self, bot_id: usize, chat_id: &str, next_state: &str) -> Result<String, ApiError> {
135
136 let url = utils::api_url("/conversation-state");
137
138 let mut data = HashMap::new();
139 data.insert("bot_id".to_owned(), Value::Number(serde_json::Number::from(bot_id)));
140 data.insert("chat_id".to_owned(), Value::String(chat_id.to_owned()));
141 data.insert("next_state".to_owned(), Value::String(next_state.to_owned()));
142
143 let response = self.client.post(&url).json(&Value::Object(data.into_iter().collect())).send().await?;
144
145 if response.status().is_success() {
146 let json_string = response.text().await.unwrap();
147 Ok(json_string)
151 } else {
152 let error = response.json::<SarufiApiError>().await?;
153 Err(ApiError::GenericError(error.message()))
154 }
155
156
157 }
158 pub async fn delete_bot(&self, id: usize) -> Result<(), ApiError> {
159 let url = utils::api_url(&format!("/chatbot/{}", id));
160 let response = self.client.delete(&url).send().await?;
161
162 if response.status().is_success() {
163
164 Ok(())
165 } else {
166 let error = response.json::<SarufiApiError>().await?;
167 Err(ApiError::GenericError(error.message()))
168 }
169
170 }
171
172 pub async fn create_bot(&self,
174 name: &str,
175 description: Option<&str>,
176 industry: Option<&str>,
177 flow: Option<HashMap<String, Value>>,
178 intents: Option<HashMap<String, Vec<String>>>,
179 webhook_url: Option<&str>,
180 webhook_trigger_intents: Option<Vec<String>>,
181 visible_on_community: Option<bool>) -> Result<Bot, ApiError> {
182
183 let url = utils::api_url("/chatbot");
184 let mut data = HashMap::new();
185
186 data.insert("name".to_owned(), Value::String(name.to_owned()));
187
188 if let Some(description) = description {
189 data.insert("description".to_owned(), Value::String(description.to_owned()));
190 }
191
192 if let Some(industry) = industry {
193 data.insert("industry".to_owned(), Value::String(industry.to_owned()));
194 }
195
196 if let Some(flow) = flow {
197 data.insert("flow".to_owned(), Value::Object(flow.into_iter().collect()));
198 }
199
200 if let Some(intents) = intents {
201 data.insert(
202 "intents".to_owned(),
203 Value::Object(
204 intents
205 .into_iter()
206 .map(|(k, v)| (k, Value::Array(v.into_iter().map(Value::String).collect())))
207 .collect(),
208 ),
209 );
210 }
211
212 if let Some(webhook_url) = webhook_url {
213 data.insert("webhook_url".to_owned(), Value::String(webhook_url.to_owned()));
214 }
215
216 if let Some(webhook_trigger_intents) = webhook_trigger_intents {
217 data.insert(
218 "webhook_trigger_intents".to_owned(),
219 Value::Array(webhook_trigger_intents.into_iter().map(Value::String).collect()),
220 );
221 }
222
223 if let Some(visible_on_community) = visible_on_community {
224 data.insert("visible_on_community".to_owned(), Value::Bool(visible_on_community));
225 }
226
227 let response = self.client.post(&url).json(&Value::Object(data.into_iter().collect())).send().await?;
228
229
230 if response.status().is_success() {
231
232 let mut result = response.json::<Bot>().await?;
233
234 if let Some(e_metrics) = result.evaluation_metrics {
236
237 result.evaluation_metrics = Some(e_metrics);
238 }
239
240 if let Some(confidence_threshold) = result.confidence_threshold {
241
242 result.confidence_threshold = Some(confidence_threshold);
243 }
244 Ok(result)
250 } else {
251 let error = response.json::<SarufiApiError>().await?;
252 Err(ApiError::GenericError(error.message()))
253 }
254
255
256 }
257
258
259 pub async fn create_bot_from_file(
260 &self,
261 file_path: &str,
262 ) -> Result<Bot, ApiError> {
263 let file = File::open(file_path)?;
264 let reader = BufReader::new(file);
265 let data: Value = serde_json::from_reader(reader)?;
266 let data = data.as_object().ok_or_else(|| ApiError::GenericError("Invalid JSON".to_owned()))?;
267 print!("{:?}", data);
268
269 let url = utils::api_url("/chatbot");
270 let response = self.client.post(&url).json(&data).send().await?;
271
272 if response.status().is_success() {
273 let mut result = response.json::<Bot>().await?;
274
275 if let Some(e_metrics) = result.evaluation_metrics {
276 result.evaluation_metrics = Some(e_metrics);
277 }
278
279 if let Some(confidence_threshold) = result.confidence_threshold {
280 result.confidence_threshold = Some(confidence_threshold);
281 }
282
283 Ok(result)
284 } else {
285 let error = response.json::<SarufiApiError>().await?;
286 Err(ApiError::GenericError(error.message()))
287 }
288 }
289
290 pub async fn update_bot(&self,
291 id: usize,
292 name: &str,
293 description: Option<&str>,
294 industry: Option<&str>,
295 flow: Option<HashMap<String, Value>>,
296 intents: Option<HashMap<String, Vec<String>>>,
297 webhook_url: Option<&str>,
298 webhook_trigger_intents: Option<Vec<String>>,
299 visible_on_community: Option<bool>) -> Result<Bot, ApiError> {
300
301 let url = utils::api_url(&format!("/chatbot/{}", id));
302 let mut data = HashMap::new();
303
304 data.insert("name".to_owned(), Value::String(name.to_owned()));
305
306 if let Some(description) = description {
307 data.insert("description".to_owned(), Value::String(description.to_owned()));
308 }
309
310 if let Some(industry) = industry {
311 data.insert("industry".to_owned(), Value::String(industry.to_owned()));
312 }
313
314 if let Some(flow) = flow {
315 data.insert("flow".to_owned(), Value::Object(flow.into_iter().collect()));
316 }
317
318 if let Some(intents) = intents {
319 data.insert(
320 "intents".to_owned(),
321 Value::Object(
322 intents
323 .into_iter()
324 .map(|(k, v)| (k, Value::Array(v.into_iter().map(Value::String).collect())))
325 .collect(),
326 ),
327 );
328 }
329
330 if let Some(webhook_url) = webhook_url {
331 data.insert("webhook_url".to_owned(), Value::String(webhook_url.to_owned()));
332 }
333
334 if let Some(webhook_trigger_intents) = webhook_trigger_intents {
335 data.insert(
336 "webhook_trigger_intents".to_owned(),
337 Value::Array(webhook_trigger_intents.into_iter().map(Value::String).collect()),
338 );
339 }
340
341 if let Some(visible_on_community) = visible_on_community {
342 data.insert("visible_on_community".to_owned(), Value::Bool(visible_on_community));
343 }
344
345 let response = self.client.put(&url).json(&Value::Object(data.into_iter().collect())).send().await?;
346
347 if response.status().is_success() {
348 let result = response.json::<Bot>().await?;
349 Ok(result)
350 } else {
351 let error = response.json::<SarufiApiError>().await?;
352 Err(ApiError::GenericError(error.message()))
353 }
354
355 }
356
357
358}
359
360