- JavaScript 87.1%
- CSS 7%
- Shell 5.3%
- Dockerfile 0.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xUVkV6yMi8qS7jLeR2wpH |
||
| deploy | ||
| docs | ||
| scripts | ||
| src | ||
| test | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| CLAUDE.md | ||
| docker-compose.build.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Sud Ouest — téléchargement automatique du journal
v1.3.0 : l'application tourne dans un LXC Proxmox (sans Docker), avec archive classée par année/mois, purge du dossier de réception, replis d'édition et extinction automatique. État et commandes :
docs/HANDOFF.md. Si le site Sud Ouest change et que ça ne marche plus :docs/MAINTENANCE.md. Le reste de ce README décrit l'ancien déploiement Docker (v1.2.0).
Conteneur Docker qui se connecte chaque matin au kiosque abonné de Sud Ouest, télécharge l'édition PDF du jour et la dépose dans un sous-dossier du partage média du NAS.
- Conteneur sur le serveur Debian Docker, partage NAS monté sur l'hôte dans
/mnt/media, visible dans le conteneur sous/media. - Aucun fichier
.env: la configuration fixe est dansdocker-compose.yml, le reste se règle dans l'interface web. - Explorateur de dossiers intégré : l'interface parcourt
/mediaet permet de choisir (ou créer) le dossier de destination. - Exécution planifiée à 05:00 (
Europe/Paris), modifiable dans l'interface. - Nouvelles tentatives toutes les 15 minutes jusqu'à 08:00 si l'édition n'est pas encore en ligne.
- Rattrapage au démarrage si l'heure planifiée est passée et que le PDF manque.
- Un seul téléchargement par jour, idempotent.
- Édition par défaut : Pays basque (
12Den semaine,PYRle dimanche — résolution automatique).
Usage strictement personnel : le compte doit être un abonné Sud Ouest actif. Un téléchargement par jour correspond au quota de l'abonnement ; ne pas rediffuser les PDF.
1. Fonctionnement technique (vérifié sur le site)
| Étape | Détail |
|---|---|
| Connexion | https://kiosque.sudouest.fr/login/auto → OAuth profil.sudouest.fr (formulaire #loginForm_username / #loginForm_password). |
| Liste des éditions | GET https://kiosque.sudouest.fr/api/newspapers/list/?type=journal (JSON). |
| Quota | GET https://kiosque.sudouest.fr/api/user → token_quantity. |
GET https://kiosque.sudouest.fr/download/journal/{AAAA-MM-JJ}/{journal}/{edition}/ |
|
| Codes utiles | Pays basque 12D (journal 01), Pays basque/Béarn PYR (dimanche, journal 02) |
Le téléchargement utilise les cookies de la session Playwright : le kiosque renvoie directement le binaire PDF (HTTP 403 si quota épuisé ou abonnement inactif).
2. Prérequis sur le serveur Debian
- Docker + Docker Compose.
- Le partage SMB du Synology monté sur l'hôte dans
/mnt/media(fstab ou unité systemd). /mnt/mediaaccessible en écriture par le conteneur (celui-ci tourne en root, les droits réels sont ceux du montage CIFS).
Exemple d'entrée /etc/fstab :
//Diskstation/Media /mnt/media cifs credentials=/etc/sudouest-nas.cred,uid=0,gid=0,iocharset=utf8,file_mode=0664,dir_mode=0775,vers=3.0,nofail 0 0
Puis :
sudo mkdir -p /mnt/media
sudo mount /mnt/media
ls "/mnt/media/Ebooks/!Download/SO du jour"
Le montage CIFS est géré par l'hôte, plus par Docker. Le conteneur ne voit que
/media, monté depuis/mnt/media. Si le NAS est absent au démarrage,/mnt/mediapeut être vide : monter le partage avant de lancer le conteneur.
3. Installation
L'image est publiée dans le registre Forgejo : git.arbisa.fr/daniel/sudouest-journal:1.2.0 (linux/amd64).
Le docker-compose.yml la télécharge : rien à construire sur la machine cible.
Les fichiers docker-compose.yml, docker-compose.build.yml et README.md sont aussi attachés à la
release v1.2.0.
3.1 Placer le projet
sudo mkdir -p /dockers/sudouest
cd /dockers/sudouest
# récupérer docker-compose.yml depuis la release, ou :
git clone https://git.arbisa.fr/daniel/sudouest-journal.git .
3.2 Se connecter au registre
L'image et le dépôt sont privés. Sur la machine cible :
echo "<ton token Forgejo>" | docker login git.arbisa.fr -u daniel --password-stdin
Utilise un token avec le droit read:package (ou ton token habituel).
3.3 Démarrer
docker compose pull
docker compose up -d
docker compose logs -f
Le fichier docker-compose.yml contient déjà toute la configuration :
environment:
TZ: Europe/Paris
SO_EMAIL: "mon.email@exemple.fr"
SO_PASSWORD: "motdepasse"
MEDIA_ROOT: /media
OUTPUT_DIR: "/media/Ebooks/!Download/SO du jour"
WEB_PORT: "8080"
...
volumes:
- /dockers/sudouest/data:/data
- /mnt/media:/media
SO_EMAIL et SO_PASSWORD sont facultatifs : s'ils sont renseignés, ils servent de
valeurs par défaut au premier démarrage.
3.4 Configurer dans l'interface
Ouvrir http://<ip-du-serveur>:8082.
Au premier démarrage, l'application crée /dockers/sudouest/data/settings.json à partir des
environment: du compose (e-mail, mot de passe, édition, cron, destination). L'interface affiche
ces valeurs, mot de passe compris (champ masqué, bouton Afficher).
- vérifier ou modifier l'e-mail et le mot de passe ;
- cliquer sur Tester la connexion (le test utilise les valeurs du formulaire, sans les enregistrer) ;
- cliquer sur Parcourir… dans la carte Destination, naviguer dans
/mediaet choisir le dossier (ou en créer un) ; - cliquer sur Enregistrer les réglages.
Toute modification est écrite dans settings.json, qui devient prioritaire sur le compose.
Supprimer ce fichier réinitialise les réglages avec les valeurs du compose.
Portainer : le chemin est volontairement absolu (
/dockers/sudouest/data). Un chemin relatif comme./dataserait résolu dans le dossier interne du stack Portainer, et les réglages seraient perdus si le stack est supprimé puis recréé.
3.5 Mise à jour
docker compose pull
docker compose up -d
3.6 Construire localement (développement)
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
4. Interface d'administration
Ouvrir http://<ip-du-serveur>:8082.
- Dernière exécution : statut, date, édition, fichier déposé, erreur éventuelle.
- Connexion Sud Ouest : e-mail, mot de passe (champ vide = inchangé), test de connexion.
- Édition : code
12Det nom de repli pour le dimanche. - Planification : cron, intervalle entre tentatives, heure limite, purge des anciens PDF.
- Destination : explorateur de dossiers sous
/media+ création de dossier. - Notifications : ntfy / webhook.
- Journaux : 200 dernières lignes.
Le test de connexion et le téléchargement s'exécutent en arrière-plan : la page reste réactive et le résultat s'affiche automatiquement.
4.1 Absence d'authentification
L'interface n'a pas de mot de passe : elle est prévue pour le réseau local uniquement.
- Ne jamais exposer le port
8082sur Internet. - N'importe quel appareil du réseau local peut modifier les réglages.
- Protection CSRF conservée (en-tête
X-Requested-With+ contrôle d'origine). - Le mot de passe est prérempli dans le formulaire (champ masqué, bouton « Afficher ») depuis
settings.jsonou le compose. Comme l'interface n'a pas d'authentification, toute personne ayant accès au port8082peut le consulter : ne jamais l'exposer sur Internet.
4.2 Destination et sécurité des chemins
- L'explorateur ne peut naviguer que sous
/media(MEDIA_ROOT). - Les chemins hors racine, les remontées
..et les liens symboliques sortants sont refusés. - Le dossier choisi doit exister et être accessible en écriture ; il est enregistré dans
/dockers/sudouest/data/settings.json. OUTPUT_DIRdans le compose ne sert que de valeur initiale au premier démarrage.
Tous les réglages (identifiants, édition, cron, destination, notifications) sont dans
/dockers/sudouest/data/settings.json sur l'hôte, en droits 600. Ce fichier survit à
docker compose restart, down/up, pull/up -d et aux mises à jour de stack. Il n'est
perdu que si le dossier /dockers/sudouest/data est supprimé.
4.3 Précédence de la configuration
- valeurs par défaut du code ;
- variables
environment:dudocker-compose.yml; - réglages enregistrés dans
/dockers/sudouest/data/settings.jsonvia l'interface (prioritaires).
Pour revenir aux valeurs du compose : arrêter le conteneur et supprimer /dockers/sudouest/data/settings.json.
5. Variables du docker-compose
| Variable | Valeur par défaut | Rôle |
|---|---|---|
TZ |
Europe/Paris |
Fuseau de planification. |
SO_EMAIL |
"" |
E-mail Sud Ouest par défaut, recopié dans settings.json au premier démarrage. |
SO_PASSWORD |
"" |
Mot de passe par défaut, recopié dans settings.json au premier démarrage. |
DATA_DIR |
/data |
Données internes (profil Chromium, settings.json, logs). |
MEDIA_ROOT |
/media |
Racine du média ; limite l'explorateur de dossiers. |
OUTPUT_DIR |
/media/Ebooks/!Download/SO du jour |
Destination initiale (ensuite gérée dans l'interface). |
WEB_ENABLED |
true |
Active l'interface. |
WEB_PORT |
8080 |
Port d'écoute interne ; l'hôte expose 8082 via ports: "8082:8080". |
WEB_HOST |
0.0.0.0 |
Interface d'écoute dans le conteneur. |
RUN_AT_CRON |
0 5 * * * |
Planification initiale (modifiable dans l'interface). |
RETRY_INTERVAL_MIN |
15 |
Intervalle initial entre deux tentatives. |
RETRY_UNTIL |
08:00 |
Heure limite initiale. |
RUN_ON_START |
false |
Tente un téléchargement au démarrage. |
KEEP_LAST_DAYS |
0 |
Purge initiale (0 = tout conserver). |
LOG_LEVEL |
info |
debug, info, warn, error. |
HEADLESS |
true |
false uniquement avec un affichage. |
Les identifiants, l'édition, le cron, les tentatives et la destination se modifient dans l'interface.
Ils peuvent aussi être fournis au premier démarrage via SO_EMAIL, SO_PASSWORD, SO_EDITION_ID, SO_EDITION_NAME, NTFY_URL, WEBHOOK_URL dans environment: : ces valeurs servent alors à créer settings.json, qui reste ensuite prioritaire.
6. Dépannage
| Symptôme | Cause probable / action |
|---|---|
/media vide dans l'explorateur |
Le partage n'est pas monté sur l'hôte. Vérifier `mount |
| « Chemin en dehors de la racine média » | La destination choisie n'est pas sous MEDIA_ROOT (/media). |
| « Dossier non accessible en écriture » | Droits du montage CIFS (uid, gid, file_mode, dir_mode) ou compte SMB. |
Connexion refusée |
Identifiants Sud Ouest invalides, compte Google/Apple, ou abonné papier à connecter via numéro d'abonné. |
| HTTP 403 au téléchargement | Quota quotidien épuisé (/api/user → token_quantity: 0), abonnement inactif, édition pas encore ouverte. |
Aucune édition publiée |
L'édition n'est pas encore en ligne ; réessais jusqu'à 08:00. |
| Interface inaccessible | docker compose ps, pare-feu, port 8082. |
port is already allocated |
Le port hôte est pris. Changer ports: "8082:8080" en ports: "8083:8080" (garder 8080 côté conteneur). |
NetworkError / « Service injoignable » |
Conteneur arrêté ou redémarré ; recharger la page après docker compose ps. |
Journaux : docker compose logs, data/sudouest.log, onglet « Journaux » de l'interface.
Diagnostics : data/debug/ (captures + HTML si la connexion échoue).
7. Commandes utiles
docker compose ps
docker compose logs -f --tail=100
docker compose restart
docker compose down
docker compose pull && docker compose up -d
8. Développement local
npm install
npm test
node src/index.js --help
Pour tester sans NAS, pointer MEDIA_ROOT et OUTPUT_DIR vers un dossier local :
MEDIA_ROOT=/tmp/media OUTPUT_DIR=/tmp/media/Ebooks DATA_DIR=/tmp/so-data WEB_PORT=8080 npm start
Les tests unitaires ne nécessitent ni réseau ni navigateur.