diff --git a/main.py b/main.py index 022cb95..9e2b390 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ import json import google_reader import tomllib import sys +import argparse from datetime import datetime from zoneinfo import ZoneInfo from pathlib import Path @@ -102,13 +103,13 @@ def mark_deleted_as_read(config, client_session): marked_as_read = 0 to_mark_as_read = [] - for stored_item in config.json_root.glob("*.json"): - item_json = json.load(stored_item.open("r")) + for json_path in config.json_root.glob("*.json"): + item_json = json.load(json_path.open("r")) html_path = config.html_root / item_json["html_path"] if not html_path.exists(): to_mark_as_read.append(item_json["id"]) # delete JSON file - stored_item.unlink() + json_path.unlink() marked_as_read += 1 for i in range(0, len(to_mark_as_read), config.items_per_query): @@ -141,6 +142,11 @@ def get_html_path(config, item_json): def format_datetime(config, timestamp): return datetime.fromtimestamp(timestamp, config.timezone).strftime(config.time_format) +def set_computed_fields_json(config, item_json): + item_json["published_formatted"] = format_datetime(config, item_json["published"]) + item_json["updated_formatted"] = format_datetime(config, item_json["updated"]) + item_json["html_path"] = str(get_html_path(config, item_json).relative_to(config.html_root)) + def synchronize_with_server(config, client_session): # Synchronize items from the server, generating and deleting JSON and HTML files accordingly config.update_lock.touch() @@ -163,9 +169,7 @@ def synchronize_with_server(config, client_session): "folder": folder_name, "title": item_content.title, "published": item_content.published, - "published_formatted": format_datetime(config, item_content.published), "updated": item_content.updated, - "updated_formatted": format_datetime(config, item_content.updated), "author": item_content.author, "summary": item_content.summary.content, "content": item_content.content.content, @@ -173,7 +177,7 @@ def synchronize_with_server(config, client_session): "origin_url": item_content.origin.html_url, "canonical_url": item_content.canonical[0].href, } - item_json["html_path"] = str(get_html_path(config, item_json).relative_to(config.html_root)) + set_computed_fields_json(config, item_json) json_path = config.json_root / f"{ sha256(item_json["id"].encode("utf-8")).hexdigest() }.json" grabbed_item_paths.append(json_path) @@ -240,18 +244,42 @@ def remove_empty_html_directories(config): if len(dirnames) == 0 and len(filenames) == 0: dirpath.rmdir() -def process(config, client_session): +def update(config, client_session): # Do a full feather update mark_deleted_as_read(config, client_session) synchronize_with_server(config, client_session) remove_empty_html_directories(config) +def regenerate_files(config): + for json_path in config.json_root.glob("*.json"): + item_json = json.load(json_path.open("r")) + remove_html_for_item(config, item_json, ignore_deleted=True) # path might change so we preemptively remove the old file + set_computed_fields_json(config, item_json) # recompute formatted datetime & path from the current configuration + # rewrite JSON + with json_path.open("w") as f: + json.dump(item_json, f) + # rewrite HTML + generate_html_for_item(config, item_json, regenerate=True) + #%% Run feather def main(): + parser = argparse.ArgumentParser( + prog="feather", + description="file-based RSS reader" + ) + parser.add_argument( + "action", choices=("update", "regenerate"), + help='''use update to perform a full synchronization with the server; regenerate will regenerate all HTML files from the local data''' + ) + args = parser.parse_args() + config = Config() - client_session = ClientSession(config) - process(config, client_session) + if args.action == "update": + client_session = ClientSession(config) + update(config, client_session) + elif args.action == "regenerate": + regenerate_files(config) if __name__ == "__main__": main()