Ajoute une journalisation détaillée (login, mail, présence, rappels)
Niveau configurable via LOG_LEVEL (défaut DEBUG). Les erreurs de config JSON invalide remontent maintenant un message clair (fichier + position) au lieu d'un JSONDecodeError brut.
This commit is contained in:
@ -1,10 +1,13 @@
|
||||
"""Reminders: nag via ntfy when present-but-unpointed or departed-but-not-depointed."""
|
||||
import asyncio
|
||||
import logging
|
||||
import urllib.request
|
||||
from datetime import datetime
|
||||
|
||||
from models import list_users, load_notif_config, load_presence, load_week_pointages
|
||||
|
||||
logger = logging.getLogger("pointeuse.notifications")
|
||||
|
||||
NTFY_BASE = "https://ntfy.sh"
|
||||
CHECK_INTERVAL_SECONDS = 300
|
||||
RAPPEL_DEBUT_H = 7
|
||||
@ -20,8 +23,10 @@ def send_ntfy(topic: str, message: str, title: str):
|
||||
)
|
||||
try:
|
||||
urllib.request.urlopen(req, timeout=10).close()
|
||||
logger.info("notif ntfy envoyée: topic=%r title=%r", topic, title)
|
||||
except Exception:
|
||||
pass # best-effort: a missed reminder isn't worth crashing the loop
|
||||
logger.exception("échec de l'envoi ntfy: topic=%r title=%r", topic, title)
|
||||
# best-effort: a missed reminder isn't worth crashing the loop
|
||||
|
||||
|
||||
def _todays_pointage(user_id: str, today: datetime) -> dict:
|
||||
@ -35,22 +40,33 @@ async def check_user(user_id: str, now: datetime):
|
||||
notif = load_notif_config(user_id)
|
||||
topic = notif.get("ntfy_topic")
|
||||
if not topic:
|
||||
logger.debug("check_user(%r): pas de topic ntfy configuré, ignoré", user_id)
|
||||
return
|
||||
if now.weekday() >= 5 or not (RAPPEL_DEBUT_H <= now.hour < RAPPEL_FIN_H):
|
||||
logger.debug("check_user(%r): hors plage de rappel (%s)", user_id, now)
|
||||
return
|
||||
|
||||
presence = load_presence(user_id)
|
||||
jour = _todays_pointage(user_id, now)
|
||||
logger.debug(
|
||||
"check_user(%r): presence=%s matin_entree=%r aprem_sortie=%r",
|
||||
user_id, presence.get("present"), jour.get("matin_entree"), jour.get("aprem_sortie"),
|
||||
)
|
||||
|
||||
if presence.get("present") and not jour.get("matin_entree"):
|
||||
logger.info("rappel 'pense à pointer' pour %r", user_id)
|
||||
await asyncio.to_thread(send_ntfy, topic, "Tu es dans les locaux mais pas encore pointé ce matin.", "⏰ Pense à pointer")
|
||||
elif not presence.get("present") and jour.get("matin_entree") and not jour.get("aprem_sortie"):
|
||||
logger.info("rappel 'pense à dépointer' pour %r", user_id)
|
||||
await asyncio.to_thread(send_ntfy, topic, "Tu as quitté les locaux sans dépointer la sortie.", "⏰ Pense à dépointer")
|
||||
|
||||
|
||||
async def reminder_loop():
|
||||
logger.info("boucle de rappels démarrée (intervalle=%ss)", CHECK_INTERVAL_SECONDS)
|
||||
while True:
|
||||
now = datetime.now()
|
||||
for user_id in list_users():
|
||||
users = list_users()
|
||||
logger.debug("cycle de vérification pour %d utilisateur(s)", len(users))
|
||||
for user_id in users:
|
||||
await check_user(user_id, now)
|
||||
await asyncio.sleep(CHECK_INTERVAL_SECONDS)
|
||||
|
||||
Reference in New Issue
Block a user