git-fit 0.12.0 → 0.13.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2f295d660e818e0baf5fcd3a624aabff068288c1cc93cbb4a661b046fd58a3c
4
- data.tar.gz: ee63230c3e1ae93aa7ef1bec736b5011ccbfcf013b35e70c39afcc38acbe2c06
3
+ metadata.gz: c3e935c4e4949dfd80ef84c659f9f64a727d9c1d3aab7c2b6303d6571f42156b
4
+ data.tar.gz: 771f645e5ae8a369c89237d3df03c00b06d5887f5331e7cfec306af0c57f8eb6
5
5
  SHA512:
6
- metadata.gz: 6498333581ad0d68044f77c8de1ffddb1a3a4f6634a92f99081df76e5dda26fc7eb25eeb0eaf8ac0b04637db40257d43ade12c2325a6ebdec63cb95430964113
7
- data.tar.gz: edda04a53ebaadd13d4bd15c325251bf4ab0f7b500917fe323c52968ca55303162f5fe95a62f4baaf2734ff8e9dc278c1786e44506b32fedcbb9cad43dbfe5c2
6
+ metadata.gz: 926a648129246714657066e5d7a21b9663682af63516a98d21646e9c58167b4c962150697a8d1d9e14068c834d1d010f9d3696628f8edae9b6ee8f2c614d36cc
7
+ data.tar.gz: 7bebd70ae9b51e18fc97278f7e691466ea5ca4aec07594c83bc7ca2c9ff913f85566dcf9b98b6013a279a3c2927216fd60ad82d860d8185b8fb133a873fbc5fe
data/lib/git-fit.rb CHANGED
@@ -63,7 +63,7 @@ require_relative 'git_fit/util'
63
63
  require_relative 'git_fit/sync/lorem'
64
64
  require_relative 'git_fit/sync/garmin_base'
65
65
  require_relative 'git_fit/sync/garmin_base_di'
66
- require_relative 'git_fit/sync/garmin'
66
+ require_relative 'git_fit/sync/garmin_com'
67
67
  require_relative 'git_fit/sync/garmin_cn'
68
68
  require_relative 'git_fit/sync/strava'
69
69
  require_relative 'git_fit/sync/keep'
@@ -15,7 +15,7 @@ module GitFit
15
15
  # Persists the pre-auth login session created during an interrupted MFA
16
16
  # flow. This is a *temporary* session (30-minute TTL matching the MFA code
17
17
  # validity window), distinct from the long-lived persistent session cookie
18
- # (garmin_playwright_session_*.json) that Strategy B keeps after success.
18
+ # (data/auth/garmin/session.json) that Strategy B keeps after success.
19
19
  module LoginSession
20
20
  DIR = 'data/cache'
21
21
  TTL_SECONDS = 30 * 60
@@ -2,7 +2,8 @@
2
2
 
3
3
  require_relative 'di_exchange'
4
4
  require_relative 'login_session'
5
- require_relative '../../sync/garmin_base'
5
+ require_relative '../../sync/garmin_com'
6
+ require_relative '../paths'
6
7
  require 'json'
7
8
  require 'fileutils'
8
9
 
@@ -18,7 +19,6 @@ module GitFit
18
19
  MOBILE_SERVICE = 'https://mobile.integration.garmin.com/gcm/android'
19
20
  LOGIN_DELAY_MIN = 30.0
20
21
  LOGIN_DELAY_MAX = 45.0
21
- SESSION_CACHE_DIR = 'data/cache'
22
22
  REDIRECT_STATUSES = [301, 302, 303, 307, 308].freeze
23
23
  AUTH_FLAG = '-B'
24
24
 
@@ -204,8 +204,8 @@ module GitFit
204
204
  sleep(delay)
205
205
  end
206
206
 
207
- def _session_file_path(domain)
208
- File.join(SESSION_CACHE_DIR, "garmin_playwright_session_#{domain.tr('.', '_')}.json")
207
+ def _session_file_path(_domain)
208
+ Auth.file(GitFit::Sync::GarminCom.source_prefix, 'session.json')
209
209
  end
210
210
 
211
211
  def _load_session(session_path)
@@ -4,6 +4,8 @@ require_relative 'garmin/strategy_a'
4
4
  require_relative 'garmin/strategy_b'
5
5
  require_relative 'garmin/di_exchange'
6
6
  require_relative 'garmin/login_session'
7
+ require_relative 'paths'
8
+ require_relative '../sync/garmin_com'
7
9
  require_relative '../config'
8
10
  require_relative '../cli/gh_cli'
9
11
  require 'json'
@@ -189,7 +191,7 @@ module GitFit
189
191
 
190
192
  def token_path
191
193
  garmin_cfg['token_path'] ||
192
- File.join('data', 'auth', "garmin_#{domain.tr('.', '_')}_tokens.json")
194
+ Auth.file(GitFit::Sync::GarminCom.source_prefix, 'tokens.json')
193
195
  end
194
196
 
195
197
  def gh_ladder(seed)
@@ -10,7 +10,7 @@ module GitFit
10
10
  # commands, CI token checks).
11
11
  class GarminToken
12
12
  def self.for_intl(config)
13
- authenticate_with(GitFit::Sync::Garmin, config, 'garmin.com')
13
+ authenticate_with(GitFit::Sync::GarminCom, config, 'garmin.com')
14
14
  end
15
15
 
16
16
  def self.for_cn(config)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitFit
4
+ module Auth
5
+ module_function
6
+
7
+ # Canonical per-source auth storage: data/auth/{source}/{name}. All sync
8
+ # adapters, the auth orchestrator and strategies must resolve token/session
9
+ # defaults through this helper so they can never drift apart.
10
+ def file(source, name)
11
+ File.join('data', 'auth', source, name)
12
+ end
13
+ end
14
+ end
@@ -4,6 +4,7 @@ require 'thor'
4
4
  require 'fileutils'
5
5
  require 'tzinfo'
6
6
  require 'stravaweb'
7
+ require_relative '../auth/paths'
7
8
 
8
9
  module GitFit
9
10
  class StravaCLI < Thor
@@ -60,7 +61,7 @@ module GitFit
60
61
  FileUtils.mkdir_p(output_dir)
61
62
  cache_dir = File.join('data', 'cache', 'strava_downloads')
62
63
  FileUtils.mkdir_p(cache_dir)
63
- cookie_path = File.join('data', 'cache', 'strava_session.yml')
64
+ cookie_path = web_cfg['cookie_path'] || GitFit::Auth.file('strava', 'session.yml')
64
65
 
65
66
  if activity_ids.empty?
66
67
  activity_ids = pending_ids(config, output_dir)
@@ -19,6 +19,7 @@ module GitFit
19
19
  # web_auth: # web original-file fetch (git fit strava fetch)
20
20
  # jwt: "" # env: GIT_FIT_STRAVA_WEB_AUTH_JWT (strava_remember_token)
21
21
  # auth_seed: "" # env: GIT_FIT_STRAVA_WEB_AUTH_AUTH_SEED (base64 JWT)
22
+ # cookie_path: "" # default data/auth/strava/session.yml
22
23
 
23
24
  # garmin: # env: GIT_FIT_GARMIN_EMAIL
24
25
  # email: "" # env: GIT_FIT_GARMIN_PASSWORD
@@ -44,12 +45,14 @@ module GitFit
44
45
  # xoss: # env: GIT_FIT_XOSS_EMAIL
45
46
  # email: "" # env: GIT_FIT_XOSS_PASSWORD
46
47
  # password: ""
48
+ # token_path: "" # env: GIT_FIT_XOSS_TOKEN_PATH
49
+ # # default data/auth/xoss/tokens.json
47
50
 
48
51
  # xingzhe: # env: GIT_FIT_XINGZHE_EMAIL
49
52
  # email: "" # env: GIT_FIT_XINGZHE_PASSWORD
50
53
  # password: ""
51
54
  # session_path: "" # env: GIT_FIT_XINGZHE_SESSION_PATH
52
- # # default data/cache/xingzhe_session.json
55
+ # # default data/auth/xingzhe/session.json
53
56
 
54
57
  export:
55
58
  json:
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'base'
4
4
  require_relative '../fit/decoder'
5
+ require_relative '../auth/paths'
5
6
  require 'ostruct'
6
7
  require 'base64'
7
8
  require 'oauth'
@@ -29,12 +30,17 @@ module GitFit
29
30
  OAUTH_CONSUMER_URL = 'https://thegarth.s3.amazonaws.com/oauth_consumer.json'
30
31
 
31
32
  SSO_HEADERS = {
32
- 'User-Agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
33
+ 'User-Agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) ' \
34
+ 'AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
33
35
  'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
34
36
  'Accept-Language' => 'en-US,en;q=0.9',
35
37
  }.freeze
36
38
 
37
39
  def initialize(...)
40
+ if instance_of?(GarminBase)
41
+ raise NotImplementedError,
42
+ 'GarminBase is abstract — instantiate a concrete subclass (Garmin, GarminCN)'
43
+ end
38
44
  super
39
45
  @domain = 'garmin.com'
40
46
  @email = @config['email']
@@ -53,19 +59,18 @@ module GitFit
53
59
  def authenticate
54
60
  @oauth_consumer = fetch_oauth_consumer
55
61
 
56
- if @secret
57
- if parse_secret_string(@secret)
58
- if access_token_valid?
59
- @auth_method = 'secret'
62
+ if @secret && parse_secret_string(@secret)
63
+ if access_token_valid?
64
+ @auth_method = 'secret'
65
+ return true
66
+ end
67
+ begin
68
+ if refresh_oauth2_via_oauth1
69
+ @auth_method = 'refreshed'
60
70
  return true
61
71
  end
62
- begin
63
- if refresh_oauth2_via_oauth1
64
- @auth_method = 'refreshed'
65
- return true
66
- end
67
- rescue AuthError
68
- end
72
+ rescue AuthError => e
73
+ warn e.message
69
74
  end
70
75
  end
71
76
 
@@ -144,6 +149,14 @@ module GitFit
144
149
  attrs
145
150
  end
146
151
 
152
+ def self.source_prefix
153
+ raise NotImplementedError, "#{self} must implement source_prefix"
154
+ end
155
+
156
+ def source_prefix
157
+ self.class.source_prefix
158
+ end
159
+
147
160
  private
148
161
 
149
162
  def access_token_valid?
@@ -164,7 +177,7 @@ module GitFit
164
177
  oauth_token: o1['oauth_token'],
165
178
  oauth_token_secret: o1['oauth_token_secret'],
166
179
  mfa_token: o1['mfa_token'],
167
- domain: @domain
180
+ domain: @domain,
168
181
  )
169
182
  @access_token = o2
170
183
  true
@@ -190,7 +203,7 @@ module GitFit
190
203
  return unless File.exist?(path)
191
204
 
192
205
  cfg = YAML.safe_load(File.read(path)) || {}
193
- source = @domain == 'garmin.cn' ? 'garmin_cn' : 'garmin'
206
+ source = source_prefix
194
207
  cfg['sync'] ||= {}
195
208
  cfg['sync'][source] ||= {}
196
209
  cfg['sync'][source]['secret'] = @generated_secret
@@ -222,8 +235,8 @@ module GitFit
222
235
  save_tokens
223
236
  true
224
237
  rescue StandardError => e
225
- raise AuthError, "Garmin OAuth refresh failed: #{e.message}" +
226
- " — #{reauth_hint}"
238
+ raise AuthError, "Garmin OAuth refresh failed: #{e.message}" \
239
+ " — #{reauth_hint}"
227
240
  end
228
241
 
229
242
  def fetch_oauth_consumer
@@ -258,16 +271,14 @@ module GitFit
258
271
  mfaVerificationCode: mfa_code,
259
272
  rememberMyBrowser: false,
260
273
  reconsentList: [],
261
- mfaSetup: false
274
+ mfaSetup: false,
262
275
  )
263
276
  resp = sso_post(sso_base, '/mobile/api/mfa/verifyCode', login_params, mfa_body, jar)
264
277
  body = JSON.parse(resp.body)
265
278
  status = body.dig('responseStatus', 'type')
266
279
  end
267
280
 
268
- unless status == 'SUCCESSFUL'
269
- raise "Garmin login failed (#{body.dig("responseStatus", "message") || status})"
270
- end
281
+ raise "Garmin login failed (#{body.dig('responseStatus', 'message') || status})" unless status == 'SUCCESSFUL'
271
282
 
272
283
  body['serviceTicketId']
273
284
  end
@@ -314,7 +325,8 @@ module GitFit
314
325
  def fetch_oauth1_token(ticket)
315
326
  base_url = "https://connectapi.#{@domain}/oauth-service/oauth/"
316
327
  login_url = "https://mobile.integration.#{@domain}/gcm/android"
317
- url = "#{base_url}preauthorized?ticket=#{CGI.escape(ticket)}&login-url=#{CGI.escape(login_url)}&accepts-mfa-tokens=true"
328
+ url = "#{base_url}preauthorized?ticket=#{CGI.escape(ticket)}" \
329
+ "&login-url=#{CGI.escape(login_url)}&accepts-mfa-tokens=true"
318
330
 
319
331
  oauth_consumer = OAuth::Consumer.new(
320
332
  @oauth_consumer['consumer_key'], @oauth_consumer['consumer_secret'],
@@ -328,7 +340,7 @@ module GitFit
328
340
  req['User-Agent'] = 'com.garmin.android.apps.connectmobile'
329
341
  oauth_consumer.sign!(req, nil)
330
342
 
331
- resp = retry_on_429(3, 5) { send_http(URI(url), req) }
343
+ resp = retry_on_rate_limit(3, 5) { send_http(URI(url), req) }
332
344
  raise "OAuth1 error: #{resp.code}" unless resp.code.to_i == 200
333
345
 
334
346
  parsed = CGI.parse(resp.body).transform_keys(&:to_s).transform_values(&:first)
@@ -337,7 +349,7 @@ module GitFit
337
349
  oauth_token: parsed['oauth_token'],
338
350
  oauth_token_secret: parsed['oauth_token_secret'],
339
351
  mfa_token: parsed['mfa_token'],
340
- domain: @domain
352
+ domain: @domain,
341
353
  )
342
354
  end
343
355
 
@@ -359,7 +371,7 @@ module GitFit
359
371
  req.body = URI.encode_www_form(body_params)
360
372
  oauth_consumer.sign!(req, token)
361
373
 
362
- resp = retry_on_429 { send_http(URI(url), req) }
374
+ resp = retry_on_rate_limit { send_http(URI(url), req) }
363
375
  raise "OAuth2 exchange error: #{resp.code}" unless resp.code.to_i == 200
364
376
 
365
377
  result = JSON.parse(resp.body)
@@ -374,7 +386,7 @@ module GitFit
374
386
 
375
387
  def existing_run_ids
376
388
  @db[:activities].where(source: source_prefix).select_map(:run_id)
377
- .map { |id| id.sub("#{source_prefix}_", '') }
389
+ .map { |id| id.sub("#{source_prefix}_", '') }
378
390
  end
379
391
 
380
392
  def fetch_activity_list(start, limit)
@@ -388,9 +400,9 @@ module GitFit
388
400
  def api_get(path)
389
401
  uri = URI("#{connectapi_base}#{path}")
390
402
  req = Net::HTTP::Get.new(uri)
391
- req['Authorization'] = "Bearer #{@access_token["access_token"]}"
403
+ req['Authorization'] = "Bearer #{@access_token['access_token']}"
392
404
  req['User-Agent'] = 'GCM-iOS-5.22.1.4'
393
- resp = retry_on_429 { send_http(uri, req) }
405
+ resp = retry_on_rate_limit { send_http(uri, req) }
394
406
  return nil unless resp.code.to_i == 200
395
407
  JSON.parse(resp.body)
396
408
  end
@@ -408,14 +420,14 @@ module GitFit
408
420
  http.start { |h| h.request(request) }
409
421
  end
410
422
 
411
- def retry_on_429(max_retries = 3, base_delay = 2)
423
+ def retry_on_rate_limit(max_retries = 3, base_delay = 2)
412
424
  retries = 0
413
425
  loop do
414
426
  resp = yield
415
427
  return resp unless resp.code.to_i == 429 && retries < max_retries
416
428
 
417
429
  retries += 1
418
- sleep(base_delay * (2 ** retries))
430
+ sleep(base_delay * (2**retries))
419
431
  end
420
432
  end
421
433
 
@@ -424,15 +436,17 @@ module GitFit
424
436
  end
425
437
 
426
438
  def resolve_local_time(start_utc, activity_id, polyline = nil)
427
- lat = lng = nil
439
+ nil
428
440
 
429
441
  lat, lng = first_gps_from_l2(activity_id)
430
442
 
431
443
  if lat.nil? && polyline
432
- decoded = GitFit::Geo::Polyline.decode(polyline) rescue nil
433
- if decoded && decoded.any?
434
- lat, lng = decoded.first
444
+ decoded = begin
445
+ GitFit::Geo::Polyline.decode(polyline)
446
+ rescue StandardError
447
+ nil
435
448
  end
449
+ lat, lng = decoded.first if decoded&.any?
436
450
  end
437
451
 
438
452
  tz_string = tz_resolver.resolve(lat, lng)
@@ -450,11 +464,11 @@ module GitFit
450
464
  l2 = JSON.parse(File.read(l2_path))
451
465
  return [nil, nil] unless l2.is_a?(Array) && l2.any?
452
466
 
453
- first = l2.find { |r|
467
+ first = l2.find do |r|
454
468
  lat = r['positionLat']
455
469
  lng = r['positionLong']
456
470
  lat && lng && lat.to_f != 0.0 && lng.to_f != 0.0
457
- }
471
+ end
458
472
  return [nil, nil] unless first
459
473
 
460
474
  [first['positionLat'].to_f, first['positionLong'].to_f]
@@ -462,10 +476,6 @@ module GitFit
462
476
  [nil, nil]
463
477
  end
464
478
 
465
- def source_prefix
466
- 'garmin'
467
- end
468
-
469
479
  def reauth_hint
470
480
  "Re-auth: set sync.#{source_prefix}.secret in config/config.yml"
471
481
  end
@@ -560,7 +570,7 @@ module GitFit
560
570
  oauth_token: o1['oauth_token'],
561
571
  oauth_token_secret: o1['oauth_token_secret'],
562
572
  mfa_token: o1['mfa_token'],
563
- domain: @domain
573
+ domain: @domain,
564
574
  )
565
575
  @access_token = data['oauth2']
566
576
  @saved_expires_at = @access_token&.dig('expires_at')
@@ -571,7 +581,7 @@ module GitFit
571
581
  end
572
582
 
573
583
  def token_path
574
- @config['token_path'] || File.join('data', 'auth', "garmin_#{@domain.tr(".", "_")}_tokens.json")
584
+ @config['token_path'] || GitFit::Auth.file(source_prefix, 'tokens.json')
575
585
  end
576
586
 
577
587
  FIT_EPOCH = 631_065_600
@@ -598,9 +608,9 @@ module GitFit
598
608
  def download_fit_raw(activity_id)
599
609
  uri = URI("#{connectapi_base}/download-service/files/activity/#{activity_id}")
600
610
  req = Net::HTTP::Get.new(uri)
601
- req['Authorization'] = "Bearer #{@access_token.fetch("access_token")}"
611
+ req['Authorization'] = "Bearer #{@access_token.fetch('access_token')}"
602
612
  req['User-Agent'] = 'GCM-iOS-5.22.1.4'
603
- resp = retry_on_429 { send_http(uri, req) }
613
+ resp = retry_on_rate_limit { send_http(uri, req) }
604
614
  return false unless resp.code.to_i == 200
605
615
 
606
616
  zip_data = resp.body
@@ -652,13 +662,13 @@ module GitFit
652
662
  nil
653
663
  end
654
664
 
655
- def write_standardized_json(l2, activity_id)
656
- return unless l2
665
+ def write_standardized_json(l2_data, activity_id)
666
+ return unless l2_data
657
667
 
658
668
  dir = std_dir
659
669
  FileUtils.mkdir_p(dir)
660
670
  tmp = File.join(dir, ".#{activity_id}.json.tmp")
661
- File.write(tmp, JSON.generate(l2))
671
+ File.write(tmp, JSON.generate(l2_data))
662
672
  File.rename(tmp, std_path(activity_id))
663
673
  end
664
674
  end
@@ -5,6 +5,10 @@ require_relative 'garmin_base'
5
5
  module GitFit
6
6
  module Sync
7
7
  class GarminBaseDI < GarminBase
8
+ def self.source_prefix
9
+ 'garmin'
10
+ end
11
+
8
12
  DI_CLIENT_IDS = %w[
9
13
  GARMIN_CONNECT_MOBILE_ANDROID_DI_2025Q2
10
14
  GARMIN_CONNECT_MOBILE_ANDROID_DI_2024Q4
@@ -131,10 +135,10 @@ module GitFit
131
135
  req.body = URI.encode_www_form(
132
136
  grant_type: 'refresh_token',
133
137
  client_id: client_id,
134
- refresh_token: @access_token['refresh_token']
138
+ refresh_token: @access_token['refresh_token'],
135
139
  )
136
140
 
137
- resp = retry_on_429 { send_http(uri, req) }
141
+ resp = retry_on_rate_limit { send_http(uri, req) }
138
142
  unless resp.code.to_i == 200
139
143
  msg = "DI refresh error: #{resp.code}"
140
144
  if resp.code.to_i == 400
@@ -8,6 +8,10 @@ module GitFit
8
8
  register_adapter
9
9
  register_config :email, :password, :secret, :token_path
10
10
 
11
+ def self.source_prefix
12
+ 'garmin_cn'
13
+ end
14
+
11
15
  def initialize(config:, db:, activity_filter: nil, privacy: nil, time_budget: nil)
12
16
  super
13
17
  @domain = 'garmin.cn'
@@ -21,10 +25,6 @@ module GitFit
21
25
  def std_dir
22
26
  File.join('data', 'std', 'garmin_cn')
23
27
  end
24
-
25
- def source_prefix
26
- 'garmin_cn'
27
- end
28
28
  end
29
29
  end
30
30
  end
@@ -4,15 +4,21 @@ require_relative 'garmin_base_di'
4
4
 
5
5
  module GitFit
6
6
  module Sync
7
- class Garmin < GarminBaseDI
7
+ class GarminCom < GarminBaseDI
8
8
  register_adapter
9
- register_config :email, :password, :secret, :auth_seed, :token_path
10
9
  config_key 'garmin'
10
+ register_config :email, :password, :secret, :auth_seed, :token_path
11
11
 
12
12
  def initialize(config:, db:, activity_filter: nil, privacy: nil, time_budget: nil)
13
13
  super
14
14
  @domain = 'garmin.com'
15
15
  end
16
+
17
+ protected
18
+
19
+ def source_label
20
+ 'Garmin'
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'base'
4
+ require_relative '../auth/paths'
4
5
  require 'fileutils'
5
6
  require 'openssl'
6
7
  require 'tzinfo'
@@ -32,7 +33,7 @@ module GitFit
32
33
  super
33
34
  @email = @config['email']
34
35
  @password = @config['password']
35
- @session_path = @config['session_path'] || File.join('data', 'cache', 'xingzhe_session.json')
36
+ @session_path = @config['session_path'] || GitFit::Auth.file('xingzhe', 'session.json')
36
37
  end
37
38
 
38
39
  def before_call
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'base'
4
+ require_relative '../auth/paths'
4
5
  require 'fileutils'
5
6
  require 'tzinfo'
6
7
 
@@ -32,7 +33,7 @@ module GitFit
32
33
  super
33
34
  @email = @config['email']
34
35
  @password = @config['password']
35
- @token_path = @config['token_path'] || File.join('data', 'auth', 'xoss_tokens.json')
36
+ @token_path = @config['token_path'] || GitFit::Auth.file('xoss', 'tokens.json')
36
37
  end
37
38
 
38
39
  def before_call
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GitFit
4
- VERSION = '0.12.0'
4
+ VERSION = '0.13.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-fit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lax
@@ -252,6 +252,7 @@ files:
252
252
  - lib/git_fit/auth/garmin/strategy_a.rb
253
253
  - lib/git_fit/auth/garmin/strategy_b.rb
254
254
  - lib/git_fit/auth/garmin_token.rb
255
+ - lib/git_fit/auth/paths.rb
255
256
  - lib/git_fit/auth/strava.rb
256
257
  - lib/git_fit/cli.rb
257
258
  - lib/git_fit/cli/checkpointable.rb
@@ -312,10 +313,10 @@ files:
312
313
  - lib/git_fit/std/resolver.rb
313
314
  - lib/git_fit/strava_web/file_check.rb
314
315
  - lib/git_fit/sync/base.rb
315
- - lib/git_fit/sync/garmin.rb
316
316
  - lib/git_fit/sync/garmin_base.rb
317
317
  - lib/git_fit/sync/garmin_base_di.rb
318
318
  - lib/git_fit/sync/garmin_cn.rb
319
+ - lib/git_fit/sync/garmin_com.rb
319
320
  - lib/git_fit/sync/igpsport.rb
320
321
  - lib/git_fit/sync/keep.rb
321
322
  - lib/git_fit/sync/lorem.rb