#!/usr/bin/env python3 """Smol listing manager.""" import string import subprocess from pathlib import Path import smolcgi as scgi scgi.require_client_cert() STORAGE_PATH = Path("/home/gemini/storage/lists") if not STORAGE_PATH.exists(): STORAGE_PATH.mkdir(parents=True) ALLOWED_LIST_NAME_CHARS = string.ascii_lowercase + string.digits + "_" def get_user_dir(): user_dir = STORAGE_PATH / scgi.tls_client_hash[7:] if not user_dir.is_dir(): user_dir.mkdir() return user_dir def show_lists(): user_dir = get_user_dir() scgi.header(20, "text/gemini") print("# Lists") for child in user_dir.iterdir(): if child.is_file(): print(f"=> {scgi.script_name}/{child.name} 📄 {child.name}") print(f"=> {scgi.script_name}/_/create ✨ Create a new list") def show_list(list_name): list_file = get_user_dir() / list_name try: with open(list_file, "rt") as f: content = f.read() except FileNotFoundError: scgi.not_found() else: scgi.header(20, "text/gemini") print("# " + list_name) print(content) print(f"=> {scgi.script_name}/{list_name}/add Append item") print(f"=> {scgi.script_name}/{list_name}/pop Pop first item") def process_action(list_name, action): if list_name == "_" and action == "create": process_creation() elif action == "add": process_add(list_name) elif action == "pop": process_pop(list_name) else: scgi.not_found() def process_creation(): if not (new_list_name := scgi.query_string_dec): meta = "List name (allowed chars: lowercase, digits, underscore)" scgi.require_input(meta) else: for char in new_list_name: if char not in ALLOWED_LIST_NAME_CHARS: scgi.temp_error(f"Illegal character in list name: {char}") list_file = get_user_dir() / new_list_name list_file.touch(mode=0o660) redirect_to_list(new_list_name) def process_add(list_name): if not (item := scgi.query_string_dec): scgi.require_input("Enter your item") else: if "\n" in item: scgi.temp_error("No new line allowed in item.") line = f"* {item}\n" list_file = get_user_dir() / list_name try: with open(list_file, "at") as f: f.write(line) except FileNotFoundError: scgi.not_found() else: redirect_to_list(list_name) def process_pop(list_name): list_file = get_user_dir() / list_name subprocess.run(["sed", "-i", "1d", str(list_file)]) redirect_to_list(list_name) def redirect_to_list(list_name): scgi.redirect_temp(scgi.script_name + "/" + list_name) path_components = scgi.path_info.lstrip("/").split("/", maxsplit=1) list_name = path_components[0] action = path_components[1] if len(path_components) > 1 else '' if not list_name: show_lists() elif not action and list_name != "_": show_list(list_name) else: process_action(list_name, action)