my_blog/src/main.rs

192 lines
4.8 KiB
Rust

use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
extern crate tera;
use tera::{
Context,
Tera,
};
use serde::{
Deserialize,
Serialize,
};
const BLOG_BASE_TITLE: &'static str = "chmod777's blog: ";
#[derive(Clone, Debug, Serialize, Deserialize)]
struct Post {
full_url: Option<String>,
url: String,
title: String,
summary: String,
date_published: String,
date_modified: Option<String>,
template_name: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct TechDemo {
full_url: Option<String>,
url: String,
title: String,
summary: String,
template_name: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct Config {
posts: Vec<Post>,
tech_demos: Vec<TechDemo>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct MyContext {
title: String,
description: String,
canonical_url: String,
favicon_image: String,
page_image: String,
og_type: String,
og_locale: String,
og_site_name: String,
twitter_card: String,
posts: Vec<Post>,
tech_demos: Vec<TechDemo>,
}
impl Default for MyContext {
fn default() -> Self {
Self {
title: "chmod777's homepage".to_owned(),
description: "A place where chmod777 puts their blog posts, project updates, and tech demos.".to_owned(),
canonical_url: "http://tilde.club/~chmod777".to_owned(),
favicon_image: "http://tilde.club/~chmod777/favicon.svg".to_owned(),
page_image: "http://tilde.club/~chmod777/favicon.svg".to_owned(),
og_type: "website".to_owned(),
og_locale: "en-US".to_owned(),
og_site_name: "tilde.club".to_owned(),
twitter_card: "summary".to_owned(),
posts: Vec::new(),
tech_demos: Vec::new(),
}
}
}
fn write_to_file(path: &str, content: &str) {
let path = Path::new(path);
let display = path.display();
let mut file = match File::create(path) {
Ok(file) => file,
Err(error) => panic!("Couldn't create file {}: {}", &display, &error),
};
file.write_all(content.as_bytes()).unwrap();
}
fn read_file(path: &str) -> String {
fs::read_to_string(path).expect(&format!("Failed to read file: {}", path))
}
fn append_str(base: &str, extend: &str) -> String {
let mut s = base.to_owned();
s.push_str(extend);
s
}
fn main() {
let tera = match Tera::new("templates/**/*") {
Ok(tera) => tera,
Err(error_s) => panic!("Parsing error(s): {}", error_s),
};
let config_json_string = read_file("config.json");
let config: Config = serde_json::from_str(&config_json_string).unwrap();
let mut context = MyContext::default();
let base_url = "http://tilde.club/~chmod777";
for mut post in config.posts.iter().cloned() {
post.full_url = Some(append_str(base_url, &post.url));
context.posts.push(post);
}
for mut demo in config.tech_demos.iter().cloned() {
demo.full_url = Some(append_str(base_url, &demo.url));
context.tech_demos.push(demo)
}
{
let index = tera
.render("index.html", &Context::from_serialize(&context).unwrap())
.unwrap();
write_to_file("public/index.html", &index);
}
{
context.title = "chmod777's blog".to_owned();
let blog_context = Context::from_serialize(&context).unwrap();
let blog = tera
.render(
"blog/blog.html",
&blog_context,
)
.unwrap();
write_to_file("public/blog/blog.html", &blog);
let rss_feed = tera
.render("feed.rss", &blog_context)
.unwrap();
write_to_file("public/feed.rss", &rss_feed);
context.og_type = "article".to_owned();
for post in context.posts.iter() {
context.title = append_str(BLOG_BASE_TITLE, &post.title);
context.canonical_url = post.full_url.clone().unwrap();
context.description = post.summary.clone();
let tera_context = &Context::from_serialize(&context).unwrap();
let rendered_post =
tera.render(&post.template_name, &tera_context).unwrap();
let path = {
let mut s = "public".to_owned();
s.push_str(&post.url);
s
};
write_to_file(&path, &rendered_post);
}
}
{
context.title = "chmod777's tech demos".to_owned();
context.og_type = "website".to_owned();
context.canonical_url = "".to_owned();
context.description = "".to_owned();
let tech_demos_context = Context::from_serialize(&context).unwrap();
let tech_demos = tera
.render(
"tech_demos/tech_demos.html",
&tech_demos_context,
)
.unwrap();
write_to_file("public/tech_demos/tech_demos.html", &tech_demos);
for demo in context.tech_demos.iter() {
context.title = append_str("chmod777's ", &demo.title);
context.canonical_url = demo.full_url.clone().unwrap();
context.description = demo.summary.clone();
let demo_context = &Context::from_serialize(&context).unwrap();
let rendered_demo =
tera.render(&demo.template_name, &demo_context).unwrap();
let path = {
let mut s = "public".to_owned();
s.push_str(&demo.url);
s
};
write_to_file(&path, &rendered_demo);
}
}
}