1
0
Fork 0
mirror of https://codeberg.org/Reuh/feather.git synced 2025-10-28 10:39:32 +00:00

feat: add command to regenerate local files

This commit is contained in:
Étienne Fildadut 2025-10-09 17:51:01 +02:00
parent e5b9fec570
commit c421cf3509

46
main.py
View file

@ -4,6 +4,7 @@ import json
import google_reader import google_reader
import tomllib import tomllib
import sys import sys
import argparse
from datetime import datetime from datetime import datetime
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from pathlib import Path from pathlib import Path
@ -102,13 +103,13 @@ def mark_deleted_as_read(config, client_session):
marked_as_read = 0 marked_as_read = 0
to_mark_as_read = [] to_mark_as_read = []
for stored_item in config.json_root.glob("*.json"): for json_path in config.json_root.glob("*.json"):
item_json = json.load(stored_item.open("r")) item_json = json.load(json_path.open("r"))
html_path = config.html_root / item_json["html_path"] html_path = config.html_root / item_json["html_path"]
if not html_path.exists(): if not html_path.exists():
to_mark_as_read.append(item_json["id"]) to_mark_as_read.append(item_json["id"])
# delete JSON file # delete JSON file
stored_item.unlink() json_path.unlink()
marked_as_read += 1 marked_as_read += 1
for i in range(0, len(to_mark_as_read), config.items_per_query): 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): def format_datetime(config, timestamp):
return datetime.fromtimestamp(timestamp, config.timezone).strftime(config.time_format) 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): def synchronize_with_server(config, client_session):
# Synchronize items from the server, generating and deleting JSON and HTML files accordingly # Synchronize items from the server, generating and deleting JSON and HTML files accordingly
config.update_lock.touch() config.update_lock.touch()
@ -163,9 +169,7 @@ def synchronize_with_server(config, client_session):
"folder": folder_name, "folder": folder_name,
"title": item_content.title, "title": item_content.title,
"published": item_content.published, "published": item_content.published,
"published_formatted": format_datetime(config, item_content.published),
"updated": item_content.updated, "updated": item_content.updated,
"updated_formatted": format_datetime(config, item_content.updated),
"author": item_content.author, "author": item_content.author,
"summary": item_content.summary.content, "summary": item_content.summary.content,
"content": item_content.content.content, "content": item_content.content.content,
@ -173,7 +177,7 @@ def synchronize_with_server(config, client_session):
"origin_url": item_content.origin.html_url, "origin_url": item_content.origin.html_url,
"canonical_url": item_content.canonical[0].href, "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" json_path = config.json_root / f"{ sha256(item_json["id"].encode("utf-8")).hexdigest() }.json"
grabbed_item_paths.append(json_path) grabbed_item_paths.append(json_path)
@ -240,18 +244,42 @@ def remove_empty_html_directories(config):
if len(dirnames) == 0 and len(filenames) == 0: if len(dirnames) == 0 and len(filenames) == 0:
dirpath.rmdir() dirpath.rmdir()
def process(config, client_session): def update(config, client_session):
# Do a full feather update # Do a full feather update
mark_deleted_as_read(config, client_session) mark_deleted_as_read(config, client_session)
synchronize_with_server(config, client_session) synchronize_with_server(config, client_session)
remove_empty_html_directories(config) 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 #%% Run feather
def main(): 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() config = Config()
client_session = ClientSession(config) if args.action == "update":
process(config, client_session) client_session = ClientSession(config)
update(config, client_session)
elif args.action == "regenerate":
regenerate_files(config)
if __name__ == "__main__": if __name__ == "__main__":
main() main()