123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- use std::env;
- use std::fs::File;
- use std::io::prelude::*;
- use std::io::{Error, ErrorKind};
- use std::path::PathBuf;
-
- use chrono::prelude::{Local, NaiveDate};
- use dotenv;
- use serde::{Deserialize, Serialize};
- use serde_json;
- use tera::{Context, Tera};
- use tide::utils::After;
- use tide::{Body, Response, StatusCode};
- use uuid::Uuid;
-
- #[derive(Debug, Serialize, Deserialize)]
- struct Post {
- id: String,
- title: String,
- body: String,
- date: String,
- }
-
- impl Post {
- fn save(&mut self) -> std::io::Result<()> {
- let mut path: PathBuf = get_posts_directory()?;
- let filename = format!("{}.json", self.id);
- path = path.join(&filename);
- let mut file = match File::create(&path) {
- Err(why) => panic!("couldn't create {}: {}", self.id, why),
- Ok(file) => file,
- };
- match file.write_all(serde_json::to_string(&self)?.as_bytes()) {
- Err(why) => Err(Error::new(
- ErrorKind::Other,
- format!("couldn't write to {}.json: {}", self.id, why),
- )),
- Ok(_) => Ok(()),
- }
- }
- }
-
- fn get_posts_directory() -> Result<PathBuf, std::io::Error> {
- match env::var("POSTS_DIR") {
- Ok(dir) => Ok(dir.into()),
- Err(_) => Err(Error::new(
- ErrorKind::Other,
- "Posts directory environment variable not set",
- )),
- }
- }
-
- #[async_std::main]
- async fn main() -> std::io::Result<()> {
- dotenv::dotenv().ok();
- tide::log::start();
- let mut app = tide::new();
-
- app.with(After(|mut res: Response| async {
- if let Some(err) = res.downcast_error::<async_std::io::Error>() {
- println!("{:?}", res);
- if let ErrorKind::NotFound = err.kind() {
- res.set_status(StatusCode::NotFound);
- }
- }
-
- Ok(res)
- }));
-
- app.with(After(|mut res: Response| async {
- res.set_content_type(tide::http::mime::HTML);
- Ok(res)
- }));
-
- app.at("/admin").get(|_| async {
- let tera = Tera::new("templates/**/*.html")?;
- let html = tera.render("admin/index.html", &Context::new())?;
- Ok(Body::from_string(html))
- });
-
- app.at("/admin/posts")
- .post(|mut req: tide::Request<()>| async move {
- let mut post: Post = req.body_form().await?;
- post.id = Uuid::new_v4().to_string();
- post.date = Local::now().date().naive_local().to_string();
- post.save()?;
- Ok(tide::Redirect::new("/admin"))
- });
-
- app.listen("127.0.0.1:8080").await?;
-
- Ok(())
- }
|