Ajoute les rappels de pointage via ntfy et détection de présence Tasker
Notifie l'utilisateur toutes les 5 min s'il est présent dans les locaux sans avoir pointé le matin, ou parti sans avoir dépointé la sortie.
This commit is contained in:
56
app/main.py
56
app/main.py
@ -1,22 +1,30 @@
|
||||
import asyncio
|
||||
import json
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
from itertools import groupby
|
||||
|
||||
from fastapi import FastAPI, Form, Request, Response
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from models import (
|
||||
load_config, load_week_pointages, save_week_pointages, load_conges,
|
||||
toggle_conge, list_all_weeks, needs_migration, migrate_legacy_to_user,
|
||||
load_notif_config, save_notif_config, find_user_by_token, save_presence,
|
||||
)
|
||||
from calcul import compute_week, minutes_to_hhmm, hhmm_to_minutes, heures_dues
|
||||
from stats import compute_all_stats
|
||||
from classement import compute_classement
|
||||
from notifications import reminder_loop
|
||||
|
||||
app = FastAPI(title="Décompte Horaire")
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def _start_reminder_loop():
|
||||
asyncio.create_task(reminder_loop())
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
templates.env.filters["zip"] = zip
|
||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
@ -370,6 +378,52 @@ def stats_page(request: Request):
|
||||
})
|
||||
|
||||
|
||||
@app.get("/settings", response_class=HTMLResponse)
|
||||
def settings_page(request: Request):
|
||||
user_id = _get_user(request)
|
||||
if not user_id:
|
||||
return RedirectResponse("/login", status_code=302)
|
||||
|
||||
notif = load_notif_config(user_id)
|
||||
base_url = str(request.base_url).rstrip("/")
|
||||
return templates.TemplateResponse("settings.html", {
|
||||
"request": request,
|
||||
"current_user": user_id,
|
||||
"ntfy_topic": notif.get("ntfy_topic") or "",
|
||||
"arrivee_url": f"{base_url}/presence/{notif['token']}/arrivee",
|
||||
"depart_url": f"{base_url}/presence/{notif['token']}/depart",
|
||||
"saved": request.query_params.get("saved") == "1",
|
||||
})
|
||||
|
||||
|
||||
@app.post("/settings", response_class=HTMLResponse)
|
||||
def settings_save(request: Request, ntfy_topic: str = Form("")):
|
||||
user_id = _get_user(request)
|
||||
if not user_id:
|
||||
return RedirectResponse("/login", status_code=302)
|
||||
|
||||
save_notif_config(user_id, ntfy_topic)
|
||||
return RedirectResponse("/settings?saved=1", status_code=303)
|
||||
|
||||
|
||||
@app.get("/presence/{token}/arrivee")
|
||||
def presence_arrivee(token: str):
|
||||
user_id = find_user_by_token(token)
|
||||
if not user_id:
|
||||
return JSONResponse({"error": "invalid token"}, status_code=404)
|
||||
save_presence(user_id, present=True, since=datetime.now().isoformat())
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@app.get("/presence/{token}/depart")
|
||||
def presence_depart(token: str):
|
||||
user_id = find_user_by_token(token)
|
||||
if not user_id:
|
||||
return JSONResponse({"error": "invalid token"}, status_code=404)
|
||||
save_presence(user_id, present=False, since=datetime.now().isoformat())
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@app.get("/classement", response_class=HTMLResponse)
|
||||
def classement_page(request: Request):
|
||||
user_id = _get_user(request)
|
||||
|
||||
Reference in New Issue
Block a user