選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

main.rs 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. use std::env;
  2. use std::fs::File;
  3. use std::io::prelude::*;
  4. use std::io::{Error, ErrorKind};
  5. use std::path::PathBuf;
  6. use chrono::prelude::{Local, NaiveDate};
  7. use dotenv;
  8. use serde::{Deserialize, Serialize};
  9. use serde_json;
  10. use tera::{Context, Tera};
  11. use tide::utils::After;
  12. use tide::{Body, Response, StatusCode};
  13. use uuid::Uuid;
  14. #[derive(Debug, Serialize, Deserialize)]
  15. struct Post {
  16. id: String,
  17. title: String,
  18. body: String,
  19. date: String,
  20. }
  21. impl Post {
  22. fn save(&mut self) -> std::io::Result<()> {
  23. let mut path: PathBuf = get_posts_directory()?;
  24. let filename = format!("{}.json", self.id);
  25. path = path.join(&filename);
  26. let mut file = match File::create(&path) {
  27. Err(why) => panic!("couldn't create {}: {}", self.id, why),
  28. Ok(file) => file,
  29. };
  30. match file.write_all(serde_json::to_string(&self)?.as_bytes()) {
  31. Err(why) => Err(Error::new(
  32. ErrorKind::Other,
  33. format!("couldn't write to {}.json: {}", self.id, why),
  34. )),
  35. Ok(_) => Ok(()),
  36. }
  37. }
  38. }
  39. fn get_posts_directory() -> Result<PathBuf, std::io::Error> {
  40. match env::var("POSTS_DIR") {
  41. Ok(dir) => Ok(dir.into()),
  42. Err(_) => Err(Error::new(
  43. ErrorKind::Other,
  44. "Posts directory environment variable not set",
  45. )),
  46. }
  47. }
  48. #[async_std::main]
  49. async fn main() -> std::io::Result<()> {
  50. dotenv::dotenv().ok();
  51. tide::log::start();
  52. let mut app = tide::new();
  53. app.with(After(|mut res: Response| async {
  54. if let Some(err) = res.downcast_error::<async_std::io::Error>() {
  55. println!("{:?}", res);
  56. if let ErrorKind::NotFound = err.kind() {
  57. res.set_status(StatusCode::NotFound);
  58. }
  59. }
  60. Ok(res)
  61. }));
  62. app.with(After(|mut res: Response| async {
  63. res.set_content_type(tide::http::mime::HTML);
  64. Ok(res)
  65. }));
  66. app.at("/admin").get(|_| async {
  67. let tera = Tera::new("templates/**/*.html")?;
  68. let html = tera.render("admin/index.html", &Context::new())?;
  69. Ok(Body::from_string(html))
  70. });
  71. app.at("/admin/posts")
  72. .post(|mut req: tide::Request<()>| async move {
  73. let mut post: Post = req.body_form().await?;
  74. post.id = Uuid::new_v4().to_string();
  75. post.date = Local::now().date().naive_local().to_string();
  76. post.save()?;
  77. Ok(tide::Redirect::new("/admin"))
  78. });
  79. app.listen("127.0.0.1:8080").await?;
  80. Ok(())
  81. }