nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

commit 0171fecbfd4a4f3b4065d8a179bae9f2bdceecb4
parent 7e01a2fc74577a5f7a10f65b40770e9971f3cda2
Author: myadzel <myadzel@gmail.com>
Date:   Wed, 26 Sep 2018 11:04:35 +0300

parsing tracks from movescount

Diffstat:
Msrc/lib/leaflet.control.track-list/lib/geo_file_formats.js | 9++++++---
Asrc/lib/leaflet.control.track-list/lib/movescount.js | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/leaflet.control.track-list/track-list.js | 2+-
Msrc/lib/xhr-promise/index.js | 3++-
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}`; } }