diff --git a/trikiff b/trikiff new file mode 100755 index 0000000..28f0010 --- /dev/null +++ b/trikiff @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +"""Smol “three good things” notepad.""" + +import datetime +import re + +import smolcgi as scgi +scgi.require_client_cert() + + +def get_month_dir(year, month): + return scgi.get_user_dir() / f"{str(year).zfill(4)}-{str(month).zfill(2)}" + + +def get_day_file(year, month, day): + filename = str(day).zfill(2) + ".gmi" + return get_month_dir(year, month) / filename + + +def reply_home(): + scgi.header(20, "text/gemini") + print("# Trikiff! 🌄🥰🌃") + + print("## Actions") + scgi.link("/new/today", "Add kiffs of today") + scgi.link("/new/yesterday", "Add kiffs of yesterday") + scgi.link("/new", "Add kiffs for another day") + + print("## This month") + today = datetime.date.today() + month_dir = get_month_dir(today.year, today.month) + if month_dir.is_dir(): + print_month(month_dir) + else: + print("No kiffs yet!") + + print("## Past months") + scgi.link("/browse", "Browse archives") + + +def reply_new(date: datetime.date): + if (kiffs := scgi.query_string_dec): + kiffs = filter(lambda s: s, kiffs.split(";")) + kiffs = map(lambda s: "* " + s.strip(), kiffs) + content = "\n".join(kiffs) + "\n" + day_file = get_day_file(date.year, date.month, date.day) + if not (parent_dir := day_file.parent).exists(): + parent_dir.mkdir(parents=True) + with open(get_day_file(date.year, date.month, date.day), "at") as f: + f.write(content) + scgi.redirect_temp(f"{scgi.script_name}") + else: + scgi.require_input("Input one or more kiffs (separated with ';')") + + +def reply_prompt_day(): + if (query := scgi.query_string_dec): + try: + if (match := re.match(r"^\d{1,2}$", query)): + date = datetime.date.today().replace(day=int(match.group(0))) + elif (match := re.match(r"^\d{4}-\d{2}-\d{2}$", query)): + date = datetime.date.fromisoformat(match.group(0)) + else: + scgi.bad_request("Invalid day or date format") + except ValueError: + scgi.bad_request("Invalid day or date format") + scgi.redirect_temp(f"{scgi.script_name}/new/{date.isoformat()}") + else: + scgi.require_input( + "Which day? You can input only the day for the current month, " + "or a complete date using the YYYY-MM-DD format." + ) + + +def reply_browse(directory=None): + if directory: + path = scgi.get_user_dir() / directory + if not path.is_dir(): + scgi.not_found() + scgi.header(20, "text/gemini") + print(f"# Kiffs for {directory}") + print_month(path) + else: + scgi.header(20, "text/gemini") + print("# Trikiff archives 📜") + for path in sorted(scgi.get_user_dir().iterdir(), reverse=True): + if not path.is_dir(): + continue + scgi.link(f"/browse/{path.name}", path.name) + + +def print_month(month_dir): + for day_filename in sorted(month_dir.iterdir(), reverse=True): + day = day_filename.name[:-4] + print(f"### {day}") + with open(day_filename, "rt") as f: + print(f.read()) + + +if scgi.path_info == "/new/today": + reply_new(datetime.date.today()) +elif scgi.path_info == "/new/yesterday": + reply_new(datetime.date.today() - datetime.timedelta(days=1)) +elif scgi.path_info == "/new": + reply_prompt_day() +elif (match := re.match(r"^/new/(\d{4}-\d{2}-\d{2})$", scgi.path_info)): + try: + reply_new(datetime.date.fromisoformat(match.group(1))) + except ValueError: + scgi.not_found() +elif scgi.path_info == "/browse": + reply_browse() +elif (match := re.match(r"^/browse/(\d{4}-\d{2})$", scgi.path_info)): + reply_browse(directory=match.group(1)) +else: + reply_home()