#![feature(proc_macro_hygiene, decl_macro)] pub mod misc; pub mod models; pub mod schema; #[macro_use] extern crate rocket; #[macro_use] extern crate diesel; extern crate comrak; extern crate dotenv; 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 diesel::result::Error; use dotenv::dotenv; use misc::get_context; use rocket::Request; use rocket_contrib::serve::StaticFiles; use rocket_contrib::templates::Template; use std::env; use std::vec::Vec; 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 = get_context(); 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("posts", &posts); context.insert("total_pages", &total_pages); context.insert("actual_page", &page); Template::render("index", context) } fn get_post(id_number: i32) -> Result { use schema::posts::dsl::*; let connection = establish_connection(); let post = posts.find(id_number).first(&connection); post } #[get("/post/")] fn show_post(title: String) -> Template { let mut context = get_context(); let title_splited: Vec<&str> = title.split('-').collect(); let id = title_splited.last().unwrap().parse().unwrap(); let post = get_post(id); match post { Ok(mut p) => { let content = markdown_to_html(&p.content, &ComrakOptions::default()); p.content = content; context.insert("post", &p); Template::render("post", context) } Err(_e) => { let uri = format!("/post/{}", title_splited.join("-")); context.insert("url", &uri); Template::render("404", context) } } } #[catch(404)] fn not_found_404(req: &Request) -> Template { let mut context = get_context(); let uri = format!("{}", req.uri()); 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(); }