use chrono::{DateTime, TimeZone}; use clap::Parser; use lazy_static::lazy_static; use sbse::fatal; use toml::Table; use std::{cmp, fs}; pub mod act; pub mod db; pub type Res = Result; macro_rules! toml { ($x:expr, $k:expr, $m:ident) => {{ match $x[$k].$m() { Some(x) => x, None => fatal!("{} not found in config", $k), } }}; } #[derive(Parser, Debug)] pub struct Args { #[arg(short, long)] cfg: String, } pub struct Cfg { pub addr: String, pub port: i64, pub title: String, pub tag: String, pub version: String, pub css: String, pub run: String, pub img: String, } lazy_static! { pub static ref ARGS: Args = Args::parse(); pub static ref CFG: Cfg = { let t = match fs::read_to_string(&ARGS.cfg) { Ok(x) => x, Err(e) => fatal!("failed to open config: {e}"), }; match t.parse::() { Ok(x) => { let r = toml!(x, "run", as_str).to_string(); Cfg { addr: toml!(x, "addr", as_str).to_string(), port: toml!(x, "port", as_integer), title: toml!(x, "title", as_str).to_string(), version: toml!(x, "version", as_str).to_string(), tag: toml!(x, "tag", as_str).to_string(), css: toml!(x, "css", as_str).to_string(), run: r.as_str().to_string(), img: format!("{r}/img"), } } Err(e) => fatal!("failed to parse config: {e}"), } }; } pub mod macros { pub use crate::{ex, un}; } pub fn truncate(x: T, n: usize) -> String where String: From, { let x = String::from(x); format!("{}", &x[0..cmp::min(n, x.len())]) } pub fn fmt_date(x: DateTime) -> String where T: TimeZone, ::Offset: std::fmt::Display, { x.format("%Y-%m-%d %H:%M").to_string() } pub fn fmt_unix(x: i64) -> String { fmt_date(match DateTime::from_timestamp(x, 0) { Some(x) => x, /* uh oh ! */ None => fatal!("failed to format unix timestamp {x}"), }) } pub fn now_timestamp() -> i64 { chrono::Local::now().timestamp() } #[macro_export] macro_rules! ex { ($x:expr, $e:pat => $($t:tt)*) => {{ match $x { Ok(x) => Ok(x), $e => err_fmt!($($t)*), } }}; } #[macro_export] macro_rules! un { ($x:expr, $($t:tt)*) => {{ match $x { Some(x) => Ok(x), None => err_fmt!($($t)*), } }}; }