use chrono::{ DateTime, offset::FixedOffset, naive::NaiveDateTime, }; use crate::git::GitFile; use std::collections::HashMap; use tera::{Filter, Function, Value, to_value, try_get_value}; fn ts_to_date(ts: i64, offset: Option, format: Option) -> String { let offset = offset.unwrap_or(0); let dt = NaiveDateTime::from_timestamp_opt(ts + offset, 0).expect("Invalid timestamp"); let dt_tz: DateTime = DateTime::from_local(dt, FixedOffset::east_opt(offset as i32).expect("Invalid timezone")); match format { Some(f) => dt_tz.format(&f).to_string(), None => dt_tz.format("%Y-%m-%d").to_string(), } } fn ts_to_git_timestamp(ts: i64, offset: Option) -> String { let offset = offset.unwrap_or(0); let dt = chrono::naive::NaiveDateTime::from_timestamp_opt(ts + offset, 0).expect("invalid timestamp"); let dt_tz: DateTime = DateTime::from_local(dt, FixedOffset::east_opt(offset as i32).expect("Invalid timezone")); dt_tz.format("%a %b %e %T %Y %z").to_string() } pub struct FileFilter; impl Filter for FileFilter { fn filter(&self, value: &Value, _args: &HashMap ) -> Result { let file_list: Vec = try_get_value!("only_files", "value", Vec, value); let file_list: Vec = file_list.iter().filter_map(|x| match x.kind.as_str() { "file" => Some(x.clone()), _ => None, }).collect(); Ok(to_value(file_list).unwrap()) } } pub struct DirFilter; impl Filter for DirFilter { fn filter(&self, value: &Value, _args: &HashMap ) -> Result { let file_list: Vec = try_get_value!("only_dirs", "value", Vec, value); let file_list: Vec = file_list.iter().filter_map(|x| match x.kind.as_str() { "dir" => Some(x.clone()), _ => None, }).collect(); Ok(to_value(file_list).unwrap()) } } pub struct TsDateFn; impl Function for TsDateFn { fn call(&self, args: &HashMap) -> Result { let ts: Option = match args.get("ts") { Some(ts) => match tera::from_value(ts.clone()) { Ok(ts) => Some(ts), _ => None, }, _ => None, }; let ts = ts.expect("ts_to_date missing a `ts` argument"); let tz: Option = match args.get("tz") { Some(tz) => match tera::from_value(tz.clone()) { Ok(tz) => Some(tz), _ => None, }, _ => None, }; let fmt: Option = match args.get("fmt") { Some(fmt) => match tera::from_value(fmt.clone()) { Ok(fmt) => Some(fmt), _ => None, }, _ => None, }; Ok(to_value(ts_to_date(ts, tz, fmt)).unwrap()) } } pub struct TsTimestampFn; impl Function for TsTimestampFn { fn call(&self, args: &HashMap) -> Result { let ts: Option = match args.get("ts") { Some(ts) => match tera::from_value(ts.clone()) { Ok(ts) => Some(ts), _ => None, }, _ => None, }; let ts = ts.expect("ts_to_git_timestamp missing a `ts` argument"); let tz: Option = match args.get("tz") { Some(tz) => match tera::from_value(tz.clone()) { Ok(tz) => Some(tz), _ => None, }, _ => None, }; Ok(to_value(ts_to_git_timestamp(ts, tz)).unwrap()) } }