commit 0171fecbfd4a4f3b4065d8a179bae9f2bdceecb4
parent 7e01a2fc74577a5f7a10f65b40770e9971f3cda2
Author: myadzel <myadzel@gmail.com>
Date: Wed, 26 Sep 2018 11:04:35 +0300
parsing tracks from movescount
Diffstat:
4 files changed, 156 insertions(+), 5 deletions(-)
diff --git a/src/lib/leaflet.control.track-list/lib/geo_file_formats.js b/src/lib/leaflet.control.track-list/lib/geo_file_formats.js
@@ -8,6 +8,7 @@ import urlViaCorsProxy from 'lib/CORSProxy';
import {isGpsiesUrl, gpsiesXhrOptions, gpsiesParser} from './gpsies';
import {isStravaUrl, stravaXhrOptions, stravaParser} from './strava';
import {isEndomondoUrl, endomonXhrOptions, endomondoParser} from './endomondo';
+import {isMovescountUrl, movescountXhrOptions, movescountParser} from './movescount';
import {parseTrackUrlData, parseNakarteUrl, isNakarteLinkUrl, nakarteLinkXhrOptions, nakarteLinkParser} from './nktk';
import {stringToArrayBuffer, arrayBufferToString} from 'lib/binary-strings';
@@ -618,11 +619,13 @@ function loadFromUrl(url) {
}
let urlToRequest = simpleTrackFetchOptions;
let parser = simpleTrackParser;
-
-
+ let errorHandler = (e) => [{name: url, error: 'NETWORK'}];
if (isGpsiesUrl(url)) {
urlToRequest = gpsiesXhrOptions;
parser = gpsiesParser;
+ } else if (isMovescountUrl(url)) {
+ urlToRequest = movescountXhrOptions;
+ parser = movescountParser;
} else if (isEndomondoUrl(url)) {
urlToRequest = endomonXhrOptions;
parser = endomondoParser;
@@ -652,7 +655,7 @@ function loadFromUrl(url) {
.pop();
return parser(name, responses);
},
- () => [{name: url, error: 'NETWORK'}]
+ errorHandler
);
}
diff --git a/src/lib/leaflet.control.track-list/lib/movescount.js b/src/lib/leaflet.control.track-list/lib/movescount.js
@@ -0,0 +1,146 @@
+import urlViaCorsProxy from 'lib/CORSProxy';
+import {decode as utf8_decode} from 'utf8';
+
+const urlTypes = {
+ route: {
+ type: 'route',
+ url: 'http://www.movescount.com/Move/Route/{id}',
+ re: /^https?:\/\/www.movescount.com\/([a-z]{2}\/)?map\/?.*[?&]route=(\d+)/
+ },
+ move: {
+ type: 'move',
+ url: 'http://www.movescount.com/Move/Track2/{id}',
+ re: /^https?:\/\/www.movescount.com\/([a-z]{2}\/)?moves\/move(\d+)/
+ }
+};
+
+function getTrackParser(type) {
+ const parsers = {
+ route(data, type, id, name) {
+ const track = data.points.latitudes.map((lat, i) => ({
+ lat: data.points.latitudes[i],
+ lng: data.points.longitudes[i]
+ }));
+
+ name = name || data.routeName;
+
+ return [{
+ name: getTrackName(type, name, id),
+ tracks: [track]
+ }];
+ },
+
+ move(data, type, id, name) {
+ const track = data.TrackPoints.map(trackPoint => ({
+ lat: trackPoint.Latitude,
+ lng: trackPoint.Longitude
+ }));
+
+ return [{
+ name: getTrackName(type, name, id),
+ tracks: [track]
+ }];
+ }
+ };
+
+ return parsers[type];
+}
+
+function getMovescountUrlType(url, id) {
+ let urlType = Object.values(urlTypes).filter(urlType => {
+ if (id === undefined) {
+ return urlType.re.test(url);
+ } else {
+ return url === urlViaCorsProxy(urlType.url.replace('{id}', id));
+ }
+ })[0];
+
+ return urlType && urlType.type;
+}
+
+function getTrackName(type, name, id) {
+ return `${name} (${type}${id})`;
+}
+
+function isMovescountUrl(url) {
+ return Object.values(urlTypes).some(urlType => {
+ return urlType.re.test(url);
+ });
+}
+
+function movescountXhrOptions(url) {
+ let type = getMovescountUrlType(url);
+
+ let urlType = urlTypes[type];
+
+ let match = urlType.re.exec(url);
+
+ let id = match[2];
+
+ const options = [{
+ url: urlViaCorsProxy(urlType.url.replace('{id}', id)),
+ options: {
+ responseType: 'binarystring',
+ isResponseSuccess: (xhr) => xhr.status === 200 || xhr.status === 403 || xhr.status === 404
+ },
+ }];
+
+ if (type === 'move') {
+ options.push({
+ url: urlViaCorsProxy(url),
+ options: {
+ responseType: 'binarystring',
+ isResponseSuccess: (xhr) => xhr.status === 200 || xhr.status === 403 || xhr.status === 404
+ },
+ });
+ }
+
+ return options;
+}
+
+function movescountParser(id, responses) {
+ let data;
+
+ let name;
+
+ let response = responses[0];
+
+ let type = getMovescountUrlType(response.responseURL, id);
+
+ if (response.status === 403) {
+ return [{error: `Movescount user disabled viewing this ${type}`}];
+ } else {
+ try {
+ data = JSON.parse(response.responseBinaryText)
+ } catch (e) {
+ return [{name: id, error: 'UNSUPPORTED'}];
+ }
+ }
+
+ if (responses[1]) {
+ let s = responses[1].responseBinaryText;
+ s = utf8_decode(s);
+
+ let m = s.match(/<title>([^<]+)<\/title>/);
+
+ if (m) {
+ name = unescapeHtml(m[1]);
+ }
+ }
+
+ let parseTrack = getTrackParser(type);
+
+ return parseTrack(data, type, id, name);
+
+ function unescapeHtml(html) {
+ const element = document.createElement('div');
+
+ return html.replace(/&[0-9a-z#]+;/gi, s => {
+ element.innerHTML = s;
+
+ return element.innerText;
+ });
+ }
+}
+
+export {isMovescountUrl, movescountXhrOptions, movescountParser}
+\ No newline at end of file
diff --git a/src/lib/leaflet.control.track-list/track-list.js b/src/lib/leaflet.control.track-list/track-list.js
@@ -71,7 +71,7 @@ L.Control.TrackList = L.Control.extend({
<div class="leaflet-control-content">
<div class="header">
<div class="hint">
- gpx kml Ozi zip YandexMaps GPSies Strava endomondo
+ gpx kml Ozi zip YandexMaps GPSies Strava endomondo Movescount
</div>
<div class="button-minimize" data-bind="click: setMinimized"></div>
</div>
diff --git a/src/lib/xhr-promise/index.js b/src/lib/xhr-promise/index.js
@@ -13,7 +13,8 @@ class XMLHttpRequestPromiseError extends Error {
super();
this.xhr = xhr;
this.name = 'XMLHttpRequestPromiseError';
-
+ this.status = xhr.status;
+ this.url = xhr.responseURL;
this.message = xhr.status === 0 ? 'network error' : `server response is ${xhr.status}`;
}
}