Initial commit — Pedrito Hechakuaa v0
Bot de Telegram para monitoreo de notificaciones judiciales del PJ Paraguay. Multi-tenant con onboarding conversacional, audit log, y polling automático. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
76
storage.py
Normal file
76
storage.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
storage.py — Persistencia del snapshot de notificaciones.
|
||||
|
||||
Guarda en JSON local en data/snapshot.json.
|
||||
Simple a propósito: en v1 esto se reemplaza por Postgres con el mismo interface.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import structlog
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class Snapshot:
|
||||
"""
|
||||
Snapshot del estado de notificaciones.
|
||||
Guarda los IDs de las notificaciones ya notificadas al abogado.
|
||||
"""
|
||||
|
||||
def __init__(self, path: Path) -> None:
|
||||
self._path = path
|
||||
self._notificaciones_vistas: set[int] = set()
|
||||
self._last_check: datetime | None = None
|
||||
self._load()
|
||||
|
||||
def _load(self) -> None:
|
||||
if not self._path.exists():
|
||||
logger.info("snapshot_no_existe_iniciando_vacio", path=str(self._path))
|
||||
return
|
||||
|
||||
try:
|
||||
data = json.loads(self._path.read_text(encoding="utf-8"))
|
||||
self._notificaciones_vistas = set(data.get("notificaciones_vistas", []))
|
||||
last_check_str = data.get("last_check")
|
||||
if last_check_str:
|
||||
self._last_check = datetime.fromisoformat(last_check_str)
|
||||
logger.info(
|
||||
"snapshot_cargado",
|
||||
notificaciones_vistas=len(self._notificaciones_vistas),
|
||||
last_check=last_check_str,
|
||||
)
|
||||
except (json.JSONDecodeError, ValueError) as e:
|
||||
logger.warning("snapshot_corrupto_iniciando_vacio", error=str(e))
|
||||
|
||||
def _save(self) -> None:
|
||||
data = {
|
||||
"last_check": self._last_check.isoformat() if self._last_check else None,
|
||||
"notificaciones_vistas": sorted(self._notificaciones_vistas),
|
||||
}
|
||||
self._path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self._path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
def ya_vista(self, cod_notificacion: int) -> bool:
|
||||
return cod_notificacion in self._notificaciones_vistas
|
||||
|
||||
def marcar_vista(self, cod_notificacion: int) -> None:
|
||||
self._notificaciones_vistas.add(cod_notificacion)
|
||||
|
||||
def marcar_varias_vistas(self, codigos: list[int]) -> None:
|
||||
self._notificaciones_vistas.update(codigos)
|
||||
|
||||
def registrar_check(self) -> None:
|
||||
self._last_check = datetime.now(timezone.utc)
|
||||
self._save()
|
||||
|
||||
@property
|
||||
def last_check(self) -> datetime | None:
|
||||
return self._last_check
|
||||
|
||||
@property
|
||||
def total_vistas(self) -> int:
|
||||
return len(self._notificaciones_vistas)
|
||||
Reference in New Issue
Block a user