UNPKG

garmin-api-handler

Version:
250 lines (224 loc) 7.02 kB
'use strict'; var CookieApi = require('cookie-api-handler'); var FormData = require('form-data'); var restApiHandler = require('rest-api-handler'); var garminConnect = require('garmin-connect'); var GarminApiException = require('./exceptions/GarminApiException.js'); var responseDecoder = require('./helpers/responseDecoder.js'); var Activity = require('./models/Activity.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var CookieApi__default = /*#__PURE__*/_interopDefaultLegacy(CookieApi); var FormData__default = /*#__PURE__*/_interopDefaultLegacy(FormData); class GarminApi extends CookieApi__default["default"] { constructor(session) { super('https://connect.garmin.com/modern/proxy', [new restApiHandler.DefaultResponseProcessor(GarminApiException, responseDecoder)], { 'nk': 'NT', 'Content-Type': 'application/json', 'dnt': '1', 'origin': 'https://connect.garmin.com' }); this.session = session; this.addCookies({ _gid: 'X' }); } setSession(session) { this.session = session; this.addCookies({ SESSIONID: session || '' }); return this; } getSession() { return this.session; } async login(email, password) { const GCClient = new garminConnect.GarminConnect(); await GCClient.login(email, password); const { cookies } = GCClient.client.cookies._jar.toJSON(); const session = cookies.find(item => item.key === 'SESSIONID' && item.domain === 'connect.garmin.com').value; const __cflb = cookies.find(item => item.key === '__cflb' && item.domain === 'connect.garmin.com').value; this.setSession(session); this.addCookies({ __cflb }); return session; // does not pass clouflare protection /* // get ticket from login form const { data } = await this.post( 'https://sso.garmin.com/sso/login?service=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F', { username: email, password, embed: false, }, CookieApi.FORMATS.URL_ENCODED, { 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'https://sso.garmin.com/sso/signin', }, ); const ticket = /ticket=(([A-Za-z]|-|\d)*)/g.exec(data); // if ticket is no present, there is some error in html if (!ticket) { const errorMessage = /<div id="status" class="error">([A-Za-z]| |\.)*<\/div>/g.exec(data); throw new Error(errorMessage ? errorMessage[1] : 'Error in Login. Cannot find ticket.'); } // use ticket try { await this.request(`?${ticket[0]}`, 'GET', { redirect: 'manual', }); // eslint-disable-next-line no-empty } catch {} // this will load cookies await this.get('https://connect.garmin.com/modern/'); const cookies = this.getCookies(); if (!cookies) { throw new Error('Login failed. Cookies were not loaded.'); } this.setSession(cookies.SESSIONID); return cookies.SESSIONID; */ } async getActivity(id) { const { data } = await this.get(`activity-service/activity/${id}`); return Activity.fromApi(data); } async getPoints(id) { const { data } = await this.get(`activity-service/activity/${id}/details`); return data; } async getActivityGpx(id) { const { data } = await this.get(`download-service/export/gpx/activity/${id}`); return data; } async getActivityFile(id) { const { data } = await this.get(`download-service/files/activity/${id}`); return data; } async getActivities(filter) { const { startDate, endDate } = filter; const { data } = await this.get('activitylist-service/activities/search/activities', { ...filter, ...(startDate ? { starDate: startDate.toSQLDate() } : {}), ...(endDate ? { endDate: endDate.toSQLDate() } : {}) }); return data.map(activity => { return Activity.fromListApi(activity); }); } logWeight(date, kg) { return this.post('weight-service/user-weight', { gmtTimestamp: date.setZone('UTC').toISO({ includeOffset: false }), dateTimestamp: date.toISO({ includeOffset: false }), unitKey: 'kg', value: kg }); } async upload(fileContent, format) { const form = new FormData__default["default"](); form.append('file', fileContent, { filename: `activity.${format}`, contentType: 'application/octet-stream' }); const headers = this.getDefaultHeaders(); this.setDefaultHeaders({ cookie: headers.cookie, nk: headers.nk }); const response = await this.request(`upload-service/upload/.${format}`, 'POST', { body: form }); this.setDefaultHeaders(headers); return response.data.detailedImportResult.successes[0].internalId; } async uploadGpx(gpx) { return this.upload(gpx, 'gpx'); } async createActivity(activity) { return this.activityUpdater(activity); } async updateActivity(activity) { return this.activityUpdater(activity); } async activityUpdater(activity) { const distance = activity.getDistance(); const averageHR = activity.getAvgHeartRate(); const maxHR = activity.getMaxHeartRate(); const { data } = await this.post(`activity-service/activity/${activity.getId() || ''}`, { activityName: activity.getTitle() || activity.getTypeId(), activityTypeDTO: { typeKey: activity.getTypeId() }, summaryDTO: { duration: activity.getDuration().as('seconds'), startTimeLocal: `${activity.getStart().toISO({ includeOffset: false, suppressMilliseconds: true })}.0`, ...(averageHR != null ? { averageHR } : {}), ...(maxHR != null ? { maxHR } : {}), ...(distance != null ? { distance: distance.toNumber('m') } : {}) }, eventTypeDTO: { typeKey: activity.getCategory() }, timeZoneUnitDTO: { unitKey: 'Europe/Prague' }, description: activity.getNotes(), ...(activity.getId() ? { activityId: activity.getId() } : {}) }, CookieApi__default["default"].FORMATS.JSON, { ...(activity.getId() ? { 'x-http-method-override': 'PUT' } : {}) }); return activity.getId() ? activity : Activity.fromApi(data); } async addGear(activityId, gear) { const { data } = await this.post(`gear-service/gear/link/${gear}/activity/${activityId}`, {}, CookieApi__default["default"].FORMATS.JSON, { 'x-http-method-override': 'PUT' }); return data; } async getGears(activityId) { const { data } = await this.get(`gear-service/gear/filterGear?activityId=${activityId}`); return data; } } module.exports = GarminApi;