extern crate chrono; extern crate feed_rs; extern crate maud; extern crate reqwest; use rand::seq::SliceRandom; use rand::thread_rng; use std::collections::HashSet; use std::error::Error; use std::fs::write; use std::fs::DirBuilder; use std::path::Path; mod site_generator; mod utilities; mod web_fetchers; use rayon::prelude::*; fn main() -> Result<(), Box> { simple_logger::init_with_level(log::Level::Info).unwrap(); let all_posts = utilities::read_feed("feeds.txt"); let mut posts = all_posts.clone(); posts.retain(|post| post.score.is_positive()); // Keep only the first occurence of each main_url { let mut seen_urls = HashSet::new(); posts.retain(|post| seen_urls.insert(post.main_url.clone())); } let mut featured = utilities::read_feed("featured_feeds.txt"); // Give featured a small boost in points featured = featured .iter_mut() .map(|post| { post.score = (post.score as f64 * 1.5) as i64; post.clone() }) .collect::>(); posts.extend(featured); posts.par_iter_mut().for_each(utilities::find_image); posts.par_iter_mut().for_each(utilities::validate); posts.sort(); // Move the post with an image_url to the head of the list if let Some(pos) = posts.iter().position(|post| post.image_url.is_some()) { let post_with_image = posts.remove(pos); posts.insert(0, post_with_image); } utilities::retain_first_main_url(&mut posts); posts.truncate(16); let mut old_posts = all_posts; old_posts.retain(|p| !posts.contains(p)); old_posts.shuffle(&mut thread_rng()); let mut archive_posts: Vec = Vec::new(); let archive_size = 100; while (archive_posts.len() < archive_size) && (old_posts.len() > 50) { let iter_size = archive_size - archive_posts.len(); let mut extracted = old_posts .drain(0..=(iter_size + 50)) .collect::>(); extracted.par_iter_mut().for_each(utilities::validate); extracted.retain(|post| post.score != 0); archive_posts.extend(extracted); } archive_posts.truncate(archive_size); let index = site_generator::generate_index(posts.clone(), archive_posts.clone()); let index_path = Path::new("output/index.html"); DirBuilder::new() .recursive(true) .create(index_path.parent().unwrap()) .unwrap(); match write(index_path, index.into_string()) { Ok(_) => log::info!("Successfully wrote to {}", index_path.display()), Err(e) => log::error!("Failed to write to {}: {}", index_path.display(), e), } let feed = site_generator::generate_rss(posts.clone()); let feed_path = Path::new("output/feed.xml"); DirBuilder::new() .recursive(true) .create(feed_path.parent().unwrap()) .unwrap(); match write(feed_path, feed) { Ok(_) => log::info!("Successfully wrote to {}", feed_path.display()), Err(e) => log::error!("Failed to write to {}: {}", feed_path.display(), e), } Ok(()) }