use crate::{
request::{Request, Requester},
Book, Chapter, Character, Error, Item, ItemType, Movie, Quote, Response,
};
pub struct Client {
requester: Requester,
}
impl Client {
pub fn new(token: String) -> Self {
Self {
requester: Requester::new(token),
}
}
async fn request_with_url<T>(&self, url: &str) -> Result<Response<T>, Error>
where
T: serde::de::DeserializeOwned,
{
let response = self.requester.get(url).await?;
let response: Response<T> = serde_json::from_str(&response).map_err(Error::from)?;
Ok(response)
}
async fn request<T>(&self, request: Request) -> Result<Response<T>, Error>
where
T: serde::de::DeserializeOwned,
{
let response = self.requester.get_from_request(request).await?;
let response: Response<T> = serde_json::from_str(&response).map_err(Error::from)?;
Ok(response)
}
pub async fn get_books(&self) -> Result<Vec<Book>, Error> {
Ok(self.request_with_url::<Book>("book").await?.get_contents())
}
pub async fn get_movies(&self) -> Result<Vec<Movie>, Error> {
Ok(self
.request_with_url::<Movie>("movie")
.await?
.get_contents())
}
pub async fn get_quotes(&self) -> Result<Vec<Quote>, Error> {
Ok(self
.request_with_url::<Quote>("quote?limit=2400")
.await?
.get_contents())
}
pub async fn get_characters(&self) -> Result<Vec<Character>, Error> {
Ok(self
.request_with_url::<Character>("character")
.await?
.get_contents())
}
pub async fn get_chapters(&self) -> Result<Vec<Chapter>, Error> {
Ok(self
.request_with_url::<Chapter>("chapter")
.await?
.get_contents())
}
pub async fn get_book_by_id(&self, id: &str) -> Result<Book, Error> {
let url = format!("book/{}", id);
let mut books = self.request_with_url::<Book>(&url).await?.get_contents();
books
.pop()
.ok_or(Error::Other("No book with id {} found".to_string()))
}
pub async fn get_movie_by_id(&self, id: &str) -> Result<Movie, Error> {
let url = format!("movie/{}", id);
let mut movies = self.request_with_url::<Movie>(&url).await?.get_contents();
movies
.pop()
.ok_or(Error::Other("No movie with id {} found".to_string()))
}
pub async fn get_quote_by_id(&self, id: &str) -> Result<Quote, Error> {
let url = format!("quote/{}", id);
let mut quotes = self.request_with_url::<Quote>(&url).await?.get_contents();
quotes
.pop()
.ok_or(Error::Other("No quote with id {} found".to_string()))
}
pub async fn get_character_by_id(&self, id: &str) -> Result<Character, Error> {
let url = format!("character/{}", id);
let mut characters = self
.request_with_url::<Character>(&url)
.await?
.get_contents();
characters
.pop()
.ok_or(Error::Other("No character with id {} found".to_string()))
}
pub async fn get_chapter_by_id(&self, id: &str) -> Result<Chapter, Error> {
let url = format!("chapter/{}", id);
let mut chapters = self.request_with_url::<Chapter>(&url).await?.get_contents();
chapters
.pop()
.ok_or(Error::Other("No chapter with id {} found".to_string()))
}
pub async fn get_chapters_from_book(&self, book_id: &str) -> Result<Vec<Chapter>, Error> {
let url = format!("book/{}/chapter", book_id);
Ok(self.request_with_url::<Chapter>(&url).await?.get_contents())
}
pub async fn get_quotes_from_movie(&self, movie_id: &str) -> Result<Vec<Quote>, Error> {
let url = format!("movie/{}/quote", movie_id);
Ok(self.request_with_url::<Quote>(&url).await?.get_contents())
}
pub async fn get_quotes_from_character(&self, character_id: &str) -> Result<Vec<Quote>, Error> {
let url = format!("character/{}/quote", character_id);
Ok(self.request_with_url::<Quote>(&url).await?.get_contents())
}
pub async fn get_from_url<T>(&self, url: &str) -> Result<Vec<T>, Error>
where
T: serde::de::DeserializeOwned,
{
Ok(self.request_with_url::<T>(url).await?.get_contents())
}
pub async fn get(&self, request: Request) -> Result<Vec<Item>, Error> {
match request.get_item_type() {
ItemType::Book => {
let response = self.request::<Book>(request).await?;
Ok(response.into())
}
ItemType::Movie => {
let response = self.request::<Movie>(request).await?;
Ok(response.into())
}
ItemType::Quote => {
let response = self.request::<Quote>(request).await?;
Ok(response.into())
}
ItemType::Character => {
let response = self.request::<Character>(request).await?;
Ok(response.into())
}
ItemType::Chapter => {
let response = self.request::<Chapter>(request).await?;
Ok(response.into())
}
}
}
}