hummingbird 0.1.3

An unofficial Rust wrapper for the Hummingbird.me API.
extern crate hyper;
extern crate serde_json;

#[macro_use]
mod utils;

mod error;
mod models;

pub use models::*;

use error::Result;
use hyper::Client;
use utils::decode_array;

static API_URL: &'static str = "https://hummingbird.me/api/v1";

/// Retrieves data about an anime by its id.
pub fn get_anime(id: u64) -> Result<Anime> {
    let response = try!(Client::new()
        .get(&format!("{}/anime/{}", API_URL, id))
        .send());

    Anime::decode(try!(serde_json::from_reader(response)))
}

/// Searches for an anime by a query name, retrieving some of the closest
/// results.
///
/// Fuzzy searching is supported.
pub fn search_anime<S: Into<String>>(query: S) -> Result<Vec<Anime>> {
    let response = try!(Client::new()
        .get(&format!("{}/search/anime?query={}", API_URL, query.into()))
        .send());

    decode_array(try!(serde_json::from_reader(response)), Anime::decode)
}

/// Retrieves data about a user by their username.
pub fn get_user<S: Into<String>>(username: S) -> Result<User> {
    let response = try!(Client::new()
        .get(&format!("{}/users/{}", API_URL, username.into()))
        .send());

    User::decode(try!(serde_json::from_reader(response)))
}

/// Get a list of a user's favorite anime.
pub fn get_user_favorites<S: Into<String>>(username: S) -> Result<Vec<Anime>> {
    let response = try!(Client::new()
        .get(&format!("{}/users/{}/favorite_anime", API_URL, username.into()))
        .send());

    decode_array(try!(serde_json::from_reader(response)), Anime::decode)
}

/// Get a list of the user's feed in `Story` format.
pub fn get_user_feed<S: Into<String>>(username: S) -> Result<Vec<Story>> {
    let response = try!(Client::new()
        .get(&format!("{}/users/{}/feed", API_URL, username.into()))
        .send());

    decode_array(try!(serde_json::from_reader(response)), Story::decode)
}

/// Get a list of all of a user's Library.
pub fn get_user_library<S: Into<String>>(username: S) -> Result<Vec<Library>> {
    let response = try!(Client::new()
        .get(&format!("{}/users/{}/library", API_URL, username.into()))
        .send());

    decode_array(try!(serde_json::from_reader(response)), Library::decode)
}

#[cfg(test)]
mod tests {
    use ::std::env;
    #[test]
    fn anime() {
        let results = ::search_anime("non non biyori").expect("results");

        let _ = ::get_anime(results.get(0).expect("at least one result").id);

        // Test that AgeRating TV-Y7 is handled. This is not documented by
        // Hummingbird.
        let _ = ::search_anime("Avatar").expect("avatar");
    }

    #[test]
    fn user() {
        let username = env::var("HUMMINGBIRD_USER").expect("username");
        let user = ::get_user(&username[..]).expect("user");
        let _feed = ::get_user_feed(&user.name[..]).expect("user feed");
        let _favs = ::get_user_favorites(&user.name[..])
            .expect("user favorites");
        let _library = ::get_user_library(&user.name[..]).expect("user lib");
    }
}