price_checker/src/parser.rs

89 lines
2.0 KiB
Rust
Raw Normal View History

2020-07-20 20:14:05 +00:00
pub mod amazon;
2020-05-11 19:21:57 +00:00
pub mod darty;
2020-06-15 15:54:45 +00:00
pub mod du_bruit_dans_la_cuisine;
2020-07-20 20:14:05 +00:00
pub mod fnac;
2020-06-15 15:54:45 +00:00
pub mod ldlc;
2020-05-11 19:21:57 +00:00
use crate::price_result::PriceResult;
2020-07-21 18:37:26 +00:00
use anyhow::{anyhow, Result};
2020-05-11 19:21:57 +00:00
use arraygen::Arraygen;
2020-07-20 20:14:05 +00:00
use scraper::Html;
2020-05-23 14:19:04 +00:00
use url::Url;
2020-05-11 19:21:57 +00:00
2020-07-20 20:14:05 +00:00
pub trait Parser {
2020-06-21 09:32:40 +00:00
/// Create the parser
2020-07-20 20:14:05 +00:00
fn new() -> Result<Self>
where
Self: Sized;
2020-06-21 09:32:40 +00:00
/// Get the name
2020-06-23 16:29:55 +00:00
fn name(&self) -> &'static str;
2020-06-21 09:32:40 +00:00
}
2020-05-24 16:16:32 +00:00
/// Trait needed to get price from a specific website
2020-07-20 20:14:05 +00:00
pub trait PriceParser: Parser {
2020-05-24 16:16:32 +00:00
/// Indicate if it can parse this URL
2020-07-20 20:14:05 +00:00
fn can_parse(&self, url: &Url) -> bool;
2020-05-24 16:16:32 +00:00
/// Parse the html into a price
2020-07-20 20:14:05 +00:00
fn parse_price(&self, html: &Html) -> Result<PriceResult>;
2020-05-11 19:21:57 +00:00
}
2020-07-21 18:37:26 +00:00
pub trait SearchParser: PriceParser {
2020-06-23 16:29:55 +00:00
/// Return the search URL
fn search_url(&self, name: &str) -> Url;
/// Return the first occurence of result of the page if any
2020-07-20 20:14:05 +00:00
fn search(&self, html: &Html) -> Result<Option<Url>>;
2020-06-23 16:29:55 +00:00
}
2020-06-21 08:36:13 +00:00
2020-06-21 12:20:42 +00:00
macro_rules! gen_list {
( $([$module:ident::$name:ident : $($array:ident),*]),* ) => {
#[derive(Arraygen, Debug)]
2021-09-21 20:41:27 +00:00
#[gen_array(pub fn get_all: & dyn Parser)]
2020-06-21 12:20:42 +00:00
#[gen_array(pub fn get_price: & dyn PriceParser)]
2020-06-23 16:29:55 +00:00
#[gen_array(pub fn get_search: & dyn SearchParser)]
2020-06-21 12:20:42 +00:00
pub struct List {
$(
2021-09-21 20:41:27 +00:00
#[in_array(get_all, $($array),* )]
2020-06-21 12:20:42 +00:00
$module: $module::$name
),*
}
2020-05-11 19:21:57 +00:00
2020-06-21 12:20:42 +00:00
impl List {
/// Create the list
pub fn new() -> Result<Self> {
Ok(List {
$(
$module: $module::$name::new()?
),*
})
}
}
};
2020-05-24 16:16:32 +00:00
}
2020-06-21 12:20:42 +00:00
gen_list!(
2020-07-20 20:14:05 +00:00
[darty::Darty: get_price],
2020-07-21 16:43:29 +00:00
[fnac::Fnac: get_price, get_search],
2020-07-20 20:14:05 +00:00
[du_bruit_dans_la_cuisine::DuBruitDansLaCuisine: get_price],
[ldlc::LDLC: get_price],
[amazon::Amazon: get_price, get_search]
2020-06-21 12:20:42 +00:00
);
2020-07-21 18:37:26 +00:00
impl List {
pub fn get_parser(&self, name: &str) -> Result<&dyn SearchParser> {
Ok(*self
.get_search()
.iter()
.find(|&&parser| parser.name().to_lowercase() == name.to_lowercase())
.ok_or(anyhow!("Cannot find the parser {}", name))?)
}
}
2020-05-24 16:16:32 +00:00
#[test]
fn test_parser_list() {
let parser_list = List::new().unwrap();
2020-06-21 08:36:13 +00:00
assert_eq!(parser_list.get_price().len(), 5);
2020-07-21 16:43:29 +00:00
assert_eq!(parser_list.get_search().len(), 2);
2020-07-20 20:14:05 +00:00
}