rewrite into a better scheduler
This commit is contained in:
parent
cd2dbf7c12
commit
2e4851ae1c
177
src/main.rs
177
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 time::OffsetDateTime;
|
||||||
|
|
||||||
use rss::{ChannelBuilder, Item, ItemBuilder};
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
struct RemainingPlace {
|
struct RemainingPlace {
|
||||||
id: String,
|
id: String,
|
||||||
@ -11,91 +14,117 @@ struct RemainingPlace {
|
|||||||
free: usize,
|
free: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), reqwest::Error> {
|
// const URL: &str = "https://www.lfs.sachsen.de/restplatzboerse-5152.html";
|
||||||
// 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 = "http://127.0.0.1:8080/tip.html";
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let last_places: Arc<Mutex<Vec<RemainingPlace>>> = 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<Vec<RemainingPlace>, reqwest::Error> {
|
||||||
|
let body = reqwest::blocking::get(URL)?.text()?;
|
||||||
|
|
||||||
|
let start = body.find("<tbody").unwrap();
|
||||||
|
let end = body.find("</tbody>").unwrap();
|
||||||
|
|
||||||
|
let table = &body[start..=(end + 7)];
|
||||||
|
|
||||||
|
let mut places: Vec<RemainingPlace> = Vec::new();
|
||||||
|
let mut iter = table.lines();
|
||||||
|
|
||||||
|
while let Some(line) = iter.next() {
|
||||||
|
if line.contains("<tr>") {
|
||||||
|
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<RemainingPlace>) {
|
||||||
let mut channel = ChannelBuilder::default()
|
let mut channel = ChannelBuilder::default()
|
||||||
.title(String::from("LFS Restplatzbörse"))
|
.title(String::from("LFS Restplatzbörse"))
|
||||||
.link(URL.to_string())
|
.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()))
|
.language(Some("de-DE".to_string()))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut last_places: Vec<RemainingPlace> = Vec::new();
|
let title = format!("Restplatzbörse Update - {}", OffsetDateTime::now_utc());
|
||||||
let mut items: VecDeque<Item> = VecDeque::new();
|
let content = places
|
||||||
|
.iter()
|
||||||
|
.map(|place| {
|
||||||
|
format!(
|
||||||
|
"{} - {} - {} - {}",
|
||||||
|
place.id, place.description, place.date, place.free
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
loop {
|
let item = ItemBuilder::default()
|
||||||
let body = reqwest::blocking::get(URL).unwrap().text().unwrap();
|
.title(Some(title))
|
||||||
|
.content(Some(content))
|
||||||
|
.build();
|
||||||
|
|
||||||
let start = body.find("<tbody").unwrap();
|
channel.set_items(vec![item]);
|
||||||
let end = body.find("</tbody>").unwrap();
|
|
||||||
|
|
||||||
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<RemainingPlace> = Vec::new();
|
fn should_feed_be_updated(
|
||||||
let mut iter = table.lines();
|
new_places: &Vec<RemainingPlace>,
|
||||||
|
last_places: &Mutex<Vec<RemainingPlace>>,
|
||||||
|
) -> bool {
|
||||||
|
let mut last_places = last_places.lock().unwrap();
|
||||||
|
|
||||||
while let Some(line) = iter.next() {
|
let are_the_same_places = new_places.len() == last_places.len()
|
||||||
if line.contains("<tr>") {
|
&& new_places
|
||||||
let id = parse_node(iter.next().unwrap());
|
.iter()
|
||||||
let description = parse_node(iter.next().unwrap());
|
.zip(last_places.iter())
|
||||||
let date = parse_node(iter.next().unwrap());
|
.all(|(one, two)| one == two);
|
||||||
let free = parse_node(iter.next().unwrap()).parse().unwrap();
|
|
||||||
|
|
||||||
let place = RemainingPlace {
|
if !are_the_same_places {
|
||||||
id,
|
last_places.clear();
|
||||||
description,
|
last_places.append(&mut new_places.clone());
|
||||||
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::<Vec<String>>()
|
|
||||||
.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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
!are_the_same_places
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_node(input: &str) -> String {
|
fn parse_node(input: &str) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user