use async_trait::async_trait;
use errors::NaApiError;
use reqwest::ClientBuilder;
use reqwest_hickory_resolver::HickoryResolver;
use serde_json::Value;
use std::sync::Arc;
pub mod config;
pub mod endpoints;
pub mod errors;
pub use rnaapi_derive::{EndpointGetAll, EndpointGetOne};
pub struct NaClient {
pub address: String,
pub api_key: String,
pub http_client: reqwest::Client,
}
pub enum EndpointGetArgs {
NoArgs,
OneInt(u32),
TwoInt(u32, u32),
}
#[async_trait]
pub trait EndpointGetOne {
type Endpoint;
#[allow(unused)]
async fn get_one(
na_client: &NaClient, args: EndpointGetArgs,
) -> Result<Self::Endpoint, NaApiError> {
Err(NaApiError::UnknownError(
"Get All not implemented here".to_string(),
))
}
}
#[async_trait]
pub trait EndpointGetAll {
type Endpoint;
#[allow(unused)]
async fn get_all(
na_client: &NaClient, args: EndpointGetArgs,
) -> Result<Vec<Self::Endpoint>, NaApiError> {
Err(NaApiError::UnknownError(
"Get All not implemented here".to_string(),
))
}
}
impl NaClient {
pub async fn new(api_key: String, address: String) -> Self {
let mut builder = ClientBuilder::new();
builder = builder.dns_resolver(Arc::new(HickoryResolver::default()));
let http_client = builder.build().unwrap();
Self {
api_key,
address,
http_client,
}
}
async fn get(&self, path: &str) -> Result<Value, NaApiError> {
let api_key = if path.contains("?") {
format!("&key={}", &self.api_key)
} else {
format!("?key={}", &self.api_key)
};
let result = self
.http_client
.get(format!("{}{}{}", self.address, path, api_key))
.send()
.await
.map_err(|e| {
NaApiError::UnknownError(format!(
"Failed to finish request with error: {e}"
))
})?;
let result_json = result.json::<Value>().await.map_err(|e| {
NaApiError::UnknownError(format!(
"Failed to finish request with error: {e}"
))
})?;
Ok(result_json)
}
pub async fn get_data(&self, path: &str) -> Result<Value, NaApiError> {
let result = self
.get(path)
.await
.map_err(|e| NaApiError::UnknownError(format!("Got error: {e}")))?;
let result_value: Option<&Value> = result.get("data");
if let Some(inner_data) = result_value {
Ok(inner_data.clone())
} else {
let result_message = result.get("message");
if let Some(message) = result_message {
let code = result.get("code").unwrap();
Err(NaApiError::APIKeyInvalid(format!("{code}: {message}")))
} else {
Err(NaApiError::UnknownError(format!(
"Could not reach: {}{}",
self.api_key, path
)))
}
}
}
}