#![feature(proc_macro_hygiene, decl_macro)] pub mod models; pub mod schema; #[macro_use] extern crate rocket; #[macro_use] extern crate diesel; extern crate comrak; extern crate dotenv; extern crate rand; extern crate rocket_contrib; extern crate tera; use self::diesel::prelude::*; use self::models::*; use comrak::{markdown_to_html, ComrakOptions}; use diesel::pg::PgConnection; use dotenv::dotenv; use rand::Rng; use rocket::Request; use rocket_contrib::serve::StaticFiles; use rocket_contrib::templates::Template; use std::env; use std::vec::Vec; use tera::Context; const TITLES: [&str; 9] = [ "/* {} */", "# {}", "// {}", "", "{# {} #}", "-- {}", "--[[ {} --]]", "; {}", "% {}", ]; const MAX_POSTS_PER_PAGE: i64 = 20; fn establish_connection() -> PgConnection { dotenv().ok(); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL not setted"); PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url)) } fn get_posts(page: i64) -> (Vec, i64) { use schema::posts::dsl::*; let connection = establish_connection(); let visible_posts = posts .filter(published.eq(true)) .limit(MAX_POSTS_PER_PAGE) .offset(MAX_POSTS_PER_PAGE * (page - 1)) .load::(&connection) .expect("Error loading posts"); let number_of_posts: i64 = posts .filter(published.eq(true)) .count() .get_result(&connection) .expect("Error counting the posts"); (visible_posts, number_of_posts) } #[get("/?")] fn index(page: Option) -> Template { let page = page.unwrap_or_else(|| 1); let mut context = Context::new(); let mut rng = rand::thread_rng(); let title_fmt = TITLES[rng.gen_range(0, TITLES.len())]; let title = str::replace(title_fmt, "{}", "CódigoComentado"); let (posts, n_posts) = get_posts(page as i64); let total_pages = (n_posts as f64 / MAX_POSTS_PER_PAGE as f64).ceil() as i64; context.insert("title", &title); context.insert("posts", &posts); context.insert("total_pages", &total_pages); context.insert("actual_page", &page); Template::render("index", context) } fn get_post(id_number: i32) -> Post { use schema::posts::dsl::*; let connection = establish_connection(); let post = posts.find(id_number).first(&connection); post.unwrap() } #[get("/post/")] fn show_post(title: String) -> Template { let mut context = Context::new(); let title_splited: Vec<&str> = title.split('-').collect(); let id = title_splited.last().unwrap().parse().unwrap(); let mut rng = rand::thread_rng(); let title_fmt = TITLES[rng.gen_range(0, TITLES.len())]; let title = str::replace(title_fmt, "{}", "CódigoComentado"); let mut post = get_post(id); let content = markdown_to_html(&post.content, &ComrakOptions::default()); post.content = content; context.insert("title", &title); context.insert("post", &post); Template::render("post", context) } #[catch(404)] fn not_found_404(req: &Request) -> Template { let mut context = Context::new(); let mut rng = rand::thread_rng(); let title_fmt = TITLES[rng.gen_range(0, TITLES.len())]; let title = str::replace(title_fmt, "{}", "CódigoComentado"); let uri = format!("{}", req.uri()); context.insert("title", &title); context.insert("url", &uri); Template::render("404", context) } fn main() { rocket::ignite() .attach(Template::fairing()) .mount("/", routes![index, show_post]) .mount("/static", StaticFiles::from("static")) .register(catchers![not_found_404]) .launch(); }