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
|
|
|
}
|