From 5f571e08ead6ffc4b9e276857e911e2026143c89 Mon Sep 17 00:00:00 2001 From: Antoine Van Elstraete Date: Tue, 8 Sep 2026 18:08:44 +0200 Subject: [PATCH] =?UTF-8?q?Recr=C3=A9er=20la=20page=20Architecture=20avec?= =?UTF-8?q?=20corrections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Architecture.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Architecture.md diff --git a/Architecture.md b/Architecture.md new file mode 100644 index 0000000..631f5d8 --- /dev/null +++ b/Architecture.md @@ -0,0 +1,50 @@ +# Architecture + +## Vue d'ensemble + +`pronote-sync` est un pipeline qui synchronise les données de **Pronote** vers **CalDAV** (agendas) et **XMPP** (notifications). Le flux principal est : **Pronote (iCal/pronotepy) → normalisation → comparaison avec l'agenda théorique → synchronisation CalDAV → synthèse IA (optionnelle) → notification XMPP**. Les sources sont **iCal** (primaire) et `pronotepy` (repli), avec trois modes de source : `auto`, `ical` et `pronotepy`. + +## Pipeline + +1. Récupération Pronote — agenda et devoirs via iCal ou `pronotepy` ; messages et informations via `pronotepy` uniquement +1. Normalisation et parsing — parsing iCal → modèles Pydantic, déduplication, normalisation des UID +1. Récupération du blog (RSS) — `feedparser`, déduplication par GUID, cache HTTP +1. Comparaison avec l'agenda théorique — matching déterministe, détection des changements +1. Synchronisation CalDAV — sync différentielle et idempotente, UID stables, conservation des annulés +1. Synthèse IA (optionnelle) — synthèse des changements, mode dégradé si échec +1. Envoi XMPP — message structuré (synthèse + devoirs bruts) + +## Modules + +```text +pronote_sync/ +├── config/ Configuration (Pydantic Settings) +├── models/ Modèles de données (Pydantic v2) +├── sources/ Connecteurs (Pronote iCal/pronotepy, blog RSS, agenda théorique) +├── sync/ Synchronisation CalDAV et comparaison +├── synthesis/ Synthèse IA (OpenAI, litellm, openai-compatible) +├── channels/ Canaux de sortie (XMPP) +├── pipeline/ Orchestration (composition root, PipelineRunner) +├── utils/ Utilitaires (redaction, logging, UID) +└── cli/ Interface en ligne de commande +``` + +## Injection de dépendances + +Le projet utilise `typing.Protocol` et une **composition root** dans `pipeline/run.py`. Aucun singleton global n'est autorisé. Le `PipelineRunner` reçoit toutes ses dépendances via **injection par constructeur** : `PronoteFetcher`, `CalDAVClient`, `AgendaComparator`, `SynthesisProvider`, `Channel`. + +## Sources de données + +Les modes de source sont les suivants : + +- `auto` : essaie d'abord iCal, puis bascule vers `pronotepy` **uniquement** si iCal lève une exception. +- `ical` : utilise **uniquement** iCal, sans bascule silencieuse. +- `pronotepy` : utilise **uniquement** `pronotepy`, sans bascule silencieuse. +- En mode `auto`, si iCal **et** `pronotepy` échouent → erreur critique explicite. +- Une liste vide est un **succès valide**, pas une panne. +- `PRONOTE_URL` (connexion API) et `PRONOTE_ICAL_URL` (flux iCal) sont deux paramètres **distincts**. +- Les messages ne sont disponibles que via `pronotepy` (absents du flux iCal). + +## Flux de données + +Le flux de données suit ce chemin : données brutes (iCal/`pronotepy`) → modèles Pydantic (`Lesson`, `Homework`, `Message`, etc.) → `PronoteData` (agrégé) → `AgendaDiff` (comparaison) → `CalDavSyncResult` → `SynthesisInput`/`SynthesisResult` → `XmppMessage` → envoi via le canal XMPP. \ No newline at end of file