XMLTV
J’ai eu l’idée de cette bibliothèque parce que nous voulions annuler notre abonnement au guide TV papier. Avec de jeunes enfants, ma femme et moi avons rarement le temps de regarder la télévision en direct — elle rattrape souvent les émissions en replay et consulte le programme TV une ou deux fois par semaine.
XMLTV est un format XML pour les données de guide électronique des programmes (EPG). J’ai écrit cette bibliothèque parce qu’il n’existait à l’époque aucune crate Rust pour lire ou écrire des fichiers XMLTV. Elle s’appuie sur serde pour la sérialisation et la désérialisation, et aplatit les balises vides comme <new/> en booléens pour réduire le code répétitif. Pour les gros fichiers, les programmes peuvent être lus un par un plutôt que chargés entièrement en RAM.
CLI
Le binaire xmltv est le compagnon tout-en-un. Il lit un fichier local (ou - pour l’entrée standard, ex. curl … | xmltv - -f json), applique une chaîne de filtres et écrit le résultat dans le format choisi. Installation : cargo install xmltv-cli ou récupérez un binaire depuis la page des releases.
Entrée & sortie
| Option | Description |
|---|---|
FICHIER | Positionnel. Fichier XMLTV d’entrée, ou - pour lire depuis stdin. |
-l, --load <FICHIER> | Charge les valeurs par défaut depuis un fichier de configuration JSON. Les options en ligne de commande sont prioritaires. |
-m, --merge <FICHIER> | Fusionne un autre fichier XMLTV. Répétable. |
-o, --output <FICHIER> | Écrit dans un fichier au lieu de stdout. |
-f, --format <FMT> | xml (défaut), json, ical, atom, jsonfeed. |
--pretty | Indente la sortie XML et JSON. |
Filtrage
| Option | Description |
|---|---|
-c, --channels <LISTE> | Liste des chaînes à conserver séparées par des virgules (-c tf1,m6,Arte). Utilisez le préfixe id: pour un match sur l’identifiant uniquement. ? ouvre la sélection interactive dans le TUI. |
-d, --days <N> | Conserve aujourd’hui + les N jours suivants. |
--date <AAAA-MM-JJ> | Conserve les programmes commençant à cette date. |
-s, --search <REQUÊTE> | Recherche de sous-chaîne insensible à la casse sur le titre. |
--category <CAT> | Conserve les programmes de cette catégorie. Répétable, logique OU. |
--time-slot <PLAGE> | HH:MM-HH:MM, ou Mon-Fri 18:00-23:00, ou Sat,Sun 00:00-23:59. Répétable. |
--time-slot-strict | Le programme doit être entièrement contenu dans la plage. |
--exclude-time-slot | Inverse la logique de plage horaire (exclure au lieu d’inclure). |
--new-only | Conserve uniquement les programmes marqués <new/>. |
--no-reruns | Écarte les programmes marqués <previously-shown/>. |
--lang <LANG> | Préfère les titres/descriptions dans cette langue quand plusieurs sont proposés. |
--min-rating <0.0–1.0> | Note minimum en étoiles sous forme de fraction (0.6 ≈ 3/5). |
--rating-system <SYS> | Restreint --min-rating à un système de notation précis. |
Transformation
| Option | Description |
|---|---|
--cleanse <ÉLÉMENTS> | Supprime les champs volumineux pour réduire la sortie. Valeurs : credits (ou un sous-ensemble plus fin : directors, actors, writers, adapters, producers, composers, editors, presenters, commentators, guests), categories, new, countries, keywords, sub-titles, languages, videos, audios, subtitles, last-chances, descriptions, dates, origin-languages, length, premieres, previously-showns, ratings, star-ratings, reviews, images, episode-nums, icons, urls. |
-t, --timezone <TZ> | Fuseau horaire de sortie : utc (défaut), local, ou un décalage comme +0100. |
--sort | Trie les programmes par heure de début à l’intérieur de chaque chaîne. |
--deduplicate | Supprime les doublons exacts (même chaîne, même début, même titre). |
--tag <RÈGLE> | Étiquetage automatique via TAG:CHAMP:MATCH:MOTIF (ex. --tag "News:title:contains:Journal"). CHAMP = title|description|channel, MATCH = contains|starts-with|ends-with. Répétable. |
Inspection & outillage
| Option | Description |
|---|---|
--list-channels | Affiche l’identifiant et le nom d’affichage des chaînes, puis quitte. |
--stats | Récapitulatif : nombre de chaînes, de programmes, plage de dates, taille du fichier. |
--validate | Vérifie la structure du fichier et signale les erreurs sans produire de sortie. |
--epg | Ouvre l’EPG embarqué en TUI (voir plus bas). |
--past | Inclut les jours passés dans la vue EPG. |
--completions <SHELL> | Génère le script d’auto-complétion pour bash, zsh ou fish. |
Exemples
# JSON, les 3 prochains jours, trois chaînes uniquement
xmltv listings.xml -f json -d 3 -c "TF1.fr,France2.fr,Arte.tv"
# Soirées en semaine + week-ends complets
xmltv listings.xml --time-slot "Mon-Fri 18:00-23:00" --time-slot "Sat,Sun 00:00-23:59"
# Fusion de deux sources, sans les métadonnées volumineuses
xmltv main.xml -m secondary.xml --cleanse "credits,images,episode-nums"
# Extrait les matchs de football dans un fichier de calendrier
xmltv listings.xml -s "Football" -f ical -o sports.icsEPG en TUI embarqué
xmltv … --epg ouvre un EPG interactif en terminal construit avec ratatui et crossterm. Il affiche les mêmes données que la sortie CLI mais sous forme de grille navigable : chaînes à gauche (avec icônes quand le terminal supporte les protocoles graphiques Kitty, Sixel ou half-blocks via ratatui-image), axe temporel en haut, blocs de programmes au centre et panneau de détails pour la sélection courante. Les icônes de chaînes sont préchargées en parallèle avec rayon avant l’entrée dans l’écran alternatif, ce qui garde le défilement fluide. Le popup de sélection de chaînes (-c ?) sert aussi de filtre interactif pour la CLI.
Page web statique
Pour partager la grille dans un navigateur (PC, tablette, mobile), le dépôt embarque une page statique sans dépendances : un index.html, un styles.css, un app.js, ni framework ni bundler. Elle lit un fichier xmltv.json produit par la CLI :
xmltv listings.xml -f json -d 3 -o xmltv.json --prettyPlacez xmltv.json à côté de index.html, servez les deux par n’importe quel serveur HTTP statique (python3 -m http.server, Nginx, Caddy, GitHub Pages, S3), et la page s’affiche. Fonctionnalités :
- Grille PC de bureau — colonne de chaînes fixée, blocs de programmes positionnés en absolu, ligne rouge verticale pour l’instant présent, teinte rouge sur les programmes en direct. Un clic sur un bloc ouvre un tiroir de détails.
- Mobile — sous 768 px, la grille bascule en liste verticale par chaîne ; le tap ouvre une fiche détaillée en plein écran.
- Thèmes — Catppuccin Mocha / Latte avec un sélecteur
Système/Sombre/Clairpersisté danslocalStorage. - Navigation — flèches jour par jour, bouton « Live » qui centre la vue sur l’heure actuelle, filtre multi-sélection de chaînes, recherche sur titre/description avec surlignage.
- Bascules d’affichage — l’heure secondaire de chaque bloc alterne entre heure de fin (
21:45) et durée (1h30). Les timestamps sont ancrés en UTC dans le JSON et rendus dans l’heure locale du navigateur.
Un build.sh optionnel (un pipeline awk d’environ 40 lignes — sans npm, sans node) inline le CSS et le JS dans un unique dist/index.html pour distribuer sur un routeur OpenWRT ou autre ; seul xmltv.json reste externe.