Synchroniser Delicious et WordPress: l’API Delicious

Troisième volet du dossier sur Delicious. Cette fois, je vais m’intéresser à l’API de cet outil, c’est-à-dire toutes les ressources s’adressant aux développeurs pour effectuer la liaison entre le bookmarkeur et WordPress.
L’occasion de voir également, si les choses ont évolué depuis la version 2.0.

Globalement Delicious propose 3 types d’outils:

  • Des badges: petits gadgets affichant des liens du type Bookmark this avec de beaux logos,
  • Des scripts (javascript) pour afficher la liste des tags, ou des liens sur un blog,
  • Une API permettant d’accéder aux objets de la base de Delicious.

Les badges

Il s’agit, pour résumer, d’afficher un logo et une phrase, pour

  • soit enregistrer la page courante dans Delicious,
  • soit indiquer le lien vers nos favoris.

Rien n’a changé par rapport à la version précédente de Delicious. Le site propose du code HTML ou Javascript pour la sauvegarde d’un favoris, ou l’affichage d’une sorte de fiche d’identité Delicious pointant sur nos favoris.

Delicious network badge
Delicious network badge

Dans les deux cas, le code fournit peut directement être copier/coller dans une template d’un thème WordPress, ou être encapsulé dans un widget, par exemple, si votre sidebar est dynamique.

Attention cependant, j’ai constaté que les temps de réponse des scripts Javascript n’étaient pas extraordinaires. L’utilisation de ces scripts peut donc générer quelques lenteurs d’affichage sur un blog.

Affichage des informations de Delicious dans WordPress

Là encore, rien de nouveau. Deux listes sont proposées: la linkroll et la tagroll. La première est simplement une liste de liens, la seconde est un nuage des tags Delicious.
Dans les deux cas, le script javascript proposé est paramétrable grâce à une petite interface simple et rapide.

Flux RSS

L’une des API proposée par Delicious s’appuie sur les flux RSS. Delicious utilise ces flux pour publier les changements intervenants dans sa base. La syntaxe est assez simple:

  • http://feeds.delicious.com/v2/rss/recent donnera les derniers liens ajoutés à la base,
  • http://feeds.delicious.com/v2/rss/{utilisateur}/{tag} donnera les liens de l’utilisateur spécifié, et classés dans le tag donné en paramètre

Les résultats obtenus sont au format XML, dans les standards des flux RSS. Le code ci-dessous donne une idée des informations disponibles dans le flux:

1
2
3
4
5
6
7
8
9
10
11
12
13
   <item>
      <title>TemplateLite.com</title>
      <pubDate>Wed, 04 Mar 2009 14:11:02 +0000</pubDate>
      <guid isPermaLink="false">http://delicious.com/url/022b7338a028b415b0140b6b4da54167#georjon</guid>
      <link>http://www.templatelite.com/</link>
      <dc:creator><![CDATA[georjon]]></dc:creator>
      <comments>http://delicious.com/url/022b7338a028b415b0140b6b4da54167</comments>
      <wfw:commentRss>http://feeds.delicious.com/v2/rss/url/022b7338a028b415b0140b6b4da54167</wfw:commentRss>
      <source url="http://feeds.delicious.com/v2/rss/georjon">georjon's bookmarks</source>
      <description>Professional Wordpress Themes - Free and Quality Wordpress Templates</description>
      <category domain="http://delicious.com/georjon/">wordpress</category>
      <category domain="http://delicious.com/georjon/">themes-templates</category>
    </item>

Les avantages

  • Le format est standard (XML / RSS),
  • Tous les informations liées au favori y sont,
  • WordPress intègre des outils pour exploiter ce type de flux (la classe MagPieRSS dans le fichier wp-includes/rss.php).

Les inconvénients

  • La méthode ne permet pas de sauvegarder tous les liens, puisque le nombre de liens récupérables est limité (entre 1 et 100). Difficile d’utiliser cette méthode pour réaliser une synchronisation complète,
  • Cette API n’est pas totalement adaptée à une synchronisation incrémentale non plus. En effet, elle ne permet que de récupérer les n derniers liens, et pas les derniers liens depuis une date précise. Donc une synchronisation incrémentale est possible, mais elle ne sera pas sûre à 100%.

Remarque au sujet des badges

L’utilisation directe des scripts Javascript pour l’affichage des badges peut générer des latences dans l’affichage du blog. Une façon de contourner ce problème, pourrait être d’utiliser l’API RSS et de placer les informations collectées en cache.
La requête http://feeds.delicious.com/v2/{format}/userinfo/{username} permet en effet de récupérer toutes les informations fournit habituellement par les badges.

L’API HTTP

La seconde API proposée se base sur des requêtes HTTP.

Les requêtes

Le principe est simple. Delicious met à notre disposition une suite d’URL, pour requêter la base de liens. La structure des URL est toujours la même:

https://api.del.icio.us/v1/{objet à récupérer}/{action}?{options}

Par exemple, pour avoir la liste des derniers liens, la commande sera :

https://api.del.icio.us/v1/posts/get?

Si nous utilisons cette URL dans un navigateur, celui-ci nous demandera un nom d’utilisateur et un mot de passe. Hors de question d’avoir ce type de réponse si l’on veut automatiser quelque chose. Pour éviter ces cela, la syntaxe complète sera donc:

https://{username}:{password}@api.del.icio.us/v1/{object type}/{action}?{options}

Nous pouvons également passer des paramètres aux URLs pour spécifier des dates, ou des filtres.

Je ne vais pas lister toutes les requêtes, mais nous avons par exemple:

  • https://api.del.icio.us/v1/posts/all? permet de récupérer tous les liens,
  • https://api.del.icio.us/v1/posts/all?tag=wordpress permet de récupérer tous les liens dont la liste de tags contient WordPress,
  • https://api.del.icio.us/v1/tags/get donnera la liste des tags, avec le nombre d’utilisation de chacun,
  • https://api.del.icio.us/v1/tags/bundles/all? renverra la liste des bundles, avec les tags associés.

Résultats des requêtes

Les résultats des requêtes sont au format XML. L’exemple ci-dessous, est extrait de la documentation de Delicious:

$ curl https://user:passwd@api.del.icio.us/v1/posts/recent
 
<posts tag="" user="user">
  <post href="http://www.weather.com/" description="weather.com"
  hash="6cfedbe75f413c56b6ce79e6fa102aba" tag="weather reference"
  time="2005-11-29T20:30:47Z" />
    ...
  <post href="http://www.nytimes.com/"
  description="The New York Times - Breaking News, World News & Multimedia"
  extended="requires login" hash="ca1e6357399774951eed4628d69eb84b"
  tag="news media" time="2005-11-29T20:30:05Z" />
</posts>

Quelques commentaires par rapport à cet exemple:

  • Les valeurs de temps sont toujours exprimées de la même façon: yyyy-mm-ddThh:ii:ssZ. Il s’agit de l’heure UTC, c’est-à-dire de l’heure GMT, sans les changements « heure d’hiver/heure d’été » (DST Daylight Saving Time). Cette convention est assez pratique, parce qu’elle nous évite la gestion des fuseaux horaires,
  • Le champ hash est une sorte d’identifiant unique. Il est utilisé notamment avec les commandes permettant de récupérer les dernières modifications depuis une date.
  • Aucune requête ne permet de faire une relation directe entre les liens et les bundles. Il faut obligatoirement passer par les tags.

Avantages de cette API:

  • Elle est simple à utiliser: les requêtes sont rudimentaires, et le résultat est au format XML. En travaillant avec PHP 5, le résultat peut être analysé en quelques lignes de code seulement,
  • Elle donne accès à l’intégralité de la base, c’est-à-dire tous les liens, mais également les tags, et les bundles,
  • En plus de la consultation, elle autorise également des modifications (ajout de liens par exemple),

Inconvénients:

  • Pour éviter que les requêtes n’écroulent leurs machines, les gens de Delicious ont posé des sécurités qui sont, me semble-t-il, un peu « sensibles ». Si vous effectuez deux ou trois fois la même requête à quelques secondes d’intervalle, le service vous renverra très vite un beau message du type « Service indisponible, ré-essayez ultérieurement ». Je comprends tout à fait les problématiques de régulation de la charge, je le trouve simplement un peu trop sensible.
  • Les fonctions permettant de détecter les mises à jour, donnent bien la liste des liens ajoutés ou modifiés, mais ne donnent pas les liens effacés. Une vrai synchronisation bi-directionnelle sera donc plus difficile à développer.

Exemple d’utilisation avec PHP

En fonction de ce que nous venons de dire précédemment, pour notre script PHP, il nous faut:

  • de quoi lancer la requête HTTP et récupérer le résultat,
  • les outils pour interprêter le résultat (fichier XML).

PHP offre des fonctions de parsing des fichiers XML depuis la version 4, mais elles n’étaient pas, dans cette version, très pratique à utiliser. Depuis la version 5, nous avons à notre disposition un ensemble de fonctions intitulé SimpleXML, beaucoup plus pratiques.

Deux approches principales:

  • Nous séparons la phase de lecture, de la phase d’analyse,
  • Nous regroupons toutes les opérations.

La seconde solution est assez simple, puisqu’elle tient en une seule ligne:

$username= ... ;
$password= ... ;
$xml_list = simplexml_load_file('https://'.$username.':'.$password.'@api.delicious.com/v1/posts/all?');

La commande simplexml_load_file va lancer la requête, récupérer une chaîne de caractères au format XML, parser cette chaîne, et stocker les différents éléments dans un objet.

Je préfère la seconde solution:

$cache_file = ... ;
$username= ... ;
$password= ... ;
$xml_string = file_get_contents('https://'.$username.':'.$password.'@api.delicious.com/v1/posts/all?');
file_put_contents($cache_file, $xml_string);
$xml_list = simplexml_load_string($xml_string);

Dans cette solution, nous séparons la requête de l’analyse. Les opérations ne sont pas plus compliquées, mais elles nous permettent, par exemple de stocker le résultat de la requête dans un système de cache (ligne 5).
La fonction simplexml_load_string fonctionne exactement comme la fonction précédente.

Une fois le résultat parsé, il ne nous reste plus qu’à l’analyser ou le « transformer »:

foreach ($xml_list->post as $link) {
    $attrs     = $link->attributes();
    $href      = (string)$attrs->href;
    $link_name = (string)$attrs->link_name);
    echo '<a title="'.$link_name.'" href="'.$href.'">'.$link_name.'</a>';
}

Conclusion

Delicous propose un ensemble d’outils assez complets. Pour notre synchronisation, nous pouvons retenir:

  • L’API HTTP permet une synchronisation complète des liens, et des tags
  • Les synchronisations incrémentales peuvent être envisagées avec l’API HTTP ou les flux RSS.

Ces outils comportent cependant quelques petits défauts: d’abord, ils ne permettent pas de détecter les effacements, ce qui est assez pénalisant pour une synchronisation. Ensuite, dans le cas de l’API HTTP le système de contrôle est particulièrement sensible, et obligera à limiter les requêtes, où à gérer un système de cache.
Reste que disposer d’une API ne suffit pas forcement, pour une synchronisation avec WordPress, il faut regarder:

  • Quel identifiant utiliser?
  • La gestion des dates/heures (UTC pour Delicious, mais locale pour WordPress,
  • Comment gérer les tags et les bundles

La suite dans le prochain article.