use crate::types::*;
const DEFAULT_BASE_URL: &str = "https://widebible.com/api/v1/bible";
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, WideBibleError> {
let url = format!("{}{}", self.base_url, path);
let resp = self.http.get(&url).send().await?;
if !resp.status().is_success() {
return Err(WideBibleError::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, WideBibleError> {
let url = format!("{}{}", self.base_url, path);
let resp = self.http.get(&url).query(params).send().await?;
if !resp.status().is_success() {
return Err(WideBibleError::Api {
status: resp.status().as_u16(),
body: resp.text().await.unwrap_or_default(),
});
}
Ok(resp.json().await?)
}
pub async fn list_books(&self) -> Result<ListResponse<Book>, WideBibleError> {
self.get("/books/").await
}
pub async fn get_book(&self, slug: &str) -> Result<Book, WideBibleError> {
self.get(&format!("/books/{}/", slug)).await
}
pub async fn list_book_groups(&self) -> Result<ListResponse<BookGroup>, WideBibleError> {
self.get("/book-groups/").await
}
pub async fn get_book_group(&self, slug: &str) -> Result<BookGroup, WideBibleError> {
self.get(&format!("/book-groups/{}/", slug)).await
}
pub async fn list_translations(&self) -> Result<ListResponse<Translation>, WideBibleError> {
self.get("/translations/").await
}
pub async fn get_translation(&self, code: &str) -> Result<Translation, WideBibleError> {
self.get(&format!("/translations/{}/", code)).await
}
pub async fn get_verse(
&self,
book: &str,
chapter: u32,
verse: u32,
translation: &str,
) -> Result<ListResponse<Verse>, WideBibleError> {
let ch = chapter.to_string();
let v = verse.to_string();
self.get_with_params(
"/verses/",
&[
("book__slug", book),
("chapter", &ch),
("verse", &v),
("translation__code", translation),
],
)
.await
}
pub async fn search(&self, query: &str) -> Result<ListResponse<Verse>, WideBibleError> {
self.get_with_params("/verses/", &[("search", query)]).await
}
pub async fn list_people(&self) -> Result<ListResponse<Person>, WideBibleError> {
self.get("/people/").await
}
pub async fn get_person(&self, slug: &str) -> Result<Person, WideBibleError> {
self.get(&format!("/people/{}/", slug)).await
}
pub async fn list_places(&self) -> Result<ListResponse<Place>, WideBibleError> {
self.get("/places/").await
}
pub async fn get_place(&self, slug: &str) -> Result<Place, WideBibleError> {
self.get(&format!("/places/{}/", slug)).await
}
pub async fn list_topics(&self) -> Result<ListResponse<Topic>, WideBibleError> {
self.get("/topics/").await
}
pub async fn get_topic(&self, slug: &str) -> Result<Topic, WideBibleError> {
self.get(&format!("/topics/{}/", slug)).await
}
pub async fn list_cross_references(
&self,
) -> Result<ListResponse<CrossReference>, WideBibleError> {
self.get("/cross-references/").await
}
pub async fn list_glossary(&self) -> Result<ListResponse<GlossaryTerm>, WideBibleError> {
self.get("/glossary/").await
}
pub async fn get_glossary_term(&self, slug: &str) -> Result<GlossaryTerm, WideBibleError> {
self.get(&format!("/glossary/{}/", slug)).await
}
pub async fn list_eras(&self) -> Result<ListResponse<TimelineEra>, WideBibleError> {
self.get("/timeline-eras/").await
}
pub async fn list_events(&self) -> Result<ListResponse<TimelineEvent>, WideBibleError> {
self.get("/timeline-events/").await
}
pub async fn list_reading_plans(&self) -> Result<ListResponse<ReadingPlan>, WideBibleError> {
self.get("/reading-plans/").await
}
pub async fn get_reading_plan(&self, slug: &str) -> Result<ReadingPlan, WideBibleError> {
self.get(&format!("/reading-plans/{}/", slug)).await
}
}
impl Default for Client {
fn default() -> Self {
Self::new()
}
}