111 lines
2.8 KiB
Python
111 lines
2.8 KiB
Python
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
from subprocess import run
|
|
from typing import Union
|
|
import sys
|
|
import re
|
|
|
|
JOURNAL_PATH = '/Users/olari/workspace/journal'
|
|
|
|
entry_re = re.compile(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}')
|
|
|
|
def get_daily_file_paths() -> list[Path]:
|
|
return list(sorted(Path(JOURNAL_PATH).glob('*.md')))
|
|
|
|
def resolve_relative_time_expression(now: datetime, expr: str) -> datetime:
|
|
weekdays = [
|
|
'monday', 'tuesday', 'wednesday', 'thursday',
|
|
'friday', 'saturday', 'sunday'
|
|
]
|
|
|
|
if expr == 'today':
|
|
return now
|
|
elif expr == 'tomorrow':
|
|
return now + timedelta(days=1)
|
|
elif expr == 'yesterday':
|
|
return now - timedelta(days=1)
|
|
elif expr in weekdays:
|
|
return now - timedelta(days=now.weekday()) + weekdays.index(expr)
|
|
else:
|
|
return None
|
|
|
|
def parse_godword(content: str) -> list[str]:
|
|
return content.split()
|
|
|
|
def parse_habits(content: str) -> dict[str, bool]:
|
|
return {
|
|
line[4:]: line[1] == 'x'
|
|
for line in content.splitlines()
|
|
}
|
|
|
|
header_modules = {
|
|
'godword': (None, parse_godword),
|
|
'habits': (None, parse_habits),
|
|
}
|
|
|
|
def parse_header_module(content: str) -> tuple[str, Union[list, dict]]:
|
|
name, *content = content.splitlines()
|
|
name = name.removesuffix(':').lower()
|
|
content = '\n'.join(content)
|
|
_, parse = header_modules[name]
|
|
return name, parse(content)
|
|
|
|
def parse_header(header):
|
|
title, *modules = header.split('\n\n')
|
|
title = title.removeprefix('# ')
|
|
return {
|
|
'title': title,
|
|
'modules': dict(parse_header_module(module) for module in modules)
|
|
}
|
|
|
|
def parse_diet(content):
|
|
pass
|
|
|
|
def parse_content(content):
|
|
content = content.strip()
|
|
return {
|
|
'blocks': [b.replace('\n', ' ') for b in content.split('\n\n')]
|
|
}
|
|
|
|
def parse_timestamp(timestamp):
|
|
return datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S')
|
|
|
|
def parse_entry(entry):
|
|
return {
|
|
'timestamp': int(parse_timestamp(entry[:19]).timestamp()),
|
|
'content': parse_content(entry[19:]),
|
|
}
|
|
|
|
def parse_file(fpath):
|
|
header = {}
|
|
entries = []
|
|
|
|
buf = []
|
|
|
|
for i, line in enumerate(fpath.read_text().splitlines()):
|
|
if entry_re.match(line):
|
|
if not header:
|
|
header = parse_header('\n'.join([c.strip() for c in buf]))
|
|
else:
|
|
entries.append(parse_entry('\n'.join(buf)))
|
|
buf = [line]
|
|
else:
|
|
buf.append(line)
|
|
|
|
return {
|
|
'header': header,
|
|
'entries': entries,
|
|
}
|
|
|
|
def parse_journal():
|
|
result = {}
|
|
|
|
for fpath in get_daily_file_paths()[-5:]:
|
|
info = parse_file(fpath)
|
|
result[info['header']['title']] = info
|
|
|
|
return result
|
|
|
|
import json
|
|
open('journal.json', 'w').write(json.dumps(parse_journal()))
|