Update stc library to Rust 2021 edition and update dependencies. Switch from home grown scryfall library to third party one.
This commit is contained in:
parent
b9f3c8f445
commit
3286125d34
@ -2,15 +2,17 @@
|
|||||||
name="stc"
|
name="stc"
|
||||||
version="0.0.2"
|
version="0.0.2"
|
||||||
authors=["Adrian Malacoda <adrian.malacoda@monarch-pass.net>"]
|
authors=["Adrian Malacoda <adrian.malacoda@monarch-pass.net>"]
|
||||||
|
edition="2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
env_logger = "0.5.10"
|
env_logger = "0.5.10"
|
||||||
sqlite = "0.23.4"
|
sqlite = "0.23.4"
|
||||||
select = "0.4.2"
|
select = "0.4.2"
|
||||||
reqwest = "0.8.5"
|
reqwest = { version = "0.11.14", features = ["blocking"] }
|
||||||
serde_json = "1.0.17"
|
serde_json = "1.0.17"
|
||||||
retry = { git = "https://github.com/jimmycuadra/retry", rev = "3fa812e650d64ede61ea243fb83ef1a222ff0f84" }
|
retry = { git = "https://github.com/jimmycuadra/retry", rev = "3fa812e650d64ede61ea243fb83ef1a222ff0f84" }
|
||||||
mopa = "0.2.2"
|
mopa = "0.2.2"
|
||||||
linked-hash-map = "0.5.1"
|
linked-hash-map = "0.5.1"
|
||||||
scryfall = { git = "http://gitlab.monarch-pass.net/malacoda/scryfall.git" }
|
#scryfall = { git = "https://forge.ds8.zone/beyond/scryfall.git" }
|
||||||
|
scryfall = { git = "https://github.com/adrianmalacoda/scryfall-rs", rev = "e95579e7d9ee1ea7147b72f739f448a7e6dca85a" } # "0.11.1" # for sync api
|
||||||
|
6
src/lib.rs
Normal file → Executable file
6
src/lib.rs
Normal file → Executable file
@ -16,12 +16,12 @@ use mopa::Any;
|
|||||||
pub trait Link: Any {
|
pub trait Link: Any {
|
||||||
fn label (&self) -> &str;
|
fn label (&self) -> &str;
|
||||||
fn url (&self) -> &str;
|
fn url (&self) -> &str;
|
||||||
fn as_any(&self) -> &Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
mopafy!(Link);
|
mopafy!(Link);
|
||||||
|
|
||||||
impl Link for Box<Link + 'static> {
|
impl Link for Box<dyn Link + 'static> {
|
||||||
fn label (&self) -> &str {
|
fn label (&self) -> &str {
|
||||||
(**self).label()
|
(**self).label()
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ impl Link for Box<Link + 'static> {
|
|||||||
(**self).url()
|
(**self).url()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any (&self) -> &Any {
|
fn as_any (&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
src/main.rs
Normal file → Executable file
4
src/main.rs
Normal file → Executable file
@ -2,7 +2,6 @@ extern crate stc;
|
|||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
|
||||||
@ -24,12 +23,11 @@ fn main () {
|
|||||||
|
|
||||||
match searchers.exact_search(&term) {
|
match searchers.exact_search(&term) {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
|
println!("{}: {}", item.label(), item.url());
|
||||||
if let Some(card) = item.downcast_ref::<MtgCard>() {
|
if let Some(card) = item.downcast_ref::<MtgCard>() {
|
||||||
println!("{:?}", card);
|
println!("{:?}", card);
|
||||||
} else if let Some(card) = item.downcast_ref::<YugiohCard>() {
|
} else if let Some(card) = item.downcast_ref::<YugiohCard>() {
|
||||||
println!("{:?}", card);
|
println!("{:?}", card);
|
||||||
} else {
|
|
||||||
println!("{}: {}", item.label(), item.url());
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => println!("not found...")
|
None => println!("not found...")
|
||||||
|
22
src/searchers/mediawiki.rs
Normal file → Executable file
22
src/searchers/mediawiki.rs
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
use Link;
|
use crate::Link;
|
||||||
use searchers::Searcher;
|
use crate::searchers::Searcher;
|
||||||
|
|
||||||
use reqwest;
|
use reqwest;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
@ -7,14 +7,11 @@ use reqwest::StatusCode;
|
|||||||
use select::document::Document;
|
use select::document::Document;
|
||||||
use select::predicate::Name;
|
use select::predicate::Name;
|
||||||
|
|
||||||
use retry;
|
|
||||||
use retry::retry;
|
use retry::retry;
|
||||||
use retry::delay::Fixed;
|
use retry::delay::Fixed;
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
//use std::any::Any;
|
|
||||||
use mopa::Any;
|
use mopa::Any;
|
||||||
|
|
||||||
const NUM_RETRIES: usize = 10;
|
const NUM_RETRIES: usize = 10;
|
||||||
@ -35,7 +32,7 @@ impl Link for WikiPage {
|
|||||||
&self.url
|
&self.url
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any (&self) -> &Any {
|
fn as_any (&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,16 +49,17 @@ impl MediawikiSearcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn do_search (&self, name: &str) -> Result<String, Error> {
|
fn do_search (&self, name: &str) -> Result<String, Error> {
|
||||||
let mut contents = String::new();
|
|
||||||
let api_url = &format!("{}{}", self.baseurl, name);
|
let api_url = &format!("{}{}", self.baseurl, name);
|
||||||
let mut response = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || {
|
let response = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || {
|
||||||
reqwest::get(api_url)
|
reqwest::blocking::get(api_url)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
StatusCode::Ok => {
|
StatusCode::OK => {
|
||||||
response.read_to_string(&mut contents)?;
|
match response.text() {
|
||||||
Result::Ok(contents)
|
Ok(text) => Ok(text),
|
||||||
|
Err(error) => Result::Err(Error::Http(error))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Result::Err(Error::Other(String::from("Not Found")))
|
Result::Err(Error::Other(String::from("Not Found")))
|
||||||
|
14
src/searchers/mod.rs
Normal file → Executable file
14
src/searchers/mod.rs
Normal file → Executable file
@ -2,7 +2,7 @@ pub mod mtg;
|
|||||||
pub mod yugioh;
|
pub mod yugioh;
|
||||||
pub mod mediawiki;
|
pub mod mediawiki;
|
||||||
|
|
||||||
use Link;
|
use crate::Link;
|
||||||
use linked_hash_map::LinkedHashMap;
|
use linked_hash_map::LinkedHashMap;
|
||||||
|
|
||||||
pub trait Searcher<T: Link> {
|
pub trait Searcher<T: Link> {
|
||||||
@ -13,7 +13,7 @@ pub trait Searcher<T: Link> {
|
|||||||
fn exact_search (&self, name: &str) -> Option<T>;
|
fn exact_search (&self, name: &str) -> Option<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchFn = Box<Fn(String, bool) -> Option<Box<Link>>>;
|
type SearchFn = Box<dyn Fn(String, bool) -> Option<Box<dyn Link>>>;
|
||||||
pub struct AggregateSearcher {
|
pub struct AggregateSearcher {
|
||||||
searchers: LinkedHashMap<String, SearchFn>
|
searchers: LinkedHashMap<String, SearchFn>
|
||||||
}
|
}
|
||||||
@ -25,19 +25,19 @@ impl AggregateSearcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_searcher<T: Link + 'static> (&mut self, prefix: &str, searcher: Box<Searcher<T>>) {
|
pub fn add_searcher<T: Link + 'static> (&mut self, prefix: &str, searcher: Box<dyn Searcher<T>>) {
|
||||||
let searcher_closure = move |name: String, fuzzy: bool| {
|
let searcher_closure = move |name: String, fuzzy: bool| {
|
||||||
(if fuzzy {
|
(if fuzzy {
|
||||||
searcher.fuzzy_search(&name[..])
|
searcher.fuzzy_search(&name[..])
|
||||||
} else {
|
} else {
|
||||||
searcher.exact_search(&name[..])
|
searcher.exact_search(&name[..])
|
||||||
}).map(|value| Box::new(value) as Box<Link>)
|
}).map(|value| Box::new(value) as Box<dyn Link>)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.searchers.insert(String::from(prefix), Box::new(searcher_closure));
|
self.searchers.insert(String::from(prefix), Box::new(searcher_closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_all_searchers (&self, name: &str) -> Option<Box<Link>> {
|
fn run_all_searchers (&self, name: &str) -> Option<Box<dyn Link>> {
|
||||||
for (_, searcher) in &self.searchers {
|
for (_, searcher) in &self.searchers {
|
||||||
let possible_value = searcher(String::from(name), false);
|
let possible_value = searcher(String::from(name), false);
|
||||||
if possible_value.is_some() {
|
if possible_value.is_some() {
|
||||||
@ -49,8 +49,8 @@ impl AggregateSearcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Searcher<Box<Link>> for AggregateSearcher {
|
impl Searcher<Box<dyn Link>> for AggregateSearcher {
|
||||||
fn exact_search (&self, full_name: &str) -> Option<Box<Link>> {
|
fn exact_search (&self, full_name: &str) -> Option<Box<dyn Link>> {
|
||||||
match split_prefix(full_name, ":") {
|
match split_prefix(full_name, ":") {
|
||||||
Some((prefix, name)) => {
|
Some((prefix, name)) => {
|
||||||
self.searchers.get(prefix).and_then(|searcher| searcher(String::from(name), true))
|
self.searchers.get(prefix).and_then(|searcher| searcher(String::from(name), true))
|
||||||
|
75
src/searchers/mtg.rs
Normal file → Executable file
75
src/searchers/mtg.rs
Normal file → Executable file
@ -1,19 +1,16 @@
|
|||||||
use Link;
|
use crate::Link;
|
||||||
use searchers::Searcher;
|
use crate::searchers::Searcher;
|
||||||
|
|
||||||
use scryfall;
|
use scryfall;
|
||||||
use scryfall::{Scryfall, Card};
|
use scryfall::Card;
|
||||||
|
|
||||||
use retry;
|
//use retry::retry;
|
||||||
use retry::retry;
|
//use retry::delay::Fixed;
|
||||||
use retry::delay::Fixed;
|
|
||||||
|
|
||||||
use std;
|
|
||||||
|
|
||||||
use mopa::Any;
|
use mopa::Any;
|
||||||
|
|
||||||
const NUM_RETRIES: usize = 10;
|
// const NUM_RETRIES: usize = 10;
|
||||||
const RETRY_WAIT_MILLIS: u64 = 500;
|
// const RETRY_WAIT_MILLIS: u64 = 500;
|
||||||
|
|
||||||
pub type MtgCard = Card;
|
pub type MtgCard = Card;
|
||||||
|
|
||||||
@ -23,70 +20,24 @@ impl Link for Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn url (&self) -> &str {
|
fn url (&self) -> &str {
|
||||||
&self.uri
|
self.scryfall_uri.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any (&self) -> &Any {
|
fn as_any (&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MtgSearcher {
|
pub struct MtgSearcher {}
|
||||||
scryfall: Scryfall
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MtgSearcher {
|
impl MtgSearcher {
|
||||||
pub fn new () -> MtgSearcher {
|
pub fn new () -> MtgSearcher{
|
||||||
MtgSearcher {
|
MtgSearcher {}
|
||||||
scryfall: Scryfall::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_search (&self, query: &str) -> Result<Option<Card>, Error> {
|
|
||||||
let mut result = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || {
|
|
||||||
self.scryfall.search(query, None, 0)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(if !result.data.is_empty() {
|
|
||||||
Some(result.data.remove(0))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Searcher<Card> for MtgSearcher {
|
impl Searcher<Card> for MtgSearcher {
|
||||||
fn exact_search (&self, name: &str) -> Option<Card> {
|
fn exact_search (&self, name: &str) -> Option<Card> {
|
||||||
let search = format!(r#"!"{}""#, name);
|
Card::named(name).ok()
|
||||||
self.do_search(&search).unwrap_or(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Error {
|
|
||||||
Client(scryfall::Error),
|
|
||||||
Io(std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<scryfall::Error> for Error {
|
|
||||||
fn from (error: scryfall::Error) -> Error {
|
|
||||||
Error::Client(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
|
||||||
fn from (error: std::io::Error) -> Error {
|
|
||||||
Error::Io(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl From<retry::Error<scryfall::Error>> for Error {
|
|
||||||
fn from (err: retry::Error<scryfall::Error>) -> Error {
|
|
||||||
match err {
|
|
||||||
retry::Error::Operation { error, total_delay, tries } => {
|
|
||||||
Error::Client(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
src/searchers/yugioh.rs
Normal file → Executable file
23
src/searchers/yugioh.rs
Normal file → Executable file
@ -1,19 +1,14 @@
|
|||||||
use Link;
|
use crate::Link;
|
||||||
use searchers::Searcher;
|
use crate::searchers::Searcher;
|
||||||
|
|
||||||
use reqwest;
|
use reqwest;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use retry;
|
|
||||||
use retry::retry;
|
use retry::retry;
|
||||||
use retry::delay::Fixed;
|
use retry::delay::Fixed;
|
||||||
|
|
||||||
use std;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
//use std::any::Any;
|
|
||||||
use mopa::Any;
|
use mopa::Any;
|
||||||
|
|
||||||
const NUM_RETRIES: usize = 10;
|
const NUM_RETRIES: usize = 10;
|
||||||
@ -42,7 +37,7 @@ impl Link for YugiohCard {
|
|||||||
&self.url
|
&self.url
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any (&self) -> &Any {
|
fn as_any (&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,13 +50,15 @@ impl YugiohSearcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn do_search (&self, name: &str) -> Result<String, Error> {
|
fn do_search (&self, name: &str) -> Result<String, Error> {
|
||||||
let mut contents = String::new();
|
|
||||||
let api_url = &format!("http://yugiohprices.com/api/card_data/{}", name);
|
let api_url = &format!("http://yugiohprices.com/api/card_data/{}", name);
|
||||||
let mut response = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || {
|
let response = retry(Fixed::from_millis(RETRY_WAIT_MILLIS).take(NUM_RETRIES), || {
|
||||||
reqwest::get(api_url)
|
reqwest::blocking::get(api_url)
|
||||||
})?;
|
})?;
|
||||||
response.read_to_string(&mut contents)?;
|
|
||||||
Result::Ok(contents)
|
match response.text() {
|
||||||
|
Ok(text) => Ok(text),
|
||||||
|
Err(error) => Result::Err(Error::Http(error))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user