fitgem_oauth2 0.0.8 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 72e05988ee7b5c090becafe9dfd9345e1bee4aaa
4
- data.tar.gz: 7ee833ab3f11ab43816a506bb722bc19a1d51945
3
+ metadata.gz: 2c0baa9844ef7be0f66170042cec30385ab5d2e5
4
+ data.tar.gz: e1ccdc69b6a1763cf642532dab7494655b075b28
5
5
  SHA512:
6
- metadata.gz: 749bf116d19bf60c1f06aa7d95b7e4ec3783efa00a0653b2f26e8afac548a90d25bb266b20bebf81b57e135abfdf59993e3449d1dcfe799f763fc293f23971a2
7
- data.tar.gz: 8aaefdea1dc62867bf2b9e13a1a68ac37cce7ab5eab36349fe0e524c7557318e0cd017c8c7ffcd96d6d1b6eaa15a009cb40ebbb026fa1ac7e2d7f06bc26a50d9
6
+ metadata.gz: cc2840e23217566f0e460b54d4d4ba4c9c88f4251a8ac387e3403aedb6db10d76298cd7db1e244cacc8e232b1431d434b6dbedef79cce1cca3df17571cc7be1a
7
+ data.tar.gz: 5364ff2b8515a6472cc4246397e39451400138d9aea9977d5e17137f96420e4e4e029f25107be69d41627a7dc8f076a3e0462bc46d70d6a8c50575e1b3171ea3
@@ -6,17 +6,17 @@ require 'fitgem_oauth2/version'
6
6
  Gem::Specification.new do |s|
7
7
  s.name = 'fitgem_oauth2'
8
8
  s.version = FitgemOauth2::VERSION
9
- s.summary = "Fitbit API client library"
10
- s.description = "This gem allows requesting data from Fitbit API using OAuth2"
11
- s.authors = ["Ankit Gupta"]
9
+ s.summary = 'Fitbit API client library'
10
+ s.description = 'This gem allows requesting data from Fitbit API using OAuth2'
11
+ s.authors = ['Ankit Gupta']
12
12
  s.email = 'ankit.gupta2801@gmail.com'
13
- s.files = %w(fitgem_oauth2.gemspec) + `git ls-files -z`.split("\x0").select { |f| f.start_with?("lib/") }
13
+ s.files = %w(fitgem_oauth2.gemspec) + `git ls-files -z`.split("\x0").select { |f| f.start_with?('lib/') }
14
14
  s.homepage = 'http://rubygems.org/gems/fitgem_oauth2'
15
15
  s.license = 'MIT'
16
16
 
17
17
  s.add_runtime_dependency 'faraday', '~> 0.9'
18
18
 
19
- s.add_development_dependency "rspec", '~> 3.4'
20
- s.add_development_dependency "factory_girl", '~> 4.5'
21
- s.add_development_dependency "dotenv", '~> 2.1'
19
+ s.add_development_dependency 'rake', '~> 10.5'
20
+ s.add_development_dependency 'rspec', '~> 3.4'
21
+ s.add_development_dependency 'factory_girl', '~> 4.5'
22
22
  end
@@ -1,128 +1,155 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
3
 
4
- # ======================================
5
- # Activities Retrieval Methods
6
- # ======================================
7
-
8
- allowed_activity_paths = %w("calories" "caloriesBMR" "steps" "distance" "floors" "elevation" "minutesSedentary" "minutesLightlyActive" "minutesFairlyActive" "minutesVeryActive" "activityCaloriestracker/calories" "tracker/steps" "tracker/distance" "tracker/floors" "tracker/elevation" "tracker/minutesSedentary" "tracker/minutesLightlyActive" "tracker/minutesFairlyActive" "tracker/minutesVeryActive" "tracker/activityCalories")
4
+ ACTIVITY_RESOURCES = %w(calories caloriesBMR steps distance floors elevation minutesSedentary minutesLightlyActive minutesFairlyActive minutesVeryActive activityCaloriestracker/calories tracker/steps tracker/distance tracker/floors tracker/elevation tracker/minutesSedentary tracker/minutesLightlyActive tracker/minutesFairlyActive tracker/minutesVeryActive tracker/activityCalories)
9
5
 
10
- allowed_activity_periods = %w("1d" "7d" "30d" "1w" "1m" "3m" "6m" "1y" "max")
6
+ ACTIVITY_PERIODS = %w(1d 7d 30d 1w 1m 3m 6m 1y max)
11
7
 
12
- def activities_on_date(date)
13
- get_call("1/user/#{user_id}/activities/date/#{format_date(date)}.json")
8
+ def daily_activity_summary(date)
9
+ get_call("user/#{user_id}/activities/date/#{format_date(date)}.json")
14
10
  end
15
11
 
16
- def activities_in_period(resource_path, date, period)
17
- if activity_resource_path?(resource_path)
18
- if activity_period?(period)
19
- get_activities(resource_path, resource_path, period)
20
- else
21
- raise FitgemOauth2::InvalidArgumentError, "period should be one of #{allowed_activity_periods}"
22
- end
23
- else
24
- raise FitgemOauth2::InvalidArgumentError, "resource_path should be one of #{allowed_activity_paths}"
12
+ # ==================================
13
+ # Activity Time Series
14
+ # ==================================
15
+
16
+ def activity_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
17
+
18
+ unless resource && ACTIVITY_RESOURCES.include?(resource)
19
+ raise FitgemOauth2::InvalidArgumentError, "Invalid resource: #{resource}. Valid resources are #{ACTIVITY_RESOURCES}."
25
20
  end
26
- end
27
21
 
28
- def activities_in_range(resource_path, base_date, end_date)
29
- if activity_resource_path?(resource_path)
30
- get_activities(resource_path, format_date(base_date), format_dat(end_date))
31
- else
32
- raise FitgemOauth2::InvalidArgumentError, "resource_path should be one of #{allowed_activity_paths}"
22
+ unless start_date
23
+ raise FitgemOauth2::InvalidArgumentError, 'Start date must be specified.'
24
+ end
25
+
26
+ if period && end_date
27
+ raise FitgemOauth2::InvalidArgumentError, 'Both period and end_date are specified. Please specify only one.'
33
28
  end
34
- end
35
29
 
36
- # <b>DEPRECATED</b> Please use <b>activities_on_date</b> instead
37
- def calories_on_date(date)
38
- get_call("1/user/#{user_id}/activities/calories/date/#{format_date(date)}/1d.json")
30
+ if period && !ACTIVITY_PERIODS.include?(period)
31
+ raise FitgemOauth2::InvalidArgumentError, "Invalid period: #{period}. Valid periods are #{ACTIVITY_PERIODS}."
32
+ end
33
+
34
+ first = format_date(start_date)
35
+ second = period || format_date(end_date)
36
+ url = ['user', user_id, 'activities', resource, 'date', first, second].join('/')
37
+ get_call(url + '.json')
39
38
  end
40
39
 
41
- # ======================================
42
- # Intraday Series
43
- # ======================================
44
40
 
45
- def intraday_time_series(opts)
46
- unless opts[:resource] && [:calories, :steps, :distance, :floors, :elevation].include?(opts[:resource])
47
- raise FitgemOauth2::InvalidArgumentError, 'Must specify resource to fetch intraday time series data for. One of (:calories, :steps, :distance, :floors, or :elevation) is required.'
41
+
42
+ def intraday_activity_time_series(resource: nil, start_date: nil, end_date: nil, detail_level: nil,
43
+ start_time: nil, end_time: nil)
44
+
45
+ # converting to symbol to allow developer to use either 'calories' or :calories
46
+ resource = resource.to_sym
47
+
48
+ unless %i[calories steps distance floors elevation].include?(resource)
49
+ raise FitgemOauth2::InvalidArgumentError,
50
+ 'Must specify resource to fetch intraday time series data for.'\
51
+ ' One of (:calories, :steps, :distance, :floors, or :elevation) is required.'
48
52
  end
49
53
 
50
- unless opts[:date]
51
- raise FitgemOauth2::InvalidArgumentError, 'Must specify the date to fetch intraday time series data for.'
54
+ unless start_date
55
+ raise FitgemOauth2::InvalidArgumentError,
56
+ 'Must specify the start_date to fetch intraday time series data'
52
57
  end
53
58
 
54
- unless opts[:detailLevel] && %w(1min 15min).include?(opts[:detailLevel])
55
- raise FitgemOauth2::InvalidArgumentError, 'Must specify the data resolution to fetch intraday time series data for. One of (\"1d\" or \"15min\") is required.'
59
+ end_date ||= '1d'
60
+
61
+ unless detail_level && %w(1min 15min).include?(detail_level)
62
+ raise FitgemOauth2::InvalidArgumentError,
63
+ 'Must specify the data resolution to fetch intraday time series data for.'\
64
+ ' One of (\"1d\" or \"15min\") is required.'
56
65
  end
57
66
 
58
- resource = opts.delete(:resource)
59
- date = format_date(opts.delete(:date))
60
- detail_level = opts.delete(:detailLevel)
61
- time_window_specified = opts[:startTime] || opts[:endTime]
62
- resource_path = "1/user/#{@user_id}/activities/"
63
-
64
- if time_window_specified
65
- start_time = format_time(opts.delete(:startTime))
66
- end_time = format_time(opts.delete(:endTime))
67
- resource_path += "#{resource}/date/#{date}/1d/#{detail_level}/time/#{start_time}/#{end_time}.json"
68
- else
69
- resource_path += "#{resource}/date/#{date}/1d/#{detail_level}.json"
67
+ resource_path = [
68
+ 'user', @user_id,
69
+ 'activities', resource,
70
+ 'date', format_date(start_date),
71
+ end_date, detail_level
72
+ ].join('/')
73
+
74
+ if start_time || end_time
75
+ resource_path =
76
+ [resource_path, 'time', format_time(start_time), format_time(end_time)].join('/')
70
77
  end
71
- get_call(resource_path)
78
+ get_call("#{resource_path}.json")
72
79
  end
73
80
 
81
+ # ======================================
82
+ # Activity Logging Methods
83
+ # ======================================
84
+
85
+ def log_activity(params)
86
+ post_call("user/#{user_id}/activities.json", params)
87
+ end
88
+
89
+ def delete_logged_activity(id)
90
+ delete_call("user/#{user_id}/activities/#{id}.json")
91
+ end
92
+
93
+ def activity_list
94
+ get_call("user/#{user_id}/activities/list.json")
95
+ end
96
+
97
+ def activity_tcx(id)
98
+ get_call("user/#{user_id}/activities/#{id}.tcx")
99
+ end
100
+
101
+
74
102
  # ======================================
75
103
  # Activity Types
76
104
  # ======================================
77
105
  def activities
78
- get_call("1/activities.json")
106
+ get_call("activities.json")
79
107
  end
80
108
 
81
109
  def activity(id)
82
- get_call("1/activities/#{id}.json")
110
+ get_call("activities/#{id}.json")
83
111
  end
84
112
 
85
113
  def frequent_activities
86
- get_call("1/user/#{@user_id}/activities/frequent.json")
114
+ get_call("user/#{user_id}/activities/frequent.json")
87
115
  end
88
116
 
89
117
  def recent_activities
90
- get_call("1/user/#{@user_id}/activities/recent.json")
118
+ get_call("user/#{user_id}/activities/recent.json")
91
119
  end
92
120
 
93
121
  def favorite_activities
94
- get_call("1/user/#{@user_id}/activities/favorite.json")
122
+ get_call("user/#{user_id}/activities/favorite.json")
95
123
  end
96
124
 
97
- # ======================================
98
- # Activity Goals
99
- # ======================================
100
-
101
- def goals(period)
102
- unless period && [:daily, :weekly].include?(period)
103
- raise FitgemOauth2::InvalidArgumentError, "Goal period should either be 'daily' or 'weekly'"
104
- end
125
+ def add_favorite_activity(activity_id)
126
+ post_call("user/#{user_id}/activities/log/favorite/#{activity_id}.json")
105
127
  end
106
128
 
107
- def lifetime_stats
108
- get_call("1/user/#{@user_id}/activities.json")
129
+ def remove_favorite_activity(activity_id)
130
+ delete_call("user/#{user_id}/activities/log/favorite/#{activity_id}.json")
109
131
  end
110
132
 
111
133
  # ======================================
112
- # Private Methods
134
+ # Activity Goals
113
135
  # ======================================
114
136
 
115
- private
116
- def get_activities(resource_path, first, second)
117
- get_call("1/user/#{user_id}/#{resource_path}/date/#{first}/#{second}.json")
137
+ def goals(period)
138
+ unless period && %w(daily weekly).include?(period)
139
+ raise FitgemOauth2::InvalidArgumentError, "Goal period should either be 'daily' or 'weekly'"
140
+ end
141
+ get_call("user/#{user_id}/activities/goals/#{period}.json")
118
142
  end
119
143
 
120
- def activity_resource_path?(resource_path)
121
- return resource_path && allowed_activity_paths.include?(resource_path)
144
+ def update_activity_goals(period, params)
145
+ unless period && %w(daily weekly).include?(period)
146
+ raise FitgemOauth2::InvalidArgumentError, "Goal period should either be 'daily' or 'weekly'"
147
+ end
148
+ post_call("user/#{user_id}/activities/goals/#{period}.json", params)
122
149
  end
123
150
 
124
- def activity_period?(period)
125
- return period && allowed_activity_periods.include?(period)
151
+ def lifetime_stats
152
+ get_call("user/#{user_id}/activities.json")
126
153
  end
127
154
  end
128
155
  end
@@ -1,68 +1,135 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
- fat_periods = %w("1d" "7d" "1w" "1m")
4
- weight_periods = %("1d" "7d" "30d" "1w" "1m")
5
- body_goals = %("fat" "weight")
3
+ FAT_PERIODS = %w(1d 7d 1w 1m)
4
+ WEIGHT_PERIODS = %w(1d 7d 30d 1w 1m)
5
+ BODY_GOALS = %w(fat weight)
6
+ BODY_TIME_SERIES_PERIODS = %w(1d 7d 30d 1w 1m 3m 6m 1y max)
7
+
6
8
  # ======================================
7
- # Boday Fat API
9
+ # Boday Fat
8
10
  # ======================================
9
11
 
10
- def fat_on_date(date)
11
- get_call("/1/user/#{@user_id}/body/log/fat/date/#{format_date(date)}.json")
12
- end
12
+ def body_fat_logs(start_date: nil, end_date: nil, period: nil)
13
+ unless start_date
14
+ raise FitgemOauth2::InvalidArgumentError, 'must specify start_date'
15
+ end
16
+ url = ['user', user_id, 'body/log/fat/date', format_date(start_date)].join('/')
17
+ if end_date
18
+ url = [url, format_date(end_date)].join('/')
19
+ end
13
20
 
14
- def fat_for_period(base_date, period)
15
- if fat_period?(period)
16
- get_call("1/user/#{@user_id}/body/log/fat/date/#{format_date(start_date)}/#{period}.json")
17
- else
18
- raise FitgemOauth2::InvalidArgumentError, "period should be one of #{fat_periods}"
21
+ if period
22
+ if FAT_PERIODS.include?(period)
23
+ url = [url, period].join('/')
24
+ else
25
+ raise FitgemOauth2::InvalidArgumentError, "period must be one in #{FAT_PERIODS}"
26
+ end
19
27
  end
28
+
29
+ url = url + '.json'
30
+
31
+ get_call(url)
20
32
  end
21
33
 
22
- def fat_for_range(start_date, end_date)
23
- get_call("1/user/#{@user_id}/body/log/fat/date/#{format_date(start_date)}/#{format_date(end_date)}.json")
34
+ def log_body_fat(params)
35
+ post_call("user/#{user_id}/body/log/fat.json", params)
24
36
  end
25
37
 
38
+ def delete_logged_body_fat(id)
39
+ delete_call("user/#{user_id}/body/log/fat/#{id}.json")
40
+ end
41
+
42
+
43
+ # ==================================
44
+ # Body Time Series
45
+ # ==================================
46
+
47
+ def body_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
48
+ unless resource && start_date
49
+ raise FitgemOauth2::InvalidArgumentError, 'resource and start_date are required parameters. Please specify both.'
50
+ end
51
+
52
+ url = ['user', user_id, 'body', resource, 'date', format_date(start_date)].join('/')
53
+
54
+ second = ''
55
+ if end_date && period
56
+ raise FitgemOauth2::InvalidArgumentError, 'Please specify either period or end date, not both.'
57
+ end
58
+
59
+ if period
60
+ if BODY_TIME_SERIES_PERIODS.include?(period)
61
+ second = period
62
+ else
63
+ raise FitgemOauth2::InvalidArgumentError, "Invalid Period. Body time series period must be in #{BODY_TIME_SERIES_PERIODS}"
64
+ end
65
+ end
66
+
67
+ if end_date
68
+ second = format_date(end_date)
69
+ end
70
+
71
+ url = [url, second].join('/')
72
+
73
+ get_call(url + '.json')
74
+ end
75
+
76
+
26
77
  # ======================================
27
- # Body Goals API
78
+ # Body Goals
28
79
  # ======================================
29
-
30
- def body_goal(type)
31
- if type && body_goals.include?(type)
32
- get_call("1/user/#{@user_id}/body/log/#{type}/goal.json")
80
+
81
+ def body_goals(type)
82
+ if type && BODY_GOALS.include?(type)
83
+ get_call("user/#{user_id}/body/log/#{type}/goal.json")
33
84
  else
34
- raise FitgemOauth2::InvalidArgumentError, "goal type should be one of #{body_goals}"
85
+ raise FitgemOauth2::InvalidArgumentError, "invalid goal type : #{type}. must be one of #{BODY_GOALS}"
35
86
  end
36
87
  end
37
88
 
89
+ def update_body_fat_goal(params)
90
+ post_call("user/#{user_id}/body/log/fat/goal.json", params)
91
+ end
92
+
93
+ def update_weight_goal(params)
94
+ post_call("user/#{user_id}/body/log/weight/goal.json", params)
95
+ end
96
+
38
97
  # ======================================
39
- # Body Weight API
98
+ # Body Weight
40
99
  # ======================================
41
100
 
42
- def weight_on_date(date)
43
- get_call("/1/user/#{@user_id}/body/log/weight/date/#{format_date(date)}.json")
44
- end
101
+ def weight_logs(start_date: nil, end_date: nil, period: nil)
102
+ unless start_date
103
+ raise FitgemOauth2::InvalidArgumentError, 'start_date not specified.'
104
+ end
45
105
 
46
- def weight_for_period(base_date, period)
47
- if weight_period?(period)
48
- get_call("1/user/#{@user_id}/body/log/weight/date/#{format_date(start_date)}/#{period}.json")
49
- else
50
- raise FitgemOauth2::InvalidArgumentError, "period should be one of #{weight_periods}"
106
+ if period && end_date
107
+ raise FitgemOauth2::InvalidArgumentError, 'both end_date and period specified. please provide only one.'
108
+ end
109
+
110
+ if period
111
+ unless WEIGHT_PERIODS.include?(period)
112
+ raise FitgemOauth2::InvalidArgumentError, "valid period not specified. please choose a period from #{WEIGHT_PERIODS}"
113
+ end
114
+ end
115
+
116
+ first = format_date(start_date)
117
+ url = ['user', user_id, 'body/log/weight/date', first].join('/')
118
+ if period || end_date
119
+ second = period || format_date(end_date)
120
+ url = [url, second].join('/')
51
121
  end
52
- end
53
122
 
54
- def weight_for_range(start_date, end_date)
55
- get_call("1/user/#{@user_id}/body/log/weight/date/#{format_date(start_date)}/#{format_date(end_date)}.json")
123
+ get_call(url + '.json')
56
124
  end
57
125
 
58
126
 
59
- private
60
- def fat_period?(period)
61
- return period && fat_periods.include?(period)
127
+ def log_weight(params)
128
+ post_call("user/#{user_id}/body/log/weight.json", params)
62
129
  end
63
130
 
64
- def weight_period?(period)
65
- return period && weight_periods.include?(period)
131
+ def delete_logged_weight(id)
132
+ delete_call("user/#{user_id}/body/log/weight/#{id}.json")
66
133
  end
67
134
 
68
135
  end
@@ -6,7 +6,6 @@ require 'fitgem_oauth2/food.rb'
6
6
  require 'fitgem_oauth2/friends.rb'
7
7
  require 'fitgem_oauth2/heartrate.rb'
8
8
  require 'fitgem_oauth2/sleep.rb'
9
- require 'fitgem_oauth2/steps.rb'
10
9
  require 'fitgem_oauth2/subscriptions.rb'
11
10
  require 'fitgem_oauth2/users.rb'
12
11
  require 'fitgem_oauth2/utils.rb'
@@ -19,6 +18,7 @@ module FitgemOauth2
19
18
  class Client
20
19
 
21
20
  DEFAULT_USER_ID = '-'
21
+ API_VERSION = '1'
22
22
 
23
23
  attr_reader :client_id
24
24
  attr_reader :client_secret
@@ -36,33 +36,36 @@ module FitgemOauth2
36
36
  @token = opts[:token]
37
37
  @user_id = (opts[:user_id] || DEFAULT_USER_ID)
38
38
 
39
- @connection = Faraday.new("https://api.fitbit.com")
39
+ @connection = Faraday.new('https://api.fitbit.com')
40
40
  end
41
41
 
42
42
  def refresh_access_token(refresh_token)
43
43
  response = connection.post('/oauth2/token') do |request|
44
44
  encoded = Base64.strict_encode64("#{@client_id}:#{@client_secret}")
45
45
  request.headers['Authorization'] = "Basic #{encoded}"
46
- request.headers['Content-Type'] = "application/x-www-form-urlencoded"
47
- request.params['grant_type'] = "refresh_token"
46
+ request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
47
+ request.params['grant_type'] = 'refresh_token'
48
48
  request.params['refresh_token'] = refresh_token
49
49
  end
50
- return JSON.parse(response.body)
50
+ JSON.parse(response.body)
51
51
  end
52
52
 
53
53
  def get_call(url)
54
+ url = "#{API_VERSION}/#{url}"
54
55
  response = connection.get(url) { |request| set_headers(request) }
55
- return parse_response(response)
56
+ parse_response(response)
56
57
  end
57
58
 
58
59
  def post_call(url, params = {})
60
+ url = "#{API_VERSION}/#{url}"
59
61
  response = connection.post(url, params) { |request| set_headers(request) }
60
- return parse_response(response)
62
+ parse_response(response)
61
63
  end
62
64
 
63
65
  def delete_call(url)
66
+ url = "#{API_VERSION}/#{url}"
64
67
  response = connection.delete(url) { |request| set_headers(request) }
65
- return parse_response(response)
68
+ parse_response(response)
66
69
  end
67
70
 
68
71
  private
@@ -70,21 +73,27 @@ module FitgemOauth2
70
73
 
71
74
  def set_headers(request)
72
75
  request.headers['Authorization'] = "Bearer #{token}"
73
- request.headers['Content-Type'] = "application/x-www-form-urlencoded"
76
+ request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
74
77
  end
75
78
 
76
79
  def parse_response(response)
77
- headers_to_keep = ["fitbit-rate-limit-limit","fitbit-rate-limit-remaining","fitbit-rate-limit-reset"]
78
-
79
- case response.status
80
- when 200; return JSON.parse(response.body).merge!(response.headers.slice(*headers_to_keep))
81
- when 400; raise FitgemOauth2::BadRequestError
82
- when 401; raise FitgemOauth2::UnauthorizedError
83
- when 403; raise FitgemOauth2::ForbiddenError
84
- when 404; raise FitgemOauth2::NotFoundError
85
- when 500..599; raise FitgemOauth2::ServerError
80
+ headers_to_keep = %w(fitbit-rate-limit-limit fitbit-rate-limit-remaining fitbit-rate-limit-reset)
81
+
82
+ error_handler = {
83
+ 200 => lambda { JSON.parse(response.body).merge!(response.headers.slice(*headers_to_keep)) },
84
+ 400 => lambda { raise FitgemOauth2::BadRequestError },
85
+ 401 => lambda { raise FitgemOauth2::UnauthorizedError },
86
+ 403 => lambda { raise FitgemOauth2::ForbiddenError },
87
+ 404 => lambda { raise FitgemOauth2::NotFoundError },
88
+ 500..599 => lambda { raise FitgemOauth2::ServerError }
89
+ }
90
+
91
+ fn = error_handler.detect { |k , _| k === response.status }
92
+ if fn === nil
93
+ raise StandardError, "Unexpected response status #{response.status}"
94
+ else
95
+ fn.last.call
86
96
  end
87
97
  end
88
-
89
98
  end
90
99
  end
@@ -1,11 +1,30 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
+
4
+ # ==================================
5
+ # Devices
6
+ # ==================================
3
7
  def devices
4
- get_call("1/user/#{@user_id}/devices.json")
8
+ get_call("user/#{user_id}/devices.json")
5
9
  end
6
10
 
11
+ # ==================================
12
+ # Alarams
13
+ # ==================================
7
14
  def alarms(tracker_id)
8
- get_call("1/user/#{@user_id}/devices/tracker/#{tracker_id}/alarms.json")
15
+ get_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms.json")
16
+ end
17
+
18
+ def add_alarm(tracker_id, params)
19
+ post_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms.json", params)
20
+ end
21
+
22
+ def update_alarm(tracker_id, alarm_id, params)
23
+ post_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms/#{alarm_id}.json", params)
24
+ end
25
+
26
+ def remove_alarm(tracker_id, alarm_id)
27
+ delete_call("user/#{user_id}/devices/tracker/#{tracker_id}/alarms/#{alarm_id}.json")
9
28
  end
10
29
  end
11
30
  end
@@ -2,6 +2,10 @@ module FitgemOauth2
2
2
  class InvalidDateArgument < ArgumentError
3
3
  end
4
4
 
5
+ class InvalidTimeArgument < ArgumentError
6
+
7
+ end
8
+
5
9
  class InvalidArgumentError < ArgumentError
6
10
  end
7
11
 
@@ -1,58 +1,157 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
- def food_goal
4
- get_call("1/user/#{@user_id}/foods/log/goal.json")
3
+
4
+ FOOD_SERIES_RESOURCES = %w( caloriesIn water )
5
+ FOOD_SERIES_PERIODS = %w( 1d 7d 30d 1w 1m 3m 6m 1y max )
6
+
7
+
8
+ # ==================================
9
+ # Food or Water Series
10
+ # ==================================
11
+
12
+
13
+ def food_series(resource: nil, start_date: nil, end_date: nil, period: nil)
14
+
15
+ unless FOOD_SERIES_RESOURCES.include?(resource)
16
+ raise FitgemOauth2::InvalidArgumentError, "Invalid resource: #{resource}. Specify a valid resource from #{FOOD_SERIES_RESOURCES}"
17
+ end
18
+
19
+ if end_date && period
20
+ raise FitgemOauth2::InvalidArgumentError, 'Provide only one of end_date and period.'
21
+ end
22
+
23
+ if !end_date && !period
24
+ raise FitgemOauth2::InvalidArgumentError, 'Provide at least one of end_date and period.'
25
+ end
26
+
27
+ url = ['user', user_id, 'foods/log', resource, 'date', start_date].join('/')
28
+
29
+ if period
30
+ unless FOOD_SERIES_PERIODS.include?(period)
31
+ raise FitgemOauth2::InvalidArgumentError, "Invalid period: #{period}. Specify a valid period from #{FOOD_SERIES_PERIODS}"
32
+ end
33
+ end
34
+
35
+ second = period || format_date(end_date)
36
+ url = [url, second].join('/')
37
+
38
+ get_call(url + '.json')
5
39
  end
6
40
 
7
- def foods_on_date(date)
8
- get_call("1/user/#{@user_id}/foods/log/date/#{format_date(date)}.json")
41
+ # ==================================
42
+ # Collection data
43
+ # ==================================
44
+
45
+ def food_goals
46
+ get_call("user/#{user_id}/foods/log/goal.json")
9
47
  end
10
48
 
11
- def water_on_date(date)
12
- get_call("1/user/#{@user_id}/foods/log/water/date/#{format_date(date)}.json")
49
+ def food_logs(date)
50
+ get_call("user/#{user_id}/foods/log/date/#{format_date(date)}.json")
51
+ end
52
+
53
+ def water_logs(date)
54
+ get_call("user/#{user_id}/foods/log/water/date/#{format_date(date)}.json")
13
55
  end
14
56
 
15
57
  def water_goal
16
- get_call("1/user/#{@user_id}/foods/log/water/goal.json")
58
+ get_call("user/#{user_id}/foods/log/water/goal.json")
17
59
  end
18
60
 
19
- def food_in_period(resource, date, period)
20
- food_resources = ["foods/log/caloriesIn", "foods/log/water"]
21
- food_periods = %w("1d" "7d" "30d" "1w" "1m" "3m" "6m" "1y" "max")
61
+ def log_food(params)
62
+ post_call("user/#{user_id}/foods/log.json", params)
63
+ end
22
64
 
23
- unless resource && food_resources.include?(resource)
24
- raise FitgemOauth2::InvalidArgumentError, "resource should be one of #{food_resources}"
25
- end
65
+ def update_food_log(food_log_id, params)
66
+ post_call("user/#{user_id}/foods/log/#{food_log_id}.json", params)
67
+ end
26
68
 
27
- unless period && food_periods.include?(period)
28
- raise FitgemOauth2::InvalidArgumentError, "period should be one of #{food_periods}"
29
- end
69
+ def log_water(params)
70
+ post_call("user/#{user_id}/foods/log/water.json", params)
71
+ end
72
+
73
+ def update_food_goal(params)
74
+ post_call("user/#{user_id}/foods/log/goal.json", params)
75
+ end
30
76
 
31
- get_call("1/user/[user-id]/#{resource}/date/#{format_date(date)}/#{period}.json")
77
+ def update_water_goal(params)
78
+ post_call("user/#{user_id}/foods/log/water/goal.json", params)
79
+ end
32
80
 
81
+ def delete_food_log(food_log_id)
82
+ delete_call("user/#{user_id}/foods/log/#{food_log_id}.json")
33
83
  end
34
84
 
35
- def food_in_range(resource, start_date, end_date)
36
- food_resources = ["foods/log/caloriesIn", "foods/log/water"]
85
+ def update_water_log(water_log_id, params)
86
+ post_call("user/#{user_id}/foods/log/water/#{water_log_id}.json", params)
87
+ end
37
88
 
38
- unless resource && food_resources.include?(resource)
39
- raise FitgemOauth2::InvalidArgumentError, "resource should be one of #{food_resources}"
40
- end
89
+ def delete_water_log(water_log_id)
90
+ delete_call("user/#{user_id}/foods/log/water/#{water_log_id}.json")
91
+ end
92
+
93
+ # ==================================
94
+ # Collection Metadata
95
+ # ==================================
96
+
97
+ def add_favorite_food(food_id)
98
+ post_call("user/#{user_id}/foods/log/favorite/#{food_id}.json")
99
+ end
100
+
101
+ def delete_favorite_food(food_id)
102
+ delete_call("user/#{user_id}/foods/log/favorite/#{food_id}.json")
103
+ end
104
+
105
+ def recent_foods
106
+ get_call("user/#{user_id}/foods/recent.json")
107
+ end
108
+
109
+ def favorite_foods
110
+ get_call("user/#{user_id}/foods/log/favorite.json")
111
+ end
41
112
 
42
- get_call("1/user/[user-id]/#{resource}/date/#{format_date(start_date)}/#{format_date(end_date)}.json")
113
+ def frequent_foods
114
+ get_call("user/#{user_id}/foods/log/frequent.json")
115
+ end
116
+
117
+ def meals
118
+ get_call("user/#{user_id}/meals.json")
119
+ end
120
+
121
+ def create_meal(params)
122
+ post_call("user/#{user_id}/meals.json", params)
123
+ end
124
+
125
+ def meal(meal_id)
126
+ get_call("user/#{user_id}/meals/#{meal_id}.json")
127
+ end
128
+
129
+ def update_meal(meal_id, params)
130
+ post_call("user/#{user_id}/meals/#{meal_id}.json", params)
131
+ end
132
+
133
+ def delete_meal(meal_id)
134
+ delete_call("user/#{user_id}/meals/#{meal_id}.json")
135
+ end
136
+
137
+ def create_food(params)
138
+ post_call("user/#{user_id}/foods.json", params)
139
+ end
43
140
 
141
+ def delete_food(food_id)
142
+ delete_call("user/#{user_id}/foods/#{food_id}.json")
44
143
  end
45
144
 
46
145
  def food(id)
47
- get_call("1/foods/#{id}.json")
146
+ get_call("foods/#{id}.json")
48
147
  end
49
148
 
50
149
  def food_units
51
- get_call("1/foods/units.json")
150
+ get_call('foods/units.json')
52
151
  end
53
152
 
54
- def food_search
55
- get_call("1/foods/search.json")
153
+ def search_foods(params)
154
+ post_call('foods/search.json', params)
56
155
  end
57
156
  end
58
157
  end
@@ -1,19 +1,35 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
3
  def friends
4
- get_call("1/user/#{@user_id}/friends.json")
4
+ get_call("user/#{user_id}/friends.json")
5
5
  end
6
6
 
7
7
  def friends_leaderboard
8
- get_call("1/user/#{@user_id}/friends/leaderboard.json")
8
+ get_call("user/#{user_id}/friends/leaderboard.json")
9
+ end
10
+
11
+ # ==================================
12
+ # Friend Invitations
13
+ # ==================================
14
+
15
+ def invite_friend(params)
16
+ post_call("user/#{user_id}/friends/invitations.json", params)
9
17
  end
10
18
 
11
19
  def friend_invitations
12
- get_call("1/user/#{@user_id}/friends/invitations.json")
20
+ get_call("user/#{user_id}/friends/invitations.json")
13
21
  end
14
22
 
23
+ def respond_to_invitation(from_user_id, params)
24
+ post_call("user/#{user_id}/friends/invitations/#{from_user_id}.json", params)
25
+ end
26
+
27
+ # ==================================
28
+ # Badges
29
+ # ==================================
30
+
15
31
  def badges
16
- get_call("1/user/#{@user_id}/badges.json")
32
+ get_call("user/#{user_id}/badges.json")
17
33
  end
18
34
  end
19
35
  end
@@ -1,53 +1,55 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
3
 
4
- def hearrate_on_date(date)
5
- get_call("1/user/#{@user_id}/activities/heart/date/#{format_date(date)}.json")
6
- end
4
+ HR_PERIODS = %w(1d 7d 30d 1w 1m)
5
+ HR_DETAIL_LEVELS = %w(1sec 1min)
7
6
 
8
- def hearrate_in_period(date, period)
9
- periods = %w("1d" "7d" "30d" "1w" "1m")
10
- unless period && periods.include?(period)
11
- raise InvalidArgumentError, "period should be one of #{periods}"
7
+ def heartrate_time_series(start_date: nil, end_date: nil, period: nil)
8
+ unless start_date
9
+ raise FitgemOauth2::InvalidArgumentError, 'Start date not provided.'
12
10
  end
13
- get_call("1/user/#{@user_id}/activities/heart/date/#{format_date(date)}/#{period}.json")
14
- end
15
11
 
16
- def hearrate_in_range(start_date, start_range)
17
- get_call("1/user/#{@user_id}/activities/heart/date/#{format_date(start_date)}/#{format_date(end_date)}.json")
18
- end
12
+ if end_date && period
13
+ raise FitgemOauth2::InvalidArgumentError, 'Both end_date and period specified. Specify only one.'
14
+ end
19
15
 
20
- def heartrate_series_in_range(start_date, end_date, detail_level)
21
- detail_levels = %w("1sec" "1min")
22
- unless detail_level && detail_levels.include?(detail_level)
23
- raise InvalidArgumentError, "detail level should be one of #{detail_levels}"
16
+ if !end_date && !period
17
+ raise FitgemOauth2::InvalidArgumentError, 'Neither end_date nor period specified. Specify at least one.'
24
18
  end
25
- get_call("/1/user/#{@user_id}/activities/heart/date/#{format_date(start_date)}/#{format_date(end_date)}/#{detail_level}.json")
26
- end
27
19
 
28
- def heartrate_series_in_range_time(start_date, end_date, detail_level, start_time, end_time)
29
- detail_levels = %w("1sec" "1min")
30
- unless detail_level && detail_levels.include?(detail_level)
31
- raise InvalidArgumentError, "detail level should be one of #{detail_levels}"
20
+ if period && !HR_PERIODS.include?(period)
21
+ raise FitgemOauth2::InvalidArgumentError, "Invalid period: #{period}. Valid periods are #{HR_PERIODS}."
32
22
  end
33
- get_call("1/user/#{@user_id}/activities/heart/date/#{format_date(start_date)}/#{format_date(end_date)}/#{detail_level}/time/#{start_time}/#{end_time}.json")
23
+
24
+ second = period || format_date(end_date)
25
+
26
+ url = ['user', user_id, 'activities/heart/date', format_date(start_date), second].join('/')
27
+
28
+ get_call(url + '.json')
34
29
  end
35
30
 
36
- def hearrate_daily_series_in_range(start_date, detail_level)
37
- detail_levels = %w("1sec" "1min")
38
- unless detail_level && detail_levels.include?(detail_level)
39
- raise InvalidArgumentError, "detail level should be one of #{detail_levels}"
31
+ def intraday_heartrate_time_series(start_date: nil, end_date: nil, detail_level: nil, start_time: nil, end_time: nil)
32
+ unless start_date
33
+ raise FitgemOauth2::InvalidArgumentError, 'Start date not provided.'
40
34
  end
41
- get_call("1/user/#{@user_id}/activities/heart/date/#{format_date(start_date)}/1d/#{detail_level}.json")
42
- end
43
35
 
44
- def heartrate_daily_series_in_range_time(start_date, detail_level, start_time, end_time)
45
- detail_levels = %w("1sec" "1min")
46
- unless detail_level && detail_levels.include?(detail_level)
47
- raise InvalidArgumentError, "detail level should be one of #{detail_levels}"
36
+ unless detail_level && HR_DETAIL_LEVELS.include?(detail_level)
37
+ raise FitgemOauth2::InvalidArgumentError, "Please specify the defail level. Detail level should be one of #{HR_DETAIL_LEVELS}."
38
+ end
39
+
40
+ end_date = format_date(end_date) || '1d'
41
+
42
+ url = ['user', user_id, 'activities/heart/date', format_date(start_date), end_date, detail_level].join('/')
43
+
44
+ if (start_time && !end_time) || (end_time && !start_time)
45
+ raise FitgemOauth2::InvalidArgumentError, 'Either specify both the start_time and end_time or specify neither.'
46
+ end
47
+
48
+ if start_time && end_time
49
+ url = [url, 'time', format_time(start_time), format_time(end_time)].join('/')
48
50
  end
49
- get_call("1/user/#{@user_id}/activities/heart/date/#{format_date(start_date)}/1d/#{detail_level}/time/#{start_time}/#{end_time}.json")
50
- end
51
51
 
52
+ get_call(url + '.json')
53
+ end
52
54
  end
53
55
  end
@@ -2,8 +2,51 @@ module FitgemOauth2
2
2
 
3
3
  class Client
4
4
 
5
- def sleep_on_date(date)
6
- get_call("1/user/#{user_id}/sleep/date/#{format_date(date)}.json")
5
+ SLEEP_RESOURCES = %w(startTime timeInBed minutesAsleep awakeningsCount minutesAwake minutesToFallAsleep minutesAfterWakeup efficiency)
6
+ SLEEP_PERIODS = %w(1d 7d 30d 1w 1m 3m 6m 1y max)
7
+
8
+ def sleep_logs(date)
9
+ get_call("user/#{user_id}/sleep/date/#{format_date(date)}.json")
10
+ end
11
+
12
+ def sleep_goal
13
+ get_call("user/#{user_id}/sleep/goal.json")
14
+ end
15
+
16
+ def update_sleep_goal(params)
17
+ post_call("user/#{user_id}/sleep/goal.json", params)
18
+ end
19
+
20
+ def sleep_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
21
+ unless start_date
22
+ raise FitgemOauth2::InvalidArgumentError, 'Start date not provided.'
23
+ end
24
+
25
+ unless resource && SLEEP_RESOURCES.include?(resource)
26
+ raise FitgemOauth2::InvalidArgumentError, "Invalid resource: #{resource}. Valid resources are #{SLEEP_RESOURCES}."
27
+ end
28
+
29
+ if period && end_date
30
+ raise FitgemOauth2::InvalidArgumentError, 'Both end_date and period specified. Specify only one.'
31
+ end
32
+
33
+ if period && !SLEEP_PERIODS.include?(period)
34
+ raise FitgemOauth2::InvalidArgumentError, "Invalid period: #{period}. Valid periods are #{SLEEP_PERIODS}."
35
+ end
36
+
37
+ second = period || format_date(end_date)
38
+
39
+ url = ['user', user_id, 'sleep', resource, 'date', format_date(start_date), second].join('/')
40
+
41
+ get_call(url + '.json')
42
+ end
43
+
44
+ def log_sleep(params)
45
+ post_call("user/#{user_id}/sleep.json", params)
46
+ end
47
+
48
+ def delete_logged_sleep(log_id)
49
+ delete_call("user/#{user_id}/sleep/#{log_id}.json")
7
50
  end
8
51
 
9
52
  end
@@ -21,7 +21,7 @@ module FitgemOauth2
21
21
  type = opts[ :type ] || :all
22
22
  subscription_id = opts[:subscription_id]
23
23
 
24
- url = [ '1', 'user', user_id ]
24
+ url = [ 'user', user_id ]
25
25
  url << type unless type == :all
26
26
  url << 'apiSubscriptions'
27
27
  url << subscription_id if subscription_id
@@ -1,7 +1,7 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
3
  def user_info()
4
- get_call("1/user/#{user_id}/profile.json")
4
+ get_call("user/#{user_id}/profile.json")
5
5
  end
6
6
  end
7
7
  end
@@ -1,38 +1,42 @@
1
1
  module FitgemOauth2
2
2
  class Client
3
- # This function was copied from the Fitgem project (https://github.com/whazzmaster/fitgem/blob/master/lib/fitgem/helpers.rb)
4
- # Format any of a variety of date types into the formatted string
5
- # required when using the fitbit API.
6
- #
7
- # The date parameter can take several different kind of objects: a
8
- # DateTime object, a Date object, a Time object or a String object. Furthermore,
9
- # the string object may be either the date in a preformatted string
10
- # ("yyyy-MM-dd"), or it may be the string values "today" or
11
- # "tomorrow".
12
- #
13
- # @param [DateTime, Date, Time, String] date The object to format into a
14
- # date string
15
- # @raise [Fitgem::InvalidDateArgument] Raised when the object is
16
- # not a DateTime, Date, Time or a valid (yyyy-MM-dd) String object
17
- # @return [String] Date in "yyyy-MM-dd" string format
3
+
18
4
  def format_date(date)
19
- if date.is_a? String
20
- case date
21
- when 'today'
22
- return Date.today.strftime("%Y-%m-%d")
23
- when 'yesterday'
24
- return (Date.today-1).strftime("%Y-%m-%d")
25
- else
26
- unless date =~ /\d{4}\-\d{2}\-\d{2}/
27
- raise FitgemOauth2::InvalidDateArgument, "Invalid date (#{date}), must be in yyyy-MM-dd format"
28
- end
29
- return date
30
- end
5
+
6
+ if !date
7
+ return nil
8
+ end
9
+
10
+ valid_semantic_date = %w(today yesterday).include? date
11
+ valid_date_string = ((date =~ /\d{4}\-\d{2}\-\d{2}/) == 0)
12
+ if valid_date_string
13
+ date
14
+ elsif valid_semantic_date
15
+ date_from_semantic(date)
31
16
  elsif Date === date || Time === date || DateTime === date
32
- return date.strftime("%Y-%m-%d")
17
+ date.strftime('%Y-%m-%d')
33
18
  else
34
19
  raise FitgemOauth2::InvalidDateArgument, "Date used must be a date/time object or a string in the format YYYY-MM-DD; supplied argument is a #{date.class}"
35
20
  end
36
21
  end
22
+
23
+ def format_time(time)
24
+ if ( (time =~ /\d{2}:\d{2}/) == 0)
25
+ time
26
+ elsif DateTime === time || Time === time
27
+ time.strftime('%H:%M')
28
+ else
29
+ raise FitgemOauth2::InvalidTimeArgument, "Time used must be a DateTime/Time object or a string in the format hh:mm; supplied argument is a #{time.class}"
30
+ end
31
+ end
32
+
33
+ private
34
+ def date_from_semantic(semantic)
35
+ if semantic === 'yesterday'
36
+ (Date.today-1).strftime('%Y-%m-%d')
37
+ elsif semantic == 'today'
38
+ Date.today.strftime('%Y-%m-%d')
39
+ end
40
+ end
37
41
  end
38
42
  end
@@ -1,3 +1,3 @@
1
1
  module FitgemOauth2
2
- VERSION = '0.0.8'
2
+ VERSION = '1.0.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fitgem_oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ankit Gupta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-31 00:00:00.000000000 Z
11
+ date: 2016-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -25,47 +25,47 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.9'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '3.4'
33
+ version: '10.5'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '3.4'
40
+ version: '10.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: factory_girl
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '4.5'
47
+ version: '3.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '4.5'
54
+ version: '3.4'
55
55
  - !ruby/object:Gem::Dependency
56
- name: dotenv
56
+ name: factory_girl
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '2.1'
61
+ version: '4.5'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '2.1'
68
+ version: '4.5'
69
69
  description: This gem allows requesting data from Fitbit API using OAuth2
70
70
  email: ankit.gupta2801@gmail.com
71
71
  executables: []
@@ -83,7 +83,6 @@ files:
83
83
  - lib/fitgem_oauth2/friends.rb
84
84
  - lib/fitgem_oauth2/heartrate.rb
85
85
  - lib/fitgem_oauth2/sleep.rb
86
- - lib/fitgem_oauth2/steps.rb
87
86
  - lib/fitgem_oauth2/subscriptions.rb
88
87
  - lib/fitgem_oauth2/users.rb
89
88
  - lib/fitgem_oauth2/utils.rb
@@ -113,4 +112,3 @@ signing_key:
113
112
  specification_version: 4
114
113
  summary: Fitbit API client library
115
114
  test_files: []
116
- has_rdoc:
@@ -1,11 +0,0 @@
1
- module FitgemOauth2
2
-
3
- class Client
4
-
5
- def steps_on_date(date)
6
- get_call("1/user/#{user_id}/activities/steps/date/#{format_date(date)}/1d.json")
7
- end
8
-
9
- end
10
-
11
- end