From 2e4851ae1c950c752f99af9a4c6a183d2a6bdfc7 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Thu, 29 Dec 2022 22:46:13 +0100 Subject: [PATCH] rewrite into a better scheduler --- src/main.rs | 177 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 103 insertions(+), 74 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2861284..d52b5b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ -use std::{collections::VecDeque, fs::File}; +use clokwerk::{Scheduler, TimeUnits}; +use rss::{ChannelBuilder, ItemBuilder}; +use std::fs::File; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; use time::OffsetDateTime; -use rss::{ChannelBuilder, Item, ItemBuilder}; - #[derive(Clone, PartialEq, Eq)] struct RemainingPlace { id: String, @@ -11,91 +14,117 @@ struct RemainingPlace { free: usize, } -fn main() -> Result<(), reqwest::Error> { - // const URL: &str = "https://www.lfs.sachsen.de/restplatzboerse-5152.html"; - const URL: &str = "http://127.0.0.1:8080/tip.html"; +// const URL: &str = "https://www.lfs.sachsen.de/restplatzboerse-5152.html"; +const URL: &str = "http://127.0.0.1:8080/tip.html"; +fn main() { + let last_places: Arc>> = Arc::new(Mutex::new(Vec::new())); + let mut scheduler = Scheduler::new(); + + scheduler + .every(1.minutes()) + .run(move || match get_current_places() { + Ok(places) => { + if should_feed_be_updated(&places, &last_places) { + update_rss_file(places); + println!("Updated feed."); + } else { + println!("No update."); + } + } + Err(error) => { + println!("Error: {}", error); + } + }); + + loop { + scheduler.run_pending(); + thread::sleep(Duration::from_millis(10)); + } +} + +fn get_current_places() -> Result, reqwest::Error> { + let body = reqwest::blocking::get(URL)?.text()?; + + let start = body.find("").unwrap(); + + let table = &body[start..=(end + 7)]; + + let mut places: Vec = Vec::new(); + let mut iter = table.lines(); + + while let Some(line) = iter.next() { + if line.contains("") { + let id = parse_node(iter.next().unwrap()); + let description = parse_node(iter.next().unwrap()); + let date = parse_node(iter.next().unwrap()); + let free = parse_node(iter.next().unwrap()).parse().unwrap(); + + let place = RemainingPlace { + id, + description, + date, + free, + }; + places.push(place); + } + } + + Ok(places) +} + +fn update_rss_file(places: Vec) { let mut channel = ChannelBuilder::default() .title(String::from("LFS Restplatzbörse")) .link(URL.to_string()) - .description(String::from("Ein RSS Feed der Restplatzbörse der Landesfeuerwehrschule Sachsen. Nicht offiziell.")) + .description(String::from( + "Ein RSS Feed der Restplatzbörse der Landesfeuerwehrschule Sachsen. Nicht offiziell.", + )) .language(Some("de-DE".to_string())) .build(); - let mut last_places: Vec = Vec::new(); - let mut items: VecDeque = VecDeque::new(); + let title = format!("Restplatzbörse Update - {}", OffsetDateTime::now_utc()); + let content = places + .iter() + .map(|place| { + format!( + "{} - {} - {} - {}", + place.id, place.description, place.date, place.free + ) + }) + .collect::>() + .join("\n"); - loop { - let body = reqwest::blocking::get(URL).unwrap().text().unwrap(); + let item = ItemBuilder::default() + .title(Some(title)) + .content(Some(content)) + .build(); - let start = body.find("").unwrap(); + channel.set_items(vec![item]); - let table = &body[start..=(end + 7)]; + let output = File::create("rss.txt").unwrap(); + channel.pretty_write_to(output, ' ' as u8, 2).unwrap(); +} - let mut places: Vec = Vec::new(); - let mut iter = table.lines(); +fn should_feed_be_updated( + new_places: &Vec, + last_places: &Mutex>, +) -> bool { + let mut last_places = last_places.lock().unwrap(); - while let Some(line) = iter.next() { - if line.contains("") { - let id = parse_node(iter.next().unwrap()); - let description = parse_node(iter.next().unwrap()); - let date = parse_node(iter.next().unwrap()); - let free = parse_node(iter.next().unwrap()).parse().unwrap(); + let are_the_same_places = new_places.len() == last_places.len() + && new_places + .iter() + .zip(last_places.iter()) + .all(|(one, two)| one == two); - let place = RemainingPlace { - id, - description, - date, - free, - }; - places.push(place); - } - } - - let condition = places.len() == last_places.len() - && places - .iter() - .zip(last_places.iter()) - .all(|(one, two)| one == two); - - if !condition { - last_places = places.clone(); - - let title = format!("Restplatzbörse Update - {}", OffsetDateTime::now_utc()); - let content = places - .iter() - .map(|place| { - format!( - "{} - {} - {} - {}", - place.id, place.description, place.date, place.free - ) - }) - .collect::>() - .join("\n"); - - let item = ItemBuilder::default() - .title(Some(title)) - .content(Some(content)) - .build(); - - items.push_back(item); - - if items.len() > 10 { - items.pop_front().unwrap(); - } - - channel.set_items(items.clone()); - - let output = File::create("rss.txt").unwrap(); - channel.pretty_write_to(output, ' ' as u8, 2).unwrap(); - - println!("Got Update and wrote to file"); - } else { - println!("No update"); - } - std::thread::sleep(std::time::Duration::from_secs_f64(60.0)); + if !are_the_same_places { + last_places.clear(); + last_places.append(&mut new_places.clone()); } + + !are_the_same_places } fn parse_node(input: &str) -> String {