write-only-journal/src/journal.rs

68 lines
1.6 KiB
Rust

use std::{fs::{create_dir_all, read_to_string}, path::{Path, PathBuf}};
use chrono::{DateTime, FixedOffset};
use serde::{Serialize, Deserialize};
use tera::escape_html;
use std::str::FromStr;
use std::io::Result as IoRes;
const JOURNAL_PATH: &str = "./journals";
#[derive(Serialize, Deserialize, Debug)]
pub struct Line {
pub line: String,
pub uploaded_date: DateTime<FixedOffset>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Journal {
pub id: String,
pub edit_key: String,
pub lines: Vec<Line>,
}
impl Journal {
pub fn new(id: String, edit_key: String) -> Self {
Self {
id,
edit_key,
lines: Vec::new(),
}
}
pub fn load_or_create(id: String, key: String) -> Self {
match Self::load(&id) {
Some(journal) => journal,
None => Self::new(id, key),
}
}
pub fn load(id: &str) -> Option<Self> {
ensure_journal_path_exists().unwrap();
let journal_path = get_journal_path(&id);
match read_to_string(&journal_path) {
Ok(v) => Some(serde_json::from_str(&v).unwrap()),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => None,
Err(_e) => unimplemented!()
}
}
pub fn save(&self) -> IoRes<()> {
ensure_journal_path_exists().unwrap();
let journal_path = get_journal_path(&self.id);
let data = serde_json::to_string(self).unwrap();
std::fs::write(journal_path, data)
}
}
fn get_journal_path(id: &str) -> PathBuf {
let file = escape_html(id);
PathBuf::from_str(JOURNAL_PATH).unwrap().join(Path::new(&file))
}
fn ensure_journal_path_exists() -> IoRes<()> {
create_dir_all(Path::new(JOURNAL_PATH))
}