Skip to content
Snippets Groups Projects
blog.rs 2.75 KiB
Newer Older
Stephen D's avatar
Stephen D committed
use anyhow::Error;
use std::collections::HashMap;
Stephen D's avatar
Stephen D committed
use warp::hyper::StatusCode;

use crate::{image::MyImage, load::load_from_path, misc::Misc, post::Post, resp::Response};
Stephen D's avatar
Stephen D committed

pub struct Blog {
    //pages: Vec<Page>,
Stephen D's avatar
Stephen D committed
    posts: Vec<Post>,
    imgs: Vec<MyImage>,
Stephen D's avatar
Stephen D committed
}

impl Blog {
    pub fn new() -> Result<Self, Error> {
        /*let pages = fs::read_dir("pages")?
        .map(|path| Page::new(path?)?)
        .collect();*/

Stephen D's avatar
Stephen D committed
        let posts = load_from_path("posts", "posts")?;

        let imgs = load_from_path("assets/img", "")?;

        let misc = load_from_path("assets/misc", "misc")?;

        Ok(Self { posts, imgs, misc })
Stephen D's avatar
Stephen D committed
    }

Stephen D's avatar
Stephen D committed
    fn home(&mut self) -> Result<String, Error> {
        self.posts.sort();
        self.posts.reverse();

Stephen D's avatar
Stephen D committed
        let mut content =
Stephen D's avatar
Stephen D committed
            r#"<div class="centered"><h1>Stephen's Site</h1>Rewritten in Rust!</div><h4>Recent Posts</h4><table>"#
Stephen D's avatar
Stephen D committed
                .to_string();
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
        for post in &self.posts {
Stephen D's avatar
Stephen D committed
            content.push_str(&post.link()?);
Stephen D's avatar
Stephen D committed
        }

Stephen D's avatar
Stephen D committed
        content.push_str("</table>");

Stephen D's avatar
Stephen D committed
        Ok(dress_page("Stephen's Site", &content))
    }
}

pub struct RenderedBlog {
Stephen D's avatar
Stephen D committed
    pages: HashMap<String, Response>,
    not_found: Response,
Stephen D's avatar
Stephen D committed
}

impl RenderedBlog {
Stephen D's avatar
Stephen D committed
    pub fn get(&self, path: &str) -> (StatusCode, Response) {
Stephen D's avatar
Stephen D committed
        self.pages
            .get(path)
Stephen D's avatar
Stephen D committed
            .map(|x| (StatusCode::OK, x.clone()))
            .unwrap_or((StatusCode::NOT_FOUND, self.not_found.clone()))
Stephen D's avatar
Stephen D committed
    }
}

impl TryFrom<Blog> for RenderedBlog {
    type Error = Error;

Stephen D's avatar
Stephen D committed
    fn try_from(mut b: Blog) -> Result<Self, Error> {
Stephen D's avatar
Stephen D committed
        let mut pages = HashMap::new();

Stephen D's avatar
Stephen D committed
        for p in &b.posts {
Stephen D's avatar
Stephen D committed
            let body = dress_page(&p.title, &p.html()?);

Stephen D's avatar
Stephen D committed
            pages.insert(p.url.clone(), Response::html(body));
Stephen D's avatar
Stephen D committed
        }

        pages.insert(
            "/style.css".to_string(),
Stephen D's avatar
Stephen D committed
            Response::css(include_str!("assets/style.css").to_string()),
Stephen D's avatar
Stephen D committed
        );

        let home = b.home()?;
Stephen D's avatar
Stephen D committed
        pages.insert("/".to_string(), Response::html(home));

        for img in b.imgs {
            let (original_url, original, thumbnail_url, thumbnail) = img.into_responses()?;
            pages.insert(thumbnail_url, thumbnail);
            pages.insert(original_url, original);
        }

        for m in b.misc {
            pages.insert(m.url.clone(), m.response());
        }

Stephen D's avatar
Stephen D committed
        let not_found = Response::html(dress_page(
            "Page not found",
            include_str!("assets/404.html"),
        ));
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
        dbg!(pages.keys());
Stephen D's avatar
Stephen D committed

        Ok(Self { not_found, pages })
    }
}

fn dress_page(title: &str, content: &str) -> String {
    format!(
Stephen D's avatar
Stephen D committed
        r#"<!DOCTYPE html><html><head><link rel="stylesheet" href="/style.css" /><title>{title}</title></head><body><a href="/">Home</a><hr>{content}</body></html>"#
Stephen D's avatar
Stephen D committed
    )
}