lfs_scraper/src/remaining_place.rs

94 lines
2.4 KiB
Rust

use crate::html_parser::{parse_inner_node, replace_html_codes};
#[derive(Clone, PartialEq, Eq)]
pub struct RemainingPlace {
pub id: String,
pub description: String,
pub date: String,
pub free: usize,
}
impl Ord for RemainingPlace {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}
impl PartialOrd for RemainingPlace {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.id.partial_cmp(&other.id)
}
}
pub fn get_current_places(url: &str) -> 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 lines: Vec<String> = Vec::new();
let mut line = table.replace("\n", "").replace("\r", "");
while let Some(begin) = line.find("<td") {
match line.find("</td>") {
Some(end) => {
let inner_node = &line[(begin + 5)..end];
let content = parse_inner_node(inner_node);
let escaped_content = replace_html_codes(&content);
lines.push(escaped_content);
line.replace_range(begin..=end + 5, "");
}
None => break,
}
}
lines.chunks(5).for_each(|chunk| {
let free = try_parse_free_slot(&chunk[3]);
let (id, description) = if let Some((id, description)) = chunk[0].split_once(' ') {
(id, description)
} else {
return;
};
if free.is_none() {
return;
}
let new_remaining_place = RemainingPlace {
id: id.to_string(),
description: description.to_string(),
date: chunk[2].clone(),
free: free.unwrap()
};
places.push(new_remaining_place);
});
places.sort();
Ok(places)
}
fn try_parse_free_slot(content: &str) -> Option<usize> {
if let Ok(slots) = content.parse::<usize>() {
return Some(slots)
}
if let Some((left, right)) = content.split_once(' ') {
if let Ok(slots) = left.parse::<usize>() {
return Some(slots)
}
if let Ok(slots) = right.parse::<usize>() {
return Some(slots)
}
}
None
}