[Bicloo] Retrouver son Bicloo, Velib, etc …

Coucou à tous,

 

Un de mes fidèles lecteurs (@Atao) m'a transmis un challenge assez intéressant puisqu'il s'agit de suivre son Bicloo.
Pour les personnes qui ne savent pas ce qu'est un Bicloo, il s'agit des vélos en libre-service dans l’agglomération Nantaise.
On retrouve ce genre de système dans différentes villes et sous divers noms.
Le plus connu reste le Vélib' (pour les Parisiens)

 

La carte des Bicloos

Il existe un site qui référence l'ensemble des stations où sont disponibles les bicloos :
https://www.bicloo.nantesmetropole.fr/mapping
Via cette interface nous sommes en mesure de connaitre les stations où l'on peut récupérer ou garer un Bicloo.
Cependant il y a une bonne centaine de station, et vu que nous sommes un peu superstitieux nous souhaitons savoir où est notre Bicloo n°666, mais aussi connaitre les endroits qu'il a pu fréquenter (ou si je suis jalou(x|se) et que je souhaite surveiller mon amoureu(x|se au travers du Bicloo que je lui ai loué) !

Sauf que cette carte ne nous affiche pas de moteur de recherche... il faut parcourir station après station pour le savoir !

 

Les requêtes du savoir ... et leurs sécurités !

Pour parcourir chacune des stations, il nous faut connaitre la liste des stations, j'ouvre donc la console de mon super navigateur (touche F12 de votre clavier), je me rends sur l'onglet "Réseau" / "Network", et j'observe ce qui se passe ...
Chaque fois que je clique une station 2 requêtes apparaissent dans ma console :

  1. Une qui me retourne la liste des stations
  2. Une qui me retourne la liste des bicloos garés dans cette station

La liste des stations

Celle qui me récupère la liste des bicloos est la suivante :

https://api.jcdecaux.com/vls/v3/stations?apiKey=xxxxxxxxxxxxxxxxxxxxxx&contract=xxxxxx

Je constate que pour réaliser la requête, il y a une clé secrète qui est envoyée ...
J'ai eu beau chercher je ne l'ai pas trouvé.
J'ai donc opté pour une stratégie que j'ai déjà présenté dans plusieurs de mes articles ... l'utilisation des prototypes.
Ainsi j'ai surchargé une des méthodes de l'objet XMLHttpRequest qui est appelée lorsque la requête est passé pour extraire cette clé à la volée.

La liste des vélos

La requête qui récupère la liste des vélos d'une station est la suivante :

https://api.cyclocity.fr/contracts/nantes/bikes?stationNumber=xxx

Cette requête n'est réalisable qu'a une condition ...
Ajouter 2 champs dans l'entête :

Le champ "authorization" et le champ "Content-type"
J'ai creusé un peu et j'ai constaté que le champs "Authorization" était la concaténation du terme "Takvn1" surement un raccourci pour désigner le "Token V1 ?" ainsi qu'une donnée qui se trouve dans votre localStorage : toujours dans votre console, rendez-vous dans l'onglet "Application" et regardez dans votre localStorage.

 

 

Le Script magique

Une fois n'est pas coutume, je vous sers ci-dessous un script à copier dans votre console qui vous permettra directement de collecter l'ensemble des stations et les vélos qui y sont disponibles.
Cela vous permettra d'avoir le suivi d'un vélo.

/*
*	(c) Dyrk.org
*	Bicloo - Realtime Monitor
*	Dave-Hill [<~(@)~>]  Dyrk.org
*
*
*/


var refreshData = 10000, 	/* Temps en milliseconde entre chaque collecte d'information */
	biclooDatas = {}, 		/* Variable où seront stockées nos stations et leurs vélos */
	city = 'nantes', 		/* Villes de collecte */
	apiKey = null, 
	//Fonction qui réalise les requêtes de récupération des stations et de leurs vélos
	req = (type_req, url, params, func_ret) => {
        var req = new XMLHttpRequest();
        req.open(type_req, url+'&'+apiKey);
        req.setRequestHeader('Authorization',['Taknv1',localStorage.getItem('cpr_access_token')].join(' '));
        req.setRequestHeader('Content-Type','application/vnd.bikes.v2+json');
        req.addEventListener('load', func_ret);
        req.send();
    }, 
	//Récupération des vélos
	getBicycles = (stationInfo) => {
		req('GET', ['https://api.cyclocity.fr/contracts/nantes/bikes?stationNumber=', stationInfo.number].join(''), null, ((station, e)=>{ 
			station.bikes = JSON.parse(e.target.response);
			biclooDatas[station.number] = station;
		}).bind(null, stationInfo))
    },
	//Récupération des stations
    getStations = (key) => {
		req('GET', ['https://api.jcdecaux.com/vls/v3/stations?apiKey=',key,'&contract=',city].join(''), null, (e)=> { 
				JSON.parse(e.target.response).map( station => getBicycles(station) )
		});
		console.log(biclooDatas);
    },
	//Extraction de l'ApiKey de la requêtes qui renvoit la liste des stations
    initHack = (e) => {
		var test =  /stations\?apiKey=([a-zA-Z0-9]*)/.exec(e.target.responseURL),
			apiKey = e.target.responseURL && test ? test[1]:null;
        if (apiKey) {
			XMLHttpRequest.prototype.addEventListener = XMLHttpRequest.prototype.addEventListener2;
            setInterval(getStations.bind(null,apiKey) , refreshData);
        }
    };
// Hack pour récupérer l'ApiKey - Surcharge d'une méthode appelée par toutes les requêtes.
XMLHttpRequest.prototype.addEventListener2 = XMLHttpRequest.prototype.addEventListener;
XMLHttpRequest.prototype.addEventListener = function(evt, func){
	this.addEventListener2('load', initHack);
	return this.addEventListener2(evt, func);
};

Ce code est à copier dans votre console Web (touche F12, onglet "console") sur la page où vous consulter vos Bicloos / Velib' / ...
Dans le cas présent :
https://www.bicloo.nantesmetropole.fr/mapping

Une fois copier-coller, appuyer sur la touche "entrée" de votre clavier pour exécuter le code.
Et pour amorcer la collecte, cliquez sur n'importe quelle station !

Vidéo

Petite vidéo de démonstration  ;)

 

Conclusion

Encore un challenge assez sympa, je remercie @Atao pour cette excellente idée, et j'espère que cette article vous plaira et vous donnera de nouvelle idée à me communiquer.
Je souhaite aussi présenter mes plus profondes excuses pour les personnes auxquelles je ne réponds pas il faut savoir que je gère beaucoup de mails, commentaire et messages par toutes sortes de canaux (Ex : Facebook)
Je tiens également à rappeler que lorsque j'écris des "Hack" (comme celui-ci), ceux-ci ont une durée de vie, et il n'est pas dit que je soit en mesure de les reproduire si jamais la plateforme ciblée sécurise son code.
Bonne journée à tous et excellent Weekend !

Partagez ce contenu

Laisser une réponse

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *