use super::{
dns::Dns,
domain::Domain,
endpoints,
ssl::Ssl,
types::{Auth, PingResponse, PricingResponse, StatusResponse},
};
use crate::{Error, Result};
use reqwest::Client as HttpClient;
use serde::{Serialize, de::DeserializeOwned};
#[derive(Clone, Debug)]
pub struct Porkbun {
http_client: HttpClient,
pub(super) auth: Auth,
}
impl Porkbun {
pub fn new(apikey: String, secretapikey: String) -> Self {
Self {
http_client: HttpClient::new(),
auth: Auth { apikey, secretapikey },
}
}
pub async fn ping(&self) -> Result<PingResponse> {
self.post(endpoints::PING, &self.auth).await
}
pub async fn get_pricing(&self) -> Result<PricingResponse> {
self.post_unauthenticated(endpoints::PRICING_GET).await
}
pub fn domain<'a>(&'a self, domain: &'a str) -> Domain<'a> {
Domain::new(self, domain)
}
pub fn dns<'a>(&'a self, domain: &'a str) -> Dns<'a> {
Dns::new(self, domain)
}
pub fn ssl<'a>(&'a self, domain: &'a str) -> Ssl<'a> {
Ssl::new(self, domain)
}
pub(super) async fn post<T, B>(&self, path: &str, body: &B) -> Result<T>
where
T: DeserializeOwned,
B: Serialize,
{
let url = format!("{}{}", endpoints::BASE_URL, path);
let response_text = self
.http_client
.post(&url)
.json(body)
.send()
.await?
.error_for_status()? .text()
.await?;
let status_check: StatusResponse = serde_json::from_str(&response_text)?;
if status_check.status == "ERROR" {
return Err(Error::Api(
status_check.message.unwrap_or_else(|| "Unknown API error".to_string()),
));
}
let final_response: T = serde_json::from_str(&response_text)?;
Ok(final_response)
}
async fn post_unauthenticated<T: DeserializeOwned>(&self, path: &str) -> Result<T> {
let url = format!("{}{}", endpoints::BASE_URL, path);
let response_text = self
.http_client
.post(&url)
.json(&serde_json::json!({})) .send()
.await?
.error_for_status()?
.text()
.await?;
let status_check: StatusResponse = serde_json::from_str(&response_text)?;
if status_check.status == "ERROR" {
return Err(Error::Api(
status_check.message.unwrap_or_else(|| "Unknown API error".to_string()),
));
}
let final_response: T = serde_json::from_str(&response_text)?;
Ok(final_response)
}
}