# planning2ics Convertit les PDFs de planning mensuel de l'**Opéra Orchestre National Montpellier** en fichiers `.ics` (iCalendar), un fichier par série artistique. Les séries sont identifiées automatiquement grâce au site web de l'opéra (titres officiels) et à un LLM via [Ollama](https://ollama.com/). --- ## Fonctionnalités - Extraction des événements depuis les PDFs de planning mensuel - Identification des séries par correspondance avec le site web officiel - Regroupement intelligent via LLM (gère les variantes de noms, séries parallèles (A)/(B)/(A')/(B')) - Descriptions riches : œuvres répétées pour les répétitions, description officielle du site pour les concerts - Cache local pour le scraping web et le mapping LLM (évite de refaire les appels à chaque run) - **Script standalone** en ligne de commande - **Application web** avec interface drag & drop, accessible sur iOS, Android et PC --- ## Structure du projet ``` planning2ics/ ├── planning2ics.py # Script standalone (ligne de commande) ├── pdf/ # PDFs de planning à traiter (non versionnés) ├── ics/ # Fichiers ICS générés (non versionnés) ├── cache/ # Cache site web + mapping LLM (non versionné) └── webapp/ # Application web ├── app.py # Backend FastAPI ├── core.py # Logique métier partagée ├── config.json # Configuration (Ollama, authentification) ├── requirements.txt ├── Dockerfile ├── docker-compose.yml # Déploiement Docker Swarm └── static/ ├── index.html ├── app.js └── style.css ``` --- ## Prérequis - Python 3.11+ - [Ollama](https://ollama.com/) accessible sur le réseau avec les modèles : - `qwen3.5:cloud` — clustering global des séries (rapide, requiert accès internet depuis Ollama) - `qwen3:8b` — fallback local (fonctionne sur GPU 8 Go VRAM, ex : RX 7600) - Docker (pour la webapp) --- ## Script standalone ### Installation ```bash pip install pdfplumber icalendar requests beautifulsoup4 ``` ### Configuration Éditer les constantes en haut de `planning2ics.py` : ```python PDF_DIR = Path("pdf") # Dossier contenant les PDFs OUTPUT_DIR = Path("ics") # Dossier de sortie ICS OLLAMA_URL = "http://192.168.7.119:11434" CLUSTER_MODEL = "qwen3.5:cloud" # Modèle pour le clustering global OLLAMA_MODEL = "qwen3:8b" # Modèle local pour le fallback ``` ### Utilisation ```bash # Placer les PDFs dans le dossier pdf/ cp "Planning Mensuel JANV 2026.pdf" pdf/ # Lancer la conversion python3 planning2ics.py ``` Les fichiers `.ics` sont générés dans `ics/`, un par série (ex : `La_Traviata.ics`, `Falstaff.ics`). ### Cache Deux fichiers de cache sont créés dans `cache/` : | Fichier | Contenu | Quand le supprimer | |---|---|---| | `website_catalog.json` | Titres et descriptions du site web | Nouvelle saison ou mise à jour du site | | `series_mapping.json` | Mapping notes PDF → séries | Nouveaux PDFs avec de nouvelles œuvres | ```bash # Vider le cache manuellement rm cache/website_catalog.json cache/series_mapping.json ``` --- ## Application web ### Configuration Éditer `webapp/config.json` avant le déploiement : ```json { "ollama": { "url": "http://192.168.7.119:11434", "cluster_model": "qwen3.5:cloud", "local_model": "qwen3:8b" }, "site": { "calendar_url": "https://www.opera-orchestre-montpellier.fr/calendrier/?saisons=32669", "base_url": "https://www.opera-orchestre-montpellier.fr" }, "auth": { "session_secret": "une-cle-aleatoire-longue-et-unique", "users": [ {"username": "admin", "password": "votre-mot-de-passe"} ] } } ``` > **Important** : changer `session_secret` et le mot de passe avant tout déploiement. > Plusieurs utilisateurs peuvent être ajoutés dans le tableau `users`. ### Déploiement Docker Swarm ```bash # 1. Construire l'image (sur le nœud manager) docker build -t planning2ics:latest ./webapp # 2. Déployer le stack docker stack deploy -c webapp/docker-compose.yml planning2ics # 3. Vérifier le déploiement docker stack ps planning2ics ``` L'application est accessible sur `http://:8080`. ### Développement local ```bash cd webapp pip install -r requirements.txt # Adapter les chemins pour l'environnement local DATA_DIR=./data uvicorn app:app --reload --port 8000 ``` > En local, créer un fichier `webapp/config.json` et un dossier `webapp/data/`. ### Utilisation de l'interface web 1. **Connexion** avec les identifiants du `config.json` 2. **Glisser-déposer** les PDFs de planning (ou cliquer pour les sélectionner) 3. Cliquer sur **Convertir en ICS** — la progression s'affiche en temps réel 4. **Télécharger** les fichiers ICS par série, ou tout télécharger d'un coup 5. Les traitements précédents restent accessibles dans l'**Historique** Le bouton **Vider le cache** (section Paramètres) force un nouveau scraping du site et un nouveau clustering LLM au prochain traitement. --- ## Format des PDFs attendu Les PDFs doivent être les plannings mensuels de l'orchestre, avec le tableau structuré : | Jour | Date | Horaires | Titre | Lieu | Note | Déc. | Voy. | |---|---|---|---|---|---|---|---| | lun | 29/12 | 10:00 - 12:30 | Tutti Orch. | Beracasa (Le Corum) | PROGRAMME NOUVEL AN | 02:30 | | Le nom du fichier doit contenir le mois et l'année (ex : `Planning Mensuel JANV 2026.pdf`) pour la détection automatique de l'année. --- ## Séries parallèles Quand deux projets artistiques se déroulent en parallèle le même jour, le planning les distingue par les préfixes `(A)`, `(B)`, `(A')`, `(B')` dans le champ Note : ``` (A) : "Magdalena" (B) : "Élémentaire, mon cher !" ``` Ces séries sont identifiées séparément et génèrent chacune leur propre fichier ICS. --- ## À venir - Synchronisation directe avec Nextcloud via CalDAV - Script de mise à jour différentielle (gestion des PDFs "Modif") --- ## Dépendances principales | Bibliothèque | Usage | |---|---| | [pdfplumber](https://github.com/jsvine/pdfplumber) | Extraction des tableaux PDF | | [icalendar](https://github.com/collective/icalendar) | Génération des fichiers ICS | | [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/) | Scraping du site web | | [FastAPI](https://fastapi.tiangolo.com/) | Backend de la webapp | | [Ollama](https://ollama.com/) | Inférence LLM locale |