feat(capture): capture éclair — API à jeton dédié + écoute ntfy (issue #12)

POST /api/capture (X-Capture-Token ou Bearer; 503 si non configuré;
exempté Basic Auth/CSRF car machine-à-machine), JSON ou texte libre
(1re ligne = titre), dépôt par défaut KANBANTE_CAPTURE_REPO.
Module app/capture.py: parsing partagé + abonné ntfy en tâche de
fond (reconnexion, curseur kv_store anti-rejeu, tag 'kanban'...
'kanbante' ignoré). _do_capture commun: issue créée, carte placée,
événement 'created' source 'capture'.
This commit is contained in:
Spark
2026-10-11 12:40:31 -04:00
parent 05b8c506e0
commit 395ab6e14c
3 changed files with 313 additions and 2 deletions
+22 -1
View File
@@ -36,6 +36,21 @@ Environment variables:
the daily briefing is sent to ntfy.
Empty (default) = no automatic send,
the /briefing page stays available.
KANBANTE_CAPTURE_REPO Default repo for quick capture
(POST /api/capture, the /capture page
and the ntfy capture listener), e.g.
"Projets/kanbante". Empty = captures
must name their repo explicitly.
KANBANTE_CAPTURE_TOKEN Dedicated token for POST /api/capture
(header X-Capture-Token or Bearer).
Empty (default) = the endpoint is
disabled (503). Distinct from the
Gitea token; revocable on its own.
KANBANTE_CAPTURE_NTFY_TOPIC ntfy topic listened to for captures:
each message published there becomes
an issue in KANBANTE_CAPTURE_REPO.
Uses KANBANTE_NTFY_URL/_TOKEN as the
server. Empty (default) = no listener.
"""
import os
@@ -44,7 +59,7 @@ from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
APP_VERSION = "0.6.0"
APP_VERSION = "0.7.0"
def _env_bool(name: str, default: bool) -> bool:
@@ -100,6 +115,9 @@ class Settings:
ntfy_topic: str = ""
ntfy_token: str = ""
briefing_time: str = ""
capture_repo: str = ""
capture_token: str = ""
capture_ntfy_topic: str = ""
@property
def auth_enabled(self) -> bool:
@@ -129,4 +147,7 @@ def get_settings() -> Settings:
ntfy_topic=os.getenv("KANBANTE_NTFY_TOPIC", ""),
ntfy_token=os.getenv("KANBANTE_NTFY_TOKEN", ""),
briefing_time=os.getenv("KANBANTE_BRIEFING_TIME", ""),
capture_repo=os.getenv("KANBANTE_CAPTURE_REPO", ""),
capture_token=os.getenv("KANBANTE_CAPTURE_TOKEN", ""),
capture_ntfy_topic=os.getenv("KANBANTE_CAPTURE_NTFY_TOPIC", ""),
)