use axum::{ response::{IntoResponse, Redirect}, routing::{get, Router}, Extension, }; use rand::{seq::SliceRandom, thread_rng}; use sqlx::PgPool; use std::error::Error; use tower_http::services::ServeDir; use crate::database::{ link::{Link, LinkType}, PsqlData, }; use super::{ blog, garden, templates::{ AboutTemplate, AiTemplate, BlogrollTemplate, ContactTemplate, GiftsTemplate, HomeTemplate, HtmlTemplate, InterestsTemplate, LinksPageTemplate, NowTemplate, UsesTemplate }, AppState, }; pub fn get_router(pool: PgPool) -> Router { let assets_path = std::env::current_dir().unwrap(); let state = AppState { db: pool }; Router::new() .nest("/blog", blog::get_router()) .nest("/garden", garden::get_router()) .nest_service( "/assets", ServeDir::new(format!("{}/assets", assets_path.to_str().unwrap())), ) .route("/", get(home)) .route("/now", get(now)) .route("/about", get(about)) .route("/contact", get(contact)) .route("/uses", get(uses)) .route("/ai", get(ai)) .route("/blogroll", get(blogroll)) .route("/links", get(links)) .route("/interests", get(interests)) .route("/gifts", get(gifts)) .route( "/robots.txt", get(|| async { Redirect::permanent("/assets/robots.txt") }), ) .layer(Extension(state)) } async fn home() -> impl IntoResponse { HtmlTemplate(HomeTemplate {}) } async fn now() -> impl IntoResponse { HtmlTemplate(NowTemplate {}) } async fn about() -> impl IntoResponse { HtmlTemplate(AboutTemplate {}) } async fn contact() -> impl IntoResponse { HtmlTemplate(ContactTemplate {}) } async fn uses() -> impl IntoResponse { HtmlTemplate(UsesTemplate {}) } async fn ai() -> impl IntoResponse { HtmlTemplate(AiTemplate {}) } async fn interests() -> impl IntoResponse { HtmlTemplate(InterestsTemplate {}) } async fn gifts() -> impl IntoResponse { HtmlTemplate(GiftsTemplate {}) } async fn blogroll(state: Extension) -> impl IntoResponse { let blogroll_page = BlogrollTemplate { blogs: match get_links_as_list(&state.db, LinkType::BLOG).await { Ok(list) => list, Err(_) => Vec::new(), }, }; HtmlTemplate(blogroll_page) } async fn links(state: Extension) -> impl IntoResponse { let links_page = LinksPageTemplate { articles: match get_links_as_list(&state.db, LinkType::ARTICLE).await { Ok(list) => list, Err(_) => Vec::new(), }, }; HtmlTemplate(links_page) } pub async fn get_links_as_list( pool: &PgPool, link_type: LinkType, ) -> Result, Box> { let mut links: Vec = match Link::read_all(pool).await { Ok(a) => a.iter().map(|x| *x.clone()).collect(), Err(_) => Vec::new(), }; let mut rng = thread_rng(); links.shuffle(&mut rng); let list: Vec = links .into_iter() .filter(|link| link.link_type == link_type) .collect(); Ok(list) }