X-Git-Url: http://git.euphorik.ch/?a=blobdiff_plain;f=src%2Fmain.rs;h=b58f7b342f47656c5f4e01c1e6bd6f0935259969;hb=95d52b9d01c9894acc15e90d0e4be81a8df352ed;hp=fadc30d8f4f432f39e3c9aed6ffadb5a1e00e58d;hpb=bd25470e4d4c104ab661fe6212f56179d9a32b32;p=stakingWatchdog.git diff --git a/src/main.rs b/src/main.rs index fadc30d..b58f7b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,10 @@ use std::{ }; use anyhow::{Context, Result}; +use lettre::{ + message::header::ContentType, transport::smtp::authentication::Credentials, Message, + SmtpTransport, Transport, +}; use reqwest::StatusCode; use serde::Deserialize; use serde_json::{json, Value}; @@ -22,8 +26,9 @@ mod config; // mod error; const FILE_CONF: &str = "config.ron"; -const CHECK_PERIOD: Duration = Duration::from_secs(5); // 5s. -const EMAIL_RESEND_PERIOD: Duration = Duration::from_secs(12 * 60 * 60); // 12h. +const CHECK_PERIOD: Duration = Duration::from_secs(10); // 10 s. +const EMAIL_RESEND_PERIOD: Duration = Duration::from_secs(6 * 60 * 60); // 6 h. +const STATE_PRINT_PERIOD: Duration = Duration::from_secs(15 * 60); // 15 min. const BASE_URI: &str = "http://localhost:5052/eth/v1/"; fn main() -> Result<()> { @@ -31,20 +36,49 @@ fn main() -> Result<()> { let config = Config::read(FILE_CONF)?; - println!("Configuration: {:?}", config); + println!( + "Configuration: {:?}", + Config { + smtp_password: "*****".to_string(), + ..config.clone() + } + ); let mut time_last_email_send = time::Instant::now() - EMAIL_RESEND_PERIOD; + let mut time_last_state_printed = time::Instant::now() - STATE_PRINT_PERIOD; + let mut error_state = false; loop { let time_beginning_loop = time::Instant::now(); if let Err(error) = check_validators(&config.pub_keys) { + error_state = true; println!("Error: {:?}", error); if time::Instant::now() - time_last_email_send >= EMAIL_RESEND_PERIOD { // Send e-mail. println!("Sending email..."); + match send_email( + "Staking ERROR", + &format!("Error: {:?}", error), + &config.smtp_login, + &config.smtp_password, + ) { + Err(email_error) => println!("Error sending email: {:?}", email_error), + _ => { + println!("Email successfully sent"); + time_last_email_send = time::Instant::now(); + } + } + } + } else { + if error_state { + error_state = false; + println!("End of erroneous state"); + } - time_last_email_send = time::Instant::now(); + if time::Instant::now() - time_last_state_printed >= STATE_PRINT_PERIOD { + println!("No error detected"); + time_last_state_printed = time::Instant::now(); } } @@ -100,7 +134,7 @@ fn check_validators(pub_keys: &[String]) -> std::result::Result<(), CheckError> .header("accept", "application/json"); match request_health.send() { Ok(resp) => { - println!("{resp:?}"); + // println!("{resp:?}"); // For debug. match resp.status().as_u16() { 200 => (), 206 => return Err(CheckError::NotSync), @@ -115,19 +149,16 @@ fn check_validators(pub_keys: &[String]) -> std::result::Result<(), CheckError> } } - return Err(CheckError::NotSync); - for pub_key in pub_keys { let request = client .get(format!("{url}beacon/states/head/validators/0x{pub_key}")) .header("accept", "application/json"); match request.send() { Ok(resp) => { - println!("{resp:?}"); + // println!("{resp:?}"); // For debug. match resp.status().as_u16() { 200 => { let json: JsonValidatorState = resp.json()?; - // println!("JSON:\n{:?}", json); // For Debug. if json.data.status != "active_ongoing" { return Err(CheckError::ValidatorStatusError { pub_key: pub_key.clone(), @@ -137,7 +168,6 @@ fn check_validators(pub_keys: &[String]) -> std::result::Result<(), CheckError> } code => { let json: JsonError = resp.json()?; - // println!("JSON:\n{:?}", json); // For Debug. return Err(CheckError::ValidatorError { pub_key: pub_key.clone(), message: format!( @@ -149,7 +179,6 @@ fn check_validators(pub_keys: &[String]) -> std::result::Result<(), CheckError> } } Err(error) => { - println!("{error:?}"); return Err(CheckError::ValidatorError { pub_key: pub_key.clone(), message: error.to_string(), @@ -158,28 +187,29 @@ fn check_validators(pub_keys: &[String]) -> std::result::Result<(), CheckError> } } - // match request_builder - // .header("Authorization", format!("Apikey {}", api_key)) - // .send() - // { - // Ok(resp) => { - // if resp.status().is_success() { - // let content = resp.text().unwrap(); - // Ok(serde_json::from_str(&content).unwrap()) - // } else { - // Err(Box::new(Error { - // message: format!("Request unsuccessful to {}: {:#?}", &url, resp), - // })) - // } - // } - // Err(error) => Err(Box::new(Error { - // message: format!("Error during request to {}: {:?}", &url, error), - // })), - // } - - // 1) Check health. - - // 2) Check each validators. + Ok(()) +} + +fn send_email(title: &str, body: &str, login: &str, pass: &str) -> Result<()> { + let email = Message::builder() + .message_id(None) + .from("Staking Watchdog ".parse()?) + .to("Greg Burri ".parse()?) + .subject(title) + .header(ContentType::TEXT_PLAIN) + .body(body.to_string())?; + + let creds = Credentials::new(login.to_string(), pass.to_string()); + + // Open a remote connection to gmail + let mailer = SmtpTransport::relay("mail.gandi.net")? + .credentials(creds) + .build(); + + // Send the email + let response = mailer.send(&email)?; + + println!("{:?}", response); Ok(()) }