nakarte

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

garmin.js (4822B)


      1 import {urlViaCorsProxy} from '~/lib/CORSProxy';
      2 import {fetch} from '~/lib/xhr-promise';
      3 
      4 import BaseService from './baseService';
      5 
      6 class GarminBase extends BaseService {
      7     urlRe = /NOT IMPLEMENTED/u;
      8 
      9     isOurUrl() {
     10         return this.urlRe.test(this.origUrl);
     11     }
     12 
     13     async prepare() {
     14         let response;
     15         try {
     16             response = await fetch(urlViaCorsProxy(this.origUrl + '?' + Date.now()), {
     17                 isResponseSuccess: (xhr) => xhr.status === 200,
     18             });
     19         } catch {
     20             return 'NETWORK';
     21         }
     22         let dom;
     23         try {
     24             dom = new DOMParser().parseFromString(response.response, 'text/html');
     25         } catch {
     26             return 'NETWORK';
     27         }
     28         const token = dom.querySelector('meta[name="csrf-token"]')?.content;
     29         if (!token) {
     30             return 'NETWORK';
     31         }
     32         this.token = token;
     33         return null;
     34     }
     35 }
     36 
     37 function isResponseSuccess(xhr) {
     38     return xhr.status === 200 || xhr.status === 403 || xhr.status === 404;
     39 }
     40 
     41 class GarminRoute extends GarminBase {
     42     urlRe = /^https?:\/\/connect\.garmin\.com\/modern\/course\/(\d+)/u;
     43 
     44     requestOptions() {
     45         const m = this.urlRe.exec(this.origUrl);
     46         const trackId = m[1];
     47         this.trackId = trackId;
     48         return [
     49             {
     50                 url: urlViaCorsProxy(`https://connect.garmin.com/gc-api/course-service/course/${trackId}`),
     51                 options: {
     52                     responseType: 'json',
     53                     headers: [['connect-csrf-token', this.token]],
     54                     isResponseSuccess,
     55                 },
     56             },
     57         ];
     58     }
     59 
     60     parseResponse(responses) {
     61         const response = responses[0];
     62         if (response.status === 403) {
     63             return [{error: 'Garmin Connect user disabled viewing this route'}];
     64         }
     65         if (response.status === 404) {
     66             return [{error: 'Garmin Connect route does not exist'}];
     67         }
     68         let trackName = `Garmin Connect route ${this.trackId}`;
     69         const data = response.responseJSON;
     70         if (!data) {
     71             return [{name: trackName, error: 'UNSUPPORTED'}];
     72         }
     73         let points = null;
     74         let tracks = [];
     75         try {
     76             if (data.coursePoints) {
     77                 points = data.coursePoints.map((pt) => ({name: pt.name, lat: pt.lat, lng: pt.lon}));
     78             }
     79             if (data.geoPoints) {
     80                 tracks = [data.geoPoints.map((obj) => ({lat: obj.latitude, lng: obj.longitude}))];
     81             }
     82         } catch {
     83             return [{name: trackName, error: 'UNSUPPORTED'}];
     84         }
     85         trackName = data.courseName ? data.courseName : trackName;
     86         return [
     87             {
     88                 name: trackName,
     89                 points,
     90                 tracks,
     91             },
     92         ];
     93     }
     94 }
     95 
     96 class GarminActivity extends GarminBase {
     97     urlRe = /^https?:\/\/connect\.garmin\.com\/modern\/activity\/(\d+)/u;
     98 
     99     requestOptions() {
    100         const m = this.urlRe.exec(this.origUrl);
    101         const trackId = m[1];
    102         this.trackId = trackId;
    103         return [
    104             {
    105                 url: urlViaCorsProxy(`https://connect.garmin.com/gc-api/activity-service/activity/${trackId}`),
    106                 options: {
    107                     responseType: 'json',
    108                     headers: [['connect-csrf-token', this.token]],
    109                     isResponseSuccess,
    110                 },
    111             },
    112             {
    113                 url: urlViaCorsProxy(`https://connect.garmin.com/gc-api/activity-service/activity/${trackId}/details`),
    114                 options: {
    115                     responseType: 'json',
    116                     headers: [['connect-csrf-token', this.token]],
    117                     isResponseSuccess,
    118                 },
    119             },
    120         ];
    121     }
    122 
    123     parseResponse(responses) {
    124         const [infoResponse, detailsResponse] = responses;
    125         if (infoResponse.status === 403) {
    126             return [{error: 'Garmin Connect user disabled viewing this activity'}];
    127         }
    128         if (infoResponse.status === 404) {
    129             return [{error: 'Garmin Connect activity does not exist'}];
    130         }
    131         let trackName = `Garmin Connect activity ${this.trackId}`;
    132         if (!infoResponse.responseJSON) {
    133             return [{name: trackName, error: 'UNSUPPORTED'}];
    134         }
    135         trackName = infoResponse.responseJSON.activityName || trackName;
    136         let track;
    137         try {
    138             track = detailsResponse.responseJSON.geoPolylineDTO.polyline.map((obj) => ({lat: obj.lat, lng: obj.lon}));
    139         } catch {
    140             return [{name: trackName, error: 'UNSUPPORTED'}];
    141         }
    142 
    143         return [
    144             {
    145                 name: trackName,
    146                 tracks: [track],
    147             },
    148         ];
    149     }
    150 }
    151 
    152 export {GarminRoute, GarminActivity};