@gooin/garmin-connect 1.6.11 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,361 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HttpClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const form_data_1 = __importDefault(require("form-data"));
9
+ const lodash_1 = __importDefault(require("lodash"));
10
+ const luxon_1 = require("luxon");
11
+ const oauth_1_0a_1 = __importDefault(require("oauth-1.0a"));
12
+ const qs_1 = __importDefault(require("qs"));
13
+ const node_crypto_1 = __importDefault(require("node:crypto"));
14
+ const CSRF_RE = new RegExp('name="_csrf"\\s+value="(.+?)"');
15
+ const TICKET_RE = new RegExp('ticket=([^"]+)"');
16
+ const ACCOUNT_LOCKED_RE = new RegExp('var statuss*=s*"([^"]*)"');
17
+ const PAGE_TITLE_RE = new RegExp('<title>([^<]*)</title>');
18
+ const USER_AGENT_CONNECTMOBILE = 'com.garmin.android.apps.connectmobile';
19
+ const USER_AGENT_BROWSER = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36';
20
+ const USER_AGENT_BROWSER_MAC = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
21
+ const OAUTH_CONSUMER_URL = 'https://thegarth.s3.amazonaws.com/oauth_consumer.json';
22
+ const HTTP_STATUS = {
23
+ UNAUTHORIZED: 401
24
+ };
25
+ let tokenRefreshPromise = null;
26
+ let refreshSubscribers = [];
27
+ class HttpClient {
28
+ constructor(url, config) {
29
+ var _a, _b;
30
+ this.url = url;
31
+ this.client = axios_1.default.create({
32
+ timeout: (_a = config === null || config === void 0 ? void 0 : config.timeout) !== null && _a !== void 0 ? _a : 5000,
33
+ timeoutErrorMessage: `Request Timeout: > ${(_b = config === null || config === void 0 ? void 0 : config.timeout) !== null && _b !== void 0 ? _b : 5000} ms`
34
+ /**
35
+ * Charles debugger: uncomment `proxy` and `httpsAgent`, then run bellow command.
36
+ * NODE_TLS_REJECT_UNAUTHORIZED=0 node test/sync.js
37
+ */
38
+ // proxy: {
39
+ // host: '127.0.0.1',
40
+ // port: 8888,
41
+ // protocol: 'http'
42
+ // },
43
+ // httpsAgent: new (require('https').Agent)({
44
+ // rejectUnauthorized: false
45
+ // })
46
+ });
47
+ this.config = config;
48
+ this.client.interceptors.response.use((response) => response, async (error) => {
49
+ var _a;
50
+ if (axios_1.default.isAxiosError(error) &&
51
+ error.code === 'ECONNABORTED') {
52
+ throw new Error(error.message || 'Request Timeout');
53
+ }
54
+ const originalRequest = error.config;
55
+ if (((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) === HTTP_STATUS.UNAUTHORIZED &&
56
+ !(originalRequest === null || originalRequest === void 0 ? void 0 : originalRequest._retry)) {
57
+ if (!this.oauth2Token) {
58
+ throw new Error('No OAuth2 token available');
59
+ }
60
+ originalRequest._retry = true;
61
+ try {
62
+ if (!tokenRefreshPromise) {
63
+ tokenRefreshPromise =
64
+ this.refreshOauth2Token().finally(() => {
65
+ tokenRefreshPromise = null;
66
+ });
67
+ }
68
+ await tokenRefreshPromise;
69
+ originalRequest.headers.Authorization = `Bearer ${this.oauth2Token.access_token}`;
70
+ return this.client(originalRequest);
71
+ }
72
+ catch (err) {
73
+ console.error('Token refresh failed:', err);
74
+ throw err;
75
+ }
76
+ }
77
+ if (axios_1.default.isAxiosError(error) && error.response) {
78
+ this.handleError(error.response);
79
+ }
80
+ else {
81
+ // 处理没有response的情况
82
+ throw new Error('Network error or unknown error occurred');
83
+ }
84
+ throw error;
85
+ });
86
+ this.client.interceptors.request.use(async (config) => {
87
+ if (this.oauth2Token) {
88
+ config.headers.Authorization =
89
+ 'Bearer ' + this.oauth2Token.access_token;
90
+ }
91
+ return config;
92
+ });
93
+ }
94
+ async fetchOauthConsumer() {
95
+ const response = await axios_1.default.get(OAUTH_CONSUMER_URL);
96
+ this.OAUTH_CONSUMER = {
97
+ key: response.data.consumer_key,
98
+ secret: response.data.consumer_secret
99
+ };
100
+ }
101
+ async checkTokenVaild() {
102
+ if (this.oauth2Token) {
103
+ if (this.oauth2Token.expires_at < luxon_1.DateTime.now().toSeconds()) {
104
+ console.error('Token expired!');
105
+ await this.refreshOauth2Token();
106
+ }
107
+ }
108
+ }
109
+ async get(url, config) {
110
+ const response = await this.client.get(url, config);
111
+ return response === null || response === void 0 ? void 0 : response.data;
112
+ }
113
+ async post(url, data, config) {
114
+ const response = await this.client.post(url, data, config);
115
+ return response === null || response === void 0 ? void 0 : response.data;
116
+ }
117
+ async put(url, data, config) {
118
+ const response = await this.client.put(url, data, config);
119
+ return response === null || response === void 0 ? void 0 : response.data;
120
+ }
121
+ async delete(url, config) {
122
+ const response = await this.client.post(url, null, {
123
+ ...config,
124
+ headers: {
125
+ ...config === null || config === void 0 ? void 0 : config.headers,
126
+ 'X-Http-Method-Override': 'DELETE'
127
+ }
128
+ });
129
+ return response === null || response === void 0 ? void 0 : response.data;
130
+ }
131
+ setCommonHeader(headers) {
132
+ lodash_1.default.each(headers, (headerValue, key) => {
133
+ this.client.defaults.headers.common[key] = headerValue;
134
+ });
135
+ }
136
+ handleError(response) {
137
+ this.handleHttpError(response);
138
+ }
139
+ handleHttpError(response) {
140
+ const { status, statusText, data } = response;
141
+ const errorMessage = {
142
+ status,
143
+ statusText,
144
+ data: typeof data === 'object' ? JSON.stringify(data) : data
145
+ };
146
+ console.error('HTTP Error:', errorMessage);
147
+ throw new Error(`HTTP Error (${status}): ${statusText}`);
148
+ }
149
+ /**
150
+ * Login to Garmin Connect
151
+ * @param username
152
+ * @param password
153
+ * @returns {Promise<HttpClient>}
154
+ */
155
+ async login(username, password, mfaCallback) {
156
+ await this.fetchOauthConsumer();
157
+ // Step1-3: Get ticket from page.
158
+ const ticket = await this.getLoginTicket(username, password);
159
+ // Step4: Oauth1
160
+ const oauth1 = await this.getOauth1Token(ticket);
161
+ // TODO: Handle MFA
162
+ // Step 5: Oauth2
163
+ await this.exchange(oauth1);
164
+ return this;
165
+ }
166
+ async getLoginTicket(username, password) {
167
+ // Step1: Set cookie
168
+ const step1Params = {
169
+ clientId: 'GarminConnect',
170
+ locale: 'en',
171
+ service: this.url.GC_MODERN
172
+ };
173
+ const step1Url = `${this.url.GARMIN_SSO_EMBED}?${qs_1.default.stringify(step1Params)}`;
174
+ // console.log('login - step1Url:', step1Url);
175
+ await this.client.get(step1Url);
176
+ // Step2 Get _csrf
177
+ const step2Params = {
178
+ id: 'gauth-widget',
179
+ embedWidget: true,
180
+ locale: 'en',
181
+ gauthHost: this.url.GARMIN_SSO_EMBED
182
+ };
183
+ const step2Url = `${this.url.SIGNIN_URL}?${qs_1.default.stringify(step2Params)}`;
184
+ // console.log('login - step2Url:', step2Url);
185
+ const step2Result = await this.get(step2Url);
186
+ // console.log('login - step2Result:', step2Result)
187
+ const csrfRegResult = CSRF_RE.exec(step2Result);
188
+ if (!csrfRegResult) {
189
+ throw new Error('login - csrf not found');
190
+ }
191
+ const csrf_token = csrfRegResult[1];
192
+ // console.log('login - csrf:', csrf_token);
193
+ // Step3 Get ticket
194
+ const signinParams = {
195
+ id: 'gauth-widget',
196
+ embedWidget: true,
197
+ clientId: 'GarminConnect',
198
+ locale: 'en',
199
+ gauthHost: this.url.GARMIN_SSO_EMBED,
200
+ service: this.url.GARMIN_SSO_EMBED,
201
+ source: this.url.GARMIN_SSO_EMBED,
202
+ redirectAfterAccountLoginUrl: this.url.GARMIN_SSO_EMBED,
203
+ redirectAfterAccountCreationUrl: this.url.GARMIN_SSO_EMBED
204
+ };
205
+ const step3Url = `${this.url.SIGNIN_URL}?${qs_1.default.stringify(signinParams)}`;
206
+ // console.log('login - step3Url:', step3Url);
207
+ const step3Form = new form_data_1.default();
208
+ step3Form.append('username', username);
209
+ step3Form.append('password', password);
210
+ step3Form.append('embed', 'true');
211
+ step3Form.append('_csrf', csrf_token);
212
+ const step3Result = await this.post(step3Url, step3Form, {
213
+ headers: {
214
+ 'Content-Type': 'application/x-www-form-urlencoded',
215
+ Dnt: 1,
216
+ Origin: this.url.GARMIN_SSO_ORIGIN,
217
+ Referer: this.url.SIGNIN_URL,
218
+ 'User-Agent': USER_AGENT_BROWSER
219
+ }
220
+ });
221
+ console.log('step3Result:', step3Result);
222
+ this.handleAccountLocked(step3Result);
223
+ this.handlePageTitle(step3Result);
224
+ this.handleMFA(step3Result);
225
+ const ticketRegResult = TICKET_RE.exec(step3Result);
226
+ if (!ticketRegResult) {
227
+ throw new Error('login failed (Ticket not found or MFA), please check username and password');
228
+ }
229
+ const ticket = ticketRegResult[1];
230
+ return ticket;
231
+ }
232
+ // TODO: Handle MFA
233
+ handleMFA(htmlStr) { }
234
+ // TODO: Handle Phone number
235
+ handlePageTitle(htmlStr) {
236
+ const pageTitileRegResult = PAGE_TITLE_RE.exec(htmlStr);
237
+ if (pageTitileRegResult) {
238
+ const title = pageTitileRegResult[1];
239
+ console.log('login page title:', title);
240
+ if (lodash_1.default.includes(title, 'Update Phone Number')) {
241
+ // current I don't know where to update it
242
+ // See: https://github.com/matin/garth/issues/19
243
+ throw new Error('login failed (Update Phone number), please update your phone number, See: https://github.com/matin/garth/issues/19');
244
+ }
245
+ }
246
+ }
247
+ handleAccountLocked(htmlStr) {
248
+ const accountLockedRegResult = ACCOUNT_LOCKED_RE.exec(htmlStr);
249
+ if (accountLockedRegResult) {
250
+ const msg = accountLockedRegResult[1];
251
+ console.error(msg);
252
+ throw new Error('login failed (AccountLocked), please open connect web page to unlock your account');
253
+ }
254
+ }
255
+ async refreshOauth2Token() {
256
+ try {
257
+ if (!this.OAUTH_CONSUMER) {
258
+ await this.fetchOauthConsumer();
259
+ }
260
+ if (!this.oauth2Token || !this.oauth1Token) {
261
+ throw new Error('Missing required tokens for refresh');
262
+ }
263
+ const oauth1 = {
264
+ oauth: this.getOauthClient(this.OAUTH_CONSUMER),
265
+ token: this.oauth1Token
266
+ };
267
+ await this.exchange(oauth1);
268
+ console.log(`「${this.config.username}」in「${this.url.domain}」 OAuth2 token refreshed successfully`);
269
+ }
270
+ catch (error) {
271
+ console.error('Failed to refresh OAuth2 token:', error);
272
+ throw error;
273
+ }
274
+ }
275
+ async getOauth1Token(ticket) {
276
+ if (!this.OAUTH_CONSUMER) {
277
+ throw new Error('No OAUTH_CONSUMER');
278
+ }
279
+ const params = {
280
+ ticket,
281
+ 'login-url': this.url.GARMIN_SSO_EMBED,
282
+ 'accepts-mfa-tokens': true
283
+ };
284
+ const url = `${this.url.OAUTH_URL}/preauthorized?${qs_1.default.stringify(params)}`;
285
+ const oauth = this.getOauthClient(this.OAUTH_CONSUMER);
286
+ const step4RequestData = {
287
+ url: url,
288
+ method: 'GET'
289
+ };
290
+ const headers = oauth.toHeader(oauth.authorize(step4RequestData));
291
+ // console.log('getOauth1Token - headers:', headers);
292
+ const response = await this.get(url, {
293
+ headers: {
294
+ ...headers,
295
+ 'User-Agent': USER_AGENT_CONNECTMOBILE
296
+ }
297
+ });
298
+ // console.log('getOauth1Token - response:', response);
299
+ const token = qs_1.default.parse(response);
300
+ // console.log('getOauth1Token - token:', token);
301
+ this.oauth1Token = token;
302
+ return { token, oauth };
303
+ }
304
+ getOauthClient(consumer) {
305
+ const oauth = new oauth_1_0a_1.default({
306
+ consumer: consumer,
307
+ signature_method: 'HMAC-SHA1',
308
+ hash_function(base_string, key) {
309
+ return node_crypto_1.default
310
+ .createHmac('sha1', key)
311
+ .update(base_string)
312
+ .digest('base64');
313
+ }
314
+ });
315
+ return oauth;
316
+ }
317
+ //
318
+ async exchange(oauth1) {
319
+ const token = {
320
+ key: oauth1.token.oauth_token,
321
+ secret: oauth1.token.oauth_token_secret
322
+ };
323
+ // console.log('exchange - token:', token);
324
+ const baseUrl = `${this.url.OAUTH_URL}/exchange/user/2.0`;
325
+ const requestData = {
326
+ url: baseUrl,
327
+ method: 'POST',
328
+ data: null
329
+ };
330
+ const step5AuthData = oauth1.oauth.authorize(requestData, token);
331
+ // console.log('login - step5AuthData:', step5AuthData);
332
+ const url = `${baseUrl}?${qs_1.default.stringify(step5AuthData)}`;
333
+ // console.log('exchange - url:', url);
334
+ this.oauth2Token = undefined;
335
+ const response = await this.post(url, null, {
336
+ headers: {
337
+ 'User-Agent': USER_AGENT_CONNECTMOBILE,
338
+ 'Content-Type': 'application/x-www-form-urlencoded'
339
+ }
340
+ });
341
+ // console.log('exchange - response:', response);
342
+ this.oauth2Token = this.setOauth2TokenExpiresAt(response);
343
+ // console.log('exchange - oauth2Token:', this.oauth2Token);
344
+ }
345
+ setOauth2TokenExpiresAt(token) {
346
+ const now = luxon_1.DateTime.now();
347
+ const expiresAt = now.plus({ seconds: token.expires_in });
348
+ const refreshTokenExpiresAt = now.plus({
349
+ seconds: token.refresh_token_expires_in
350
+ });
351
+ return {
352
+ ...token,
353
+ last_update_date: now.toLocal().toString(),
354
+ expires_date: expiresAt.toLocal().toString(),
355
+ expires_at: expiresAt.toSeconds(),
356
+ refresh_token_expires_at: refreshTokenExpiresAt.toSeconds()
357
+ };
358
+ }
359
+ }
360
+ exports.HttpClient = HttpClient;
361
+ //# sourceMappingURL=HttpClientOLDV1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClientOLDV1.js","sourceRoot":"","sources":["../../src/common/HttpClientOLDV1.ts"],"names":[],"mappings":";;;;;;AAAA,kDAKe;AACf,0DAAiC;AACjC,oDAAuB;AACvB,iCAAiC;AACjC,4DAA+B;AAC/B,4CAAoB;AASpB,8DAAiC;AAEjC,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,+BAA+B,CAAC,CAAC;AAC5D,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAChD,MAAM,iBAAiB,GAAG,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC;AACjE,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAE3D,MAAM,wBAAwB,GAAG,uCAAuC,CAAC;AACzE,MAAM,kBAAkB,GACpB,iHAAiH,CAAC;AACtH,MAAM,sBAAsB,GACxB,uHAAuH,CAAC;AAC5H,MAAM,kBAAkB,GACpB,uDAAuD,CAAC;AAO5D,MAAM,WAAW,GAAG;IAChB,YAAY,EAAE,GAAG;CACX,CAAC;AAEX,IAAI,mBAAmB,GAAyB,IAAI,CAAC;AACrD,IAAI,kBAAkB,GAAwB,EAAE,CAAC;AAEjD,MAAa,UAAU;IAQnB,YAAY,GAAa,EAAE,MAAgB;;QACvC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,eAAK,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,mCAAI,IAAI;YAChC,mBAAmB,EAAE,sBACjB,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,mCAAI,IACvB,KAAK;YAEL;;;eAGG;YACH,WAAW;YACX,yBAAyB;YACzB,kBAAkB;YAClB,uBAAuB;YACvB,KAAK;YACL,6CAA6C;YAC7C,gCAAgC;YAChC,KAAK;SACR,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CACjC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EACtB,KAAK,EAAE,KAAK,EAAE,EAAE;;YACZ,IACI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC;gBACzB,KAAK,CAAC,IAAI,KAAK,cAAc,EAC/B;gBACE,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,iBAAiB,CAAC,CAAC;aACvD;YAED,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC;YAErC,IACI,CAAA,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,QAAQ,0CAAE,MAAM,MAAK,WAAW,CAAC,YAAY;gBACpD,CAAC,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,MAAM,CAAA,EAC1B;gBACE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;oBACnB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;iBAChD;gBAED,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC;gBAE9B,IAAI;oBACA,IAAI,CAAC,mBAAmB,EAAE;wBACtB,mBAAmB;4BACf,IAAI,CAAC,kBAAkB,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;gCACnC,mBAAmB,GAAG,IAAI,CAAC;4BAC/B,CAAC,CAAC,CAAC;qBACV;oBAED,MAAM,mBAAmB,CAAC;oBAE1B,eAAe,CAAC,OAAO,CAAC,aAAa,GAAG,UAAU,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;oBAClF,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;iBACvC;gBAAC,OAAO,GAAG,EAAE;oBACV,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;oBAC5C,MAAM,GAAG,CAAC;iBACb;aACJ;YAED,IAAI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE;gBAC7C,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;aACpC;iBAAM;gBACH,kBAAkB;gBAClB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;aAC9D;YACD,MAAM,KAAK,CAAC;QAChB,CAAC,CACJ,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,WAAW,EAAE;gBAClB,MAAM,CAAC,OAAO,CAAC,aAAa;oBACxB,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;aACjD;YACD,OAAO,MAAM,CAAC;QAClB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,kBAAkB;QACpB,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QACrD,IAAI,CAAC,cAAc,GAAG;YAClB,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe;SACxC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,eAAe;QACjB,IAAI,IAAI,CAAC,WAAW,EAAE;YAClB,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE;gBAC1D,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;gBAChC,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;aACnC;SACJ;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,MAAgC;QACtD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAI,GAAG,EAAE,MAAM,CAAC,CAAC;QACvD,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CACN,GAAW,EACX,IAAS,EACT,MAAgC;QAEhC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC9D,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,GAAG,CACL,GAAW,EACX,IAAS,EACT,MAAgC;QAEhC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7D,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,MAAM,CAAI,GAAW,EAAE,MAAgC;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAI,GAAG,EAAE,IAAI,EAAE;YAClD,GAAG,MAAM;YACT,OAAO,EAAE;gBACL,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO;gBAClB,wBAAwB,EAAE,QAAQ;aACrC;SACJ,CAAC,CAAC;QACH,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;IAC1B,CAAC;IAED,eAAe,CAAC,OAA+B;QAC3C,gBAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,EAAE;YACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;QAC3D,CAAC,CAAC,CAAC;IACP,CAAC;IAED,WAAW,CAAC,QAAuB;QAC/B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,eAAe,CAAC,QAAuB;QACnC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAC9C,MAAM,YAAY,GAAG;YACjB,MAAM;YACN,UAAU;YACV,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SAC/D,CAAC;QAEF,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,MAAM,UAAU,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,QAAgB,EAAE,WAAmC;QAC/E,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAChC,iCAAiC;QACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7D,gBAAgB;QAChB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACjD,mBAAmB;QAEnB,iBAAiB;QACjB,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,cAAc,CACxB,QAAgB,EAChB,QAAgB;QAEhB,oBAAoB;QACpB,MAAM,WAAW,GAAG;YAChB,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS;SAC9B,CAAC;QACF,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,YAAE,CAAC,SAAS,CACzD,WAAW,CACd,EAAE,CAAC;QACJ,8CAA8C;QAC9C,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEhC,kBAAkB;QAClB,MAAM,WAAW,GAAG;YAChB,EAAE,EAAE,cAAc;YAClB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;SACvC,CAAC;QACF,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,YAAE,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;QACvE,8CAA8C;QAC9C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,GAAG,CAAS,QAAQ,CAAC,CAAC;QACrD,mDAAmD;QACnD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC,aAAa,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;SAC7C;QACD,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACpC,4CAA4C;QAE5C,mBAAmB;QACnB,MAAM,YAAY,GAAG;YACjB,EAAE,EAAE,cAAc;YAClB,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;YACpC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;YAClC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;YACjC,4BAA4B,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;YACvD,+BAA+B,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;SAC7D,CAAC;QACF,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,YAAE,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC;QACxE,8CAA8C;QAC9C,MAAM,SAAS,GAAG,IAAI,mBAAQ,EAAE,CAAC;QACjC,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACvC,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACvC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,IAAI,CAAS,QAAQ,EAAE,SAAS,EAAE;YAC7D,OAAO,EAAE;gBACL,cAAc,EAAE,mCAAmC;gBACnD,GAAG,EAAE,CAAC;gBACN,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB;gBAClC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU;gBAC5B,YAAY,EAAE,kBAAkB;aACnC;SACJ,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA;QACxC,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAE5B,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,eAAe,EAAE;YAClB,MAAM,IAAI,KAAK,CACX,4EAA4E,CAC/E,CAAC;SACL;QACD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,mBAAmB;IACnB,SAAS,CAAC,OAAe,IAAS,CAAC;IAEnC,4BAA4B;IAC5B,eAAe,CAAC,OAAe;QAC3B,MAAM,mBAAmB,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,mBAAmB,EAAE;YACrB,MAAM,KAAK,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YACxC,IAAI,gBAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC,EAAE;gBAC1C,0CAA0C;gBAC1C,iDAAiD;gBACjD,MAAM,IAAI,KAAK,CACX,qHAAqH,CACxH,CAAC;aACL;SACJ;IACL,CAAC;IAED,mBAAmB,CAAC,OAAe;QAC/B,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/D,IAAI,sBAAsB,EAAE;YACxB,MAAM,GAAG,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;YACtC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,MAAM,IAAI,KAAK,CACX,mFAAmF,CACtF,CAAC;SACL;IACL,CAAC;IAED,KAAK,CAAC,kBAAkB;QACpB,IAAI;YACA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBACtB,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;aACnC;YAED,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;gBACxC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;aAC1D;YAED,MAAM,MAAM,GAAG;gBACX,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAe,CAAC;gBAChD,KAAK,EAAE,IAAI,CAAC,WAAW;aAC1B,CAAC;YAEF,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CACP,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,uCAAuC,CACxF,CAAC;SACL;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;YACxD,MAAM,KAAK,CAAC;SACf;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc;QAC/B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;SACxC;QACD,MAAM,MAAM,GAAG;YACX,MAAM;YACN,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB;YACtC,oBAAoB,EAAE,IAAI;SAC7B,CAAC;QACF,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,kBAAkB,YAAE,CAAC,SAAS,CAC3D,MAAM,CACT,EAAE,CAAC;QAEJ,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEvD,MAAM,gBAAgB,GAAG;YACrB,GAAG,EAAE,GAAG;YACR,MAAM,EAAE,KAAK;SAChB,CAAC;QACF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAClE,qDAAqD;QAErD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAS,GAAG,EAAE;YACzC,OAAO,EAAE;gBACL,GAAG,OAAO;gBACV,YAAY,EAAE,wBAAwB;aACzC;SACJ,CAAC,CAAC;QACH,uDAAuD;QACvD,MAAM,KAAK,GAAG,YAAE,CAAC,KAAK,CAAC,QAAQ,CAA4B,CAAC;QAC5D,iDAAiD;QACjD,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,cAAc,CAAC,QAAyB;QACpC,MAAM,KAAK,GAAG,IAAI,oBAAK,CAAC;YACpB,QAAQ,EAAE,QAAQ;YAClB,gBAAgB,EAAE,WAAW;YAC7B,aAAa,CAAC,WAAmB,EAAE,GAAW;gBAC1C,OAAO,qBAAM;qBACR,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC;qBACvB,MAAM,CAAC,WAAW,CAAC;qBACnB,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;SACJ,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,EAAE;IACF,KAAK,CAAC,QAAQ,CAAC,MAAe;QAC1B,MAAM,KAAK,GAAG;YACV,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW;YAC7B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,kBAAkB;SAC1C,CAAC;QACF,2CAA2C;QAE3C,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,oBAAoB,CAAC;QAC1D,MAAM,WAAW,GAAG;YAChB,GAAG,EAAE,OAAO;YACZ,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;SACb,CAAC;QAEF,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACjE,wDAAwD;QACxD,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,YAAE,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;QACxD,uCAAuC;QACvC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAe,GAAG,EAAE,IAAI,EAAE;YACtD,OAAO,EAAE;gBACL,YAAY,EAAE,wBAAwB;gBACtC,cAAc,EAAE,mCAAmC;aACtD;SACJ,CAAC,CAAC;QACH,iDAAiD;QACjD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QAC1D,4DAA4D;IAChE,CAAC;IAED,uBAAuB,CAAC,KAAmB;QACvC,MAAM,GAAG,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1D,MAAM,qBAAqB,GAAG,GAAG,CAAC,IAAI,CAAC;YACnC,OAAO,EAAE,KAAK,CAAC,wBAAwB;SAC1C,CAAC,CAAC;QAEH,OAAO;YACH,GAAG,KAAK;YACR,gBAAgB,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC1C,YAAY,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC5C,UAAU,EAAE,SAAS,CAAC,SAAS,EAAE;YACjC,wBAAwB,EAAE,qBAAqB,CAAC,SAAS,EAAE;SAC9D,CAAC;IACN,CAAC;CACJ;AAtZD,gCAsZC"}
@@ -0,0 +1,77 @@
1
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse, RawAxiosRequestHeaders } from 'axios';
2
+ import OAuth from 'oauth-1.0a';
3
+ import { UrlClass } from '../garmin/UrlClass';
4
+ import { GCConfig, IOauth1, IOauth1Consumer, IOauth1Token, IOauth2Token } from '../garmin/types';
5
+ export declare class HttpClient {
6
+ client: AxiosInstance;
7
+ url: UrlClass;
8
+ config: GCConfig;
9
+ oauth1Token: IOauth1Token | undefined;
10
+ oauth2Token: IOauth2Token | undefined;
11
+ OAUTH_CONSUMER: IOauth1Consumer | undefined;
12
+ constructor(url: UrlClass, config: GCConfig);
13
+ fetchOauthConsumer(): Promise<void>;
14
+ checkTokenVaild(): Promise<void>;
15
+ get<T>(url: string, config?: AxiosRequestConfig<any>): Promise<T>;
16
+ post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
17
+ put<T>(url: string, data: any, config?: AxiosRequestConfig<any>): Promise<T>;
18
+ delete<T>(url: string, config?: AxiosRequestConfig<any>): Promise<T>;
19
+ setCommonHeader(headers: RawAxiosRequestHeaders): void;
20
+ handleError(response: AxiosResponse): void;
21
+ handleHttpError(response: AxiosResponse): void;
22
+ /**
23
+ * Login to Garmin Connect
24
+ * @param username
25
+ * @param password
26
+ * @param mfaCallback Optional MFA callback function
27
+ * @returns {Promise<{oauth1: IOauth1; oauth2: IOauth2Token}>}
28
+ */
29
+ login(username: string, password: string, mfaCallback?: () => Promise<string>): Promise<{
30
+ oauth1: IOauth1;
31
+ oauth2: IOauth2Token;
32
+ }>;
33
+ /**
34
+ * 保存HTML内容到文件,用于调试
35
+ * @param htmlContent HTML内容
36
+ * @param filename 文件名(不含扩展名)
37
+ */
38
+ saveHtmlToFile(htmlContent: string, filename: string): void;
39
+ /**
40
+ * 处理MFA验证
41
+ * @param loginResponse 登录响应HTML
42
+ * @param signinParams 登录参数
43
+ * @param mfaCallback MFA验证码回调函数
44
+ * @returns MFA验证响应
45
+ */
46
+ handleMfaVerification(loginResponse: string, signinParams: any, mfaCallback: () => Promise<string>): Promise<string>;
47
+ /**
48
+ * 从HTML中提取CSRF令牌
49
+ * @param html HTML字符串
50
+ * @returns CSRF令牌或null
51
+ */
52
+ extractCsrfToken(html: string): string | null;
53
+ /**
54
+ * 从HTML中提取页面标题
55
+ * @param html HTML字符串
56
+ * @returns 页面标题或空字符串
57
+ */
58
+ extractPageTitle(html: string): string;
59
+ /**
60
+ * 从HTML中提取ticket
61
+ * @param html HTML字符串
62
+ * @returns ticket或null
63
+ */
64
+ extractTicket(html: string): string | null;
65
+ /**
66
+ * 处理页面标题
67
+ * @param htmlStr HTML字符串
68
+ * @returns 页面标题
69
+ */
70
+ handlePageTitle(htmlStr: string): string;
71
+ handleAccountLocked(htmlStr: string): void;
72
+ refreshOauth2Token(): Promise<void>;
73
+ getOauth1Token(ticket: string): Promise<IOauth1>;
74
+ getOauthClient(consumer: IOauth1Consumer): OAuth;
75
+ exchange(oauth1: IOauth1): Promise<void>;
76
+ setOauth2TokenExpiresAt(token: IOauth2Token): IOauth2Token;
77
+ }