2019-12-08 23:07:49 +00:00
|
|
|
pub mod admin;
|
2024-02-20 06:41:51 +00:00
|
|
|
pub mod contexts;
|
2019-12-15 23:12:07 +00:00
|
|
|
pub mod controllers;
|
2019-11-25 20:59:42 +00:00
|
|
|
pub mod misc;
|
2019-11-14 02:10:42 +00:00
|
|
|
pub mod models;
|
2019-12-17 23:02:10 +00:00
|
|
|
mod schema;
|
2019-11-14 02:10:42 +00:00
|
|
|
|
2019-11-13 07:17:38 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate rocket;
|
2019-11-14 02:10:42 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate diesel;
|
2019-11-13 07:17:38 +00:00
|
|
|
|
2024-05-31 06:54:09 +00:00
|
|
|
use comrak::{markdown_to_html, Options};
|
2019-12-16 00:34:27 +00:00
|
|
|
use controllers::posts;
|
2019-12-17 23:02:10 +00:00
|
|
|
use dotenv::dotenv;
|
2024-06-15 00:28:36 +00:00
|
|
|
use isbot::Bots;
|
2024-02-20 06:41:51 +00:00
|
|
|
use rocket::fs::{FileServer, NamedFile};
|
2024-06-15 00:28:36 +00:00
|
|
|
use rocket::http::Status;
|
|
|
|
use rocket::request::{FromRequest, Outcome, Request};
|
2024-02-20 06:41:51 +00:00
|
|
|
use rocket::response::content::RawXml;
|
2024-06-18 06:15:36 +00:00
|
|
|
use rocket::tokio::sync::OnceCell;
|
2024-02-20 06:41:51 +00:00
|
|
|
use rocket_dyn_templates::Template;
|
2019-12-15 23:24:19 +00:00
|
|
|
use std::path::Path;
|
2019-11-14 02:10:42 +00:00
|
|
|
use std::vec::Vec;
|
2019-11-25 20:59:42 +00:00
|
|
|
|
2024-06-18 06:15:36 +00:00
|
|
|
static BOTS: OnceCell<Bots> = OnceCell::const_new();
|
|
|
|
|
|
|
|
async fn is_bot(ua: &String) -> bool {
|
|
|
|
let bots = BOTS.get_or_init(|| async { Bots::default() }).await;
|
|
|
|
bots.is_bot(ua)
|
2024-06-15 00:28:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct Headers {
|
|
|
|
user_agent: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rocket::async_trait]
|
|
|
|
impl<'r> FromRequest<'r> for Headers {
|
|
|
|
type Error = ();
|
|
|
|
|
|
|
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
|
|
|
let token = request.headers().get_one("User-Agent");
|
|
|
|
match token {
|
|
|
|
Some(token) => Outcome::Success(Headers {
|
|
|
|
user_agent: token.to_string(),
|
|
|
|
}),
|
|
|
|
None => Outcome::Error((Status::Unauthorized, ())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-14 02:10:42 +00:00
|
|
|
#[get("/?<page>")]
|
2019-12-16 00:34:27 +00:00
|
|
|
fn index(page: Option<u64>) -> Template {
|
|
|
|
let page: u64 = page.unwrap_or(1);
|
2019-11-14 02:10:42 +00:00
|
|
|
|
2019-12-19 00:32:45 +00:00
|
|
|
let (posts, n_posts) = posts::get_posts(Some(page));
|
2019-11-17 05:10:06 +00:00
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
let context = contexts::PageOfPosts::new(posts, page, n_posts);
|
2019-11-17 05:10:06 +00:00
|
|
|
|
2019-11-13 07:17:38 +00:00
|
|
|
Template::render("index", context)
|
|
|
|
}
|
|
|
|
|
2023-12-11 04:53:43 +00:00
|
|
|
#[get("/feed.xml")]
|
2024-02-20 06:41:51 +00:00
|
|
|
fn rss_feed() -> RawXml<Template> {
|
2023-12-11 04:53:43 +00:00
|
|
|
let (mut posts, _) = posts::get_posts(None);
|
|
|
|
|
2024-05-31 06:54:09 +00:00
|
|
|
let mut comrak_options = Options::default();
|
|
|
|
comrak_options.extension.table = true;
|
|
|
|
comrak_options.extension.autolink = true;
|
|
|
|
comrak_options.extension.tasklist = true;
|
|
|
|
comrak_options.render.unsafe_ = true;
|
2023-12-11 04:53:43 +00:00
|
|
|
|
|
|
|
posts.iter_mut().for_each(|post| {
|
|
|
|
let content = markdown_to_html(&post.content, &comrak_options);
|
|
|
|
post.content = content;
|
|
|
|
});
|
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
let context = contexts::XmlFeed::new(posts);
|
2023-12-11 04:53:43 +00:00
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
RawXml(Template::render("rss", context))
|
2023-12-11 04:53:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/atom.xml")]
|
2024-02-20 06:41:51 +00:00
|
|
|
fn atom_feed() -> RawXml<Template> {
|
2023-12-11 04:53:43 +00:00
|
|
|
let (mut posts, _) = posts::get_posts(None);
|
|
|
|
|
2024-05-31 06:54:09 +00:00
|
|
|
let mut comrak_options = Options::default();
|
|
|
|
comrak_options.extension.table = true;
|
|
|
|
comrak_options.extension.autolink = true;
|
|
|
|
comrak_options.extension.tasklist = true;
|
|
|
|
comrak_options.render.unsafe_ = true;
|
2023-12-11 04:53:43 +00:00
|
|
|
|
|
|
|
posts.iter_mut().for_each(|post| {
|
|
|
|
let content = markdown_to_html(&post.content, &comrak_options);
|
|
|
|
post.content = content;
|
|
|
|
});
|
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
let context = contexts::XmlFeed::new(posts);
|
2023-12-11 04:53:43 +00:00
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
RawXml(Template::render("atom", context))
|
2023-12-11 04:53:43 +00:00
|
|
|
}
|
|
|
|
|
2019-11-18 08:16:16 +00:00
|
|
|
#[get("/post/<title>")]
|
2024-06-18 06:15:36 +00:00
|
|
|
async fn show_post(title: &str, headers: Headers) -> Template {
|
2019-11-17 22:09:36 +00:00
|
|
|
let title_splited: Vec<&str> = title.split('-').collect();
|
2019-12-15 23:12:07 +00:00
|
|
|
let id = title_splited.last().unwrap().parse().unwrap_or(-1);
|
2019-11-17 22:09:36 +00:00
|
|
|
|
2019-12-16 00:34:27 +00:00
|
|
|
match posts::get_post(id) {
|
2019-11-25 23:42:57 +00:00
|
|
|
Ok(mut post) => {
|
2024-06-18 06:15:36 +00:00
|
|
|
if !is_bot(&headers.user_agent).await {
|
2024-06-15 00:28:36 +00:00
|
|
|
posts::add_visit(id);
|
|
|
|
}
|
2024-06-01 07:26:37 +00:00
|
|
|
|
2024-05-31 06:54:09 +00:00
|
|
|
let mut comrak_options = Options::default();
|
|
|
|
comrak_options.extension.table = true;
|
|
|
|
comrak_options.extension.autolink = true;
|
|
|
|
comrak_options.extension.tasklist = true;
|
|
|
|
comrak_options.render.unsafe_ = true;
|
2024-06-01 07:00:42 +00:00
|
|
|
comrak_options.extension.header_ids = Some("id-".to_string());
|
2019-12-21 09:55:21 +00:00
|
|
|
|
|
|
|
let content = markdown_to_html(&post.content, &comrak_options);
|
2019-11-25 23:42:57 +00:00
|
|
|
post.content = content;
|
2019-11-17 22:09:36 +00:00
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
let context = contexts::SinglePost::new(post);
|
|
|
|
|
2019-11-24 04:44:11 +00:00
|
|
|
Template::render("post", context)
|
|
|
|
}
|
2019-12-15 23:12:07 +00:00
|
|
|
Err(_) => {
|
2024-02-20 06:59:15 +00:00
|
|
|
let url = format!("/post/{}", title_splited.join("-"));
|
2024-02-20 06:41:51 +00:00
|
|
|
|
2024-02-20 06:59:15 +00:00
|
|
|
let context = contexts::NotFound::new(url);
|
2024-02-20 06:41:51 +00:00
|
|
|
|
2019-11-24 04:44:11 +00:00
|
|
|
Template::render("404", context)
|
|
|
|
}
|
|
|
|
}
|
2019-11-17 22:09:36 +00:00
|
|
|
}
|
|
|
|
|
2019-11-23 19:05:41 +00:00
|
|
|
#[catch(404)]
|
|
|
|
fn not_found_404(req: &Request) -> Template {
|
|
|
|
let uri = format!("{}", req.uri());
|
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
let context = contexts::NotFound::new(uri);
|
|
|
|
|
2019-11-23 19:05:41 +00:00
|
|
|
Template::render("404", context)
|
|
|
|
}
|
|
|
|
|
2019-12-15 23:24:19 +00:00
|
|
|
#[get("/favicon.ico")]
|
2024-02-20 06:41:51 +00:00
|
|
|
async fn favicon() -> Option<NamedFile> {
|
|
|
|
NamedFile::open(Path::new("static/favicon.ico")).await.ok()
|
2019-12-15 23:24:19 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
#[launch]
|
|
|
|
fn rocket() -> _ {
|
2019-12-17 23:02:10 +00:00
|
|
|
dotenv().ok();
|
|
|
|
|
2024-02-20 06:41:51 +00:00
|
|
|
rocket::build()
|
2019-11-13 07:17:38 +00:00
|
|
|
.attach(Template::fairing())
|
2023-12-11 04:53:43 +00:00
|
|
|
.mount("/", routes![index, show_post, favicon, rss_feed, atom_feed])
|
2019-12-17 23:02:10 +00:00
|
|
|
.mount("/admin", admin::get_routes())
|
2024-02-20 06:41:51 +00:00
|
|
|
.mount("/static", FileServer::from("static"))
|
|
|
|
.register("/", catchers![not_found_404])
|
2019-11-13 01:57:32 +00:00
|
|
|
}
|