use reqwest::{header, Client, Error};
use serde::Serialize;
use crate::Notification;
const DEFAULT_BASE_URL: &str = "https://api.engagespot.co/v3";
pub struct EngagespotBuilder {
base_url: String,
client: Client,
}
pub struct Engagespot {
base_url: String,
client: Client,
}
fn create_default_client(api_key: &str, api_secret: &str) -> Result<Client, Error> {
let mut headers = header::HeaderMap::new();
headers.insert(
"Content-Type",
header::HeaderValue::from_static("application/json"),
);
headers.insert(
"X-ENGAGESPOT-API-KEY",
header::HeaderValue::from_str(api_key).unwrap(),
);
headers.insert(
"X-ENGAGESPOT-API-SECRET",
header::HeaderValue::from_str(api_secret).unwrap(),
);
let client = Client::builder()
.user_agent("engagespot-rust")
.default_headers(headers)
.build();
client
}
impl EngagespotBuilder {
pub fn new(api_key: &str, api_secret: &str) -> Self {
let client = create_default_client(api_key, api_secret)
.unwrap_or_else(|error| panic!("Error creating client {:?}", error));
EngagespotBuilder {
base_url: DEFAULT_BASE_URL.to_string(),
client,
}
}
pub fn base_url(mut self, base_url: &str) -> Self {
self.base_url = base_url.to_string();
self
}
pub fn build(self) -> Engagespot {
Engagespot {
base_url: self.base_url,
client: self.client,
}
}
}
impl Engagespot {
pub fn new(api_key: &str, api_secret: &str) -> Engagespot {
EngagespotBuilder::new(api_key, api_secret).build()
}
pub async fn send<T: Serialize>(
&self,
notification: &Notification<T>,
) -> Result<String, String> {
let url = self.get_url("notifications");
let response = self.client.post(&url).json(¬ification).send().await;
match response {
Ok(response) => self.handle_response(response).await,
Err(error) => Err(error.to_string()),
}
}
pub async fn create_or_update_user_attrs<T: Serialize>(&self, identifier: &str, attrs: &T) -> Result<String, String> {
let url = self.get_url(format!("users/{identifier}").as_str());
let response = self.client.put(&url).json(&attrs).send().await;
match response {
Ok(response) => self.handle_response(response).await,
Err(error) => Err(error.to_string()),
}
}
async fn handle_response(&self, response: reqwest::Response) -> Result<String, String> {
let status = response.status();
let response_text = response.text().await.unwrap();
if !status.is_success() {
return Err(response_text);
}
Ok(response_text)
}
fn get_url(&self, path: &str) -> String {
format!("{}/{}", self.base_url, path)
}
}
#[cfg(test)]
mod tests {
use crate::{Engagespot, EngagespotBuilder};
#[test]
fn builder_init() {
let client = EngagespotBuilder::new("api_key", "api_secret").build();
assert_eq!(client.base_url, "https://api.engagespot.co/v3");
}
#[test]
fn builder_methods() {
let builder = EngagespotBuilder::new("api_key", "api_secret")
.base_url("https://api.engagespot.co/v5");
let client = builder.build();
assert_eq!(client.base_url, "https://api.engagespot.co/v5");
}
#[test]
fn engagespot_init() {
let client = Engagespot::new("api_key", "api_secret");
assert_eq!(client.base_url, "https://api.engagespot.co/v3");
}
}