aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorFuwn <[email protected]>2022-03-30 03:04:48 -0700
committerFuwn <[email protected]>2022-03-30 03:04:48 -0700
commit0495bd1837087a91a36036dbaab71c83c3acc197 (patch)
tree6f1744db3bf9a7eb07da70971f0b2aa39741a0b0 /src/main.rs
downloadlocus-0495bd1837087a91a36036dbaab71c83c3acc197.tar.xz
locus-0495bd1837087a91a36036dbaab71c83c3acc197.zip
feat: 0.0.0 :star:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..e88fd9b
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,155 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+#![feature(once_cell)]
+#![deny(
+ warnings,
+ nonstandard_style,
+ unused,
+ future_incompatible,
+ rust_2018_idioms,
+ unsafe_code
+)]
+#![deny(clippy::all, clippy::nursery, clippy::pedantic)]
+#![recursion_limit = "128"]
+#![allow(clippy::cast_precision_loss)]
+
+mod constants;
+mod macros;
+mod modules;
+
+#[macro_use]
+extern crate log;
+
+use std::{lazy::SyncLazy, sync::Mutex};
+
+use constants::QUOTES;
+use pickledb::PickleDb;
+use rand::seq::SliceRandom;
+use tokio::time::Instant;
+use windmark::{Response, Router};
+use yarte::Template;
+
+static DATABASE: SyncLazy<Mutex<PickleDb>> = SyncLazy::new(|| {
+ Mutex::new({
+ if std::fs::File::open("locus.db").is_ok() {
+ PickleDb::load_json("locus.db", pickledb::PickleDbDumpPolicy::AutoDump)
+ .unwrap()
+ } else {
+ PickleDb::new_json("locus.db", pickledb::PickleDbDumpPolicy::AutoDump)
+ }
+ })
+});
+
+#[derive(Template)]
+#[template(path = "main")]
+struct Main<'a> {
+ body: &'a str,
+ hits: &'a i32,
+ quote: &'a str,
+ commit: &'a str,
+}
+
+fn hits_from_route(route: &str) -> i32 {
+ (*DATABASE.lock().unwrap()).get::<i32>(route).unwrap()
+}
+
+#[windmark::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ std::env::set_var("RUST_LOG", "windmark,locus=trace");
+ pretty_env_logger::init();
+
+ let mut time_mount = Instant::now();
+ let mut router = Router::new();
+ let uptime = Instant::now();
+
+ router.set_private_key_file(".locus/locus_private.pem");
+ router.set_certificate_chain_file(".locus/locus_pair.pem");
+ router.set_pre_route_callback(Box::new(|stream, url, _| {
+ info!(
+ "accepted connection from {} to {}",
+ stream.peer_addr().unwrap().ip(),
+ url.to_string(),
+ );
+
+ let previous_database = (*DATABASE.lock().unwrap()).get::<i32>(url.path());
+
+ match previous_database {
+ None => {
+ (*DATABASE.lock().unwrap())
+ .set::<i32>(url.path(), &0)
+ .unwrap();
+ }
+ Some(_) => {}
+ }
+
+ let new_database = (*DATABASE.lock().unwrap()).get::<i32>(url.path());
+
+ (*DATABASE.lock().unwrap())
+ .set(url.path(), &(new_database.unwrap() + 1))
+ .unwrap();
+ }));
+ router.set_error_handler(Box::new(|_| {
+ Response::NotFound(
+ "The requested resource could not be found at this time. You can try \
+ refreshing the page, if that doesn't change anything; contact Fuwn! \
+ .into(),
+ )
+ }));
+ router.mount(
+ "/uptime",
+ Box::new(move |context| {
+ success!(
+ &format!("# UPTIME\n\n{} seconds", uptime.elapsed().as_secs()),
+ context
+ )
+ }),
+ );
+
+ info!(
+ "preliminary mounts took {}ms",
+ time_mount.elapsed().as_nanos() as f64 / 1_000_000.0
+ );
+ time_mount = Instant::now();
+
+ router.attach(modules::multi_blog);
+
+ info!(
+ "blog mounts took {}ms",
+ time_mount.elapsed().as_nanos() as f64 / 1_000_000.0
+ );
+ time_mount = Instant::now();
+
+ mount_file!(router, "/robots.txt", "robots.txt");
+ mount_file!(router, "/favicon.txt", "favicon.txt");
+ mount_page!(router, "/", "index");
+ mount_page!(router, "/contact", "contact");
+ mount_page!(router, "/donate", "donate");
+ mount_page!(router, "/gemini", "gemini");
+ mount_page!(router, "/gopher", "gopher");
+ mount_page!(router, "/interests", "interests");
+ mount_page!(router, "/skills", "skills");
+
+ info!(
+ "static mounts took {}ms",
+ time_mount.elapsed().as_nanos() as f64 / 1_000_000.0
+ );
+
+ router.run().await
+}