diff options
author | Jakob Stendahl <14180120+JakobST1n@users.noreply.github.com> | 2023-11-28 16:14:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-28 16:14:34 +0100 |
commit | d32c836554772c3fca738a3629bcb244e60d67ae (patch) | |
tree | 8ae17fa304c23bdcab7827122366547aef61d3f0 | |
parent | 09ce40640757c764ce9be124a689ae244d0a2112 (diff) | |
parent | 342064df385632d50854f1d52147505297f19a04 (diff) | |
download | RSS-watcher-d32c836554772c3fca738a3629bcb244e60d67ae.tar.gz RSS-watcher-d32c836554772c3fca738a3629bcb244e60d67ae.zip |
Merge pull request #4 from micwoj92/master
format code
-rw-r--r-- | src/database.rs | 63 | ||||
-rw-r--r-- | src/main.rs | 44 | ||||
-rw-r--r-- | src/notify.rs | 26 | ||||
-rw-r--r-- | src/rss_utils.rs | 123 |
4 files changed, 155 insertions, 101 deletions
diff --git a/src/database.rs b/src/database.rs index 2cd3c3f..c48bc97 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,8 +1,8 @@ -use std::process; -use std::env; -use log::{debug, info, warn, error}; -use mysql::*; +use log::{debug, error, info, warn}; use mysql::prelude::*; +use mysql::*; +use std::env; +use std::process; #[derive(Debug, PartialEq, Eq)] pub struct FeedConf { @@ -12,7 +12,7 @@ pub struct FeedConf { pub title: String, pub message: String, pub push_url: String, - pub push_token: String + pub push_token: String, } /** @@ -23,11 +23,13 @@ fn build_opts() -> Opts { let db_base = env::var("DB_BASE").expect("$DB_BASE is not set"); let db_user = env::var("DB_USER").expect("$DB_USER is not set"); let db_pass = env::var("DB_PASS").expect("$DB_PASS is not set"); - return Opts::from(OptsBuilder::new() + return Opts::from( + OptsBuilder::new() .ip_or_hostname(Some(db_host)) .user(Some(db_user)) .pass(Some(db_pass)) - .db_name(Some(db_base))); + .db_name(Some(db_base)), + ); } pub fn new_conn() -> Option<Conn> { @@ -44,13 +46,18 @@ pub fn new_conn() -> Option<Conn> { */ fn table_exists(conn: &mut Conn) -> bool { let db_base = env::var("DB_BASE").expect("$DB_BASE is not set"); - let q = conn.prep("SELECT table_name \ + let q = conn + .prep( + "SELECT table_name \ FROM INFORMATION_SCHEMA.TABLES \ WHERE TABLE_SCHEMA=:schema \ - AND TABLE_NAME='rss-watcher-feeds'").unwrap(); - let res: Option<String> = conn.exec_first( - &q, params! {"schema" => db_base}).unwrap(); - if let None = res { return false; } + AND TABLE_NAME='rss-watcher-feeds'", + ) + .unwrap(); + let res: Option<String> = conn.exec_first(&q, params! {"schema" => db_base}).unwrap(); + if let None = res { + return false; + } return true; } @@ -91,7 +98,6 @@ fn table_create(conn: &mut Conn) { error!("Could not create table! ({:#?}", x); process::exit(1); } - } /** @@ -150,7 +156,7 @@ pub fn bootstrap() { } let mut conn = conn_res.unwrap(); info!("Connected to database"); - + if !table_exists(&mut conn) { table_create(&mut conn); } @@ -159,7 +165,10 @@ pub fn bootstrap() { if version < 2 { let res_tx = conn.start_transaction(TxOpts::default()); if let Err(x) = res_tx { - error!("Could not create transaction for updating last fetch time! {:#?}", x); + error!( + "Could not create transaction for updating last fetch time! {:#?}", + x + ); return; } let mut tx = res_tx.unwrap(); @@ -191,10 +200,18 @@ pub fn get_feeds(conn: &mut Conn) -> Option<Vec<FeedConf>> { `push_token` \ FROM `rss-watcher-feeds` \ WHERE `url` NOT LIKE 'version'"; - let res = conn.query_map(q, - |(id,url,last_fetch,title,message,push_url,push_token)| { - FeedConf{id,url,last_fetch,title,message,push_url,push_token} - },); + let res = conn.query_map( + q, + |(id, url, last_fetch, title, message, push_url, push_token)| FeedConf { + id, + url, + last_fetch, + title, + message, + push_url, + push_token, + }, + ); debug!("{:#?}", res); match res { Ok(r) => return Some(r), @@ -211,17 +228,19 @@ pub fn get_feeds(conn: &mut Conn) -> Option<Vec<FeedConf>> { pub fn update_last_fetch(feed_id: u32, last_fetch: i64, conn: &mut Conn) { let res_tx = conn.start_transaction(TxOpts::default()); if let Err(x) = res_tx { - error!("Could not create transaction for updating last fetch time! {:#?}", x); + error!( + "Could not create transaction for updating last fetch time! {:#?}", + x + ); return; } let mut tx = res_tx.unwrap(); let q = "UPDATE `rss-watcher-feeds` SET last_fetch=? WHERE id=?"; - if let Err(x) = tx.exec_drop(q, (last_fetch,feed_id,)) { + if let Err(x) = tx.exec_drop(q, (last_fetch, feed_id)) { warn!("Could not update last fetch time...! ({:#?}", x); } if let Err(x) = tx.commit() { warn!("Could not commit update! ({:#?}", x); } - } diff --git a/src/main.rs b/src/main.rs index a523b4c..55a6557 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,16 @@ -mod rss_utils; -mod notify; mod database; +mod notify; +mod rss_utils; use database::FeedConf; +use log::{debug, error, info, warn}; use std::env; use std::process; -use log::{debug, info, warn, error}; -use chrono::prelude::{Utc,DateTime,NaiveDateTime}; -use tokio::{time}; -use std::time::Duration; +use chrono::prelude::{DateTime, NaiveDateTime, Utc}; use feed_rs::model::Feed; +use std::time::Duration; +use tokio::time; /** * This calls fetch_feed, and figures out wether it succeeded or not. @@ -22,8 +22,12 @@ async fn get_feed(feed_conf: &FeedConf) -> bool { // time as that. Which means that no articles will be found. let last_fetch_time; match &feed_conf.last_fetch { - Some(x) => last_fetch_time = DateTime::from_utc( - NaiveDateTime::from_timestamp_opt(x.to_owned(),0).unwrap(), Utc), + Some(x) => { + last_fetch_time = DateTime::from_utc( + NaiveDateTime::from_timestamp_opt(x.to_owned(), 0).unwrap(), + Utc, + ) + } None => last_fetch_time = Utc::now(), } debug!("Using last_fetch_time {:?}", last_fetch_time.to_owned()); @@ -32,16 +36,18 @@ async fn get_feed(feed_conf: &FeedConf) -> bool { let res = rss_utils::fetch_feed(&feed_conf, last_fetch_time).await; let feed_res: Option<Feed>; match res { - Err(e) => { + Err(e) => { error!("Could not fetch feed ({:?})", e); return false; - }, - Ok(x) => feed_res = x + } + Ok(x) => feed_res = x, } - // If feed is empty (we got status code 304), we should skip any further + // If feed is empty (we got status code 304), we should skip any further // processing - if let None = feed_res { return false; } + if let None = feed_res { + return false; + } let feed = feed_res.unwrap(); // Process all entries in the feed @@ -57,13 +63,15 @@ async fn main_loop() { let res_conn = database::new_conn(); if let None = res_conn { - error!("Could not open database connection, waiting until next iteration before trying again!"); + error!( + "Could not open database connection, waiting until next iteration before trying again!" + ); return; }; let mut conn = res_conn.unwrap(); let res_feeds = database::get_feeds(&mut conn); - + if let None = res_feeds { error!("Could not get feeds, waiting until next iteration before trying again!"); return; @@ -80,7 +88,7 @@ async fn main_loop() { } } -/** +/** * Main app, sets up database, and then it keeps an active loop. */ async fn app() { @@ -95,11 +103,11 @@ async fn app() { process::exit(1); } interval_timeout = res.unwrap(); - }, + } Err(_e) => { warn!("$FETCH_INTERVAL not set, using default of 2m"); interval_timeout = 120000; - }, + } } let mut interval = time::interval(Duration::from_millis(interval_timeout)); diff --git a/src/notify.rs b/src/notify.rs index 19915db..9d7e81b 100644 --- a/src/notify.rs +++ b/src/notify.rs @@ -1,14 +1,19 @@ use crate::database::FeedConf; use crate::rss_utils; -use log::{info, error}; +use chrono::prelude::{DateTime, Utc}; use feed_rs::model::Feed; -use chrono::prelude::{Utc,DateTime}; +use log::{error, info}; /** * Push feed entry to gotify */ -async fn gotify(title: String, message: String, link: Option<String>, feed_conf: &FeedConf) -> Result<(), reqwest::Error> { +async fn gotify( + title: String, + message: String, + link: Option<String>, + feed_conf: &FeedConf, +) -> Result<(), reqwest::Error> { let uri = format!("{}/message", &feed_conf.push_url); // Build json string that will be sent as payload to gotify @@ -17,7 +22,7 @@ async fn gotify(title: String, message: String, link: Option<String>, feed_conf: req.push_str(format!("\"title\":\"{}\"", title).as_str()); req.push_str(format!(",\"message\":\"{}\"", message).as_str()); req.push_str(",\"priority\":1"); - + req.push_str(",\"extras\": {"); req.push_str("\"client::display\": { \"contentType\": \"text/markdown\" }"); if link.is_some() { @@ -29,12 +34,13 @@ async fn gotify(title: String, message: String, link: Option<String>, feed_conf: // Send request to gotify let client = reqwest::Client::new(); - let res = client.post(uri) - .query(&[("token",&feed_conf.push_token)]) - .body(req.to_owned()) - .header("Content-Type", "application/json") - .send() - .await?; + let res = client + .post(uri) + .query(&[("token", &feed_conf.push_token)]) + .body(req.to_owned()) + .header("Content-Type", "application/json") + .send() + .await?; if res.status().is_success() { info!("Sent notification with title \"{}\"", title); } else { diff --git a/src/rss_utils.rs b/src/rss_utils.rs index bce412d..823f6a3 100644 --- a/src/rss_utils.rs +++ b/src/rss_utils.rs @@ -1,23 +1,30 @@ use crate::database::FeedConf; -use log::{debug, info}; -use std::error::Error; -use feed_rs::parser; +use chrono::prelude::{DateTime, Utc}; use feed_rs::model; -use chrono::prelude::{Utc,DateTime}; +use feed_rs::parser; use html2md; +use log::{debug, info}; +use std::error::Error; extern crate mime; /** * Extract text field from Option */ fn extract_text(text: &Option<model::Text>, field: &str) -> String { - if text.is_none() { return String::from(format!("Field {:#?} was not in feed", field)); } + if text.is_none() { + return String::from(format!("Field {:#?} was not in feed", field)); + } let field = text.as_ref().unwrap(); match (field.content_type.type_(), field.content_type.subtype()) { (mime::TEXT, mime::HTML) => return html2md::parse_html(field.content.as_ref()), (mime::TEXT, mime::PLAIN) => return field.content.to_owned(), - _ => return String::from(format!("Unknown field content type {:#?}", field.content_type)), + _ => { + return String::from(format!( + "Unknown field content type {:#?}", + field.content_type + )) + } } } @@ -25,7 +32,9 @@ fn extract_text(text: &Option<model::Text>, field: &str) -> String { * Extract string field from Option */ fn extract_string(text: &Option<String>, field: &str) -> String { - if text.is_none() { return String::from(format!("Field {:#?} was not in feed", field)); } + if text.is_none() { + return String::from(format!("Field {:#?} was not in feed", field)); + } return text.as_ref().unwrap().to_owned(); } @@ -33,7 +42,9 @@ fn extract_string(text: &Option<String>, field: &str) -> String { * Extract string field from Option */ fn extract_datetime(date: &Option<DateTime<Utc>>, field: &str) -> String { - if date.is_none() { return String::from(format!("Field {:#?} was not in feed", field)); } + if date.is_none() { + return String::from(format!("Field {:#?} was not in feed", field)); + } return date.unwrap().to_rfc2822().replace("+0000", "UTC"); } @@ -45,25 +56,28 @@ fn person_vec_to_md(person_vec: &Vec<model::Person>) -> String { for (i, person) in person_vec.iter().enumerate() { if person.uri.is_some() && person.email.is_some() { - md_str.push_str(format!("[{}]({}) - [homepage]({})", - person.name, - person.email.as_ref().unwrap(), - person.uri.as_ref().unwrap() - ).as_str()); + md_str.push_str( + format!( + "[{}]({}) - [homepage]({})", + person.name, + person.email.as_ref().unwrap(), + person.uri.as_ref().unwrap() + ) + .as_str(), + ); } else if person.uri.is_some() { - md_str.push_str(format!("[{}]({})", - person.name, - person.uri.as_ref().unwrap(), - ).as_str()); + md_str + .push_str(format!("[{}]({})", person.name, person.uri.as_ref().unwrap(),).as_str()); } else if person.email.is_some() { - md_str.push_str(format!("[{}]({})", - person.name, - person.email.as_ref().unwrap(), - ).as_str()); + md_str.push_str( + format!("[{}]({})", person.name, person.email.as_ref().unwrap(),).as_str(), + ); } else { md_str.push_str(&person.name); } - if i < (person_vec.len() - 1) { md_str.push_str(", "); } + if i < (person_vec.len() - 1) { + md_str.push_str(", "); + } } return md_str; } @@ -76,19 +90,16 @@ fn link_vec_to_md(link_vec: &Vec<model::Link>) -> String { for (i, link) in link_vec.iter().enumerate() { if link.title.is_some() { - md_str.push_str(format!("[{}]({})", - &link.title.as_ref().unwrap(), - &link.href).as_str()); + md_str + .push_str(format!("[{}]({})", &link.title.as_ref().unwrap(), &link.href).as_str()); } else if link.rel.is_some() { - md_str.push_str(format!("[{}]({})", - &link.rel.as_ref().unwrap(), - &link.href).as_str()); + md_str.push_str(format!("[{}]({})", &link.rel.as_ref().unwrap(), &link.href).as_str()); } else { - md_str.push_str(format!("[{}]({})", - &link.href, - &link.href).as_str()); + md_str.push_str(format!("[{}]({})", &link.href, &link.href).as_str()); + } + if i < (link_vec.len() - 1) { + md_str.push_str(", "); } - if i < (link_vec.len() - 1) { md_str.push_str(", "); } } return md_str; } @@ -105,7 +116,9 @@ fn category_vec_to_md(category_vec: &Vec<model::Category>) -> String { } else { md_str.push_str(&category.term); } - if i < (category_vec.len() - 1) { md_str.push_str(", "); } + if i < (category_vec.len() - 1) { + md_str.push_str(", "); + } } return md_str; } @@ -139,7 +152,7 @@ fn fill_template_field(field: &str, entry: &model::Entry, feed: &model::Feed) -> "entry.published" => return extract_datetime(&entry.published, field).to_owned(), "entry.source" => return extract_string(&entry.source, field).to_owned(), "entry.rights" => return extract_text(&entry.rights, field).to_owned(), - _ => return String::from(format!("Unknown field {:#?}", field)) + _ => return String::from(format!("Unknown field {:#?}", field)), } } @@ -148,12 +161,13 @@ fn fill_template_field(field: &str, entry: &model::Entry, feed: &model::Feed) -> * special HTML characters. */ pub fn escape(input: String) -> String { - return input.replace("\\","\\\\") - .replace("\"", "\\\"") - .replace("\n", "\\n") - .replace("<", "<") - .replace(">", ">") - .replace("&", "$amp;"); + return input + .replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("\n", "\\n") + .replace("<", "<") + .replace(">", ">") + .replace("&", "$amp;"); } /** @@ -173,9 +187,7 @@ pub fn fill_template(template_str: &str, entry: &model::Entry, feed: &model::Fee if c == '}' { r_bracket_n += 1; if r_bracket_n > 1 { - filled_str.push_str(fill_template_field(&field, - &entry, - &feed).as_str()); + filled_str.push_str(fill_template_field(&field, &entry, &feed).as_str()); field = "".to_owned(); r_bracket_n = 0; l_bracket_n = 0; @@ -185,7 +197,9 @@ pub fn fill_template(template_str: &str, entry: &model::Entry, feed: &model::Fee } } else if c == '{' { l_bracket_n += 1; - if l_bracket_n > 1 { field = "".to_owned(); } + if l_bracket_n > 1 { + field = "".to_owned(); + } } else { l_bracket_n = 0; filled_str.push(c); @@ -196,18 +210,25 @@ pub fn fill_template(template_str: &str, entry: &model::Entry, feed: &model::Fee /** * Function takes a FeedConf struct, and makes a get request to fetch - * the feed. It then uses feed_rs to parse that feed and returns that + * the feed. It then uses feed_rs to parse that feed and returns that * parsed feed. */ -pub async fn fetch_feed(feed_conf: &FeedConf, last_fetch_time: DateTime<Utc>) -> Result<Option<model::Feed>, Box<dyn Error>> { +pub async fn fetch_feed( + feed_conf: &FeedConf, + last_fetch_time: DateTime<Utc>, +) -> Result<Option<model::Feed>, Box<dyn Error>> { info!("Fetching feed \"{}\"", &feed_conf.url); let client = reqwest::Client::new(); let last_fetch_rfc2822 = last_fetch_time.to_rfc2822().replace("+0000", "GMT"); - debug!("Using header \"If-Modified-Since {:?}\"", &last_fetch_rfc2822); - let resp = client.get(&feed_conf.url) - .header("If-Modified-Since", &last_fetch_rfc2822) - .send() - .await?; + debug!( + "Using header \"If-Modified-Since {:?}\"", + &last_fetch_rfc2822 + ); + let resp = client + .get(&feed_conf.url) + .header("If-Modified-Since", &last_fetch_rfc2822) + .send() + .await?; if resp.status() == 304 { info!("No changes since last fetch at {}", &last_fetch_rfc2822); Ok(None) |