fitbark 0.1.1

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +7 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +80 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +194 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/fitbark.gemspec +37 -0
  15. data/lib/fitbark.rb +45 -0
  16. data/lib/fitbark/auth.rb +125 -0
  17. data/lib/fitbark/client.rb +54 -0
  18. data/lib/fitbark/constants.rb +17 -0
  19. data/lib/fitbark/data/activity_daily.rb +52 -0
  20. data/lib/fitbark/data/activity_hourly.rb +46 -0
  21. data/lib/fitbark/data/activity_level.rb +28 -0
  22. data/lib/fitbark/data/breed.rb +12 -0
  23. data/lib/fitbark/data/daily_goal.rb +25 -0
  24. data/lib/fitbark/data/dog_info.rb +118 -0
  25. data/lib/fitbark/data/dog_relation.rb +27 -0
  26. data/lib/fitbark/data/medical_condition.rb +12 -0
  27. data/lib/fitbark/data/picture.rb +21 -0
  28. data/lib/fitbark/data/shared.rb +36 -0
  29. data/lib/fitbark/data/similar_dogs_stat.rb +22 -0
  30. data/lib/fitbark/data/token.rb +35 -0
  31. data/lib/fitbark/data/token_info.rb +29 -0
  32. data/lib/fitbark/data/user_info.rb +27 -0
  33. data/lib/fitbark/data/user_preview.rb +25 -0
  34. data/lib/fitbark/data/user_relation.rb +26 -0
  35. data/lib/fitbark/errors.rb +33 -0
  36. data/lib/fitbark/handler/v2/activity_series.rb +90 -0
  37. data/lib/fitbark/handler/v2/activity_total.rb +65 -0
  38. data/lib/fitbark/handler/v2/base.rb +54 -0
  39. data/lib/fitbark/handler/v2/daily_goals.rb +37 -0
  40. data/lib/fitbark/handler/v2/dog_info.rb +39 -0
  41. data/lib/fitbark/handler/v2/dog_picture.rb +39 -0
  42. data/lib/fitbark/handler/v2/dog_relations.rb +37 -0
  43. data/lib/fitbark/handler/v2/friend_dogs.rb +39 -0
  44. data/lib/fitbark/handler/v2/own_dogs.rb +38 -0
  45. data/lib/fitbark/handler/v2/set_daily_goal.rb +68 -0
  46. data/lib/fitbark/handler/v2/similar_dogs_stats.rb +37 -0
  47. data/lib/fitbark/handler/v2/time_breakdown.rb +63 -0
  48. data/lib/fitbark/handler/v2/user_info.rb +35 -0
  49. data/lib/fitbark/handler/v2/user_picture.rb +39 -0
  50. data/lib/fitbark/handler/v2/user_relations.rb +37 -0
  51. data/lib/fitbark/version.rb +4 -0
  52. metadata +234 -0
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/fitbark.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'fitbark/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'fitbark'
7
+ spec.version = Fitbark::VERSION
8
+ spec.authors = ['NatyDev']
9
+ spec.email = ['natydev@aol.com']
10
+
11
+ spec.summary = 'Wrapper for FitBark API.'
12
+ spec.description = 'Wrapper for FitBark API: It provides simple methods to handle ' \
13
+ 'authorization and to execute HTTP calls.'
14
+ spec.homepage = 'https://github.com/natydev/fitbark'
15
+ spec.license = 'MIT'
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem.
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`.split("\x0")
21
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ end
23
+ spec.bindir = 'exe'
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ['lib']
26
+
27
+ spec.add_development_dependency 'bundler', '~> 2.0'
28
+ spec.add_development_dependency 'faker', '~> 1.9'
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rspec', '~> 3.0'
31
+ spec.add_development_dependency 'rubocop', '~> 0.63'
32
+ spec.add_development_dependency 'webmock', '~> 3.5'
33
+ spec.add_dependency 'addressable', '~> 2.6'
34
+ spec.add_dependency 'faraday', '~> 0.15'
35
+ spec.add_dependency 'oj', '~> 3.7'
36
+ spec.add_dependency 'strict_open_struct', '~> 0.0.2'
37
+ end
data/lib/fitbark.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'addressable'
2
+ require 'faraday'
3
+ require 'oj'
4
+ require 'base64'
5
+ require 'strict_open_struct'
6
+
7
+ require_relative 'fitbark/version'
8
+ require_relative 'fitbark/constants'
9
+ require_relative 'fitbark/errors'
10
+ require_relative 'fitbark/auth'
11
+ require_relative 'fitbark/client'
12
+ require_relative 'fitbark/data/shared'
13
+ require_relative 'fitbark/data/token'
14
+ require_relative 'fitbark/data/token_info'
15
+ require_relative 'fitbark/data/user_info'
16
+ require_relative 'fitbark/data/picture'
17
+ require_relative 'fitbark/data/breed'
18
+ require_relative 'fitbark/data/medical_condition'
19
+ require_relative 'fitbark/data/dog_info'
20
+ require_relative 'fitbark/data/user_relation'
21
+ require_relative 'fitbark/data/dog_relation'
22
+ require_relative 'fitbark/data/activity_daily'
23
+ require_relative 'fitbark/data/activity_hourly'
24
+ require_relative 'fitbark/data/similar_dogs_stat'
25
+ require_relative 'fitbark/data/activity_level'
26
+ require_relative 'fitbark/data/daily_goal'
27
+ require_relative 'fitbark/handler/v2/base'
28
+ require_relative 'fitbark/handler/v2/user_info'
29
+ require_relative 'fitbark/handler/v2/user_picture'
30
+ require_relative 'fitbark/handler/v2/dog_relations'
31
+ require_relative 'fitbark/handler/v2/dog_info'
32
+ require_relative 'fitbark/handler/v2/dog_picture'
33
+ require_relative 'fitbark/handler/v2/user_relations'
34
+ require_relative 'fitbark/handler/v2/activity_series'
35
+ require_relative 'fitbark/handler/v2/similar_dogs_stats'
36
+ require_relative 'fitbark/handler/v2/activity_total'
37
+ require_relative 'fitbark/handler/v2/time_breakdown'
38
+ require_relative 'fitbark/handler/v2/daily_goals'
39
+ require_relative 'fitbark/handler/v2/set_daily_goal'
40
+ require_relative 'fitbark/handler/v2/own_dogs'
41
+ require_relative 'fitbark/handler/v2/friend_dogs'
42
+
43
+ module Fitbark
44
+ # :nodoc:
45
+ end
@@ -0,0 +1,125 @@
1
+ module Fitbark
2
+ # Provides oauth2 methods
3
+ class Auth
4
+ include Fitbark::Constants
5
+ # == A sample usage:
6
+ # First step to generate an authorization uri:
7
+ # client_id = 'CLIENT-ID-PROVIDED-BY-FITBARK'
8
+ # client_secret = 'CLIENT-SECRET-PROVIDED-BY-FITBARK'
9
+ # redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
10
+ # auth = Fitbark::Auth.new(client_id: client_id, redirect_uri: redirect_uri)
11
+ # auth.authorization_uri
12
+ #
13
+ # Once that authorization uri was open and fetched the authorization
14
+ # code from html (normally this operation is done with browser),
15
+ # proceed with 2nd step to retieve access token:
16
+ # authorization_code = '27e5dd1307cddc7b5d8d72264ef1...'
17
+ # auth = Fitbark::Auth.new(client_id: client_id, redirect_uri: redirect_uri,
18
+ # code: authorization_code, client_secret: client_secret)
19
+ # auth.fetch_access_token!
20
+ def initialize(client_id: nil, client_secret: nil,
21
+ redirect_uri: nil, code: nil, token: nil)
22
+ @client_id = client_id
23
+ @client_secret = client_secret
24
+ @redirect_uri = redirect_uri
25
+ @code = code
26
+ @token = read_token(token)
27
+ @uri = Addressable::URI.new(host: API_HOST, scheme: API_SCHEME)
28
+ end
29
+
30
+ attr_accessor :code
31
+ attr_writer :token
32
+ attr_reader :client_id, :client_secret, :redirect_uri,
33
+ :token_data, :token_info
34
+
35
+ # return an URI to fetch the authorization code
36
+ def authorization_uri
37
+ uri.path = AUTHORIZE_PATH
38
+ uri.query_values = {
39
+ response_type: :code,
40
+ client_id: client_id,
41
+ redirect_uri: redirect_uri
42
+ }
43
+ uri.to_s
44
+ end
45
+
46
+ # return a Fitbark::Data::Token object
47
+ def fetch_access_token!
48
+ if token_response.success?
49
+ apply_token_data(token_response)
50
+ else
51
+ token_error(token_response)
52
+ end
53
+ end
54
+
55
+ # return a Fitbark::Data::TokenInfo object
56
+ def fetch_token_info
57
+ response = token_info_response
58
+ if response.success?
59
+ apply_token_info(response)
60
+ else
61
+ token_error(response)
62
+ end
63
+ end
64
+
65
+ # return the raw access_token (String)
66
+ def token
67
+ read_token
68
+ end
69
+
70
+ private
71
+
72
+ attr_accessor :uri
73
+
74
+ def token_response
75
+ @token_response ||= Faraday.new(url: uri.site).post do |req|
76
+ req.url TOKEN_PATH
77
+ req.body = request_token_body
78
+ end
79
+ end
80
+
81
+ def request_token_body
82
+ {
83
+ client_id: client_id,
84
+ client_secret: client_secret,
85
+ grant_type: :authorization_code,
86
+ redirect_uri: redirect_uri,
87
+ code: code
88
+ }
89
+ end
90
+
91
+ def token_info_response
92
+ raise Fitbark::Errors::TokenNotProvidedError if token.nil?
93
+
94
+ Faraday.new(url: uri.site).get do |req|
95
+ req.url TOKEN_INFO_PATH
96
+ req.headers = {
97
+ 'Content-Type' => 'application/json',
98
+ 'Authorization' => "Bearer #{token}"
99
+ }
100
+ end
101
+ end
102
+
103
+ def apply_token_data(resp)
104
+ @token_data = Fitbark::Data::Token.new(parsed_body(resp))
105
+ end
106
+
107
+ def apply_token_info(resp)
108
+ @token_info = Fitbark::Data::TokenInfo.new(parsed_body(resp))
109
+ end
110
+
111
+ def token_error(resp)
112
+ raise(Fitbark::Errors::FetchTokenError
113
+ .new(code: resp.status, message:
114
+ parsed_body(resp)['error_description']))
115
+ end
116
+
117
+ def read_token(val = @token)
118
+ (token_data.respond_to?(:token) && token_data.token) || val
119
+ end
120
+
121
+ def parsed_body(resp)
122
+ Oj.load(resp.body)
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,54 @@
1
+ module Fitbark
2
+ # Provides all methods to connect to the API
3
+ # endpoints and retrieve data
4
+ class Client
5
+ include Fitbark::Constants
6
+
7
+ # === params (key/value):
8
+ #
9
+ # - *token*: access token retrieved from Fitbark::Auth
10
+ #
11
+ # alla available API methods inside
12
+ # this calss are dynamical defined by all Fitbark::Handler::V2 classes
13
+ # please read specific documentation for each of them
14
+ # == Sample usage:
15
+ #
16
+ # token = "9083a4b0d701542c9b..."
17
+ # client = Fitbark::Client.new(token: token)
18
+ # user = client.user_info
19
+ # first_dog = client.dog_relations.first.dog
20
+ # client.dog_picture(dog_slug: first_dog.slug)
21
+
22
+ def initialize(token:)
23
+ raise Fitbark::Errors::TokenNotProvidedError if token.nil?
24
+
25
+ @token = token
26
+ end
27
+
28
+ attr_reader :uri
29
+
30
+ # :nodoc:
31
+ def method_missing(method, **args)
32
+ if respond_to?(method)
33
+ klass_handler(method).new(token: token, opts: args).response
34
+ else
35
+ super
36
+ end
37
+ end
38
+
39
+ # :nodoc:
40
+ def respond_to?(method, include_private = false)
41
+ return true if klass_handler(method)
42
+ rescue NameError => e
43
+ super
44
+ end
45
+
46
+ private
47
+
48
+ def klass_handler(handler)
49
+ eval("#{PREFIX_NAME_HANDLER}#{camel(handler.to_s)}")
50
+ end
51
+
52
+ attr_reader :token
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ module Fitbark
2
+ # Provides general constants support.
3
+ module Constants
4
+ API_SCHEME = 'https'.freeze
5
+ API_HOST = 'app.fitbark.com'.freeze
6
+ API_SUBHOST = 'api/v2'.freeze
7
+ AUTHORIZE_PATH = '/oauth/authorize'.freeze
8
+ TOKEN_PATH = '/oauth/token'.freeze
9
+ TOKEN_INFO_PATH = TOKEN_PATH + '/info'.freeze
10
+ PREFIX_NAME_HANDLER = 'Fitbark::Handler::V2::'.freeze
11
+
12
+ # :nodoc:
13
+ def camel(str)
14
+ str.split('_').collect(&:capitalize).join
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,52 @@
1
+ module Fitbark
2
+ module Data
3
+ # Defines structure for dog's daily activity data.
4
+ #
5
+ # Original attribute names from source API:
6
+ # - *date*
7
+ # - *activity_value*
8
+ # - *activity_average*,
9
+ # - *min_play*,
10
+ # - *min_active*
11
+ # - *min_rest*
12
+ # - *daily_target*
13
+ # - *has_trophy*
14
+ class ActivityDaily < StrictOpenStruct
15
+ include Fitbark::Data::Shared
16
+
17
+ # parse source String value into Date for *date* attribute
18
+ def date
19
+ date_parser(self[:date])
20
+ end
21
+
22
+ alias detected_on date
23
+
24
+ # an alias for *min_play* attribute
25
+ def minutes_playing
26
+ self[:min_play]
27
+ end
28
+
29
+ # an alias for *min_active* attribute
30
+ def minutes_active
31
+ self[:min_active]
32
+ end
33
+
34
+ # an alias for *min_rest* attribute
35
+ def minutes_resting
36
+ self[:min_rest]
37
+ end
38
+
39
+ # an alias for *daily_target* attribute
40
+ def daily_goal
41
+ self[:daily_target]
42
+ end
43
+
44
+ # a predicate alias for *has_trophy* attribute
45
+ def trophy?
46
+ !self[:has_trophy].zero?
47
+ end
48
+
49
+ alias daily_goal_reached? trophy?
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,46 @@
1
+ module Fitbark
2
+ module Data
3
+ # Defines structure for dog's hourly activity data.
4
+ #
5
+ # Original attribute names from source API:
6
+ # - *date*
7
+ # - *activity_value*
8
+ # - *min_play*,
9
+ # - *min_active*
10
+ # - *min_rest*
11
+ # - *distance_in_miles*
12
+ # - *kcalories*
13
+ # - *activity_goal*
14
+ class ActivityHourly < StrictOpenStruct
15
+ include Fitbark::Data::Shared
16
+
17
+ # parse String value into Time for *date* attribute
18
+ def date
19
+ time_parser(self[:date])
20
+ end
21
+
22
+ alias detected_at date
23
+
24
+ # an alias for *min_play* attribute
25
+ def minutes_playing
26
+ self[:min_play]
27
+ end
28
+
29
+ # an alias for *min_active* attribute
30
+ def minutes_active
31
+ self[:min_active]
32
+ end
33
+
34
+ # an alias for *min_rest* attribute
35
+ def minutes_resting
36
+ self[:min_rest]
37
+ end
38
+
39
+ # convert in kilometers from *distance_in_miles* attribute
40
+ def distance_in_kms
41
+ (self[:distance_in_miles].to_f * 1.60934).round(3)
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ module Fitbark
2
+ module Data
3
+ # Defines structure for dog's activity data.
4
+ #
5
+ # Original attribute names from source API:
6
+ # - *min_play*,
7
+ # - *min_active*
8
+ # - *min_rest*
9
+ class ActivityLevel < StrictOpenStruct
10
+ include Fitbark::Data::Shared
11
+
12
+ # an alias for *min_play* attribute
13
+ def minutes_playing
14
+ self[:min_play]
15
+ end
16
+
17
+ # an alias for *min_active* attribute
18
+ def minutes_active
19
+ self[:min_active]
20
+ end
21
+
22
+ # an alias for *min_rest* attribute
23
+ def minutes_resting
24
+ self[:min_rest]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ module Fitbark
2
+ module Data
3
+ # Defines structure for dog's breed data.
4
+ #
5
+ # Original attribute names from source API:
6
+ # - *id*,
7
+ # - *name*
8
+ class Breed < StrictOpenStruct
9
+ include Fitbark::Data::Shared
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module Fitbark
2
+ module Data
3
+ # Defines structure for dog's daily points goal.
4
+ #
5
+ # Original attribute names from source API:
6
+ # - *goal*,
7
+ # - *date*
8
+ class DailyGoal < StrictOpenStruct
9
+ include Fitbark::Data::Shared
10
+
11
+ # parse String value into Date for *date* attribute
12
+ def date
13
+ date_parser(self[:date])
14
+ end
15
+
16
+ alias set_on date
17
+
18
+ # an alias for *goal* attribute
19
+ def goal_points
20
+ self[:goal]
21
+ end
22
+
23
+ end
24
+ end
25
+ end