extern crate chrono; mod config; mod theme; mod repository; use actix_web::middleware::Logger; use actix_web::{get, web, App, HttpResponse, HttpServer, Responder}; use fern; use std::{env, io}; use crate::config::Configuration; use crate::theme::Theme; use crate::repository::{ ArticlesRepository, FsRepository }; #[get("")] async fn show_articles_list() -> impl Responder { let repo: FsRepository = FsRepository {}; const CONTENT_FOLDER: &str = "./content"; let exe_dir = env::current_dir() .and_then(|dir| Ok(dir.to_str().unwrap_or("").to_string())) .unwrap(); log::trace!("Estimated content repository: {exe_dir}/{CONTENT_FOLDER}"); let paths = repo.get_directory_listing(&CONTENT_FOLDER).join("\n"); HttpResponse::Ok().body(format!("List of articles:\r\n{paths}")) } #[get("/{path:.+}")] async fn show_article(path: web::Path<(String,)>) -> impl Responder { let p = format!("./content/{}", &path.0); let exe_dir = env::current_dir() .and_then(|dir| Ok(dir.to_str().unwrap_or("").to_string())) .unwrap(); let theme_path = format!("{}/www/themes/default", exe_dir); log::info!("Theme path: {}", theme_path); let theme = Theme::new(theme_path); let rendered = theme.markdown_as_html(&p); match rendered { Ok(content) => HttpResponse::Ok().body(content), Err(e) => { log::error!("Couldn't find article located at '{}'. Error: {}", p, e); HttpResponse::NotFound().finish() } } } #[actix_web::main] async fn main() -> io::Result<()> { if !env::vars().any(|(k, _)| k == "RUST_LOG") { env::set_var("RUST_LOG", "trace"); } let config = Configuration::default(); let _ = fern::Dispatch::new() .format(|out, message, record| { out.finish(format_args!( "{}[{}][{}] {}", chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), record.target(), record.level(), message )) }) .level(log::LevelFilter::Info) .chain(io::stdout()) .apply(); HttpServer::new(|| { App::new() .wrap(Logger::default()) .service(actix_files::Files::new("/css", "./www/themes/default/css")) .service(actix_files::Files::new( "/images", "./www/themes/default/images", )) .service(actix_files::Files::new("/js", "./www/themes/default/js")) .service( web::scope("/a") .service(show_article) .service(show_articles_list), ) }) .bind((config.listen_addr, config.listen_port))? .run() .await }