me-site/src/pages/index.rs
2024-03-17 18:23:29 +01:00

195 lines
6.9 KiB
Rust

use crate::{config, pages};
use actix_web::http::header;
use actix_web::web::Form;
use actix_web::{get, post, web, Error, HttpRequest, HttpResponse, Responder, Result};
use maud::{html, PreEscaped};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct MessageForm {
msg_name: String,
message: String,
}
#[post("/message")]
pub async fn message_post(r: HttpRequest, f: Form<MessageForm>) -> impl Responder {
let config: &web::Data<config::Config> = r.app_data().expect("get config failed");
crate::msg::save_message(&f.message, &f.msg_name.to_string());
crate::notification::notify(&f.message, &f.msg_name, config.clone()).await;
web_base::func::redirect("/message")
}
#[get("/message")]
pub async fn message_page(r: HttpRequest) -> impl Responder {
let config: &web::Data<config::Config> = r.app_data().expect("get config failed");
let resp = html! {
div class="container" style="margin-top: 25px" {
h1 { "Message" };
br;
form action=(web_base::func::get_full_url(&r)) method="post" autocomplete="off" {
input value="" type="text" required name="msg_name" placeholder="Name" class="form-control bg-dark text-white" style="margin-bottom: 15px";
textarea placeholder="Message" required name="message" cols="10" rows="10" class="form-control bg-dark text-white" style="margin-bottom: 15px;" {};
input value="Send Message" type="submit" required name="submit" class="btn btn-danger text-white text-decoration-none";
}
}
};
pages::html_fn::build_site(resp.into_string(), "Message", false, true, config, &r).await
}
#[get("/mirrors.txt")]
pub async fn mirrors(r: HttpRequest) -> Result<impl Responder, Error> {
let config: &web::Data<config::Config> = r.app_data().expect("get config failed");
if let Ok(mirror_file) = std::fs::File::open("./config/mirrors.txt") {
let content = std::io::read_to_string(mirror_file).expect("could not read file");
if web_base::func::is_browser(&r) {
let resp = html! {
div style="margin: 25px;" {
pre {
(content)
};
}
};
return Ok(pages::html_fn::build_site(
resp.into_string(),
"Mirrors",
false,
true,
config,
&r,
)
.await);
}
return HttpResponse::Ok().message_body(content);
}
HttpResponse::NotFound().message_body(String::new())
}
#[get("/public_key")]
pub async fn public_key(r: HttpRequest) -> Result<impl Responder, Error> {
if web_base::func::is_browser(&r) {
let config: &web::Data<config::Config> = r.app_data().expect("get config failed");
let host = format!("http://{}", web_base::func::get_host(&r));
let key = std::io::read_to_string(
std::fs::File::open("./config/pub.key").expect("key could not be opened"),
)
.expect("could not read key");
let pgp = gnupg_rs::GnuPG::new().expect("no gpg");
let key_name = pgp.import_key(&key).expect("key not valid").name;
let key = key.replace('\n', "<br>");
let resp = html! {
div class="container" style="margin-top: 25px" {
div class="alert alert-info" {
b { "To Import: " };
span style="display: block;font-family: monospace,monospace;margin-top: 10px; font-size: 20px;overflow-wrap: break-word;" { (format!("curl -sL \"{host}/public_key\"|gpg --import")) };
};
h4 class="container card" style="padding-top: 10px; padding-bottom: 10px; background: black; margin-bottom: 15px;" { (key_name) };
};
div class="container card bg-primary" {
p { (PreEscaped(key)) }
}
};
return Ok(pages::html_fn::build_site(
resp.into_string(),
"Public Key",
true,
false,
config,
&r,
)
.await);
}
if let Ok(key_f) = std::fs::File::open("./config/pub.key") {
if let Ok(key_data) = std::io::read_to_string(key_f) {
return HttpResponse::Ok()
.insert_header(header::ContentType::plaintext())
.message_body(key_data);
}
}
HttpResponse::NotFound().message_body(String::new())
}
fn build_information_block(conf: &web::Data<config::Config>) -> String {
let name = conf.name().expect("no name found");
html! {
div class="container border-dark" style="margin-top: 20px" {
img src="/assets/me" height="200" width="200" alt="Me" class="rounded";
br;br;
h1 { (name) };
hr;
}
}
.into_string()
}
fn build_contact_block(conf: &web::Data<config::Config>) -> String {
conf.email().map_or_else(String::new, |email| {
let pgp_key_message = if std::path::Path::new("./config/pub.key").exists() {
html! {
a href="/public_key" { "My PGP Key" };
br;
a href="/message" { "Write a message" };
br;br;
}
.into_string()
} else {
String::new()
};
html! {
div class="container border-dark" {
h1 {
span class="bi bi-person-lines-fill" style="vertical-align: middle;";
span { "Contact" };
};
hr;
(PreEscaped(pgp_key_message));
a href=(format!("mailto:{email}")) { (email) };
hr;
}
}
.into_string()
})
}
fn build_donation_block(conf: &web::Data<config::Config>) -> String {
conf.xmr_address().map_or_else(String::new, |xmr_addr| {
html! {
div class="container" style="margin-top: 20px" {
h1 {
span class="bi bi-cash-coin";
span { "Donation" };
};
hr;
p {
b { "Monero: " };
span style="color: orange;overflow-wrap: break-word;" { (xmr_addr) };
}
}
}
.into_string()
})
}
#[get("/")]
pub(crate) async fn index(conf: web::Data<config::Config>, r: HttpRequest) -> impl Responder {
let information_block = build_information_block(&conf);
let contact_block = build_contact_block(&conf);
let donation_block = build_donation_block(&conf);
let own_index = std::fs::read_to_string("./config/index.html").unwrap_or_default();
let content = format!(
"
{information_block}
{contact_block}
{own_index}
{donation_block}
"
);
crate::pages::html_fn::build_site(content, "About Me", false, true, &conf, &r).await
}