fitgem_oauth2 2.0.1 → 2.1.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 +4 -4
- data/fitgem_oauth2.gemspec +22 -22
- data/lib/fitgem_oauth2.rb +6 -6
- data/lib/fitgem_oauth2/activity.rb +209 -209
- data/lib/fitgem_oauth2/body_measurements.rb +163 -163
- data/lib/fitgem_oauth2/client.rb +126 -126
- data/lib/fitgem_oauth2/devices.rb +45 -45
- data/lib/fitgem_oauth2/errors.rb +30 -30
- data/lib/fitgem_oauth2/food.rb +27 -27
- data/lib/fitgem_oauth2/food/collection.rb +51 -51
- data/lib/fitgem_oauth2/food/metadata.rb +63 -63
- data/lib/fitgem_oauth2/food/series.rb +55 -55
- data/lib/fitgem_oauth2/friends.rb +44 -44
- data/lib/fitgem_oauth2/heartrate.rb +85 -85
- data/lib/fitgem_oauth2/sleep.rb +86 -86
- data/lib/fitgem_oauth2/subscriptions.rb +32 -32
- data/lib/fitgem_oauth2/users.rb +7 -7
- data/lib/fitgem_oauth2/utils.rb +48 -48
- data/lib/fitgem_oauth2/version.rb +3 -3
- metadata +5 -5
@@ -1,163 +1,163 @@
|
|
1
|
-
module FitgemOauth2
|
2
|
-
class Client
|
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
|
-
|
8
|
-
# ======================================
|
9
|
-
# Boday Fat
|
10
|
-
# ======================================
|
11
|
-
|
12
|
-
# retrieves a list of all user's body fat log entries
|
13
|
-
# note: provide either end_date or period
|
14
|
-
# @param start_date start date for the logs
|
15
|
-
# @param end_date (optional)end date for the logs
|
16
|
-
# @param period (optional) period for the logs
|
17
|
-
def body_fat_logs(start_date: nil, end_date: nil, period: nil)
|
18
|
-
unless start_date
|
19
|
-
raise FitgemOauth2::InvalidArgumentError, 'must specify start_date'
|
20
|
-
end
|
21
|
-
url = ['user', user_id, 'body/log/fat/date', format_date(start_date)].join('/')
|
22
|
-
if end_date
|
23
|
-
url = [url, format_date(end_date)].join('/')
|
24
|
-
end
|
25
|
-
|
26
|
-
if period
|
27
|
-
if FAT_PERIODS.include?(period)
|
28
|
-
url = [url, period].join('/')
|
29
|
-
else
|
30
|
-
raise FitgemOauth2::InvalidArgumentError, "period must be one in #{FAT_PERIODS}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
url = url + '.json'
|
35
|
-
|
36
|
-
get_call(url)
|
37
|
-
end
|
38
|
-
|
39
|
-
# logs body fat
|
40
|
-
# @param params POST parameters for logging body fat
|
41
|
-
def log_body_fat(params)
|
42
|
-
post_call("user/#{user_id}/body/log/fat.json", params)
|
43
|
-
end
|
44
|
-
|
45
|
-
# delete logged body fat
|
46
|
-
# @param id ID of the log to be deleted.
|
47
|
-
def delete_logged_body_fat(id)
|
48
|
-
delete_call("user/#{user_id}/body/log/fat/#{id}.json")
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
# ==================================
|
53
|
-
# Body Time Series
|
54
|
-
# ==================================
|
55
|
-
|
56
|
-
# retrieve body time series for the user; provide at least one of end_date and period
|
57
|
-
# @param resource (required)the resource requested ['bmi', 'fat', or 'weight']
|
58
|
-
# @param start_date (required)the start date for the series
|
59
|
-
# @param end_date (optional)the end date for the series
|
60
|
-
# @param period (optional)period for the time series. valid periods are BODY_TIME_SERIES_PERIODS
|
61
|
-
def body_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
|
62
|
-
unless resource && start_date
|
63
|
-
raise FitgemOauth2::InvalidArgumentError, 'resource and start_date are required parameters. Please specify both.'
|
64
|
-
end
|
65
|
-
|
66
|
-
url = ['user', user_id, 'body', resource, 'date', format_date(start_date)].join('/')
|
67
|
-
|
68
|
-
second = ''
|
69
|
-
if end_date && period
|
70
|
-
raise FitgemOauth2::InvalidArgumentError, 'Please specify either period or end date, not both.'
|
71
|
-
end
|
72
|
-
|
73
|
-
if period
|
74
|
-
if BODY_TIME_SERIES_PERIODS.include?(period)
|
75
|
-
second = period
|
76
|
-
else
|
77
|
-
raise FitgemOauth2::InvalidArgumentError, "Invalid Period. Body time series period must be in #{BODY_TIME_SERIES_PERIODS}"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
if end_date
|
82
|
-
second = format_date(end_date)
|
83
|
-
end
|
84
|
-
|
85
|
-
url = [url, second].join('/')
|
86
|
-
|
87
|
-
get_call(url + '.json')
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
|
-
# ======================================
|
92
|
-
# Body Goals
|
93
|
-
# ======================================
|
94
|
-
|
95
|
-
# retrieves body goals based on the type specified
|
96
|
-
# @param type 'fat' or 'weight'
|
97
|
-
def body_goals(type)
|
98
|
-
if type && BODY_GOALS.include?(type)
|
99
|
-
get_call("user/#{user_id}/body/log/#{type}/goal.json")
|
100
|
-
else
|
101
|
-
raise FitgemOauth2::InvalidArgumentError, "invalid goal type : #{type}. must be one of #{BODY_GOALS}"
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# update body fat goal
|
106
|
-
# @param params POST params for updating body fat goal
|
107
|
-
def update_body_fat_goal(params)
|
108
|
-
post_call("user/#{user_id}/body/log/fat/goal.json", params)
|
109
|
-
end
|
110
|
-
|
111
|
-
# update weight goal
|
112
|
-
# @param params POST params for updating weight goal
|
113
|
-
def update_weight_goal(params)
|
114
|
-
post_call("user/#{user_id}/body/log/weight/goal.json", params)
|
115
|
-
end
|
116
|
-
|
117
|
-
# ======================================
|
118
|
-
# Body Weight
|
119
|
-
# ======================================
|
120
|
-
|
121
|
-
# retrieve weight logs; specify either the end_date or period
|
122
|
-
# @param start_date start date for the logs
|
123
|
-
# @param end_date (optional)end_date for the logs
|
124
|
-
# @param period (optional)period for the logs
|
125
|
-
def weight_logs(start_date: nil, end_date: nil, period: nil)
|
126
|
-
unless start_date
|
127
|
-
raise FitgemOauth2::InvalidArgumentError, 'start_date not specified.'
|
128
|
-
end
|
129
|
-
|
130
|
-
if period && end_date
|
131
|
-
raise FitgemOauth2::InvalidArgumentError, 'both end_date and period specified. please provide only one.'
|
132
|
-
end
|
133
|
-
|
134
|
-
if period
|
135
|
-
unless WEIGHT_PERIODS.include?(period)
|
136
|
-
raise FitgemOauth2::InvalidArgumentError, "valid period not specified. please choose a period from #{WEIGHT_PERIODS}"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
first = format_date(start_date)
|
141
|
-
url = ['user', user_id, 'body/log/weight/date', first].join('/')
|
142
|
-
if period || end_date
|
143
|
-
second = period || format_date(end_date)
|
144
|
-
url = [url, second].join('/')
|
145
|
-
end
|
146
|
-
|
147
|
-
get_call(url + '.json')
|
148
|
-
end
|
149
|
-
|
150
|
-
# logs weight for the user
|
151
|
-
# @param params POST message for logging weight
|
152
|
-
def log_weight(params)
|
153
|
-
post_call("user/#{user_id}/body/log/weight.json", params)
|
154
|
-
end
|
155
|
-
|
156
|
-
# delete logged weight
|
157
|
-
# @param id ID of the weight log to be deleted
|
158
|
-
def delete_logged_weight(id)
|
159
|
-
delete_call("user/#{user_id}/body/log/weight/#{id}.json")
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|
163
|
-
end
|
1
|
+
module FitgemOauth2
|
2
|
+
class Client
|
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
|
+
|
8
|
+
# ======================================
|
9
|
+
# Boday Fat
|
10
|
+
# ======================================
|
11
|
+
|
12
|
+
# retrieves a list of all user's body fat log entries
|
13
|
+
# note: provide either end_date or period
|
14
|
+
# @param start_date start date for the logs
|
15
|
+
# @param end_date (optional)end date for the logs
|
16
|
+
# @param period (optional) period for the logs
|
17
|
+
def body_fat_logs(start_date: nil, end_date: nil, period: nil)
|
18
|
+
unless start_date
|
19
|
+
raise FitgemOauth2::InvalidArgumentError, 'must specify start_date'
|
20
|
+
end
|
21
|
+
url = ['user', user_id, 'body/log/fat/date', format_date(start_date)].join('/')
|
22
|
+
if end_date
|
23
|
+
url = [url, format_date(end_date)].join('/')
|
24
|
+
end
|
25
|
+
|
26
|
+
if period
|
27
|
+
if FAT_PERIODS.include?(period)
|
28
|
+
url = [url, period].join('/')
|
29
|
+
else
|
30
|
+
raise FitgemOauth2::InvalidArgumentError, "period must be one in #{FAT_PERIODS}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
url = url + '.json'
|
35
|
+
|
36
|
+
get_call(url)
|
37
|
+
end
|
38
|
+
|
39
|
+
# logs body fat
|
40
|
+
# @param params POST parameters for logging body fat
|
41
|
+
def log_body_fat(params)
|
42
|
+
post_call("user/#{user_id}/body/log/fat.json", params)
|
43
|
+
end
|
44
|
+
|
45
|
+
# delete logged body fat
|
46
|
+
# @param id ID of the log to be deleted.
|
47
|
+
def delete_logged_body_fat(id)
|
48
|
+
delete_call("user/#{user_id}/body/log/fat/#{id}.json")
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# ==================================
|
53
|
+
# Body Time Series
|
54
|
+
# ==================================
|
55
|
+
|
56
|
+
# retrieve body time series for the user; provide at least one of end_date and period
|
57
|
+
# @param resource (required)the resource requested ['bmi', 'fat', or 'weight']
|
58
|
+
# @param start_date (required)the start date for the series
|
59
|
+
# @param end_date (optional)the end date for the series
|
60
|
+
# @param period (optional)period for the time series. valid periods are BODY_TIME_SERIES_PERIODS
|
61
|
+
def body_time_series(resource: nil, start_date: nil, end_date: nil, period: nil)
|
62
|
+
unless resource && start_date
|
63
|
+
raise FitgemOauth2::InvalidArgumentError, 'resource and start_date are required parameters. Please specify both.'
|
64
|
+
end
|
65
|
+
|
66
|
+
url = ['user', user_id, 'body', resource, 'date', format_date(start_date)].join('/')
|
67
|
+
|
68
|
+
second = ''
|
69
|
+
if end_date && period
|
70
|
+
raise FitgemOauth2::InvalidArgumentError, 'Please specify either period or end date, not both.'
|
71
|
+
end
|
72
|
+
|
73
|
+
if period
|
74
|
+
if BODY_TIME_SERIES_PERIODS.include?(period)
|
75
|
+
second = period
|
76
|
+
else
|
77
|
+
raise FitgemOauth2::InvalidArgumentError, "Invalid Period. Body time series period must be in #{BODY_TIME_SERIES_PERIODS}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
if end_date
|
82
|
+
second = format_date(end_date)
|
83
|
+
end
|
84
|
+
|
85
|
+
url = [url, second].join('/')
|
86
|
+
|
87
|
+
get_call(url + '.json')
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# ======================================
|
92
|
+
# Body Goals
|
93
|
+
# ======================================
|
94
|
+
|
95
|
+
# retrieves body goals based on the type specified
|
96
|
+
# @param type 'fat' or 'weight'
|
97
|
+
def body_goals(type)
|
98
|
+
if type && BODY_GOALS.include?(type)
|
99
|
+
get_call("user/#{user_id}/body/log/#{type}/goal.json")
|
100
|
+
else
|
101
|
+
raise FitgemOauth2::InvalidArgumentError, "invalid goal type : #{type}. must be one of #{BODY_GOALS}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# update body fat goal
|
106
|
+
# @param params POST params for updating body fat goal
|
107
|
+
def update_body_fat_goal(params)
|
108
|
+
post_call("user/#{user_id}/body/log/fat/goal.json", params)
|
109
|
+
end
|
110
|
+
|
111
|
+
# update weight goal
|
112
|
+
# @param params POST params for updating weight goal
|
113
|
+
def update_weight_goal(params)
|
114
|
+
post_call("user/#{user_id}/body/log/weight/goal.json", params)
|
115
|
+
end
|
116
|
+
|
117
|
+
# ======================================
|
118
|
+
# Body Weight
|
119
|
+
# ======================================
|
120
|
+
|
121
|
+
# retrieve weight logs; specify either the end_date or period
|
122
|
+
# @param start_date start date for the logs
|
123
|
+
# @param end_date (optional)end_date for the logs
|
124
|
+
# @param period (optional)period for the logs
|
125
|
+
def weight_logs(start_date: nil, end_date: nil, period: nil)
|
126
|
+
unless start_date
|
127
|
+
raise FitgemOauth2::InvalidArgumentError, 'start_date not specified.'
|
128
|
+
end
|
129
|
+
|
130
|
+
if period && end_date
|
131
|
+
raise FitgemOauth2::InvalidArgumentError, 'both end_date and period specified. please provide only one.'
|
132
|
+
end
|
133
|
+
|
134
|
+
if period
|
135
|
+
unless WEIGHT_PERIODS.include?(period)
|
136
|
+
raise FitgemOauth2::InvalidArgumentError, "valid period not specified. please choose a period from #{WEIGHT_PERIODS}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
first = format_date(start_date)
|
141
|
+
url = ['user', user_id, 'body/log/weight/date', first].join('/')
|
142
|
+
if period || end_date
|
143
|
+
second = period || format_date(end_date)
|
144
|
+
url = [url, second].join('/')
|
145
|
+
end
|
146
|
+
|
147
|
+
get_call(url + '.json')
|
148
|
+
end
|
149
|
+
|
150
|
+
# logs weight for the user
|
151
|
+
# @param params POST message for logging weight
|
152
|
+
def log_weight(params)
|
153
|
+
post_call("user/#{user_id}/body/log/weight.json", params)
|
154
|
+
end
|
155
|
+
|
156
|
+
# delete logged weight
|
157
|
+
# @param id ID of the weight log to be deleted
|
158
|
+
def delete_logged_weight(id)
|
159
|
+
delete_call("user/#{user_id}/body/log/weight/#{id}.json")
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
data/lib/fitgem_oauth2/client.rb
CHANGED
@@ -1,126 +1,126 @@
|
|
1
|
-
require 'fitgem_oauth2/activity.rb'
|
2
|
-
require 'fitgem_oauth2/body_measurements.rb'
|
3
|
-
require 'fitgem_oauth2/devices.rb'
|
4
|
-
require 'fitgem_oauth2/errors.rb'
|
5
|
-
require 'fitgem_oauth2/food.rb'
|
6
|
-
require 'fitgem_oauth2/friends.rb'
|
7
|
-
require 'fitgem_oauth2/heartrate.rb'
|
8
|
-
require 'fitgem_oauth2/sleep.rb'
|
9
|
-
require 'fitgem_oauth2/subscriptions.rb'
|
10
|
-
require 'fitgem_oauth2/users.rb'
|
11
|
-
require 'fitgem_oauth2/utils.rb'
|
12
|
-
require 'fitgem_oauth2/version.rb'
|
13
|
-
|
14
|
-
require 'base64'
|
15
|
-
require 'faraday'
|
16
|
-
|
17
|
-
module FitgemOauth2
|
18
|
-
class Client
|
19
|
-
|
20
|
-
DEFAULT_USER_ID = '-'
|
21
|
-
API_VERSION = '1'
|
22
|
-
|
23
|
-
attr_reader :client_id
|
24
|
-
attr_reader :client_secret
|
25
|
-
attr_reader :token
|
26
|
-
attr_reader :user_id
|
27
|
-
attr_reader :unit_system
|
28
|
-
|
29
|
-
def initialize(opts)
|
30
|
-
missing = [:client_id, :client_secret, :token] - opts.keys
|
31
|
-
if missing.size > 0
|
32
|
-
raise FitgemOauth2::InvalidArgumentError, "Missing required options: #{missing.join(',')}"
|
33
|
-
end
|
34
|
-
|
35
|
-
@client_id = opts[:client_id]
|
36
|
-
@client_secret = opts[:client_secret]
|
37
|
-
@token = opts[:token]
|
38
|
-
@user_id = (opts[:user_id] || DEFAULT_USER_ID)
|
39
|
-
@unit_system = opts[:unit_system]
|
40
|
-
@connection = Faraday.new('https://api.fitbit.com')
|
41
|
-
end
|
42
|
-
|
43
|
-
def refresh_access_token(refresh_token)
|
44
|
-
response = connection.post('/oauth2/token') do |request|
|
45
|
-
encoded = Base64.strict_encode64("#{@client_id}:#{@client_secret}")
|
46
|
-
request.headers['Authorization'] = "Basic #{encoded}"
|
47
|
-
request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
48
|
-
request.params['grant_type'] = 'refresh_token'
|
49
|
-
request.params['refresh_token'] = refresh_token
|
50
|
-
end
|
51
|
-
JSON.parse(response.body)
|
52
|
-
end
|
53
|
-
|
54
|
-
def get_call(url)
|
55
|
-
url = "#{API_VERSION}/#{url}"
|
56
|
-
response = connection.get(url) { |request| set_headers(request) }
|
57
|
-
parse_response(response)
|
58
|
-
end
|
59
|
-
|
60
|
-
# This method is a helper method (like get_call) for 1.2 version of the API_VERSION
|
61
|
-
# This method is needed because Fitbit API supports both versions as of current
|
62
|
-
# date (Nov 5, 2017)
|
63
|
-
def get_call_1_2(url)
|
64
|
-
url = "1.2/#{url}"
|
65
|
-
response = connection.get(url) {|request| set_headers(request)}
|
66
|
-
parse_response(response)
|
67
|
-
end
|
68
|
-
|
69
|
-
def post_call(url, params = {})
|
70
|
-
url = "#{API_VERSION}/#{url}"
|
71
|
-
response = connection.post(url, params) { |request| set_headers(request) }
|
72
|
-
parse_response(response)
|
73
|
-
end
|
74
|
-
|
75
|
-
def post_call_1_2(url, params = {})
|
76
|
-
url = "1.2/#{url}"
|
77
|
-
response = connection.post(url, params) { |request| set_headers(request) }
|
78
|
-
parse_response(response)
|
79
|
-
end
|
80
|
-
|
81
|
-
def delete_call(url)
|
82
|
-
url = "#{API_VERSION}/#{url}"
|
83
|
-
response = connection.delete(url) { |request| set_headers(request) }
|
84
|
-
parse_response(response)
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
attr_reader :connection
|
89
|
-
|
90
|
-
def set_headers(request)
|
91
|
-
request.headers['Authorization'] = "Bearer #{token}"
|
92
|
-
request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
93
|
-
request.headers['Accept-Language'] = unit_system unless unit_system == nil
|
94
|
-
end
|
95
|
-
|
96
|
-
def parse_response(response)
|
97
|
-
headers_to_keep = %w(fitbit-rate-limit-limit fitbit-rate-limit-remaining fitbit-rate-limit-reset)
|
98
|
-
|
99
|
-
error_handler = {
|
100
|
-
200 => lambda {
|
101
|
-
body = JSON.parse(response.body)
|
102
|
-
body = {body: body} if body.is_a?(Array)
|
103
|
-
headers = response.headers.to_hash.keep_if { |k,v|
|
104
|
-
headers_to_keep.include? k
|
105
|
-
}
|
106
|
-
body.merge!(headers)
|
107
|
-
},
|
108
|
-
201 => lambda { },
|
109
|
-
204 => lambda { },
|
110
|
-
400 => lambda { raise FitgemOauth2::BadRequestError },
|
111
|
-
401 => lambda { raise FitgemOauth2::UnauthorizedError },
|
112
|
-
403 => lambda { raise FitgemOauth2::ForbiddenError },
|
113
|
-
404 => lambda { raise FitgemOauth2::NotFoundError },
|
114
|
-
429 => lambda { raise FitgemOauth2::ApiLimitError },
|
115
|
-
500..599 => lambda { raise FitgemOauth2::ServerError }
|
116
|
-
}
|
117
|
-
|
118
|
-
fn = error_handler.detect { |k, _| k === response.status }
|
119
|
-
if fn === nil
|
120
|
-
raise StandardError, "Unexpected response status #{response.status}"
|
121
|
-
else
|
122
|
-
fn.last.call
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
1
|
+
require 'fitgem_oauth2/activity.rb'
|
2
|
+
require 'fitgem_oauth2/body_measurements.rb'
|
3
|
+
require 'fitgem_oauth2/devices.rb'
|
4
|
+
require 'fitgem_oauth2/errors.rb'
|
5
|
+
require 'fitgem_oauth2/food.rb'
|
6
|
+
require 'fitgem_oauth2/friends.rb'
|
7
|
+
require 'fitgem_oauth2/heartrate.rb'
|
8
|
+
require 'fitgem_oauth2/sleep.rb'
|
9
|
+
require 'fitgem_oauth2/subscriptions.rb'
|
10
|
+
require 'fitgem_oauth2/users.rb'
|
11
|
+
require 'fitgem_oauth2/utils.rb'
|
12
|
+
require 'fitgem_oauth2/version.rb'
|
13
|
+
|
14
|
+
require 'base64'
|
15
|
+
require 'faraday'
|
16
|
+
|
17
|
+
module FitgemOauth2
|
18
|
+
class Client
|
19
|
+
|
20
|
+
DEFAULT_USER_ID = '-'
|
21
|
+
API_VERSION = '1'
|
22
|
+
|
23
|
+
attr_reader :client_id
|
24
|
+
attr_reader :client_secret
|
25
|
+
attr_reader :token
|
26
|
+
attr_reader :user_id
|
27
|
+
attr_reader :unit_system
|
28
|
+
|
29
|
+
def initialize(opts)
|
30
|
+
missing = [:client_id, :client_secret, :token] - opts.keys
|
31
|
+
if missing.size > 0
|
32
|
+
raise FitgemOauth2::InvalidArgumentError, "Missing required options: #{missing.join(',')}"
|
33
|
+
end
|
34
|
+
|
35
|
+
@client_id = opts[:client_id]
|
36
|
+
@client_secret = opts[:client_secret]
|
37
|
+
@token = opts[:token]
|
38
|
+
@user_id = (opts[:user_id] || DEFAULT_USER_ID)
|
39
|
+
@unit_system = opts[:unit_system]
|
40
|
+
@connection = Faraday.new('https://api.fitbit.com')
|
41
|
+
end
|
42
|
+
|
43
|
+
def refresh_access_token(refresh_token)
|
44
|
+
response = connection.post('/oauth2/token') do |request|
|
45
|
+
encoded = Base64.strict_encode64("#{@client_id}:#{@client_secret}")
|
46
|
+
request.headers['Authorization'] = "Basic #{encoded}"
|
47
|
+
request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
48
|
+
request.params['grant_type'] = 'refresh_token'
|
49
|
+
request.params['refresh_token'] = refresh_token
|
50
|
+
end
|
51
|
+
JSON.parse(response.body)
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_call(url)
|
55
|
+
url = "#{API_VERSION}/#{url}"
|
56
|
+
response = connection.get(url) { |request| set_headers(request) }
|
57
|
+
parse_response(response)
|
58
|
+
end
|
59
|
+
|
60
|
+
# This method is a helper method (like get_call) for 1.2 version of the API_VERSION
|
61
|
+
# This method is needed because Fitbit API supports both versions as of current
|
62
|
+
# date (Nov 5, 2017)
|
63
|
+
def get_call_1_2(url)
|
64
|
+
url = "1.2/#{url}"
|
65
|
+
response = connection.get(url) {|request| set_headers(request)}
|
66
|
+
parse_response(response)
|
67
|
+
end
|
68
|
+
|
69
|
+
def post_call(url, params = {})
|
70
|
+
url = "#{API_VERSION}/#{url}"
|
71
|
+
response = connection.post(url, params) { |request| set_headers(request) }
|
72
|
+
parse_response(response)
|
73
|
+
end
|
74
|
+
|
75
|
+
def post_call_1_2(url, params = {})
|
76
|
+
url = "1.2/#{url}"
|
77
|
+
response = connection.post(url, params) { |request| set_headers(request) }
|
78
|
+
parse_response(response)
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_call(url)
|
82
|
+
url = "#{API_VERSION}/#{url}"
|
83
|
+
response = connection.delete(url) { |request| set_headers(request) }
|
84
|
+
parse_response(response)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
attr_reader :connection
|
89
|
+
|
90
|
+
def set_headers(request)
|
91
|
+
request.headers['Authorization'] = "Bearer #{token}"
|
92
|
+
request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
93
|
+
request.headers['Accept-Language'] = unit_system unless unit_system == nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_response(response)
|
97
|
+
headers_to_keep = %w(fitbit-rate-limit-limit fitbit-rate-limit-remaining fitbit-rate-limit-reset)
|
98
|
+
|
99
|
+
error_handler = {
|
100
|
+
200 => lambda {
|
101
|
+
body = JSON.parse(response.body)
|
102
|
+
body = {body: body} if body.is_a?(Array)
|
103
|
+
headers = response.headers.to_hash.keep_if { |k,v|
|
104
|
+
headers_to_keep.include? k
|
105
|
+
}
|
106
|
+
body.merge!(headers)
|
107
|
+
},
|
108
|
+
201 => lambda { },
|
109
|
+
204 => lambda { },
|
110
|
+
400 => lambda { raise FitgemOauth2::BadRequestError },
|
111
|
+
401 => lambda { raise FitgemOauth2::UnauthorizedError },
|
112
|
+
403 => lambda { raise FitgemOauth2::ForbiddenError },
|
113
|
+
404 => lambda { raise FitgemOauth2::NotFoundError },
|
114
|
+
429 => lambda { raise FitgemOauth2::ApiLimitError },
|
115
|
+
500..599 => lambda { raise FitgemOauth2::ServerError }
|
116
|
+
}
|
117
|
+
|
118
|
+
fn = error_handler.detect { |k, _| k === response.status }
|
119
|
+
if fn === nil
|
120
|
+
raise StandardError, "Unexpected response status #{response.status}"
|
121
|
+
else
|
122
|
+
fn.last.call
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|