1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
pub mod validation;

use std::collections::HashMap;

use chrono::NaiveDate;
use serde_json::from_str;

use crate::ZeroBounce;
use crate::utility::{ZBError, ZBResult};
use crate::utility::{ENDPOINT_ACTIVITY_DATA, ENDPOINT_API_USAGE, ENDPOINT_CREDITS};
use crate::utility::structures::{ActivityData, ApiUsage};

impl ZeroBounce {

    fn get_credits_from_string(string_value: String) -> ZBResult<i64> {
        from_str::<serde_json::Value>(string_value.as_ref())?
            .get("Credits")
            .and_then(serde_json::Value::as_str)
            .map(str::parse::<i64>)
            .ok_or(ZBError::explicit("credits value not in json"))?
            .map_err(ZBError::IntParseError)
    }

    pub fn get_credits(&self) -> ZBResult<i64> {
        let query_args = HashMap::from([
            ("api_key", self.api_key.as_str()),
        ]);

        let response_content = self.generic_get_request(
            ENDPOINT_CREDITS, query_args
        )?;

        Self::get_credits_from_string(response_content)
    }

    pub fn get_api_usage(&self, start_date: NaiveDate, end_date:NaiveDate) -> ZBResult<ApiUsage> {
        let start_date_str = start_date.format("%F").to_string();
        let end_date_str = end_date.format("%F").to_string();
        let query_args = HashMap::from([
            ("api_key", self.api_key.as_str()),
            ("start_date", start_date_str.as_str()),
            ("end_date", end_date_str.as_str()),
        ]);

        let response_content = self.generic_get_request(ENDPOINT_API_USAGE, query_args)?;

        let api_usage = from_str::<ApiUsage>(&response_content)?;
        Ok(api_usage)
    }

    pub fn get_api_usage_overall(&self) -> ZBResult<ApiUsage> {
        self.get_api_usage(NaiveDate::MIN, NaiveDate::MAX)
    }

    pub fn get_activity_data(&self, email: &str) -> ZBResult<ActivityData> {
        let query_args = HashMap::from([
            ("api_key", self.api_key.as_str()),
            ("email", email),
        ]);

        let response_content = self.generic_get_request(
            ENDPOINT_ACTIVITY_DATA, query_args
        )?;

        let activity_data = from_str::<ActivityData>(&response_content)?;
        Ok(activity_data)
    }

}

#[cfg(test)]
mod tests {
    use crate::utility::mock_constants::CREDITS_RESPONSE_OK;
    use crate::utility::mock_constants::CREDITS_RESPONSE_NEGATIVE;

    use super::*;

    #[test]
    fn test_credits_negative() {
        let credits = ZeroBounce::get_credits_from_string(CREDITS_RESPONSE_NEGATIVE.to_string());
        assert!(credits.is_ok());
        
        let amount = credits.unwrap();
        assert_eq!(amount, -1);
    }

    #[test]
    fn test_credits_ok() {
        let credits = ZeroBounce::get_credits_from_string(CREDITS_RESPONSE_OK.to_string());
        assert!(credits.is_ok());
        
        let amount = credits.unwrap();
        assert_eq!(amount, 123456);
    }

}