fitbark 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +80 -0
- data/LICENSE.txt +21 -0
- data/README.md +194 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fitbark.gemspec +37 -0
- data/lib/fitbark.rb +45 -0
- data/lib/fitbark/auth.rb +125 -0
- data/lib/fitbark/client.rb +54 -0
- data/lib/fitbark/constants.rb +17 -0
- data/lib/fitbark/data/activity_daily.rb +52 -0
- data/lib/fitbark/data/activity_hourly.rb +46 -0
- data/lib/fitbark/data/activity_level.rb +28 -0
- data/lib/fitbark/data/breed.rb +12 -0
- data/lib/fitbark/data/daily_goal.rb +25 -0
- data/lib/fitbark/data/dog_info.rb +118 -0
- data/lib/fitbark/data/dog_relation.rb +27 -0
- data/lib/fitbark/data/medical_condition.rb +12 -0
- data/lib/fitbark/data/picture.rb +21 -0
- data/lib/fitbark/data/shared.rb +36 -0
- data/lib/fitbark/data/similar_dogs_stat.rb +22 -0
- data/lib/fitbark/data/token.rb +35 -0
- data/lib/fitbark/data/token_info.rb +29 -0
- data/lib/fitbark/data/user_info.rb +27 -0
- data/lib/fitbark/data/user_preview.rb +25 -0
- data/lib/fitbark/data/user_relation.rb +26 -0
- data/lib/fitbark/errors.rb +33 -0
- data/lib/fitbark/handler/v2/activity_series.rb +90 -0
- data/lib/fitbark/handler/v2/activity_total.rb +65 -0
- data/lib/fitbark/handler/v2/base.rb +54 -0
- data/lib/fitbark/handler/v2/daily_goals.rb +37 -0
- data/lib/fitbark/handler/v2/dog_info.rb +39 -0
- data/lib/fitbark/handler/v2/dog_picture.rb +39 -0
- data/lib/fitbark/handler/v2/dog_relations.rb +37 -0
- data/lib/fitbark/handler/v2/friend_dogs.rb +39 -0
- data/lib/fitbark/handler/v2/own_dogs.rb +38 -0
- data/lib/fitbark/handler/v2/set_daily_goal.rb +68 -0
- data/lib/fitbark/handler/v2/similar_dogs_stats.rb +37 -0
- data/lib/fitbark/handler/v2/time_breakdown.rb +63 -0
- data/lib/fitbark/handler/v2/user_info.rb +35 -0
- data/lib/fitbark/handler/v2/user_picture.rb +39 -0
- data/lib/fitbark/handler/v2/user_relations.rb +37 -0
- data/lib/fitbark/version.rb +4 -0
- metadata +234 -0
data/bin/setup
ADDED
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
|
data/lib/fitbark/auth.rb
ADDED
@@ -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,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
|