import datetime import json from decimal import Decimal from logging import getLogger from pathlib import Path from typing import Any import frontmatter logger = getLogger(__name__) StatisticKey = str class ObsidianVault: def __init__(self, vault_path: Path, read_only: bool = 'silent'): self.vault_path = vault_path assert (self.vault_path / '.obsidian').exists(), 'Not an Obsidian Vault' with open(self.vault_path / '.obsidian' / 'daily-notes.json') as f: daily_notes_config = json.load(f) self.daily_folder = daily_notes_config['folder'] self.path_format = daily_notes_config['format'] self.template_file_path = daily_notes_config['template'] self.read_only = read_only def get_statistic( self, date: datetime.date, statistic_key: StatisticKey, ) -> Any | None: try: with open(self._date_file_path(date)) as f: data = frontmatter.load(f) except FileNotFoundError: return None return data.metadata.get(statistic_key) def add_statistic( self, date: datetime.date, statistic_key: StatisticKey, amount: Any, ) -> bool: if self.read_only == 'silent': logger.info( 'Real only ObsidianVault ignoring add_statistic(%s, "%s", %s)', date, statistic_key, amount, ) return False self._create_date_if_not_present(date) with open(self._date_file_path(date)) as f: data = frontmatter.load(f) if isinstance(amount, Decimal): amount = float(amount) if data.metadata.get(statistic_key) == amount: return False data.metadata[statistic_key] = amount if amount is None: del data.metadata[statistic_key] with open(self._date_file_path(date), 'wb') as f: frontmatter.dump(data, f) return True def add_event(self, date: datetime.date, verb: str, subject: str) -> None: if self.read_only == 'silent': logger.info( 'Real only ObsidianVault ignoring add_event(%s, "%s", ?)', date, verb, ) return self._create_date_if_not_present(date) # TODO def _create_date_if_not_present(self, date: datetime.date): date_file = self._date_file_path(date) if date_file.exists(): return logger.info('File "%s" doesn\'t exist, creating...', date) with open(self._daily_template_path()) as f: template_text = f.read() with open(date_file, 'w') as f: f.write(template_text) def _date_file_path(self, date: datetime.date): path = ( self.path_format.replace('YYYY', str(date.year)) .replace('MM', f'{date.month:02d}') .replace('DD', f'{date.day:02d}') ) return (self.vault_path / self.daily_folder / path).with_suffix('.md') def _daily_template_path(self): return (self.vault_path / self.template_file_path).with_suffix('.md')