use std::{env, error::Error, collections::HashMap, process::exit, sync::Arc}; use reqwest::ClientBuilder; use serde::Deserialize; use axum::{Router, Extension}; use tera::Tera; mod routes; pub struct State { pub templates: Tera, pub pages: HashMap } #[derive(Deserialize)] pub struct Page { name: String, url: String } async fn load_state() -> Result> { let mut templates = Tera::new("public/templates/**")?; templates.autoescape_on(vec![]); let client = ClientBuilder::new() .use_rustls_tls() .build()?; let json = client.get("https://raw.githubusercontent.com/bucketfish/bucket-webring/master/webring.json") .send() .await? .json::>() .await?; let mut pages = HashMap::new(); for (i, page) in json.iter().enumerate() { let prev = json[(i + json.len() - 1) % json.len()].url.clone(); let next = json[(i + json.len() + 1) % json.len()].url.clone(); pages.insert(page.name.clone(), (prev, next)); } Ok(State{ templates, pages }) } #[tokio::main] async fn main() { let port: u16 = env::var("PORT") .unwrap_or_else(|_| String::new()) .parse::() .unwrap_or(8080); let addr = format!("[::]:{port}") .parse::() .expect("Failed to create port binding"); let state = match load_state().await { Ok(s) => s, Err(e) => { eprintln!("Parsing error: {e}"); exit(1); } }; let router = Router::new() .fallback_service(routes::router()) .layer(Extension(Arc::new(state))); axum::Server::bind(&addr) .serve(router.into_make_service()) .await .expect("Failed to launch web server"); }