La plupart des lecteurs vivent probablement la même expérience que moi : chaque jour, de très (trop) nombreuses minutes gaspillées à aller voir d’éventuelles mises à jour sur différents sites et forums. Avec RSS et maintenant Atom, un premier pas a été fait pour résoudre ce problème, avec des agrégateurs spécialisés. Restaient deux soucis :
- Que faire des sites ne possédant pas de flux RSS ?
- L’information à surveiller reste dispersée à deux endroits différents: le client de courriel et l’agrégateur RSS.
Pour le second point, différentes solutions sont apparues, toutes avec des noms assez explicites (liste loin d’être exhaustive) : rss2mail, rss2email, rss-to-mail, et ma propre solution maildir-feed.
Restait le premier point. Jusqu’ici, ma solution (par exemple pour le site mangareader) était d’écrire un serveur web par source d’information qui faisait la transformation sous RSS. Solution vaguement satisfaisante jusqu’à un certain point que j’ai fini par atteindre, et qui m’a forcé à penser à une solution un peu plus générique, dont UA (Universal Aggregator) est le résultat.
Sommaire
UA est une solution très générique, dans le sens où il s’agit plus d’un méta-projet rassemblant plusieurs minuscules projets :
- tout d’abord, la définition d’un format (JSON) pour décrire un message, pour que les différents composants communiquent entre eux ;
- des producteurs, qui produisent des messages à partir d’une source d’information. Pour l’instant, seuls trois existent:
rss2json
(le nom se suffit à lui-même),mangareader2json
(l’équivalent à mon exemple plus haut) etipboard2json
(exporte les messages d’un forum IPBoard) ; - d’éventuels filtres pour transformer les messages. Pour l’instant un seul est présent,
ua-inline
, qui télécharge les images pour les introduire dans le message lui-même (pour les clients de courriels interdisant le téléchargement de ressources externes) ; - un consommateur, qui présente ces messages à l’utilisateur. Pour l’instant, un seul est présent,
maildir-put
, qui envoie les messages sous forme de courriel dans une boîte de type maildir ; - un « chef d’orchestre » pour faire le lien entre tout ce beau monde,
ggs
.
Configuration
La configuration se fait à partir du chef d’orchestre, ggs
. Il est donc nécessaire de le présenter un peu. Il s’agit d’un service lançant périodiquement des commandes, un peu comme cron. Trois points le différencient de ce dernier :
- il fonctionne à l’aide d’une logique d’intervalle entre deux lancements (« lance moi cette commande toutes les deux heures »), alors que cron fonctionne avec une logique d’évènement temporel (« lance moi cette commande toutes les heures impaires ») ;
- il sait limiter le nombre de processus lancés en parallèle (à l’aide de la directive de configuration
workers
) et le temps alloué à chaque tâche (timeout=
) ; - sa configuration est beaucoup plus riche: le fichier de configuration est un script shell.
Commençons simple : nous voulons recevoir par courriel tous les journaux de LinuxFr.org :
command 2000 "rss2json https://linuxfr.org/journaux.atom | maildir-put"
Cette ligne signifie « toutes les 2000 secondes » (environ une demi-heure), lance la commande rss2json https://linuxfr.org/journaux.atom | maildir-put
. Cette commande n’a rien de spécifique à ua : vous pouvez tout autant la lancer telle quelle dans le shell et aura le même résultat. Vous comprenez immédiatement que pour une autre source, il suffit donc de remplacer la partie gauche du pipe. Effectuons-le pour mangareader, par exemple:
command 2000 "mangareader2json http://mangareader.net/yotsubato | maildir-put"
command 2000 "mangareader2json http://mangareader.net/kuroshitsuji | maildir-put"
Ajoutons les news de LinuxFr.org, ainsi que le flux pour XKCD et SMBC. Pour peu que vous ayez beaucoup de sources d’informations actives, votre boîte risque d’être rapidement en désordre. Le choix de maildir (plutôt que d’envoyer les messages en SMTP) vient de cette problématique : la possibilité d’envoyer les messages dans des dossiers spécifiques. Par exemple, mettons les messages de LinuxFr.org dans le dossier DLFP, mangareader dans mangareader et XKCD et SMBC dans Fun :
command 2000 "rss2json https://linuxfr.org/journaux.atom | maildir-put -folder DLFP"
command 2000 "rss2json https://linuxfr.org/news.atom | maildir-put -folder DLFP"
command 2000 "mangareader2json http://mangareader.net/yotsubato | maildir-put -folder Mangas"
command 2000 "mangareader2json http://mangareader.net/kuroshitsuji | maildir-put -folder Mangas"
command 2000 "rss2json http://xkcd.com/atom.xml | maildir-put -folder Fun"
command 2000 "rss2json http://feeds.feedburner.com/smbc-comics/PvLb | maildir-put -folder Fun"
Tout ceci est un peu fastidieux à écrire. Aucun problème, le fichier de configuration est un script shell, il est tout à fait possible de factoriser :
rss() {
command 2000 "rss2json \"$1\" |"\
" maildir-put -folder \"$2\""
}
manga() {
command 2000 "mangareader2json http://mangareader.net/$1 | maildir-put -folder Manga"
}
rss https://linuxfr.org/journaux.atom DLFP
rss https://linuxfr.org/news.atom DLFP
manga yotsubato
manga kuroshitsuji
rss http://xkcd.com/atom.xml Fun
rss http://feeds.feedburner.com/smbc-comics/PvLb Fun
Dernier souci : le client de courriel n’affiche pas les images par défaut, ce qui est particulièrement gênant pour XKCD et SMBC. Si vous avez suivi la description plus haut, vous aurez vu qu’il y a un filtre pour ça :
rss() {
command 2000 "rss2json \"$1\" | ua-inline |"\
"maildir-put -folder \"$2\""
}
manga() {
command 2000 "mangareader2json http://mangareader.net/$1 | maildir-put -folder Manga"
}
rss https://linuxfr.org/journaux.atom DLFP
rss https://linuxfr.org/news.atom DLFP
manga yotsubato
manga kuroshitsuji
rss http://xkcd.com/atom.xml Fun
rss http://feeds.feedburner.com/smbc-comics/PvLb Fun
Et voilà le résultat :
Installation
Pour les utilisateurs d’Arch, un PKGBUILD est disponible sur AUR. Pour les autres, rien de plus simple :
git clone https://github.com/sloonz/ua.git
make && sudo make install
Vous aurez besoin de libxml et go ; les scripts mangareader2json et ipboard2json nécessitent Python 3, PyQuery et aiohttp. Le tout est installé dans /usr/local
; vous pouvez polluer /usr
en ajoutant PREFIX=/usr
à make install
.
Licence
Ce logiciel est distribué sous licence MIT. Quant au nom, toute suggestion pour en trouver un meilleur est la bienvenue.
Aller plus loin
- Le projet sur github (236 clics)
# Bravo
Posté par barmic . Évalué à 4.
Je ne l'ai pas essayé mais ça a l'air très intéressant comme projet.
Ça a l'air très flexible et assez facilement extensible, y a t'il une description des formats d'entrée/sortie des différents outils ?
Qui s'occupe de la dé-duplication des items ? maildir-put ?
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Bravo
Posté par Moonz . Évalué à 5. Dernière modification le 19 mars 2014 à 09:48.
La description commune est dans maildir-put (ou
man maildir-put
)Oui. Dans mon précédent projet c’était fait au niveau de rss2maildir (dans mon ancien projet producteur et consommateur étaient mélangés, la seule séparation étant faire entre le spawner et le reste), et ça c’est révélé une très mauvaise décision, m’empêchant de coder simplement une source pour medscape (ce que je vais faire ce week end pour ua).
Ceci dit si d’autres consommateurs voient le jour, il semblerait logique d’en faire un filtre.
# Complément d’information
Posté par Moonz . Évalué à 3.
Pour information, si vous voulez utiliser ua-inline et que votre client mail est Geary, vous devez utiliser la 0.6 : https://bugzilla.gnome.org/show_bug.cgi?id=726468
# Et vers rss?
Posté par NilugeKiWi . Évalué à 1.
Je suppose qu'il est ensuite relativement facile de créer un 2em "consommateur" qui génère des rss normalisés?
Est-ce facile d'écrire une telle chose avec un flux rss par input? ou tag/catégorie que des inputs ou filtres pourraient créer?
(Ce mécanisme de tag est présent dans logstash, qui est un aggrégateur de logs (il fonctionne de façon étrangement similaire à UA: des inputs, des filtres, des outputs; d'ailleurs UA pourrait certainement être réécrit en en logstash).
[^] # Re: Et vers rss?
Posté par barmic . Évalué à 2.
Je pense que ce que tu cherche à faire n'est pas possible facilement. RSS c'est du polling et là il faudrait que ton consommateur fasse du push. Pour reproduire un agrégateur classique il faut créer un consommateur qui stocke les flux dans une base de données (SQL, noSQL, fichier,…) et que tu crée un client RSS capable d'aller se plugger sur ces données.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Et vers rss?
Posté par Moonz . Évalué à 2.
Oui, même si j’ai du mal à voir l’intérêt, ça donnerait
rss2json http://linuxfr.org/news.atom | json2rss
:)Je ne suis pas sûr d’avoir bien compris ta question…
[^] # Re: Et vers rss?
Posté par barmic . Évalué à 3.
Ça peut avoir un intérêt si tu fait des traitement dans le pipe :
Et paf tu as tes flux anorexiques qui reprennent des couleurs ^
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Et vers rss?
Posté par FabienC . Évalué à 2.
Ca peut avoir un interet pour des sites qui ne proposent pas de flux RSS… Par exemple mangaReader :D
[^] # Re: Et vers rss?
Posté par NilugeKiWi . Évalué à 1.
L'intérêt comme dit plus haut c'est 1/ de pouvoir générer des flux rss pour des sources qui n'en ont pas, et 2/ pouvoir enrichir, ou filtrer des items d'un flux rss, et 3/ avoir des flux rss en sortie, pour pouvoir brancher n'importe quel client rss, que je préfère pour l'instant encore à une sortie mail.
L'output actuel c'est un maildir, avec un sous répertoire par input, par exemple. Je souhaitais en savoir plus sur comment les items d'inputs sont dispatchés dans tel ou tel répertoire du maildir, afin de savoir s'il était facile de faire pareil pour générer des sorties rss.
Mon objectif global est de savoir si je peux remplacer mes scripts perso en python qui font de la création et modification de flux rss par UA, histoire de factoriser les efforts.
[^] # Re: Et vers rss?
Posté par Moonz . Évalué à 2. Dernière modification le 21 mars 2014 à 13:33.
Grosso modo le dispatch se fait par flux.
Tu as
Qui revient à
Qui dit de mettre le flux des actualités de linuxfr dans le dossier DLFP.
Par contre tous les items du flux sont forcément dans DLFP. Avec grep tu devrait être capable de séparer les deux, par exemple séparer les articles firefox du reste :
# Temps-réel?
Posté par NilugeKiWi . Évalué à 1.
Les flux RSS/atom ont la possibilité de pusher en temps-réel les nouvelles entrées PubSubHubHub; assez souvent on perd ce genre de fonctionnalités dans tous les outils du genre qui essayent d'abstraire les flux RSS en une notion plus vague et générique.
Tous les exemples montrent du polling bête et méchant sur les inputs. Une évolution future gérant des inputs en temps réel est-elle prévue? Ou bien est-ce que c'est fondamentalement incompatible avec les choix architecturaux de UA?
De même une fois qu'on a des inputs en temps réel, on voudrait les outputs aussi (et dans le cas d'un output RSS, réimplémenter un serveur PubSubHubHub) (pour les output mails ce serait certainement plutôt au serveur imap de surveiller le FS je suppose).
[^] # Re: Temps-réel?
Posté par Moonz . Évalué à 3.
Pour les input en temps réel il « suffirait » de coder un
pubsubhubhub2json
qui fasse un flux continu. Grosso-modo ça donnerait:où
pubsubhubhub2json
serait un serveur web qui enverrait sur stdout et dans le bon format toutes les notifications qu’il reçoit.Donc pour la première question oui c’est possible, pour la seconde question (prévu à court terme) très certainement que non, vu qu’à ma connaissance les seuls services proposant pubsubhubhub sont des agrégateurs qui font eux-même du polling, ce qui limite fortement l’intérêt de la chose :)
Pour les output c’est effectivement le rôle du serveur IMAP de gérer ça ; je sais pas comment c’est implémenté dans dovecot mais il le fait très bien : dès que j’ajoute un mail il apparait dans mon client mail.
[^] # Re: Temps-réel?
Posté par barmic . Évalué à 2.
Je me suis probablement planté, mais j'ai pas vu où c'était géré par rapport au nombre de processus maximum lancé. Pour moi il faudrait décompter ce processus.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Temps-réel?
Posté par Moonz . Évalué à 2. Dernière modification le 19 mars 2014 à 18:09.
Il prendrait un slot effectivement, mais vu que le nombre de workers est configurable ce n’est pas un vraiment un problème.
Vu que le nombre de workers par défaut est 5, il suffit d’ajouter
workers=6
dans le fichier de conf :)(ou de se dire que 4 pour le reste des processus est suffisant)
[^] # Re: Temps-réel?
Posté par NilugeKiWi . Évalué à 1.
L'intérêt de PubSubHubhub (PuSH) c'est que c'est chainable: même si la source originelle n'est pas compatible, le next hop dans la chaine peut faire du polling une fois pour toutes: les autres acteurs pourront ensuite utiliser PuSH sur ce next hop, ou sur un suivant, et ne pas spammer à nouveau la source originelle à coup de polling. UA ressemble bien à un agrégateur, du coup je pense que c'est bien utile qu'il gère PuSH.
Donc ça a l'air faisable, grâce aux pipes ou sockets qui peuvent marcher en mode stream. Parfait.
[^] # Re: Temps-réel?
Posté par barmic . Évalué à 2.
Pour faire ça, je présume qu'il faut commencer par avoir un démon client PubSubHubHub. De ce que je vois ggs n'est pas vraiment fait pour lancer un démon mais ça ne doit pas être monstrueux (par rapport à créer le client PSHH), ensuite de l'autre coté c'est pareil, il te faut un démon et faire en sorte qu'il lise sur une socket unix ou un pipe nomé.
AMHA avis le plus gros boulot c'est d'avoir d'écrire le client et le serveur PSHH.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Temps-réel?
Posté par rakoo (site web personnel) . Évalué à 3.
PSHB (Le nom correct est PubSubHubBub).
Ouais, ce nom est relativement naze.
[^] # Re: Temps-réel?
Posté par Schnouki (Mastodon) . Évalué à 1.
En fait le nom correct est PubSubHubbub (pas de B majuscule), et c'est généralement abrégé en PuSH.
# Intérêt du JSON
Posté par rakoo (site web personnel) . Évalué à 2.
Super projet ! J'adore l'idée de séparer les bouts de logique et de faire communiquer sur
stdout
. Philisophie UNIX toussa.Par contre je m'interroge sur l'intérêt de mettre une couche intermédiaire de JSON. À ce que je sache, le JSON n'apporte rien fonctionnellement ou techniquement par rapport aux entrées qui sont déjà formatées et normalisées, que ce soit RSS ou Atom.
[^] # Re: Intérêt du JSON
Posté par Moonz . Évalué à 8.
Pour parser du JSON vers une structure native au langage (généralement dictionnaire ou objet anonyme + liste), c’est à peu près une ligne de code de type
json_decode
dans quasiment tous les langages, le plus souvent intégré dans la lib standard. Pour RSS/Atom c’est déjà plus compliqué, surtout que chacun de ces deux formats a plusieurs version. Et à l’intérieur d’une seule version d’un format tu as des subtilités peu intéressantes que je ne veux pas me trimballer d’un bout à l’autre du pipe (par exemple la différence entre publication date, creation date et modification date: typiquement un truc que le producteur veut abstraire pour simplifier tout le reste de la chaine de traitement).Niveau production, le JSON est tout aussi simple, un
json_encode
d’une structure langage du standard (la même quejson_decode
) et c’est plié.Par comparaison avec RSS/Atom, dans la plupart des langages dans la lib standard tu as au mieux une API type DOM pour faire du XML. Et lire/produire du RSS/Atom à partir d’une simple API type DOM, ce n’est certes pas la fin du monde, mais c’est infiniment plus compliqué et ce n’est certainement pas quelque chose que tu veux refaire n fois un dans un projet composé d’une multitude d’exécutables différents et indépendants et même écrits dans des langages différents.
tl;dr: haters gonna hate, mais aujourd’hui en 2014 JSON a gagné haut la main et c’est LE langage d’interopérabilité par excellence. On ne devrait plus justifier l’utilisation de JSON mais bien plutôt sa non-utilisation, et dans le cas de la non-utilisation la justification devrait être solide.
[^] # Re: Intérêt du JSON
Posté par rakoo (site web personnel) . Évalué à 3.
Oh oui je suis tout à fait d'accord, le JSON est bien plus facile à utiliser dans n'importe quel langage puisqu'il y aura à peu près tout le temps une librairie pour le faire. C'est aussi plus agréable de bosser avec.
Je demandais ça parce que le RSS et l'Atom ont déjà un format, qui en plus est fait pour les traitements automatisés. Ce format est normalisé et spécifié un peu partout (contrairement au tien qui bien que simple, n'existe que sur un README en plus du code) et pour lequel tu trouveras déjà de la documentation et des outils.
Si tout le monde utilisait des flux RSS en JSON, ça serait quand même plus simple.
[^] # Re: Intérêt du JSON
Posté par NilugeKiWi . Évalué à 1.
Il faudrait peut-être alors normaliser ce JSON, et/ou regarder ce qui existe déjà, comme (au hasard) JSON Activity Streams.
# interfacer avec weboob ?
Posté par ZeroHeure . Évalué à 3.
Je pensais bricoler la même chose en partant de Weboob.
Ce srait pas mal de les interfacer pour pouvoir utiliser UA sur des sites avec authentification ou tout bêtement pour recevoir les infos weboob dans son courriel.
"La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay
[^] # Re: interfacer avec weboob ?
Posté par Moonz . Évalué à 2.
Un producer pour boobank est déjà prévu ;)
[^] # Re: interfacer avec weboob ?
Posté par laurentb (site web personnel) . Évalué à 1.
Le RSS est géré par le module Newsfeed.
L'envoi vers les mails est possible avec monboob.
Une application comme boobmsg peut utiliser divers formateurs, dont JSON.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.