12.03
Le développement des applications mobile du le Site du Zéro (disponible depuis le 21 novembre 2011 pour la version Android) a été l’occasion pour les développeurs de Simple IT de commencer une ébauche d’API afin d’assurer la livraison du contenu aux applications en question. En effet, même si à ce jour ces dernières ne sont que des webviews reliées par quelques menus, il n’était pas envisageable de récupérer directement les pages du Site du Zéro pour les afficher sur le mobile : elles ne sont pas adaptées parce que trop lourdes et bourrées d’éléments qui n’ont pas leur place sur une app : menus, header, etc.
Hélas, cette API n’est pas accessible publiquement. Simple IT a prévu de l’ouvrir aux développeurs à moyen terme. En attendant une documentation officielle, cet article explique le fonctionnement de l’API utilisée pour les applications mobiles. Je l’ai réalisé en analysant le code de l’app Android disponible sur le Store. Si vous en venez à utiliser cette documentation, soyez conscients que
- ces spécifications sont susceptibles d’évoluer à tout moment et notamment lors de la mise à jour des applications développées par Simple IT. J’essaierai au mieux de maintenir à jour cet article mais mon emploi du temps chargé n’aidera pas ;
- il m’est impossible de vous dire si vous avez le droit d’utiliser cette API autrement que par l’utilisation des applications officielles : Simple IT n’a — à ma connaissance — pas publié de conditions d’utilisation.
N’hésitez pas à me faire part (en commentaire, par e-mail ou autre) de vos commentaires, notamment si vous repérez des erreurs.
Vue d’ensemble
L’API utilise le bien connu protocole HTTP et plus précisément sa variante chiffrée, HTTPS (l’utilisation d’HTTP provoquera une erreur 403 Forbidden). Pour le moment, seules des actions de lecture sont disponibles. Il n’y a pas d’interaction faisant intervenir le compte des membres du site.
Toutes les requêtes (modulo les fichiers statiques comme les feuilles de style ou les images) sont réalisées sur api.siteduzero.com et demandent une identification par le biais d’un paramètre GET token. Sans ce token, il vous sera demandé une identification HTTP, donc l’API ne sera pas accessible.
L’API n’est pas restreinte à un User-agent particulier. Elle est servie par un serveur Apache.
On ne sait pas si l’API est limitée en nombre de requêtes par unité de temps. Une utilisation mesurée, en « bon père de famille », est donc conseillée.
Format de la réponse
Toutes les réponses sont au format JSON, dans le jeu de caractère UTF-8 (comme sur le Site du Zéro). Toute requête qui s’est bien déroulée renverra un dictionnaire de deux éléments :
- status : doit être égal à « ok » ;
- results : contient le corps de la réponse en temps que telle ; c’est ce contenu que j’appellerai « réponse type » dans la suite.
En cas d’erreur (méthode qui n’existe pas, requête sur un élément inconnu, etc.), la réponse est étrange : vous ne recevez pas un dictionnaire JSON avec autre chose que « ok » comme status mais plutôt une demande d’authentification HTTP, donc finalement une erreur 401 Unauthorized. Vous êtes prévenu !
Détail des méthodes disponibles
Références
Les réponses contiennent parfois des structures réutilisées un peu partout. Cette section liste ces structures communes auxquelles vous devez vous référer quand il est indiqué /* réf. machin */.
Catégorie
{ "id": 42, "title": "Nom de la catégorie" }
Liste d’auteurs
[ { "id": 42, "username": "Bidule" } , ... ]
Liste de tutoriels
[ { "type": <"big" ou "mini">, "id": 42, "title": "Titre du tutoriel" } , ... ]
Difficulté d’un tutoriel
1 pour facile, 2 pour modéré et 3 pour difficile.
<"1" ou "2" ou "3">
Navigation dans un chapitre
Quand vous obtenez un mini-tutoriel qui n’est pas un chapitre d’un big-tutoriel, cet objet est :
{"big": "", "next": "", "previous": ""}
En revanche, quand le mini-tutoriel fait partie d’un big-tutoriel, cet objet devient :
{ "big": { "id": "40", /* notez le string */ "title": "Titre du big-tuto auquel appartient ce chapitre" }, "previous": { "id": "41", /* notez le string */ "title": "Titre du chapitre (mini-tuto) précédent" }, "next": { "id": "43", /* notez le string */ "title": "Titre du chapitre (mini-tuto) suivant" } }
Les éléments previous et/ou next peuvent être égaux à "" (chaîne vide) si le chapitre en cours est respectivement le premier et/ou le dernier chapitre de la partie.
Sommaine d’un mini-tutoriel
[ "<a href=\"#ss_part_1\" >Titre du paragraphe 1</a>", "<a href=\"#ss_part_2\" >Titre du paragraphe 2</a>" , ... ]
Sommaine d’un big-tutoriel
[ { "title": "Titre de la partie (ensemble de chapitres) 1", "mini": [ { "icon": '', "id": 42, "index": /* réf. sommaire d'un mini-tutoriel */, "title": "Titre du chapitre (mini-tuto) 1" } , ... /* chapitres suivants */ ] } , ... /* parties suivantes */ ]
Contenu HTML
Les contenus textuels (donc au format HTML) sont formatés de la manière suivante (mais sans espaces) :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="http://www.siteduzero.com/css/appli_mobile.css"> <title>Titre</title> <!-- présent selon les cas --> </head> <body> <!-- contenu réel, souvent dans un div --> </body> </html>
Dates/heures
Les dates sont au format AAAA-MM-JJ HH:MM:SS ou plus clairement année-mois-jour heure:minute:seconde.
Méthodes
Maintenant, voici les méthodes à proprement parler.
Hiérarchie des catégories de tutoriels
/category/tutorial
/category/tutorial/<id>
Récupère la liste des descendants hiérarchiques (fils) d’une catégorie <id> de tutoriels dans l’arbre de catégories. Si /<id> n’est pas précisé, il s’agira uniquement de la catégorie racine ie. les tutoriels (id 352), comme sur l’accueil des cours.
Remarquez que les articles, eux, ne sont pas accessibles : même si vous tentez d’en récupérer la liste en appelant /category/tutorial/353, la réponse ne contiendra pas d’élément category ! En revanche, si vous connaissez l’id d’un tutoriel se trouvant dans la catégorie Articles, rien ne vous empêche de le demander avec /mini-tutorial ou /big-tutorial.
Réponse type :
[ { "title": "Nom de la catégorie", "id": 42, "icon": "http://uploads.siteduzero.com/cat/thb/1_1000/352.png", "total_element": 1337, "category": /* une liste de dictionnaires qui suivent la même structure que celui-ci, sans l'élément "category" ou "tutorial" bien-sûr (il n'y a qu'un seul niveau de récursion) */ } , ... ]
Si la catégorie est une feuille de la hiérarchie (elle ne contient pas d’autres catégories), c’est alors une liste des tutoriels pour cette catégorie qui est retournée, dans l’élément tutorial.
Réponse type :
[ { "tutorial": /* réf. liste de tutoriels */, "icon": "http://uploads.siteduzero.com/cat/thb/1_1000/102.png", "id": 42, "total_element": 1337, "title": "Titre de la catégorie (feuille)" } , ... ]
Liste des news (raccourcies)
/news?offset=<offset>&range=<range>
Récupère la liste des range dernières news (sans leur contenu, uniquement le résumé s’il existe) à partir de la offsetième plus récente. Dans l’application officielle, range = 8.
Réponse type :
[ { "title": "Titre de la news", "id": 42, "icon": "http://uploads.siteduzero.com/nws/thb/43001_44000/43306.png", "published_at": /* réf dates/heures */, "summary": "Résume de la news" } , ... ]
Contenu d’une news
/news/<id>
Récupère le contenu et les détails de la news <id>.
Attention à l’absurdité : le dictionnaire (unique, évidemment) est imbriqué dans une liste à un élément.
Réponse type :
[{ "author": /* réf. liste d'auteurs */, "category": /* réf. catégorie */, "icon": "http://uploads.siteduzero.com/nws/thb/43001_44000/43306.png", "id": 42, "published_at": /* réf dates/heures */, "summary": "Résume de la news", "title": "Titre de la news", "content": "Contenu de la news" /* HTML sans conteneur */ }]
Récupération d’un mini-tuto
/mini-tutorial/<id>
Récupère la structure et les détails du mini-tutoriel <id>.
Le type (big ou mini) d’un tutoriel est précisé dans toute structure du type liste de tutoriels.
Notez que l’on ne peut savoir ni la date de création, ni la date de dernière modification des tutoriels.
Attention à l’absurdité : le dictionnaire (unique, évidemment) est imbriqué dans une liste à un élément.
Réponse type :
[{ "author": /* réf. liste d'auteurs */, "conclusion": "Conclusion du tutoriel" /* réf. contenu HTML, sans <title> */, "introduction": "Introduction du tutoriel" /* réf. contenu HTML, sans <title> */, "estimated_time": "120", /* en minutes, 0 si pas précisé ; notez le string */ "icon": "http://uploads.siteduzero.com/icones/257001_258000/257707.png", "id": 42, "level": /* réf. difficulté d'un tutoriel */, "mcq": "100", /* id du QCM associé ; notez le string */ "navigation": /* réf. navigation dans un big-tutoriel */, "title": "Titre du mini-tutoriel", "type": "mini", "index": /* réf. sommaire d'un mini-tutoriel */, "content": "Contenu du mini-tutoriel" /* réf. contenu HTML, avec <title> */ }]
Récupération d’un big-tuto
/big-tutorial/<id>
Récupère la structure et les détails du big-tutoriel <id>.
Attention à l’absurdité : le dictionnaire (unique, évidemment) est imbriqué dans une liste à un élément.
Réponse type :
[{ "author": /* réf. liste d'auteurs */, "conclusion": "Conclusion du tutoriel" /* réf. contenu HTML, sans <title> */, "introduction": "Introduction du tutoriel" /* réf. contenu HTML, sans <title> */, "estimated_time": "120", /* en minutes, 0 si pas précisé ; notez le string */ "icon": "http://uploads.siteduzero.com/icones/257001_258000/257707.png", "id": 42, "level": /* réf. difficulté d'un tutoriel */, "title": "Titre du big-tutoriel", "type": "big", "index": /* réf. sommaire d'un big-tutoriel */, }]
Récupération d’un QCM
/tutorial/mcq/<id>
Récupère le QCM <id>.
Les QCM ne sont pas directement dans la réponse d’un mini-tutoriel. Il faut faire une deuxième requête en utilisant l’id donné dans mcq de la réponse d’un mini-tutoriel.
Attention à l’absurdité : le dictionnaire (unique, évidemment) est imbriqué dans une liste à un élément.
Réponse type :
[{ "id": 42, /* id du QCM */ "questions": [ { "comment": "Commentaire pour la question", "text": "Contenu de la question", /* HTML sans conteneur */ "id": 420, /* id de la question */ "answers": [ { "text": "Texte de la réponse", "id": 4200, /* id de la réponse */ "is_correct": <true ou false> /* est bonne réponse si vrai */ } , ... /* réponses suivantes */ ] } , ... /* questions suivantes */ ] }]
Recherche de tutoriels
/search/tutorial/<query>
Effectue une recherche sur l’expression <query> (qui doit être URL-encodée).
Remarquez la structure : les résultats sont classés par catégories, puis par tutoriels.
Réponse type :
[ { "icon": "http://uploads.siteduzero.com/cat/thb/1_1000/70.png", "id": 42, "title": "Nom de la catégorie", "total_element": 1337, "tutorial": /* réf. liste de tutoriels */ } , ... ]


