113 lines
2.9 KiB
Rust
113 lines
2.9 KiB
Rust
use Link;
|
|
use searchers::Searcher;
|
|
|
|
use reqwest;
|
|
use reqwest::Client;
|
|
|
|
use serde_json;
|
|
use serde_json::Value;
|
|
|
|
use std;
|
|
use std::io::Read;
|
|
|
|
use std::any::Any;
|
|
|
|
#[derive(Debug)]
|
|
pub struct MtgCard {
|
|
name: String,
|
|
cost: String,
|
|
typeline: String,
|
|
rules: String,
|
|
flavor: Option<String>,
|
|
power: Option<String>,
|
|
toughness: Option<String>,
|
|
url: String,
|
|
image_url: String
|
|
}
|
|
|
|
impl Link for MtgCard {
|
|
fn label (&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
fn url (&self) -> &str {
|
|
&self.url
|
|
}
|
|
|
|
fn as_any (&self) -> &Any {
|
|
self
|
|
}
|
|
}
|
|
|
|
pub struct MtgSearcher {
|
|
client: Client
|
|
}
|
|
|
|
impl MtgSearcher {
|
|
pub fn new () -> MtgSearcher {
|
|
MtgSearcher {
|
|
client: Client::new().unwrap()
|
|
}
|
|
}
|
|
|
|
fn do_search (&self, name: &str) -> Result<String, Error> {
|
|
let mut contents = String::new();
|
|
let api_url = &format!("https://api.magicthegathering.io/v1/cards?name={}", name);
|
|
self.client.get(api_url).send()?.read_to_string(&mut contents)?;
|
|
Result::Ok(contents)
|
|
}
|
|
}
|
|
|
|
fn parse_entry (page: String) -> Result<MtgCard, Error> {
|
|
let parsed: Value = serde_json::from_str(&page)?;
|
|
let ref parsed_entry = parsed["cards"][0];
|
|
if let Some(_) = parsed_entry.as_object() {
|
|
Result::Ok(MtgCard {
|
|
name: parsed_entry["name"].as_str().map(String::from).expect("expected name in json data"),
|
|
cost: parsed_entry["manaCost"].as_str().map(String::from).expect("expected cost in json data"),
|
|
typeline: parsed_entry["type"].as_str().map(String::from).expect("expected type in json data"),
|
|
rules: parsed_entry["text"].as_str().map(String::from).expect("expected text in json data"),
|
|
flavor: parsed_entry["flavor"].as_str().map(String::from),
|
|
power: parsed_entry["power"].as_str().map(String::from),
|
|
toughness: parsed_entry["toughness"].as_str().map(String::from),
|
|
url: parsed_entry["imageUrl"].as_str().map(String::from).expect("expected image url in json data"),
|
|
image_url: parsed_entry["imageUrl"].as_str().map(String::from).expect("expected image url in json data")
|
|
})
|
|
} else {
|
|
Result::Err(Error::Other(String::from("No card info found")))
|
|
}
|
|
}
|
|
|
|
impl Searcher<MtgCard> for MtgSearcher {
|
|
fn exact_search (&self, name: &str) -> Option<MtgCard> {
|
|
let search = format!(r#""{}""#, name);
|
|
self.do_search(&search).and_then(parse_entry).ok()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
enum Error {
|
|
Http(reqwest::Error),
|
|
Io(std::io::Error),
|
|
Json(serde_json::Error),
|
|
Other(String)
|
|
}
|
|
|
|
impl From<reqwest::Error> for Error {
|
|
fn from (error: reqwest::Error) -> Error {
|
|
Error::Http(error)
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for Error {
|
|
fn from (error: std::io::Error) -> Error {
|
|
Error::Io(error)
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::Error> for Error {
|
|
fn from (error: serde_json::Error) -> Error {
|
|
Error::Json(error)
|
|
}
|
|
}
|