174 lines
5.2 KiB
Rust
174 lines
5.2 KiB
Rust
use actix_web::{get, routes, web, HttpRequest, Responder};
|
|
use cached::proc_macro::once;
|
|
use glob::glob;
|
|
use ramhorns::Content;
|
|
use std::fs::read_to_string;
|
|
|
|
use crate::{
|
|
config::Config,
|
|
misc::{
|
|
markdown::{read_file, File, TypeFileMetadata},
|
|
utils::{make_kw, Html},
|
|
},
|
|
template::{Infos, NavBar},
|
|
};
|
|
|
|
pub fn pages(cfg: &mut web::ServiceConfig) {
|
|
// Here define the services used
|
|
let routes = |route_path| {
|
|
web::scope(route_path)
|
|
.service(page)
|
|
.service(service_redirection)
|
|
};
|
|
|
|
// Here define the routes aliases
|
|
cfg.service(routes("/contact")).service(routes("/c"));
|
|
}
|
|
|
|
#[get("")]
|
|
async fn page(config: web::Data<Config>) -> impl Responder {
|
|
Html(build_page(config.get_ref().to_owned()))
|
|
}
|
|
|
|
/// Contact node
|
|
#[derive(Clone, Debug)]
|
|
struct ContactLink {
|
|
service: String,
|
|
scope: Option<String>,
|
|
link: String,
|
|
}
|
|
|
|
#[once(time = 60)]
|
|
fn find_links(directory: String) -> Vec<ContactLink> {
|
|
// TOML filename
|
|
let toml_file = "links.toml";
|
|
|
|
// Read the TOML file and parse it
|
|
let toml_str = read_to_string(format!("{directory}/{toml_file}")).unwrap_or_default();
|
|
|
|
let mut redirections = vec![];
|
|
match toml::de::from_str::<toml::Value>(&toml_str) {
|
|
Ok(data) => {
|
|
if let Some(section) = data.as_table() {
|
|
section.iter().for_each(|(key, value)| {
|
|
// Scopes are delimited with `/`
|
|
let (service, scope) = match key.split_once('/') {
|
|
Some((service, scope)) => (service.to_owned(), Some(scope.to_owned())),
|
|
None => (key.to_owned(), None),
|
|
};
|
|
|
|
redirections.push(ContactLink {
|
|
service,
|
|
scope,
|
|
link: value.as_str().unwrap().to_owned(),
|
|
});
|
|
});
|
|
}
|
|
}
|
|
Err(_) => return vec![],
|
|
}
|
|
|
|
redirections
|
|
}
|
|
|
|
#[routes]
|
|
#[get("/{service}")]
|
|
#[get("/{service}/{scope}")]
|
|
async fn service_redirection(config: web::Data<Config>, req: HttpRequest) -> impl Responder {
|
|
let info = req.match_info();
|
|
let link = find_links(format!("{}/contacts", config.locations.data_dir))
|
|
.iter()
|
|
// Find requested service
|
|
.filter(|&x| x.service == *info.query("service"))
|
|
// Search for a potential scope
|
|
.filter(|&x| match (info.get("scope"), x.scope.to_owned()) {
|
|
// The right scope is accepted
|
|
(Some(str_value), Some(string_value)) if str_value == string_value.as_str() => true,
|
|
// No scope provided is accepted
|
|
(None, None) => true,
|
|
// Else we reject
|
|
_ => false,
|
|
})
|
|
// Returns the link
|
|
.map(|data| data.link.clone())
|
|
.collect::<Vec<String>>();
|
|
|
|
// This shouldn't be more than one link here
|
|
match link.len() {
|
|
// Redirect to the desired service
|
|
1 => actix_web::web::Redirect::to(link[0].clone()),
|
|
// By default, returns to the contact page
|
|
_ => actix_web::web::Redirect::to("/contact"),
|
|
}
|
|
}
|
|
|
|
#[derive(Content, Debug)]
|
|
struct NetworksTemplate {
|
|
navbar: NavBar,
|
|
|
|
socials_exists: bool,
|
|
socials: Vec<File>,
|
|
|
|
forges_exists: bool,
|
|
forges: Vec<File>,
|
|
|
|
others_exists: bool,
|
|
others: Vec<File>,
|
|
}
|
|
|
|
fn remove_paragraphs(list: &mut [File]) {
|
|
list.iter_mut()
|
|
.for_each(|file| file.content = file.content.replace("<p>", "").replace("</p>", ""));
|
|
}
|
|
|
|
#[once(time = 60)]
|
|
fn build_page(config: Config) -> String {
|
|
let contacts_dir = format!("{}/contacts", config.locations.data_dir);
|
|
let ext = ".md";
|
|
|
|
let socials_dir = "socials";
|
|
let mut socials = glob(&format!("{contacts_dir}/{socials_dir}/*{ext}"))
|
|
.unwrap()
|
|
.map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Contact).unwrap())
|
|
.collect::<Vec<File>>();
|
|
|
|
let forges_dir = "forges";
|
|
let mut forges = glob(&format!("{contacts_dir}/{forges_dir}/*{ext}"))
|
|
.unwrap()
|
|
.map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Contact).unwrap())
|
|
.collect::<Vec<File>>();
|
|
|
|
let others_dir = "others";
|
|
let mut others = glob(&format!("{contacts_dir}/{others_dir}/*{ext}"))
|
|
.unwrap()
|
|
.map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Contact).unwrap())
|
|
.collect::<Vec<File>>();
|
|
|
|
// Remove paragraphs in custom statements
|
|
[&mut socials, &mut forges, &mut others]
|
|
.iter_mut()
|
|
.for_each(|it| remove_paragraphs(it));
|
|
|
|
config.tmpl.render(
|
|
"contact/index.html",
|
|
NetworksTemplate {
|
|
navbar: NavBar {
|
|
contact: true,
|
|
..NavBar::default()
|
|
},
|
|
socials_exists: !socials.is_empty(),
|
|
socials,
|
|
|
|
forges_exists: !forges.is_empty(),
|
|
forges,
|
|
|
|
others_exists: !others.is_empty(),
|
|
others,
|
|
},
|
|
Infos {
|
|
page_title: Some("Contacts".into()),
|
|
page_desc: Some(format!("Réseaux d'{}", config.fc.name.unwrap_or_default())),
|
|
page_kw: make_kw(&["réseaux sociaux", "email", "contact", "linktree"]),
|
|
},
|
|
)
|
|
}
|