From 60efb9f5272e5f4d5a9a293934f8cb64c3b067bf Mon Sep 17 00:00:00 2001 From: Adrian Malacoda Date: Sun, 6 May 2018 03:20:02 -0500 Subject: [PATCH] use scryfall for mtg searcher --- Cargo.toml | 1 + src/lib.rs | 1 + src/searchers/mtg.rs | 99 ++++++++++++-------------------------------- 3 files changed, 28 insertions(+), 73 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5eb3450..aaa2bce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ serde_json = "1.0.17" retry = { git = "https://github.com/jimmycuadra/retry", rev = "3fa812e650d64ede61ea243fb83ef1a222ff0f84" } mopa = "0.2.2" linked-hash-map = "0.5.1" +scryfall = { git = "http://gitlab.monarch-pass.net/malacoda/scryfall.git" } diff --git a/src/lib.rs b/src/lib.rs index 37e1f83..f3e72bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ extern crate select; extern crate serde_json; extern crate retry; extern crate linked_hash_map; +extern crate scryfall; #[macro_use] extern crate mopa; diff --git a/src/searchers/mtg.rs b/src/searchers/mtg.rs index 56556fc..26f2585 100644 --- a/src/searchers/mtg.rs +++ b/src/searchers/mtg.rs @@ -1,45 +1,27 @@ use Link; use searchers::Searcher; -use hyper; -use hyper::Client; - -use serde_json; -use serde_json::Value; +use scryfall; +use scryfall::{Scryfall, Card}; use retry; use retry::retry; use retry::delay::Fixed; use std; -use std::io::Read; -//use std::any::Any; use mopa::Any; const NUM_RETRIES: usize = 10; const RETRY_WAIT_MILLIS: u64 = 500; -#[derive(Debug)] -pub struct MtgCard { - pub name: String, - pub cost: Option, - pub typeline: String, - pub rules: Option, - pub flavor: Option, - pub power: Option, - pub toughness: Option, - pub url: String, - pub image_url: String -} - -impl Link for MtgCard { +impl Link for Card { fn label (&self) -> &str { &self.name } fn url (&self) -> &str { - &self.url + &self.uri } fn as_any (&self) -> &Any { @@ -48,69 +30,45 @@ impl Link for MtgCard { } pub struct MtgSearcher { - client: Client + scryfall: Scryfall } impl MtgSearcher { pub fn new () -> MtgSearcher { MtgSearcher { - client: Client::new() + scryfall: Scryfall::new() } } - fn do_search (&self, name: &str) -> Result { - let mut contents = String::new(); - let api_url = &format!("https://api.magicthegathering.io/v1/cards?name={}", name); - let mut response = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || { - self.client.get(api_url).send() + fn do_search (&self, query: &str) -> Result, Error> { + let mut result = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || { + self.scryfall.search(query, None, 0) })?; - response.read_to_string(&mut contents)?; - Result::Ok(contents) + + Ok(if !result.data.is_empty() { + Some(result.data.remove(0)) + } else { + None + }) } } -fn parse_entry (page: String) -> Result { - let parsed: Value = serde_json::from_str(&page)?; - for entry in parsed["cards"].as_array().unwrap_or(&vec![]) { - if entry["imageUrl"].as_str().is_some() { - let card_name = entry["name"].as_str().map(String::from).expect("expected name in json data"); - let card_url = format!("http://magiccards.info/query?q=!{}", card_name.replace(" ", "+")); - - return Result::Ok(MtgCard { - name: card_name, - cost: entry["manaCost"].as_str().map(String::from), - typeline: entry["type"].as_str().map(String::from).expect("expected type in json data"), - rules: entry["text"].as_str().map(String::from), - flavor: entry["flavor"].as_str().map(String::from), - power: entry["power"].as_str().map(String::from), - toughness: entry["toughness"].as_str().map(String::from), - url: card_url, - image_url: entry["imageUrl"].as_str().map(String::from).expect("expected image url in json data") - }); - } - } - - Result::Err(Error::Other(String::from("No card info found"))) -} - -impl Searcher for MtgSearcher { - fn exact_search (&self, name: &str) -> Option { - let search = format!(r#""{}""#, name); - self.do_search(&search).and_then(parse_entry).ok() +impl Searcher for MtgSearcher { + fn exact_search (&self, name: &str) -> Option { + let search = format!(r#"!{}"#, name); + self.do_search(&search).unwrap_or(None) } } #[derive(Debug)] enum Error { - Http(hyper::error::Error), + Client(scryfall::Error), Io(std::io::Error), - Json(serde_json::Error), - Other(String) } -impl From for Error { - fn from (error: hyper::error::Error) -> Error { - Error::Http(error) +impl From for Error { + fn from (error: scryfall::Error) -> Error { + Error::Client(error) } } @@ -120,17 +78,12 @@ impl From for Error { } } -impl From for Error { - fn from (error: serde_json::Error) -> Error { - Error::Json(error) - } -} -impl From> for Error { - fn from (err: retry::Error) -> Error { +impl From> for Error { + fn from (err: retry::Error) -> Error { match err { retry::Error::Operation { error, total_delay, tries } => { - Error::Http(error) + Error::Client(error) } } }