use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub const DIR_USER_ROOT: &str = "/";
pub const DIR_ARCHIVE: &str = "archive";
pub const DIR_MEDIA: &str = "media";
pub const DIR_JOURNAL: &str = "journal";
pub const DIR_HABITS: &str = "habits";
pub const DIR_INSIGHTS: &str = "insights";
pub const CHAT_FILENAME: &str = "Chat.md";
pub const LATER_FILENAME: &str = "Later.md";
pub const DONE_FILENAME: &str = "Done.md";
pub const SHOP_FILENAME: &str = "Shop.md";
pub const WATCH_FILENAME: &str = "Watch.md";
pub const READ_FILENAME: &str = "Read.md";
pub const POMODORO_TASK: &str = "Finished a break";
pub const MD_EXT: &str = ".md";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileEntry {
pub name: String,
pub hash: String,
pub display_name: String,
pub ctime: i64,
pub has_content: bool,
pub is_dir: bool,
pub parent_dir: String,
}
impl FileEntry {
pub fn new(
name: String,
hash: String,
display_name: String,
ctime: i64,
has_content: bool,
is_dir: bool,
parent_dir: String,
) -> Self {
Self {
name,
hash,
display_name,
ctime,
has_content,
is_dir,
parent_dir,
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum FsError {
#[error("storage quota exceeded")]
QuotaExceeded,
#[error("unsafe path, possible security issue")]
UnsafePath,
#[error("cannot unhash, maybe the file is missing")]
CannotUnhash,
#[error("{0}")]
Io(#[from] std::io::Error),
}
pub const STATUS_OK: &str = "ok";
pub const STATUS_NOT_MODIFIED: &str = "notModified";
pub const STATUS_UPDATED_ON_SERVER: &str = "updatedOnServer";
pub const STATUS_MERGED: &str = "merged";
pub const MAX_TEXT_SIZE: usize = 5 * 1024 * 1024;
pub const MAX_TEXTS_SIZE: usize = 10 * 1024 * 1024;
pub const MAX_MEDIA_SIZE: usize = 20 * 1024 * 1024;
pub const MAX_MEDIAS_SIZE: usize = 512 * 1024;
pub const MAX_TOKEN_SIZE: usize = 4 * 1024;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncFile {
pub status: String,
pub path: String,
#[serde(rename = "lastModified")]
pub last_modified: i64,
#[serde(rename = "clientLastModified", default)]
pub client_last_modified: i64,
#[serde(rename = "clientLastSynced", default)]
pub client_last_synced: i64,
#[serde(default)]
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncRequest {
pub modified: Vec<SyncFile>,
pub deleted: Vec<String>,
pub timestamps: HashMap<String, i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncResponse {
pub status: String,
#[serde(default)]
pub files: Vec<SyncFile>,
#[serde(default)]
pub timestamps: HashMap<String, i64>,
#[serde(default)]
pub renames: HashMap<String, String>,
}
impl Default for SyncResponse {
fn default() -> Self {
SyncResponse {
status: STATUS_OK.to_string(),
files: vec![],
timestamps: HashMap::new(),
renames: HashMap::new(),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum SyncError {
#[error("invalid JSON")]
InvalidJson,
#[error("file not found")]
NotFound,
#[error("quota exceeded")]
QuotaExceeded,
#[error("storage error: {0}")]
Storage(String),
#[error("internal error: {0}")]
Internal(String),
}
impl From<FsError> for SyncError {
fn from(err: FsError) -> Self {
match err {
FsError::QuotaExceeded => SyncError::QuotaExceeded,
_ => SyncError::Storage(err.to_string()),
}
}
}
pub type YearHabits = HashMap<i32, i32>;
pub type Habits = HashMap<String, YearHabits>;
pub const HABIT_SKIPPED: &str = "⚪️";
pub const HABIT_COMPLETED: &str = "🟢";
pub const HABIT_COMPLETED_AT_WEEKEND: &str = "🟡";
pub const MOOD_HABIT: &str = "Mood";
pub const MOOD_EMOJIS: &[&str] = &["⚪️", "🤕", "😔", "😐", "🙂", "😊"];
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Schedule {
pub filename: String,
pub scheduled_at: i64,
pub cron: String,
#[serde(default)]
pub cmd: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeConfig {
#[serde(default = "default_language")]
pub language: String,
#[serde(default = "default_timezone")]
pub timezone: String,
#[serde(default)]
pub move_to_commands: Vec<String>,
#[serde(default = "default_pomodoro_duration")]
pub pomodoro_duration_in_minutes: i64,
#[serde(default)]
pub schedules: Vec<Schedule>,
#[serde(default)]
pub quick_commands: Vec<String>,
#[serde(default)]
pub two_emojis_enabled: bool,
#[serde(default = "default_mode")]
pub mode: String,
#[serde(default)]
pub quick_habits_enabled: bool,
#[serde(default)]
pub channels: Vec<i64>,
}
fn default_language() -> String {
"en".to_string()
}
fn default_timezone() -> String {
"UTC".to_string()
}
fn default_pomodoro_duration() -> i64 {
50
}
fn default_mode() -> String {
"full".to_string()
}
impl Default for KnowledgeConfig {
fn default() -> Self {
Self {
language: default_language(),
timezone: default_timezone(),
move_to_commands: vec![],
pomodoro_duration_in_minutes: default_pomodoro_duration(),
schedules: vec![],
quick_commands: vec![],
two_emojis_enabled: false,
mode: default_mode(),
quick_habits_enabled: false,
channels: vec![],
}
}
}
pub const MODE_CHAT: &str = "chat";
pub const MODE_FULL: &str = "full";
pub const MODE_TASKS: &str = "tasks";
pub const MODE_NOTES: &str = "notes";
pub const MODE_JOURNAL: &str = "journal";