[Pronote] · 19:00
Planning du lundi 7 septembre
Journée longue pour Alice, pensez au sac de sport pour l'EPS en fin d'après-midi. Bob a un cours de français annulé ce matin.
GitHub Action · Pronote · sans serveur
Pronote a toutes les informations. Il faut juste aller les chercher, tous les soirs, enfant par enfant. pronote-digest le fait pour vous : un mail à 17h30 pour les devoirs, un mail à 19h pour le planning. Rien à installer, rien à héberger.
17:30
les devoirs
19:00
le planning
[Pronote] · 19:00
Journée longue pour Alice, pensez au sac de sport pour l'EPS en fin d'après-midi. Bob a un cours de français annulé ce matin.
Pourquoi
01
Voir la journée de demain, c'est ouvrir Pronote, changer d'enfant, ouvrir l'emploi du temps, puis le cahier de textes. Tous les soirs.
02
À quelle heure ça commence, à quelle heure ça finit, s'il y a sport, ce qu'il y a à rendre, si un cours saute. Le reste, c'est du bruit.
03
17h30 pour vérifier les devoirs avant le dîner, 19h pour préparer le cartable. Pas de notification, pas d'application : un mail, que vous lisez ou pas.
Ce que vous recevez
[Pronote] · 17:30
ANGLAIS LV1 · THOMAS C. · donné le jeudi 3 septembre
lesson + vocabulary : être capable de reparler des deux bandes-annonces avec le vocabulaire noté en classe
FRANCAIS · MARTIN A. · donné le jeudi 3 septembre
Apporter le manuel de français couvert, avec l’étiquette complétée.
HISTOIRE-GEOGRAPHIE · DAVID P. · donné le jeudi 3 septembre
Illustrer la première page du cahier avec des éléments en lien avec le programme de l’année.
MATHEMATIQUES · ROUX O. · donné le jeudi 3 septembre
Apporter les deux cahiers (48 pages et 96 pages) et tout le matériel attendu.
17:30, les devoirs. Le travail à rendre pour le prochain jour de classe, tel que saisi par les enseignants dans le cahier de textes. Matière, enseignant, date où le devoir a été donné, consigne. Rien les jours sans cours.
[Pronote] · 19:00
Journée longue pour Alice, pensez au sac de sport pour l'EPS en fin d'après-midi. Bob a un cours de français annulé ce matin.
19:00, le planning. Les cours du prochain jour de classe, heure de début et de fin de journée, salles, cours annulés ou déplacés barrés, rappel de la tenue de sport. Et, si vous l'activez, une introduction rédigée par le modèle d'IA de votre choix.
Comment ça marche
1 · Pronote
Chaque compte élève expose un calendrier iCal avec les cours, les annulations, et le cahier de textes si l'établissement l'a activé. C'est la seule source.
2 · GitHub Actions
Deux workflows planifiés téléchargent le flux, calculent le jour visé, et rendent le mail. Le quota gratuit de GitHub couvre largement deux runs par jour.
3 · Votre SMTP
Brevo, Mailgun, Postmark, OVH, votre Gmail avec un mot de passe d'application. Le mail part de chez vous, vers qui vous voulez.
Introduction rédigée · optionnel
Si vous le souhaitez, un modèle d'IA lit le planning du lendemain et en tire trois à cinq phrases : la journée est longue, il y a sport, un cours saute, un manuel à ne pas oublier. Le tableau reste en dessous, l'introduction ne le remplace pas.
Vous choisissez le fournisseur : Claude, GPT, Gemini, Mistral, ou un modèle qui tourne chez vous avec Ollama. Le modèle ne voit que le contenu du mail, jamais Pronote ni votre boîte. Et si vous ne configurez rien, il n'y a pas d'introduction, et aucun appel n'est fait.
Ce qui est factuel reste écrit par le programme. Si le modèle invente une heure, son texte est écarté et le mail part sans.
Extrait d'un planning · 19:00
« Journée longue pour Alice, qui finit par du sport : prévoyez ses affaires d'EPS et le manuel de français couvert. Bob a un cours de français annulé en fin de matinée. Deux cahiers de mathématiques et le chevalet pour l'anglais sont à glisser dans son cartable. »
Mise en place
Étape 1
Espace Parents ou Élève, emploi du temps, export iCal. Vous obtenez une URL par enfant, du type …/pronote/ical/Edt_prenom.ics?icalsecurise=…. Elle contient un jeton : traitez-la comme un mot de passe.
Étape 2
Il ne contiendra que deux workflows, vos secrets et l'archive des envois. Privé, parce que l'archive porte les prénoms, les enseignants et les consignes.
Étape 3
Settings, Secrets and variables, Actions : CHILDREN avec le JSON ci-contre, puis SMTP_HOST, SMTP_USER, SMTP_PASS etMAIL_TO.
Étape 4
Copiez-les dans .github/workflows/. Lancez-en un à la main avecdry_run coché : le rendu est archivé dans le dépôt sans rien envoyer. Puis décochez.
[
{ "name": "Alice", "ics": "https://…/pronote/ical/Edt_alice.ics?icalsecurise=…&version=…¶m=…" },
{ "name": "Bob", "ics": "https://…/pronote/ical/Edt_bob.ics?icalsecurise=…&version=…¶m=…" }
]name: Planning du lendemain
on:
schedule:
# 19h13 Paris, heure d'été et heure d'hiver
# Minute non ronde : les crons à :00 et :30 sont les plus retardés par GitHub
- cron: '13 17 * * *'
- cron: '13 18 * * *'
workflow_dispatch:
inputs:
dry_run:
type: boolean
default: false
permissions:
contents: write
jobs:
digest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# On compare le décalage de Paris et l'entrée cron qui a déclenché le run,
# pas l'heure d'exécution : un cron lancé en retard doit quand même passer.
- name: Décalage de Paris
id: paris
run: echo "offset=$(TZ=Europe/Paris date +%z)" >> "$GITHUB_OUTPUT"
- name: Digest
if: >-
github.event_name != 'schedule'
|| (steps.paris.outputs.offset == '+0200' && github.event.schedule == '13 17 * * *')
|| (steps.paris.outputs.offset == '+0100' && github.event.schedule == '13 18 * * *')
uses: yoanbernabeu/pronote-digest@v0
with:
children: ${{ secrets.CHILDREN }}
digest: planning
smtp_host: ${{ secrets.SMTP_HOST }}
smtp_port: 587
smtp_user: ${{ secrets.SMTP_USER }}
smtp_pass: ${{ secrets.SMTP_PASS }}
mail_from: 'Pronote Digest <digest@example.com>'
mail_to: ${{ secrets.MAIL_TO }}
dry_run: ${{ inputs.dry_run }}
- name: Archive
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add archive
git diff --cached --quiet || git commit -m "chore: archive $(date -u +%F)"
git pull --rebase --autostash
git pushname: Devoirs du lendemain
on:
schedule:
# 17h33 Paris, heure d'été et heure d'hiver
# Minute non ronde : les crons à :00 et :30 sont les plus retardés par GitHub
- cron: '33 15 * * *'
- cron: '33 16 * * *'
workflow_dispatch:
inputs:
dry_run:
type: boolean
default: false
permissions:
contents: write
jobs:
digest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# On compare le décalage de Paris et l'entrée cron qui a déclenché le run,
# pas l'heure d'exécution : un cron lancé en retard doit quand même passer.
- name: Décalage de Paris
id: paris
run: echo "offset=$(TZ=Europe/Paris date +%z)" >> "$GITHUB_OUTPUT"
- name: Digest
if: >-
github.event_name != 'schedule'
|| (steps.paris.outputs.offset == '+0200' && github.event.schedule == '33 15 * * *')
|| (steps.paris.outputs.offset == '+0100' && github.event.schedule == '33 16 * * *')
uses: yoanbernabeu/pronote-digest@v0
with:
children: ${{ secrets.CHILDREN }}
digest: homework
on_no_school: skip
smtp_host: ${{ secrets.SMTP_HOST }}
smtp_port: 587
smtp_user: ${{ secrets.SMTP_USER }}
smtp_pass: ${{ secrets.SMTP_PASS }}
mail_from: 'Pronote Digest <digest@example.com>'
mail_to: ${{ secrets.MAIL_TO }}
dry_run: ${{ inputs.dry_run }}
- name: Archive
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add archive
git diff --cached --quiet || git commit -m "chore: archive $(date -u +%F)"
git pull --rebase --autostash
git pushDonnées et sécurité
L'action les masque dans les logs du workflow. Elles n'apparaissent ni dans le code, ni dans l'archive, ni dans les messages d'erreur.
Pronote, le runner GitHub, votre SMTP. C'est tout. Le fournisseur d'IA n'est appelé que si vous l'activez, et ne reçoit que le contenu du digest.
Les consignes du cahier de textes sont nettoyées avant d'entrer dans le mail : pas de script, pas de style, pas de lien douteux.
Le parseur est testé sur de vrais flux anonymisés. Chaque version est compilée et taguée par la CI, et publiée sur le GitHub Marketplace.
Questions fréquentes
Le planning fonctionne. Le digest devoirs, lui, ne peut pas : l’action le détecte au premier run et échoue avec un message clair, plutôt que d’envoyer des mails vides. L’inclusion du cahier de textes dans l’export iCal est un réglage côté établissement.
Dans la soirée, autour de l’heure choisie. GitHub Actions ne garantit pas l’heure exacte d’un cron : des retards de quelques minutes à plus d’une heure sont courants, et un run peut être sauté en période de forte charge. D’où la minute non ronde dans les exemples. Les deux entrées cron du workflow couvrent l’heure d’été et l’heure d’hiver ; un garde-fou n’en laisse passer qu’une, en se basant sur l’entrée qui a déclenché le run et non sur l’heure d’exécution, pour rester juste même quand GitHub est en retard.
Le prochain jour de classe : lundi le vendredi soir, le jour de reprise la veille des vacances. Le dimanche de fin de vacances, le lundi de reprise est bien envoyé. Les jours de classe sont déduits des cours présents dans le flux, donc les fériés et journées banalisées sont gérés sans configuration.
Ça arrive, souvent à la rentrée. Le run échoue avec un message explicite et GitHub vous prévient par mail. Récupérez les nouvelles URL dans Pronote et mettez à jour le secret CHILDREN.
Non, elle est désactivée par défaut. Si vous renseignez un fournisseur, le modèle reçoit le digest en texte et rédige trois à cinq phrases en tête du planning. Tout ce qui est factuel reste produit par le code : si le modèle cite une heure absente des données, l’intro est écartée et le mail part sans.
Nulle part ailleurs que dans votre dépôt privé. Le flux est téléchargé par le runner GitHub, transformé en mail, envoyé par votre SMTP, et le rendu est archivé dans votre dépôt. Aucun service tiers n’est appelé, hormis le fournisseur d’IA si vous l’activez.
Référence
Ce tableau est généré au build à partir du fichier action.yml du dépôt : il correspond toujours à la version publiée.
| Entrée | Défaut | Description |
|---|---|---|
| children | requis | Tableau JSON des enfants : [{"name":"Alice","ics":"https://…/Edt_x.ics?icalsecurise=…"}]. À passer via un secret. |
| digest | requis | Type de digest : planning ou homework. |
| channels | Canaux, séparés par des virgules : email, file. | |
| subject_prefix | [Pronote] | Préfixe du sujet des messages. |
| archive_dir | archive | Répertoire où archiver le JSON et les rendus de chaque envoi. none pour désactiver. |
| on_no_school | notify | Jour sans cours : notify (message court) ou skip (aucun envoi). |
| require_homework_data | true | Échouer si aucun flux ne contient de cahier de textes (digest homework). |
| date | — | Jour de préparation AAAA-MM-JJ. Par défaut aujourd’hui, heure de Paris. |
| dry_run | false | true pour ne rien envoyer (l’archive est tout de même écrite). |
| fetch_timeout_ms | 20000 | Délai maximal de téléchargement d’un flux, en millisecondes. |
| smtp_host | — | Serveur SMTP (canal email). |
| smtp_port | 587 | Port SMTP. |
| smtp_secure | false | true pour TLS implicite (port 465). |
| smtp_user | — | Identifiant SMTP. |
| smtp_pass | — | Mot de passe SMTP. À passer via un secret. |
| mail_from | — | Expéditeur. |
| mail_to | — | Destinataires, séparés par des virgules. |
| file_dir | out | Répertoire de sortie du canal file. |
| ai_provider | — | Fournisseur pour l’introduction rédigée (optionnel) : anthropic, openai, mistral, google, ollama, openai-compatible. Vide pour désactiver. |
| ai_model | — | Identifiant du modèle chez le fournisseur choisi. |
| ai_api_key | — | Clé d’API du fournisseur IA. À passer via un secret. |
| ai_base_url | — | URL de base pour ollama ou un endpoint compatible OpenAI. |
| ai_digests | planning | Digests qui reçoivent une introduction rédigée : planning, homework (séparés par des virgules). |