diff --git a/Cargo.toml b/Cargo.toml index b85a158..dddb903 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "wow-such-doge" +name = "i-can-has-cat" version = "0.0.1" authors = ["A. Malacoda "] @@ -7,5 +7,5 @@ authors = ["A. Malacoda "] reqwest = "0.8.0" serde = "1.0.14" serde_derive = "1.0.14" -serde_json = "1.0.3" +serde-xml-rs = "0.2.1" derive-error = "0.0.4" diff --git a/README.md b/README.md index 06d44b2..fa9b1d2 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,16 @@ -# Wow Such Doge -[Dog API](https://dog.ceo/dog-api/) client in Rust. +# I Can Has Cat +[The Cat API](http://thecatapi.com/) client in Rust. ## Usage ### Command Line -* `cargo run`: output list of breeds -* `cargo run ` output all dogs of breed -* `cargo run random`: output random dog -* `cargo run random ` output random dog of breed +* `cargo run`: output list of categories +* `cargo run random`: output random cat +* `cargo run random ` output random cat of category ### Library - use wow_such_doge::Dogs; - let dogs = Dogs::new(); - let breeds = Dogs::breeds(); - let random_dog = Dogs::random_image(); - let random_dog_of_breed = Dogs::random_image_by_breed(""); + use i_can_has_cat::Cats; + let cats = Cats::new(); + let categories = cats.categories(); + let random_cat = cats.random_image(); + let random_cat_of_breed = cats.random_image_of_category(""); diff --git a/src/lib.rs b/src/lib.rs index 0931f8d..bafb86f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,61 +1,47 @@ extern crate serde; -extern crate serde_json; +extern crate serde_xml_rs; #[macro_use] extern crate serde_derive; extern crate reqwest; #[macro_use] extern crate derive_error; -use std::collections::HashMap; use std::io::Read; use std::fmt; use std::fmt::{Display, Formatter}; -pub struct Dogs { +pub struct Cats { url: String } -impl Dogs { - pub fn new() -> Dogs { - Dogs::with_url("https://dog.ceo/api/") +impl Cats { + pub fn new() -> Cats { + Cats::with_url("http://thecatapi.com/api/") } - pub fn with_url(url: &str) -> Dogs { + pub fn with_url(url: &str) -> Cats { let mut api_url = url.to_owned(); if api_url.ends_with("/") { api_url.remove(url.len() - 1); } - Dogs { + Cats { url: api_url } } pub fn random_image(&self) -> Result { - Ok(self.make_call("/breeds/image/random")?.message) + let mut response : Response = self.make_call("/images/get?format=xml")?; + Ok(response.data.images.images.remove(0)) } - pub fn breeds(&self) -> Result { - Ok(self.make_call("/breeds/list/all")?.message) + pub fn categories(&self) -> Result { + let response : Response = self.make_call("/categories/list?format=xml")?; + Ok(response.data.categories) } - pub fn subbreeds(&self, breed: &str) -> Result { - Ok(self.make_call(&format!("/breed/{}/list", breed))?.message) - } - - pub fn images_by_breed(&self, breed: &str) -> Result { - Ok(self.make_call(&format!("/breed/{}/images", breed))?.message) - } - - pub fn random_image_by_breed(&self, breed: &str) -> Result { - Ok(self.make_call(&format!("/breed/{}/images/random", breed))?.message) - } - - pub fn images_by_subbreed(&self, breed: &str, subbreed: &str) -> Result { - Ok(self.make_call(&format!("/breed/{}/{}/images", breed, subbreed))?.message) - } - - pub fn random_image_by_subbreed(&self, breed: &str, subbreed: &str) -> Result { - Ok(self.make_call(&format!("/breed/{}/{}/images/random", breed, subbreed))?.message) + pub fn random_image_of_category(&self, category: &str) -> Result { + let mut response : Response = self.make_call(&format!("/images/get?format=xml&category={}", category))?; + Ok(response.data.images.images.remove(0)) } fn make_call(&self, endpoint: &str) -> Result, Error> @@ -69,21 +55,11 @@ impl Dogs { let mut content = String::new(); response.read_to_string(&mut content)?; - let parsed_response: Response = serde_json::from_str(&content)?; - if parsed_response.is_success() { - Ok(parsed_response) - } else { - Err(Error::API(serde_json::from_str(&content)?)) - } + let parsed_response: Response = serde_xml_rs::deserialize(content.as_bytes())?; + Ok(parsed_response) } } -pub type Breed = String; -pub type Image = String; -pub type Images = Vec; -pub type Subbreeds = Vec; -pub type Breeds = HashMap; - #[derive(Debug, Error)] pub enum Error { /// HTTP request failed @@ -91,7 +67,7 @@ pub enum Error { /// IO error IO(std::io::Error), /// Failed to parse - Parse(serde_json::Error), + Parse(serde_xml_rs::Error), /// Error from API API(APIError) } @@ -123,12 +99,67 @@ impl Display for APIError { #[derive(Serialize, Deserialize, Debug)] struct Response { - status: String, - message: T + data: T } -impl Response { - pub fn is_success(&self) -> bool { - self.status == "success" +#[derive(Serialize, Deserialize, Debug)] +struct ImagesData { + images: Images +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Images { + #[serde(rename="image")] + images: Vec +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Image { + id: String, + url: String, + source_url: String +} + +#[derive(Serialize, Deserialize, Debug)] +struct CategoriesData { + categories: Categories +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Categories { + #[serde(rename="category")] + categories: Vec +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Category { + id: String, + name: String +} + +mod test { + use serde_xml_rs; + use {Image, Images}; + + #[test] + fn test_deserialize_cat () { + let xml = r#" + http://25.media.tumblr.com/tumblr_m99be6qgNT1qejbiro1_500.jpg + MjA0MjYyMA + http://thecatapi.com/?id=MjA0MjYyMA + "#; + let cat: Image = serde_xml_rs::deserialize(xml.as_bytes()).unwrap(); + } + + #[test] + fn test_deserialize_cats () { + let xml = r#" + + http://25.media.tumblr.com/tumblr_m99be6qgNT1qejbiro1_500.jpg + MjA0MjYyMA + http://thecatapi.com/?id=MjA0MjYyMA + + "#; + let cats: Images = serde_xml_rs::deserialize(xml.as_bytes()).unwrap(); } } diff --git a/src/main.rs b/src/main.rs index de3f092..fc2ba28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,17 @@ -extern crate wow_such_doge; -use wow_such_doge::Dogs; +extern crate i_can_has_cat; +use i_can_has_cat::Cats; use std::env; fn main() { - let dogs = Dogs::new(); + let cats = Cats::new(); match env::args().nth(1).as_ref().map(|arg| arg.as_str()) { Some("random") => { match env::args().nth(2).as_ref().map(|arg| arg.as_str()) { - Some(breed) => { - match env::args().nth(3).as_ref().map(|arg| arg.as_str()) { - Some(subbreed) => println!("{}", dogs.random_image_by_subbreed(breed, subbreed).unwrap()), - None => println!("{}", dogs.random_image_by_breed(breed).unwrap()) - } - }, - None => println!("{}", dogs.random_image().unwrap()) + Some(category) => println!("{:?}", cats.random_image_of_category(category).unwrap()), + None => println!("{:?}", cats.random_image().unwrap()) } }, - Some(breed) => { - match env::args().nth(2).as_ref().map(|arg| arg.as_str()) { - Some(subbreed) => println!("{:?}", dogs.images_by_subbreed(breed, subbreed).unwrap()), - None => println!("{:?}", dogs.images_by_breed(breed).unwrap()) - } - }, - None => println!("{:?}", dogs.breeds()) + Some(_) => println!("{:?}", cats.categories()), + None => println!("{:?}", cats.categories()) } }