183 lines
4.6 KiB
Rust
183 lines
4.6 KiB
Rust
extern crate serde;
|
|
extern crate serde_json;
|
|
#[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 Scryfall {}
|
|
|
|
impl Scryfall {
|
|
pub fn new() -> Scryfall {
|
|
Scryfall {}
|
|
}
|
|
|
|
pub fn search(&self, query: &str, order: Option<&str>, page: i32) -> Result<CardList, Error> {
|
|
let mut response = reqwest::get(&format!(
|
|
"https://api.scryfall.com/cards/search?q={}&order={}&page={}",
|
|
query,
|
|
order.unwrap_or("name"),
|
|
page
|
|
))?;
|
|
|
|
let mut content = String::new();
|
|
response.read_to_string(&mut content);
|
|
|
|
match serde_json::from_str(&content) {
|
|
Ok(list) => Ok(list),
|
|
Err(error) => {
|
|
match serde_json::from_str(&content) {
|
|
Ok(api_error) => Err(Error::API(api_error)),
|
|
Err(_) => Err(Error::Parse(error))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct CardList {
|
|
pub data: Vec<Card>,
|
|
pub has_more: bool,
|
|
pub next_page: Option<String>,
|
|
pub total_cards: u32,
|
|
pub warnings: Option<Vec<String>>
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct Card {
|
|
pub id: String,
|
|
pub multiverse_ids: Vec<u32>,
|
|
pub mtgo_id: Option<u32>,
|
|
pub mtgo_foil_id: Option<u32>,
|
|
pub uri: String,
|
|
pub scryfall_uri: String,
|
|
pub rulings_uri: String,
|
|
|
|
pub name: String,
|
|
pub layout: String,
|
|
pub cmc: f32,
|
|
pub type_line: Option<String>,
|
|
pub oracle_text: Option<String>,
|
|
pub mana_cost: Option<String>,
|
|
pub power: Option<String>,
|
|
pub toughness: Option<String>,
|
|
pub loyalty: Option<String>,
|
|
pub life_modifier: Option<String>,
|
|
pub hand_modifier: Option<String>,
|
|
pub colors: Option<Colors>,
|
|
pub color_indicator: Option<Colors>,
|
|
pub color_identity: Colors,
|
|
pub all_parts: Option<Vec<RelatedCard>>,
|
|
pub card_faces: Option<Vec<CardFace>>,
|
|
pub legalities: HashMap<String, String>,
|
|
pub reserved: bool,
|
|
pub edhrec_rank: Option<u32>,
|
|
|
|
pub set: String,
|
|
pub set_name: String,
|
|
pub collector_number: String,
|
|
pub set_search_uri: String,
|
|
pub scryfall_set_uri: String,
|
|
pub image_uris: Option<HashMap<String, String>>,
|
|
pub highres_image: bool,
|
|
pub reprint: bool,
|
|
pub digital: bool,
|
|
pub rarity: String,
|
|
pub flavor_text: Option<String>,
|
|
pub artist: Option<String>,
|
|
pub frame: String,
|
|
pub full_art: bool,
|
|
pub watermark: Option<String>,
|
|
pub border_color: String,
|
|
pub story_spotlight_number: Option<u32>,
|
|
pub story_spotlight_uri: Option<String>,
|
|
pub timeshifted: bool,
|
|
pub colorshifted: bool,
|
|
pub futureshifted: bool
|
|
}
|
|
|
|
type Colors = Vec<String>;
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct RelatedCard {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub uri: String
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct CardFace {
|
|
pub name: String,
|
|
pub type_line: String,
|
|
pub oracle_text: Option<String>,
|
|
pub mana_cost: String,
|
|
pub colors: Option<Colors>,
|
|
pub color_indicator: Option<Colors>,
|
|
pub power: Option<String>,
|
|
pub toughness: Option<String>,
|
|
pub loyalty: Option<String>,
|
|
pub flavor_text: Option<String>,
|
|
pub image_uris: Option<HashMap<String, String>>
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum Error {
|
|
/// HTTP request failed
|
|
HTTP(reqwest::Error),
|
|
/// Failed to parse
|
|
Parse(serde_json::Error),
|
|
/// Error from API
|
|
API(APIError)
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct APIError {
|
|
pub status: i32,
|
|
pub code: String,
|
|
pub details: String,
|
|
pub error_type: Option<String>,
|
|
pub warnings: Option<Vec<String>>
|
|
}
|
|
|
|
impl std::error::Error for APIError {
|
|
fn description(&self) -> &str {
|
|
&self.details
|
|
}
|
|
fn cause(&self) -> Option<&std::error::Error> {
|
|
None
|
|
}
|
|
}
|
|
|
|
impl Display for APIError {
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
write!(f, "{}", self.details)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use serde_json;
|
|
use *;
|
|
|
|
#[test]
|
|
fn deserialize_is_funny() {
|
|
let list: CardList = serde_json::from_str(include_str!("../test_data/is_funny.json")).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn deserialize_o_transform() {
|
|
let list: CardList = serde_json::from_str(include_str!("../test_data/o_transform.json")).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn deserialize_t_plane() {
|
|
let list: CardList = serde_json::from_str(include_str!("../test_data/t_plane.json")).unwrap();
|
|
}
|
|
}
|