Votre premier script GreaseMonkey : urlExpander

Pré-requis pour ce tutoriel

  • Des connaissances en Javascript
  • Firefox (une version récente de préférence)
  • L’extension GreaseMonkey de Firefox (nous vous épargnons les détails sur l’installation)

Présentation de GreaseMonkey

GreaseMonkey est une extension permettant d’exécuter le Javascript de votre choix au chargement d’une page web afin d’en modifier le comportement, l’aspect ou bien de proposer de nouvelles fonctionnalités. Il existe des scripts GreaseMonkey pour pratiquement tous les sites « célèbres ». Ainsi certains scripts permettent sur Facebook d’afficher l’image d’un contact en plus grand au survol de celle-ci, d’autres suppriment les commentaires (inutiles) sous les vidéos Youtube, de nombreux scripts permettent de tricher sur des sites jeux en ligne en ajoutant du contenu tiré d’une base de données tierce. Les exemples ne manquant pas, nous allons arrêter ici pour cette liste non exhaustive.

Présentation du script urlExpander

Le but du script que nous allons développer ici va être de « traduire » les urls raccourcies qui foisonnent sur Twitter et consort. De cette manière, on pourra se faire une idée du type de site vers lequel on se dirige et éviter ainsi de se retrouver sur un site de phishing. Pour faire simple, notre script va uniquement traduire les urls raccourcies venant de bit.ly. Une fois que vous aurez compris le principe, vous pourrez parfaitement étendre le script. L’idée ici est de comprendre GreaseMonkey peut améliorer votre expérience utilisateur sur le web.

Étape 1 : Le script qui dit bonjour à tout le monde !

Pour commencer on va faire simple et se contenter d’afficher le classique « Hello World! » que tout le monde connaît si bien. L’objectif ici est de comprendre comment installer un script et comment celui-ci s’exécute. Pour ce faire vous allez devoir créer un fichier Javascript que vous nommerez « urlExpander.user.js », nous insistons sur la présence du « user » car GreaseMonkey va reconnaître votre script grâce à cela. Ajoutez dans ce fichier le code suivant :

1.// ==UserScript==2.// @name           Epershand urlExpander
3.// @namespace      https://www.epershand.net
4.// @description    Traduit les urls raccourcies et affiche le lien entier
5.// @include        https://twitter.com/*
6.// ==/UserScript==
7. 
8.alert('Hello World!');

Maintenant que vous avez créé votre fichier JS, faites un glisser/déplacer de ce fichier vers la fenêtre de Firefox, vous devriez voir apparaître le message suivant :

greasemonkey-installation-script

Une fois votre script installé il vous suffit d’aller sur Twitter pour voir s’afficher le résultat de notre premier script :

greasemonkey-hello-world

Si vous avez été attentif vous aurez remarqué que le script contient des commentaires un peu particuliers @include (et son contraire @exclude). Ces deux types de commentaires permettent de définir sur quels sites le script est autorisé à s’exécuter et sur lesquels il n’est pas autorisé. De cette manière vous pourrez cibler Twitter si vous souhaitez que le script s’exécute uniquement dessus.

  Introduction à la colorisation sous Photoshop

Étape 2 : Lire la documentation de l’API de bit.ly

Pour être en mesure de traduire les urls raccourcies par bit.ly il va nous falloir dialoguer avec l’API de bit.ly, jetons donc ensemble un œil à la fonction « expand » de l’API de bit.ly (en).

La documentation nous apprend que la fonction expand :

  • est accessible via une adresse de la forme : http://api.bit.ly/expand?version=2.0.1&shortUrl=<url>&login=<login>&apiKey=<api_key>
  • reçoit en paramètre une shortUrl ou bien un hash (le code bizarre qu’on retrouve après l’url raccourcie)

Dans le cadre du développement d’une vraie application utilisant l’API bit.ly je vous conseillerai de créer un compte afin d’obtenir votre clef personnelle vers l’API. Dans notre exemple nous nous contenterons d’utiliser le compte de test que bit.ly utilise dans sa doc, mais chute faut pas le dire 

Étape 3 : Utiliser l’API de bit.ly

Vous pouvez maintenant tester l’API en cliquant sur le lien suivant : http://api.bit.ly/expand?version=2.0.1&shortUrl=http://bit.ly/4s0bFQ&log[…]5f52f629d2d71bf07. Vous devriez obtenir le résultat suivant :

01.{
02."errorCode": 0,
03."errorMessage": "",
04."results": {
05."4s0bFQ": {
06."longUrl": "https://www.epershand.net"
07.}
08.},
09."statusCode": "OK"
10.}

Étant donné que l’API a été développé pour être appelée par des programmes tiers (un peu comme si on appelait un web service plus light), les données que celle-ci renvoie doivent être dans un format simple et souple. C’est pourquoi le format JSON est utilisé ici. Par ailleurs le format JSON est très facilement manipulable avec du Javascript, et c’est justement ce que nous allons faire !

Certains d’entre vous se demandent sans doute comment nous allons pouvoir appeler l’API avec du Javascript et pouvoir traiter le résultat, et bien dans ce cas l’invite ces personnes à se documenter un peu sur Ajax et l’utilisation de l’objet XmlHttpRequest.

Pour les autres et bien sachez qu’il suffit de faire une simple requête GET sur l’URL de l’API et d’interpréter les résultats renvoyés par bit.ly avec un eval, et comme nous voulions afficher en clair les urls cibles pour nos utilisateurs, il nous suffira de faire quelques rechercher/remplacer en Javascript dans la page pour obtenir le résultat escompté ! Allez en avant !

Étape 4: Développement du script

Et là nous sentons que vous vous demandez si l’on va vraiment développer une fonction pour faire des requêtes Ajax alors qu’il y a déjà un bon paquets de librairies qui le font, et bien nous rassurons les sceptiques tout de suite, GreaseMonkey intègre fort heureusement un ensemble de fonctions qui permet par exemple d’afficher des messages de logs, de faire des requêtes Ajax, d’enregistrer des données cache, etc.

Étape 4.1 : Interroger l’API bit.ly

Pour effectuer une requête Ajax avec GM, il faut utiliser la fonction GM_xmlhttpRequest qui reçoit en paramètre un objet JSON contenant :

  • method : le type de requête HTTP envoyée, GET ou POST
  • url : l’adresse appelée par le script
  • onload : la fonction qui sera exécutée lorsque la requête sera terminée
  Comprendre les jointures avec MySQL

Nous allons effectuer une première modification sur notre script pour vérifier que l’appel à l’API s’effectue correctement, et pour cela nous utiliserons la fonction GM_log (en) qui permet d’afficher des messages d’erreur dans la console Javascript de votre navigateur, nous vous conseillons quand même d’utiliser console.log si vous avez Firebug, ca sera nettement plus agréable. 

01.var api = 'http://api.bit.ly/expand?version=2.0.1'+
02.'&shortUrl;=http://bit.ly/4s0bFQ'+
03.'&login;=bitlyapidemo'+
04.'&apiKey;=R_0da49e0a9118ff35f52f629d2d71bf07';
05. 
06.GM_xmlhttpRequest({
07.method: "GET",
08.url: api,
09.onload: function(response) {
10.GM_log(response); // ou console.log(response);
11.}
12.});

Vous devriez voir s’afficher dans la console Firebug le résultat suivant en cliquant sur « Object » :

greasemonkey-firebug-log

Étape 4.2 : Traiter les données de l’API

Maintenant que nous savons comment interroger l’API, il va nous falloir exploiter ces données pour en extraire l’URL complète. Pour pouvoir manipuler la réponse de la requête au format JSON il faut évaluer la chaîne de caractères comme du Javascript grâce à la fonction eval, cette fonction nous renverra donc le résultat sous la forme d’un objet. Une fois cette transformation effectuée, il ne reste plus qu’à parcourir l’objet JSON pour en extraire l’information voulue.

Voici le code qui nous permet d’effectuer ce traitement :

01.// l'url que nous souhaitons traiter
02.var shortUrl = 'http://bit.ly/4s0bFQ';
03. 
04.// on extrait le 'hash' de l'url, ici il s'agit de '4s0bFQ'
05.var hash = shortUrl.substr(shortUrl.lastIndexOf('/')+1);
06. 
07.var api = 'http://api.bit.ly/expand?version=2.0.1'+
08.'&shortUrl;='+shortUrl+
09.'&login;=bitlyapidemo'+
10.'&apiKey;=R_0da49e0a9118ff35f52f629d2d71bf07';
11. 
12.// requête Ajax sur l'API bit.ly
13.GM_xmlhttpRequest({
14.method: "GET",
15.url: api,
16.onload: function(response) {
17.var data = eval('('+response.responseText+')');
18.if(data.errorCode == 0) {
19.GM_log(data.results[hash].longUrl); // ou console.log(data.results[hash].longUrl);
20.}
21.}
22.});

Étape 4.3 : Remplacer les URLs raccourcies par les URLs longues

Notre script pour le moment ne fonctionne que sur une seule URL, celle définie en dur, pour qu’il fonctionne sur toutes les urls de la page nous allons le transformer en fonction comme ceci :

01.// Traduit une URL courte bit.ly
02.function expand(shortUrl) {
03.// on extrait le 'hash' de l'url, ici il s'agit de '4s0bFQ'
04.var hash = shortUrl.substr(shortUrl.lastIndexOf('/')+1);
05. 
06.// url de l'API
07.var api = 'http://api.bit.ly/expand?version=2.0.1'+
08.'&shortUrl;='+shortUrl+
09.'&login;=bitlyapidemo'+
10.'&apiKey;=R_0da49e0a9118ff35f52f629d2d71bf07';
11.
12.// requête Ajax sur l'API bit.ly
13.GM_xmlhttpRequest({
14.method: "GET",
15.url: api,
16.onload: function(response) {
17.var data = eval('('+response.responseText+')');
18.if(data.errorCode == 0) {
19.console.log(data.results[hash].longUrl);
20.}
21.}
22.});
23.}
24. 
25.expand('http://bit.ly/4s0bFQ');

Arrivé ici, nous avons fait la plus grosse partie du travail, en effet nous avons réussi à interroger l’API de bit.ly pour récupérer l’URL en version longue, pour rendre le script opérationnel il nous faut désormais remplacer les URLs présentent dans la page par leur équivalent en format long. Pour cela nous allons parcourir le document HTML à l’aide du DOM à la recherche de toutes les ancres et appeler la fonction sur chaque ancre :

01.// récupère toutes les ancres de la page
02.var links = document.getElementsByTagName('a');
03. 
04.// parcourt le tableau des ancres
05.for(var i=0; i<links.length; i++) {
06.var link = links[i];
07. 
08.// appelle la fonction "expand" uniquement
09.// sur les urls ayant pour nom de domaine bit.ly
10.if(link.hostname == 'bit.ly') {
11.expand(link.href);
12.}
13.}

La touche finale de notre script va être le remplacement de tous les liens bit.ly dans la page, pour cela il va falloir modifier la fonction de callback passée en paramètre à GM_xmlhttpRequest. C’est cette fonction qui aura la charge d’effectuer la modification du texte du lien, nous allons donc devoir améliorer la fonction pour passer en paramètre l’objet DOM de l’ancre et non plus le lien seul, de cette manière la fonction de callback pourra effectuer le remplacement dès que la réponse sera revenue.

01.// Traduit une URL courte bit.ly
02.function expand(link) {
03.var shortUrl = link.href;
04. 
05.// on extrait le 'hash' de l'url, ici il s'agit de '4s0bFQ'
06.var hash = shortUrl.substr(shortUrl.lastIndexOf('/')+1);
07. 
08.// url de l'API
09.var api = 'http://api.bit.ly/expand?version=2.0.1'+
10.'&shortUrl;='+shortUrl+
11.'&login;=bitlyapidemo'+
12.'&apiKey;=R_0da49e0a9118ff35f52f629d2d71bf07';
13. 
14.// requête Ajax sur l'API bit.ly
15.GM_xmlhttpRequest({
16.method: "GET",
17.url: api,
18.onload: function(response) {
19.var data = eval('('+response.responseText+')');
20.if(data.errorCode == 0) {
21.var longUrl = data.results[hash].longUrl;
22.with(link) {
23.innerHTML = longUrl;
24.href = longUrl;
25.}
26.}
27.}
28.});
29.}
30. 
31.// récupère toutes les ancres de la page
32.var links = document.getElementsByTagName('a');
33. 
34.// parcourt le tableau des ancres
35.for(var i=0; i<links.length; i++) {
36.var link = links[i];
37. 
38.// appelle la fonction "expand" uniquement
39.// sur les urls ayant pour nom de domaine bit.ly
40.if(link.hostname == 'bit.ly') {
41.expand(link);
42.}
43.}

Étape 5 : Améliorer le code

Ci-dessous vous trouverez une version améliorée du script proposant un début de modélisation objet en Javascript. De cette manière vous pourrez éventuellement étendre le fonctionnement du script à d’autres types de raccourcisseurs d’URL ou bien ajouter les autres fonctions de l’API. Pourquoi pas une infobulle qui affiche les informations sur le lien à son survol ? 

01.// ==UserScript==
02.// @name           Epershand urlExpander
03.// @namespace      https://www.epershand.net
04.// @description    Traduit les urls raccourcies et affiche le lien entier
05.// @include        https://twitter.com/*
06.// ==/UserScript==
07. 
08.// transmet en paramètre à la fonction le document HTML
09.// et lance immédiatement l'exécution
10.(function(d) {
11. 
12.var bitly = {
13.expand: function(link) {
14.var shortUrl = link.href;
15. 
16.// on extrait le 'hash' de l'url, ici il s'agit de '4s0bFQ'
17.var hash = shortUrl.substr(shortUrl.lastIndexOf('/')+1);
18. 
19.// url de l'API
20.var api = 'http://api.bit.ly/expand?version=2.0.1'+
21.'&shortUrl;='+shortUrl+
22.'&login;=bitlyapidemo'+
23.'&apiKey;=R_0da49e0a9118ff35f52f629d2d71bf07';
24. 
25.// requête Ajax sur l'API bit.ly
26.GM_xmlhttpRequest({
27.method: "GET",
28.url: api,
29.onload: function(response) {
30.var data = eval('('+response.responseText+')');
31.if(data.errorCode == 0) {
32.var longUrl = data.results[hash].longUrl;
33.with(link) {
34.innerHTML = longUrl;
35.href = longUrl;
36.}
37.}
38.}
39.});
40.}
41.};
42. 
43.// récupère toutes les ancres de la page
44.var links = d.getElementsByTagName('a');
45. 
46.// parcourt le tableau des ancres
47.for(var i=0; i<links.length; i++) {
48.var link = links[i];
49. 
50.// appelle la fonction "expand" uniquement
51.// sur les urls ayant pour nom de domaine bit.ly
52.if(link.hostname == 'bit.ly') {
53.bitly.expand(link);
54.}
55.}
56. 
57.})(document);

Pour aller plus loin

Vous pouvez consulter le très bon manuel Dive into GreaseMonkey (en) et télécharger le code source complet du script GreaseMonkey Epershand urlExpander.

  Comment vider son Dyson modèle V7 et V8 ? 
Retour en haut