activite 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c0fc49292ff1cc617edec317ddb65991c408d8b1
4
- data.tar.gz: 21d949774ed01cea6fc2eb219616926a5b2f4096
3
+ metadata.gz: 5acc9c4ef6a8ab53a295b64452a46565c9dddf15
4
+ data.tar.gz: 46be771ce03ba475e7a051f2264da1a058f2b5ec
5
5
  SHA512:
6
- metadata.gz: 1e92cca90c65cb4c40ee0af4644aefa399d08395eb06675d8a7e9123fd1bd49b36f800c3c29d7056dfdc455856e85e519cff16358bd915661457c767912307cf
7
- data.tar.gz: 3634d67561efa2d67346fd6b5cb52c3c1cd02e8922b97a2fb050e1def9dd500e96a1979ba903c0c5cb02db8f0b9ed7948a9b12324430823ac4843572e3217343
6
+ metadata.gz: 6bc688ecea0f2ec2c218898516d64b45a7827ea7ac796d2494f41b73b35e24dac8819652e7543f847e4a8dd8a16f118e0f481bbc4cd0d8dbba1d71f6445a9356
7
+ data.tar.gz: a1b991504b8afb86f74aee85d107bca4e6ecc4c82eb8727f5678464f14b540e3ac47a7bec0ff98ae8c4ec69af3ae7395f39794c408bf7783f77350bcd897c195
data/README.md CHANGED
@@ -4,20 +4,16 @@
4
4
  [![Code Climate](https://codeclimate.com/github/paulosman/activite/badges/gpa.svg)][codeclimate]
5
5
  [![Test Coverage](https://codeclimate.com/github/paulosman/activite/badges/coverage.svg)][coverage]
6
6
  [![Dependency Status](https://gemnasium.com/paulosman/activite.svg)][gemnasium]
7
+ [![Gem Version](https://badge.fury.io/rb/activite.svg)][gemversion]
7
8
 
8
9
  This gem provides access to data collected by [Withings](http://withings.com/) devices through
9
10
  their [HTTP API](https://oauth.withings.com/api/doc).
10
11
 
11
- NOTE: This gem is a work in progress. It is not yet available via RubyGems.
12
-
13
12
  [travis]: https://travis-ci.org/paulosman/activite
14
13
  [codeclimate]: https://codeclimate.com/github/paulosman/activite
15
14
  [coverage]: https://codeclimate.com/github/paulosman/activite
16
15
  [gemnasium]: https://gemnasium.com/paulosman/activite
17
-
18
- ### TODO
19
-
20
- * Notifications
16
+ [gemversion]: https://badge.fury.io/rb/activite
21
17
 
22
18
  ## Installation
23
19
 
@@ -133,7 +129,7 @@ sleep_details = client.sleep_series(user_id, {
133
129
 
134
130
  ## Development
135
131
 
136
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
132
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
137
133
 
138
134
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
139
135
 
@@ -2,15 +2,17 @@ require 'activite/error'
2
2
  require 'activite/http/request'
3
3
  require 'activite/activity'
4
4
  require 'activite/measurement_group'
5
+ require 'activite/notification'
5
6
  require 'activite/sleep_series'
6
7
  require 'activite/sleep_summary'
8
+ require 'activite/response'
7
9
 
8
10
  module Activite
9
11
  class Client
10
12
  include Activite::HTTP::OAuthClient
11
13
 
12
14
  attr_writer :user_agent
13
-
15
+
14
16
  # Initializes a new Client object used to communicate with the Withings API.
15
17
  #
16
18
  # An authenticated Client can be created with an access token and access token
@@ -109,7 +111,7 @@ module Activite
109
111
  #
110
112
  # NOTE: user_id isn't actually used in this API call (so I assume it is
111
113
  # derived from the OAuth credentials) but I was uncomfortable introducing
112
- # this inconsitency into this gem.
114
+ # this inconsistency into this gem.
113
115
  #
114
116
  # @param user_id [Intger]
115
117
  # @param options [Hash]
@@ -121,6 +123,55 @@ module Activite
121
123
  }.merge(options))
122
124
  end
123
125
 
126
+ # Register a webhook / notification with the Withings API. This allows
127
+ # you to be notified when new data is available for a user.
128
+ #
129
+ # @param user_id [Integer]
130
+ # @param options [Hash]
131
+ #
132
+ # @return [Activite::Response]
133
+ def create_notification(user_id, options = {})
134
+ perform_request(:post, '/notify', Activite::Response, nil, {
135
+ action: 'subscribe'
136
+ }.merge(options))
137
+ end
138
+
139
+ # Get information about a specific webhook / notification.
140
+ #
141
+ # @param user_id [Integer]
142
+ # @param options [Hash]
143
+ #
144
+ # @return [Activite::Notification]
145
+ def get_notification(user_id, options = {})
146
+ perform_request(:get, '/notify', Activite::Notification, nil, {
147
+ action: 'get'
148
+ }.merge(options))
149
+ end
150
+
151
+ # Return a list of registered webhooks / notifications.
152
+ #
153
+ # @param user_id [Integer]
154
+ # @param options [Hash]
155
+ #
156
+ # @return [Array<Activite::Notification>]
157
+ def list_notifications(user_id, options = {})
158
+ perform_request(:get, '/notify', Activite::Notification, 'profiles', {
159
+ action: 'list'
160
+ }.merge(options))
161
+ end
162
+
163
+ # Revoke previously subscribed webhook / notification.
164
+ #
165
+ # @param user_id [Integer]
166
+ # @param options [Hash]
167
+ #
168
+ # @return [Activite::Response]
169
+ def revoke_notification(user_id, options = {})
170
+ perform_request(:get, '/notify', Activite::Response, nil, {
171
+ action: 'revoke'
172
+ }.merge(options))
173
+ end
174
+
124
175
  private
125
176
 
126
177
  # Helper function that handles all API requests
@@ -139,7 +190,9 @@ module Activite
139
190
  options = Activite::Utils.normalize_date_params(options)
140
191
  request = Activite::HTTP::Request.new(@access_token, { 'User-Agent' => user_agent })
141
192
  response = request.send(http_method, path, options)
142
- if response.has_key? key
193
+ if key.nil?
194
+ klass.new(response)
195
+ elsif response.has_key? key
143
196
  response[key].collect do |element|
144
197
  klass.new(element)
145
198
  end
@@ -4,6 +4,7 @@ module Activite
4
4
  module HTTP
5
5
  module OAuthClient
6
6
  attr_accessor :consumer_key, :consumer_secret, :token, :secret
7
+ attr_writer :consumer
7
8
 
8
9
  DEFAULT_OPTIONS = {
9
10
  site: 'https://oauth.withings.com',
@@ -13,7 +14,7 @@ module Activite
13
14
  access_token_path: '/account/access_token',
14
15
  scheme: :query_string
15
16
  }
16
-
17
+
17
18
  def request_token(options = {})
18
19
  consumer.get_request_token(options)
19
20
  end
@@ -34,13 +35,13 @@ module Activite
34
35
  def existing_access_token(token, secret)
35
36
  OAuth::AccessToken.new(consumer, token, secret)
36
37
  end
37
-
38
+
38
39
  def connected?
39
40
  !@access_token.nil?
40
41
  end
41
42
 
42
43
  private
43
-
44
+
44
45
  def consumer
45
46
  @consumer ||= OAuth::Consumer.new(@consumer_key, @consumer_secret, DEFAULT_OPTIONS)
46
47
  end
@@ -13,22 +13,48 @@ module Activite
13
13
  end
14
14
 
15
15
  def get(path, options = {})
16
+ request(:get, path, options)
17
+ end
18
+
19
+ def post(path, options = {})
20
+ request(:post, path, options)
21
+ end
22
+
23
+ protected
24
+
25
+ def hash_to_query(hash)
26
+ return URI.encode(hash.map{|k,v| "#{k}=#{v}"}.join("&"))
27
+ end
28
+
29
+ def request_with_body(method, path, options = {})
30
+ body = hash_to_query(options)
31
+ uri = "#{BASE_URI}#{path}"
32
+ @access_token.send(method, uri, body, @headers)
33
+ end
34
+
35
+ def request_with_query_string(method, path, options = {})
16
36
  uri = "#{BASE_URI}#{path}?#{hash_to_query(options)}"
17
- response = @access_token.get(uri, @headers)
37
+ @access_token.send(method, uri, @headers)
38
+ end
39
+
40
+ def request(method, path, options = {})
41
+ if [:post, :put].include? method
42
+ response = request_with_body(method, path, options)
43
+ else
44
+ response = request_with_query_string(method, path, options)
45
+ end
46
+
18
47
  if response.code.to_i < 200 or response.code.to_i >= 400
19
48
  raise Activite::Error::ClientConfigurationError, response.body
20
49
  end
50
+
21
51
  body = JSON.parse(response.body)
22
52
  if body['status'].to_i != 0
23
53
  raise Activite::Error::InvalidResponseError, "#{body['status']} - #{body['error']}"
24
54
  end
25
- body['body']
26
- end
27
-
28
- protected
29
55
 
30
- def hash_to_query(hash)
31
- return URI.encode(hash.map{|k,v| "#{k}=#{v}"}.join("&"))
56
+ body['body'] ||= body
57
+ body['body']
32
58
  end
33
59
  end
34
60
  end
@@ -0,0 +1,4 @@
1
+ module Activite
2
+ class Notification < Base
3
+ end
4
+ end
@@ -0,0 +1,13 @@
1
+ module Activite
2
+
3
+ # A Response is used to represent an empty API response with a status
4
+ # code and no additional information.
5
+ class Response
6
+ # @return [Integer]
7
+ attr_reader :status
8
+
9
+ def initialize(attrs = {})
10
+ @status = attrs['status'].to_i if attrs.has_key? 'status'
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Activite
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Osman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-01 00:00:00.000000000 Z
11
+ date: 2015-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth
@@ -93,6 +93,8 @@ files:
93
93
  - lib/activite/http/request.rb
94
94
  - lib/activite/measurement_group.rb
95
95
  - lib/activite/measures.rb
96
+ - lib/activite/notification.rb
97
+ - lib/activite/response.rb
96
98
  - lib/activite/sleep_series.rb
97
99
  - lib/activite/sleep_summary.rb
98
100
  - lib/activite/utils.rb