tempus_cli/
session.rs

1use std::fs::{self, File};
2use std::io::{ErrorKind, Write};
3
4use chrono::{DateTime, FixedOffset, Local};
5
6use crate::utils;
7
8#[derive(Debug)]
9pub enum SessionStatus {
10    Started(DateTime<FixedOffset>),
11    NotStarted,
12}
13
14#[derive(Debug)]
15pub struct Session<'a> {
16    started_at: Option<DateTime<FixedOffset>>,
17    ended_at: Option<DateTime<FixedOffset>>,
18    session_dir: &'a str,
19    session_path: String,
20    pub status: SessionStatus,
21    session_name: &'a str,
22}
23
24impl Session<'_> {
25    pub fn new<'a>(session_dir: &'a str, session_name: &'a str) -> Session<'a> {
26        let session_path = format!("{}/{}", session_dir, session_name);
27        let status = Session::get_status(&session_path);
28        let started_at = match status {
29            SessionStatus::Started(secs) => Some(secs),
30            SessionStatus::NotStarted => None,
31        };
32
33        Session {
34            started_at,
35            ended_at: None,
36            session_dir,
37            status,
38            session_path,
39            session_name,
40        }
41    }
42
43    /// Try to retrieve metadata on the session file
44    /// If it exists, that means the session has already been started
45    /// If the file doesn't exist, that means the session hasn't yet
46    /// been started
47    fn get_status(path: &str) -> SessionStatus {
48        match fs::metadata(&path) {
49            Ok(metadata) => SessionStatus::Started(utils::get_metadata_created(metadata)),
50            Err(e) => {
51                if e.kind() == ErrorKind::NotFound {
52                    SessionStatus::NotStarted
53                } else {
54                    panic!("error getting session metadata: {}", e);
55                }
56            }
57        }
58    }
59
60    /// Start the session & return the start time
61    pub fn start(&self) -> DateTime<FixedOffset> {
62        if let SessionStatus::Started(_) = self.status {
63            panic!("Tried to start a session that is already started.");
64        }
65
66        match File::create(&self.session_path) {
67            Ok(file) => match file.metadata() {
68                Ok(metadata) => utils::get_metadata_created(metadata),
69                Err(e) => panic!("error getting session start time: {}", e),
70            },
71            Err(e) => panic!("error creating session file: {}", e),
72        }
73    }
74
75    /// End the session & return the end time
76    pub fn end(&mut self) -> DateTime<FixedOffset> {
77        if let SessionStatus::NotStarted = self.status {
78            panic!("Tried to end a session that hasn't been started.");
79        }
80
81        // delete session file - don't need it anymore
82        if let Err(e) = fs::remove_file(&self.session_path) {
83            panic!("error removing session file: {}", e);
84        }
85
86        let ended_at = utils::local_to_fixed_offset(Local::now());
87
88        // we want two copies - one to save to the session & one to return
89        self.ended_at = Some(ended_at.clone());
90        ended_at
91    }
92
93    /// Creates the log file if it doesn't already exist &
94    /// records the start & end of the session
95    pub fn record(&self, log_name: &str) {
96        let log_file_path = format!("{}/{}", self.session_dir, log_name);
97        let mut file = utils::create_or_open_file(&log_file_path);
98
99        let start = self.started_at.unwrap();
100        let end = self.ended_at.unwrap();
101
102        let start_dt = utils::format_datetime(&start);
103        let end_dt = utils::format_datetime(&end);
104        let session_record = format!("{},{}\n", &start_dt, &end_dt);
105
106        file.write(&session_record.as_bytes()).unwrap_or_else(|e| {
107            let session_info = format!("start,end,length\n{}", &session_record);
108            panic!("Error logging session:\n{}\nerror: {}", &session_info, e);
109        });
110    }
111}