use crate::types::*;
const DEFAULT_BASE_URL: &str = "https://wideholy.com/api/v1";
pub struct Client {
base_url: String,
http: reqwest::Client,
}
impl Client {
pub fn new() -> Self {
Self {
base_url: DEFAULT_BASE_URL.to_string(),
http: reqwest::Client::new(),
}
}
pub fn with_base_url(base_url: &str) -> Self {
Self {
base_url: base_url.to_string(),
http: reqwest::Client::new(),
}
}
async fn get<T: serde::de::DeserializeOwned>(&self, path: &str) -> Result<T, WideHolyError> {
let url = format!("{}{}", self.base_url, path);
let resp = self.http.get(&url).send().await?;
if !resp.status().is_success() {
return Err(WideHolyError::Api {
status: resp.status().as_u16(),
body: resp.text().await.unwrap_or_default(),
});
}
Ok(resp.json().await?)
}
async fn get_with_params<T: serde::de::DeserializeOwned>(
&self,
path: &str,
params: &[(&str, &str)],
) -> Result<T, WideHolyError> {
let url = format!("{}{}", self.base_url, path);
let resp = self.http.get(&url).query(params).send().await?;
if !resp.status().is_success() {
return Err(WideHolyError::Api {
status: resp.status().as_u16(),
body: resp.text().await.unwrap_or_default(),
});
}
Ok(resp.json().await?)
}
pub async fn verse_of_the_day(
&self,
religion: &str,
date: Option<&str>,
) -> Result<VerseOfTheDay, WideHolyError> {
let mut params = vec![("religion", religion)];
if let Some(d) = date {
params.push(("date", d));
}
self.get_with_params("/verse-of-the-day/", ¶ms).await
}
pub async fn random_verse(
&self,
religion: Option<&str>,
) -> Result<RandomVerse, WideHolyError> {
match religion {
Some(r) => self.get_with_params("/random/", &[("religion", r)]).await,
None => self.get("/random/").await,
}
}
pub async fn compare(
&self,
ref_a: &str,
ref_b: &str,
) -> Result<CompareResult, WideHolyError> {
self.get_with_params("/compare/", &[("a", ref_a), ("b", ref_b)])
.await
}
pub async fn search_suggest(
&self,
query: &str,
religion: Option<&str>,
) -> Result<SearchSuggestions, WideHolyError> {
let mut params = vec![("q", query)];
if let Some(r) = religion {
params.push(("religion", r));
}
self.get_with_params("/search/suggest/", ¶ms).await
}
pub async fn topic_verses(&self, topic: &str) -> Result<TopicVerses, WideHolyError> {
self.get(&format!("/topics/{}/verses/", topic)).await
}
pub async fn cross_religion(&self, topic: &str) -> Result<CrossReligion, WideHolyError> {
self.get(&format!("/cross-religion/{}/", topic)).await
}
pub async fn calendar(
&self,
religion: Option<&str>,
year: Option<u32>,
month: Option<u32>,
) -> Result<CalendarEvents, WideHolyError> {
let mut params: Vec<(&str, String)> = Vec::new();
if let Some(r) = religion {
params.push(("religion", r.to_string()));
}
if let Some(y) = year {
params.push(("year", y.to_string()));
}
if let Some(m) = month {
params.push(("month", m.to_string()));
}
let param_refs: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
self.get_with_params("/calendar/", ¶m_refs).await
}
pub async fn commentary(&self, verse_ref: &str) -> Result<CommentaryResult, WideHolyError> {
self.get(&format!("/commentary/{}/", verse_ref)).await
}
}
impl Default for Client {
fn default() -> Self {
Self::new()
}
}