fitgem_oauth2 0.0.8 → 1.0.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.
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