use actix_web::{get, http::header::ContentType, routes, web, HttpResponse, Responder}; use cached::proc_macro::once; use ramhorns::Content; use crate::{ config::Config, template::{InfosPage, NavBar}, utils::{ markdown::{File, TypeFileMetadata}, misc::{make_kw, read_file, Html}, routes::blog::{build_rss, get_post, get_posts, Post, BLOG_DIR, MIME_TYPE_RSS, POST_DIR}, }, }; #[get("/blog")] pub async fn index(config: web::Data) -> impl Responder { Html(build_index(config.get_ref().to_owned())) } #[derive(Content, Debug)] struct BlogIndexTemplate { navbar: NavBar, about: Option, posts: Vec, no_posts: bool, } #[once(time = 60)] fn build_index(config: Config) -> String { let blog_dir = format!("{}/{}", config.locations.data_dir, BLOG_DIR); let mut posts = get_posts(&format!("{blog_dir}/{POST_DIR}")); // Get about let about: Option = read_file(&format!("{blog_dir}/about.md"), &TypeFileMetadata::Generic); // Sort from newest to oldest posts.sort_by_cached_key(|p| (p.date.year, p.date.month, p.date.day)); posts.reverse(); config.tmpl.render( "blog/index.html", BlogIndexTemplate { navbar: NavBar { blog: true, ..NavBar::default() }, about, no_posts: posts.is_empty(), posts, }, InfosPage { title: Some("Blog".into()), desc: Some(format!( "Liste des posts d'{}", config.fc.name.unwrap_or_default() )), kw: Some(make_kw(&["blog", "blogging"])), }, ) } #[derive(Content, Debug)] struct BlogPostTemplate { navbar: NavBar, post: Option, toc: String, } #[get("/blog/p/{id}")] pub async fn page(path: web::Path<(String,)>, config: web::Data) -> impl Responder { Html(build_post( &path.into_inner().0, config.get_ref().to_owned(), )) } fn build_post(file: &str, config: Config) -> String { let mut post = None; let (infos, toc) = get_post( &mut post, file, &config.fc.name.unwrap_or_default(), &config.locations.data_dir, ); config.tmpl.render( "blog/post.html", BlogPostTemplate { navbar: NavBar { blog: true, ..NavBar::default() }, post, toc, }, infos, ) } #[routes] #[get("/blog/blog.rss")] #[get("/blog/rss")] pub async fn rss(config: web::Data) -> impl Responder { HttpResponse::Ok() .content_type(ContentType(MIME_TYPE_RSS.parse().unwrap())) .body(build_rss(config.get_ref().to_owned())) }