zero_bounce/api/
bulk.rs

1use std::collections::HashMap;
2
3use serde_json::from_str;
4
5use crate::ZeroBounce;
6use crate::utility::{ZBResult, ZBError};
7use crate::utility::{CONTENT_TYPE_JSON, CONTENT_TYPE_STREAM};
8use crate::utility::{ENDPOINT_FILE_SEND, ENDPOINT_FILE_STATUS, ENDPOINT_FILE_RESULT, ENDPOINT_FILE_DELETE};
9use crate::utility::{ENDPOINT_SCORING_DELETE, ENDPOINT_SCORING_STATUS, ENDPOINT_SCORING_RESULT, ENDPOINT_SCORING_SEND};
10use crate::utility::structures::bulk::{ZBBulkResponse, ZBFile, ZBFileFeedback, ZBFileStatus};
11
12
13impl ZeroBounce {
14
15    fn generic_file_submit(&self, endpoint: &str, zb_file: &ZBFile) -> ZBResult<ZBFileFeedback> {
16        let multi_part_form = zb_file.generate_multipart()?
17            .text("api_key", self.api_key.clone());
18
19        let url = self.url_provider.bulk_url_of(endpoint);
20        let response = self.client.post(url)
21            .multipart(multi_part_form)
22            .send()?;
23
24        let response_ok = response.status().is_success();
25        let response_content = response.text()?;
26
27        // Debug: Print raw response to examine structure in debug mode
28        #[cfg(debug_assertions)]
29        {
30            eprintln!("Raw API response: {}", response_content);
31        }
32
33        if !response_ok {
34            return Err(ZBError::ExplicitError(response_content));
35        }
36
37        let feedback_object = from_str::<ZBFileFeedback>(&response_content)?;
38        Ok(feedback_object)
39    }
40
41    fn generic_file_status_check(&self, endpoint: &str, file_id: &str) -> ZBResult<ZBFileStatus> {
42        let query_args = HashMap::from([
43            ("file_id", file_id),
44        ]);
45
46        let response_content = self.generic_get_request(
47            self.url_provider.bulk_url_of(endpoint), query_args
48        )?;
49
50        let file_status = from_str::<ZBFileStatus>(&response_content)?;
51        Ok(file_status)
52    }
53
54    fn generic_result_fetch(&self, endpoint: &str, file_id: &str) -> ZBResult<ZBBulkResponse> {
55        let query_args = HashMap::from([
56            ("file_id", file_id),
57        ]);
58
59        let url = &self.url_provider.bulk_url_of(endpoint);
60        let response = self.client
61            .get(url)
62            .query(&query_args)
63            .send()?;
64
65        // check if the response is a file, based on the content type
66        let content_type = response
67            .headers()
68            .get("Content-Type")
69            .ok_or(ZBError::explicit("content type not specified in response"))?
70            .to_str()
71            .map_err(|error| ZBError::ExplicitError(error.to_string()))?
72            .to_string();
73
74        let status_amount = response.status().as_u16();
75        if !response.status().is_success() {
76            let response_content = response.text()?;
77            // Debug: Print raw response to examine structure in debug mode
78            #[cfg(debug_assertions)]
79            {
80                eprintln!("Raw API response: {}", response_content);
81            }
82            return Err(ZBError::ExplicitError(response_content))
83        }
84
85        if content_type == CONTENT_TYPE_STREAM {
86            let content = response.bytes()?;
87            return Ok(ZBBulkResponse::Content(content));
88        }
89
90        let response_content = response.text()?;
91
92        // Debug: Print raw response to examine structure in debug mode (only for JSON responses)
93        #[cfg(debug_assertions)]
94        {
95            if content_type == CONTENT_TYPE_JSON {
96                eprintln!("Raw API response: {}", response_content);
97            }
98        }
99
100        if content_type == CONTENT_TYPE_JSON {
101            let feedback_res = from_str::<ZBFileFeedback>(&response_content);
102            if let Ok(file_feedback) = feedback_res {
103                return Ok(ZBBulkResponse::Feedback(file_feedback));
104            }
105        }
106
107        // content was not the expected one
108        let error_ = format!(
109            "Status: {}. Content-type: {}. Response content: {}",
110            status_amount,
111            content_type,
112            response_content,
113        );
114        Err(ZBError::ExplicitError(error_))
115    }
116
117    fn generic_result_delete(&self, endpoint: &str, file_id: &str) -> ZBResult<ZBFileFeedback>{
118        let query_args = HashMap::from([
119            ("file_id", file_id),
120        ]);
121
122        let response_content = self.generic_get_request(
123            self.url_provider.bulk_url_of(endpoint), query_args
124        )?;
125
126        let file_status = from_str::<ZBFileFeedback>(&response_content)?;
127        Ok(file_status)
128    }
129
130    pub fn bulk_validation_file_submit(&self, zb_file: &ZBFile) -> ZBResult<ZBFileFeedback> {
131        self.generic_file_submit(ENDPOINT_FILE_SEND, zb_file)
132    }
133
134    pub fn bulk_validation_file_status_check(&self, file_id: &str) -> ZBResult<ZBFileStatus> {
135        self.generic_file_status_check(ENDPOINT_FILE_STATUS, file_id)
136    }
137
138    pub fn bulk_validation_result_fetch(&self, file_id: &str) -> ZBResult<ZBBulkResponse> {
139        self.generic_result_fetch(ENDPOINT_FILE_RESULT, file_id)
140    }
141
142    pub fn bulk_validation_result_delete(&self, file_id: &str) -> ZBResult<ZBFileFeedback> {
143        self.generic_result_delete(ENDPOINT_FILE_DELETE, file_id)
144    }
145
146    pub fn ai_scoring_file_submit(&self, zb_file: &ZBFile) -> ZBResult<ZBFileFeedback> {
147        self.generic_file_submit(ENDPOINT_SCORING_SEND, zb_file)
148    }
149
150    pub fn ai_scoring_file_status_check(&self, file_id: &str) -> ZBResult<ZBFileStatus> {
151        self.generic_file_status_check(ENDPOINT_SCORING_STATUS, file_id)
152    }
153
154    pub fn ai_scoring_result_fetch(&self, file_id: &str) -> ZBResult<ZBBulkResponse> {
155        self.generic_result_fetch(ENDPOINT_SCORING_RESULT, file_id)
156    }
157
158    pub fn ai_scoring_result_delete(&self, file_id: &str) -> ZBResult<ZBFileFeedback> {
159        self.generic_result_delete(ENDPOINT_SCORING_DELETE, file_id)
160    }
161
162
163}