Skip to content
Snippets Groups Projects
Commit 5deb3436 authored by Marvin Weiler's avatar Marvin Weiler
Browse files

Added email notification and an config-parser

parent 3cf0e9df
No related branches found
No related tags found
No related merge requests found
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
#exclude the config file
config.json
......@@ -7,7 +7,10 @@ edition = "2021"
[dependencies]
fantoccini = "0.18.0"
scraper = "0.12.0"
penguin-config = "0.1.1"
serde = "1.0.136"
tokio = { version = "1", features = ["full"] }
lettre = "0.9"
lettre_email = "0.9"
lettre = { version = "0.10.0-rc.4", features = [
"smtp-transport",
"native-tls",
] }
{"smtp_host":"","smtp_user":"","smtp_pass":"","smtp_from":"","filters":[],"recipients":[]}
use fantoccini::error::CmdError;
use fantoccini::{ClientBuilder, Locator};
use lettre::transport::smtp::authentication::{Credentials, Mechanism};
use lettre::{Message, SmtpTransport, Transport};
use penguin_config::*;
use std::process::Command;
struct Product {
name: String,
price: String,
available: bool,
}
#[derive(Deserialize, PenguinConfigFile, Default)]
#[penguin_config(path = "config.json")]
struct Config {
smtp_host: String,
smtp_user: String,
smtp_pass: String,
smtp_from: String,
filters: Vec<String>,
recipients: Vec<String>,
}
#[tokio::main]
async fn main() {
let filters = vec!["RX 6800", "RX 6700"];
loop {
let products = get_html_products().await.unwrap();
let filtered: Vec<Product> = products
.into_iter()
.filter(|el| {
for s in &filters {
if el.name.contains(s) {
return el.available;
}
let config = Config::read_config();
let filters = config.filters;
let products = get_html_products().await.unwrap();
let filtered: Vec<Product> = products
.into_iter()
.filter(|el| {
for s in &filters {
if el.name.contains(s) {
return el.available;
}
false
})
.collect();
if filtered.len() > 0 {
println!("The following products are available");
} else {
println!("Sorry, all products are out of stock. :/");
}
}
}
}
false
})
.collect();
#[derive(Debug)]
pub struct Product {
name: String,
price: String,
available: bool,
if filtered.len() > 0 {
println!("Found {} products.\nSending mail.", filtered.len());
send_email(filtered);
} else {
println!("Sorry, all products are out of stock. :/");
}
}
async fn get_html_products() -> Result<Vec<Product>, CmdError> {
// start the geckodriver
let mut geckodriver = Command::new("sh")
.arg("-c")
.arg("./geckodriver")
.spawn()
.expect("sh command failed to start geckodriver");
// navigate to amd-site
let mut webc = ClientBuilder::native()
.connect("http://localhost:4444")
......@@ -71,5 +92,43 @@ async fn get_html_products() -> Result<Vec<Product>, CmdError> {
webc.close()
.await
.expect("Failed to terminate webdriver sessions");
// stop the geckodriver
geckodriver.kill().expect("Failed to kill geckodriver!");
return Ok(products);
}
fn send_email(config: Config, products: Vec<Product>) -> () {
let mut message = String::from(
"The following products are available at: https://www.amd.com/de/direct-buy \n\n",
);
for product in products {
message.push_str(format!(" - {}, Price: {}\n", product.name, product.price).as_str());
}
for recipient in config.recipients {
let mail = Message::builder()
.from(
config
.smtp_from
.parse()
.expect(format!("From address: {} is invalid", config.smtp_from).as_str()),
)
.to(recipient
.parse()
.expect(format!("To adress: {} is invalid", recipient).as_str()))
.subject("Products are available at the AMD website")
.body(message)
.expect("Failed to construct email message");
let creds = Credentials::new(config.smtp_user, config.smtp_pass);
let mailer = SmtpTransport::relay(&config.smtp_host)
.expect("Failed to connect to mailerver")
.credentials(creds)
.authentication(vec![Mechanism::Plain])
.build();
mailer.send(&mail).expect("Error sending mail");
println!("Mail was send to {}.", recipient);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment