#!/usr/bin/env python3 """Reescribe el bloque DIRECTO de index.html con los últimos posts del pub. Lee de stdin el JSON de tools/ultimos.js y sustituye lo que haya entre y . Escritura atómica: el servidor web nunca ve un fichero a medias. node tools/ultimos.js @feed.ed25519 5 | python3 tools/directo.py /var/www/acampada26s.net/index.html """ import html import json import os import re import sys import tempfile from datetime import datetime from urllib.parse import quote from zoneinfo import ZoneInfo INI = "" FIN = "" MAX = 400 # caracteres por post TZ = ZoneInfo("Europe/Madrid") def limpia(texto): # fuera markdown de imágenes/enlaces y referencias ssb, queda el texto texto = re.sub(r"!\[[^\]]*\]\([^)]*\)", "", texto) texto = re.sub(r"\[([^\]]*)\]\([^)]*\)", r"\1", texto) texto = " ".join(texto.split()) if len(texto) > MAX: texto = texto[:MAX].rsplit(" ", 1)[0] + "…" return texto def bloque(posts): li = [] for p in posts: t = datetime.fromtimestamp(p["ts"] / 1000, tz=TZ) img = "" if p.get("img"): src = "/c/blob/" + quote(p["img"], safe="") img = f'\n ' li.append( "
  • \n" f' {img}\n' f"

    {html.escape(limpia(p['text']))}

    \n" "
  • " ) if not li: return f"{INI}\n {FIN}" return ( f'{INI}\n
    \n

    Directo

    \n' f'
      \n{chr(10).join(li)}\n
    \n' f'

    Todo en OASIS

    \n
    \n {FIN}' ) def main(): if len(sys.argv) != 2: sys.exit("uso: ... | directo.py ruta/index.html") ruta = sys.argv[1] posts = json.load(sys.stdin) if not isinstance(posts, list): sys.exit("entrada no es una lista") with open(ruta, encoding="utf-8") as f: doc = f.read() i, j = doc.find(INI), doc.find(FIN) if i < 0 or j < i: sys.exit("no están las marcas directo:inicio / directo:fin") nuevo = doc[:i] + bloque(posts) + doc[j + len(FIN):] if nuevo == doc: return d = os.path.dirname(os.path.abspath(ruta)) fd, tmp = tempfile.mkstemp(dir=d, prefix=".index.") try: with os.fdopen(fd, "w", encoding="utf-8") as f: f.write(nuevo) os.chmod(tmp, 0o644) os.replace(tmp, ruta) except BaseException: os.unlink(tmp) raise if __name__ == "__main__": main()