washbullet 0.3.1 → 0.4.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/.gitignore +3 -0
- data/.rspec +1 -1
- data/.travis.yml +3 -0
- data/README.md +61 -24
- data/Rakefile +6 -1
- data/lib/washbullet.rb +5 -0
- data/lib/washbullet/api.rb +3 -1
- data/lib/washbullet/api/contacts.rb +13 -3
- data/lib/washbullet/api/devices.rb +9 -3
- data/lib/washbullet/api/me.rb +1 -1
- data/lib/washbullet/api/pushes.rb +14 -55
- data/lib/washbullet/api/subscriptions.rb +17 -0
- data/lib/washbullet/{basic_authentication.rb → authorization.rb} +1 -1
- data/lib/washbullet/channel.rb +29 -0
- data/lib/washbullet/client.rb +18 -18
- data/lib/washbullet/contact.rb +35 -0
- data/lib/washbullet/device.rb +27 -0
- data/lib/washbullet/entity.rb +27 -0
- data/lib/washbullet/http_exception.rb +19 -14
- data/lib/washbullet/push.rb +27 -0
- data/lib/washbullet/pushable.rb +59 -0
- data/lib/washbullet/pushable/file.rb +55 -0
- data/lib/washbullet/pushable/link.rb +13 -0
- data/lib/washbullet/pushable/note.rb +13 -0
- data/lib/washbullet/request.rb +1 -1
- data/lib/washbullet/user.rb +9 -0
- data/lib/washbullet/version.rb +1 -1
- data/spec/fixtures/green.png +0 -0
- data/spec/spec_helper.rb +48 -68
- data/spec/vcr/Washbullet_API_Contacts/_contacts/Get_own_active_contacts.yml +48 -0
- data/spec/vcr/Washbullet_API_Devices/_devices/Get_own_active_devices.yml +50 -0
- data/spec/vcr/Washbullet_API_Me/_me/Get_the_self_information.yml +50 -0
- data/spec/vcr/Washbullet_API_Subscriptions/_channel_info/when_channel_is_existing/Get_information_about_a_channel.yml +49 -0
- data/spec/vcr/Washbullet_API_Subscriptions/_channel_info/when_channel_is_not_existing/raise_error.yml +49 -0
- data/spec/vcr/Washbullet_API_Subscriptions/_subscriptions/Get_list_subscriptions.yml +50 -0
- data/spec/vcr/Washbullet_Pushable_File/_push/.yml +170 -0
- data/spec/vcr/Washbullet_Pushable_Link/_push/.yml +52 -0
- data/spec/vcr/Washbullet_Pushable_Note/_push/.yml +51 -0
- data/spec/washbullet/api/contacts_spec.rb +15 -0
- data/spec/washbullet/api/devices_spec.rb +14 -0
- data/spec/washbullet/api/me_spec.rb +11 -0
- data/spec/washbullet/api/subscriptions_spec.rb +31 -0
- data/spec/washbullet/pushable/file_spec.rb +23 -0
- data/spec/washbullet/pushable/link_spec.rb +24 -0
- data/spec/washbullet/pushable/note_spec.rb +20 -0
- data/washbullet.gemspec +5 -1
- metadata +107 -29
- data/spec/fixtures/contacts.json +0 -16
- data/spec/fixtures/devices.json +0 -19
- data/spec/fixtures/push.json +0 -18
- data/spec/fixtures/pushes.json +0 -24
- data/spec/fixtures/upload_request.json +0 -14
- data/spec/fixtures/users.json +0 -31
- data/spec/washbullet/client_spec.rb +0 -9
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'washbullet/entity'
|
2
|
+
|
3
|
+
module Washbullet
|
4
|
+
class Contact < Entity
|
5
|
+
def self.from_response(response)
|
6
|
+
response.body['contacts'].each_with_object([]) {|attributes, memo|
|
7
|
+
next unless attributes['active']
|
8
|
+
|
9
|
+
memo << new(attributes)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
body['name']
|
15
|
+
end
|
16
|
+
|
17
|
+
def email
|
18
|
+
body['email']
|
19
|
+
end
|
20
|
+
|
21
|
+
def image_url
|
22
|
+
body['image_url']
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def receiver
|
28
|
+
:email
|
29
|
+
end
|
30
|
+
|
31
|
+
def identifier
|
32
|
+
body['email']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'washbullet/entity'
|
2
|
+
|
3
|
+
module Washbullet
|
4
|
+
class Device < Entity
|
5
|
+
def self.from_response(response)
|
6
|
+
response.body['devices'].each_with_object([]) {|attributes, memo|
|
7
|
+
next unless attributes['active']
|
8
|
+
|
9
|
+
memo << new(attributes)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def identifier
|
14
|
+
body['iden']
|
15
|
+
end
|
16
|
+
|
17
|
+
def nickname
|
18
|
+
body['nickname']
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def receiver
|
24
|
+
:device
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Washbullet
|
2
|
+
class Entity
|
3
|
+
attr_reader :body
|
4
|
+
|
5
|
+
def initialize(response_body)
|
6
|
+
@body = response_body
|
7
|
+
end
|
8
|
+
|
9
|
+
def created
|
10
|
+
Time.at(body['created'])
|
11
|
+
end
|
12
|
+
|
13
|
+
def modified
|
14
|
+
Time.at(body['modified'])
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def receiver
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def identifier
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -9,21 +9,26 @@ module Washbullet
|
|
9
9
|
class HttpException < Faraday::Response::Middleware
|
10
10
|
def call(env)
|
11
11
|
@app.call(env).on_complete do |response|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
when 500..505
|
24
|
-
raise Washbullet::ServerError, 'Something went wrong on PushBullet\'s side'
|
25
|
-
end
|
12
|
+
exception =
|
13
|
+
case response.status
|
14
|
+
when 400 then Washbullet::BadRequest
|
15
|
+
when 401 then Washbullet::Unauthorized
|
16
|
+
when 402 then Washbullet::RequestFailed
|
17
|
+
when 403 then Washbullet::Forbidden
|
18
|
+
when 404 then Washbullet::NotFound
|
19
|
+
when 500..505 then Washbullet::ServerError
|
20
|
+
end
|
21
|
+
|
22
|
+
raise exception, error_message(response.body) if exception
|
26
23
|
end
|
27
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def error_message(response_body)
|
29
|
+
hash = JSON.parse(response_body)['error']
|
30
|
+
|
31
|
+
[hash['message'], hash['cat']].join(' ')
|
32
|
+
end
|
28
33
|
end
|
29
34
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Washbullet
|
2
|
+
class Push
|
3
|
+
attr_reader :body
|
4
|
+
|
5
|
+
def initialize(response_body)
|
6
|
+
@body = response_body
|
7
|
+
end
|
8
|
+
|
9
|
+
def type
|
10
|
+
body['type']
|
11
|
+
end
|
12
|
+
|
13
|
+
def created
|
14
|
+
Time.at(body['created'])
|
15
|
+
end
|
16
|
+
|
17
|
+
def modified
|
18
|
+
Time.at(body['modified'])
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def identifier
|
24
|
+
body['iden']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'washbullet/push'
|
2
|
+
|
3
|
+
module Washbullet
|
4
|
+
class Pushable
|
5
|
+
class MissingParameter < StandardError; end
|
6
|
+
|
7
|
+
attr_reader :client, :receiver, :identifier, :params
|
8
|
+
|
9
|
+
def self.push(client, receiver, identifier, params)
|
10
|
+
response = new(client, receiver, identifier, params).push
|
11
|
+
|
12
|
+
Push.new(response.body)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(client, receiver, identifier, params)
|
16
|
+
@client = client
|
17
|
+
@receiver = receiver
|
18
|
+
@identifier = identifier
|
19
|
+
@params = params
|
20
|
+
end
|
21
|
+
|
22
|
+
def push
|
23
|
+
raise MissingParameter unless params.keys == required_parameters
|
24
|
+
|
25
|
+
payload = params.merge(type: type)
|
26
|
+
|
27
|
+
payload = specify_receiver(payload)
|
28
|
+
|
29
|
+
client.post('/v2/pushes', payload)
|
30
|
+
end
|
31
|
+
|
32
|
+
def type
|
33
|
+
raise NotImplementedError
|
34
|
+
end
|
35
|
+
|
36
|
+
def required_parameters
|
37
|
+
raise NotImplementedError
|
38
|
+
end
|
39
|
+
|
40
|
+
def specify_receiver(payload)
|
41
|
+
if receiver && identifier
|
42
|
+
payload.merge(receiver_type => identifier)
|
43
|
+
else
|
44
|
+
payload
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def receiver_type
|
49
|
+
case receiver
|
50
|
+
when :device then :device_iden
|
51
|
+
when :email then receiver
|
52
|
+
when :channel then :channel_tag
|
53
|
+
when :client then :client_iden
|
54
|
+
else
|
55
|
+
raise NotImplementedError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Washbullet
|
2
|
+
class Pushable
|
3
|
+
class File < Washbullet::Pushable
|
4
|
+
def push
|
5
|
+
raise MissingParameter unless params.keys == required_parameters
|
6
|
+
|
7
|
+
file_name = params[:file_name]
|
8
|
+
file_path = params[:file_path]
|
9
|
+
|
10
|
+
upload_file(file_name, file_path) do |data|
|
11
|
+
payload = {
|
12
|
+
file_name: data['file_name'],
|
13
|
+
file_type: data['file_type'],
|
14
|
+
file_url: data['file_url'],
|
15
|
+
body: params['body'],
|
16
|
+
type: type
|
17
|
+
}
|
18
|
+
|
19
|
+
payload = specify_receiver(payload)
|
20
|
+
|
21
|
+
client.post('/v2/pushes', payload)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def type
|
26
|
+
:file
|
27
|
+
end
|
28
|
+
|
29
|
+
def required_parameters
|
30
|
+
%i(file_name file_path body)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def upload_file(file_name, file_path, &block)
|
36
|
+
mime_type = MIME::Types.type_for(file_path).first.to_s
|
37
|
+
|
38
|
+
data = upload_request(file_name, mime_type)
|
39
|
+
|
40
|
+
upload_url = data.body['upload_url']
|
41
|
+
params = data.body['data']
|
42
|
+
|
43
|
+
io = Faraday::UploadIO.new(file_path, mime_type)
|
44
|
+
|
45
|
+
client.post upload_url, params.merge(file: io)
|
46
|
+
|
47
|
+
yield data.body
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload_request(file_name, mime_type)
|
51
|
+
client.post '/v2/upload-request', file_name: file_name, file_type: mime_type
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/washbullet/request.rb
CHANGED
@@ -15,7 +15,7 @@ module Washbullet
|
|
15
15
|
private
|
16
16
|
|
17
17
|
def request(method, path, params = {})
|
18
|
-
|
18
|
+
connection.send(method) {|request|
|
19
19
|
request.url path
|
20
20
|
request.params = params if method == :get
|
21
21
|
request.body = params if method == :post
|
data/lib/washbullet/version.rb
CHANGED
Binary file
|
data/spec/spec_helper.rb
CHANGED
@@ -1,82 +1,62 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
4
|
-
# file to always be loaded, without a need to explicitly require it in any files.
|
5
|
-
#
|
6
|
-
# Given that it is always loaded, you are encouraged to keep this file as
|
7
|
-
# light-weight as possible. Requiring heavyweight dependencies from this file
|
8
|
-
# (such as loading up an entire rails app) will add to the boot time of your
|
9
|
-
# test suite on EVERY test run, even for an individual file that may not need
|
10
|
-
# all of that loaded.
|
11
|
-
#
|
12
|
-
# The `.rspec` file also contains a few flags that are not defaults but that
|
13
|
-
# users commonly want.
|
14
|
-
#
|
15
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
16
|
-
RSpec.configure do |config|
|
17
|
-
# The settings below are suggested to provide a good initial experience
|
18
|
-
# with RSpec, but feel free to customize to your heart's content.
|
19
|
-
=begin
|
20
|
-
# These two settings work together to allow you to limit a spec run
|
21
|
-
# to individual examples or groups you care about by tagging them with
|
22
|
-
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
23
|
-
# get run.
|
24
|
-
config.filter_run :focus
|
25
|
-
config.run_all_when_everything_filtered = true
|
1
|
+
require 'pry'
|
2
|
+
require 'json'
|
26
3
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
config.full_backtrace = true
|
4
|
+
require 'washbullet'
|
5
|
+
require 'webmock/rspec'
|
6
|
+
require 'vcr'
|
7
|
+
|
8
|
+
def test_api_key
|
9
|
+
ENV.fetch('API_KEY', '<API_KEY>')
|
10
|
+
end
|
35
11
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
12
|
+
VCR.configure do |config|
|
13
|
+
config.cassette_library_dir = 'spec/vcr'
|
14
|
+
config.hook_into :webmock
|
15
|
+
config.configure_rspec_metadata!
|
16
|
+
|
17
|
+
config.filter_sensitive_data('<API_KEY>') do
|
18
|
+
test_api_key
|
40
19
|
end
|
41
20
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
21
|
+
config.before_record do |interaction|
|
22
|
+
next if interaction.response.body.empty?
|
23
|
+
|
24
|
+
response = JSON.parse(interaction.response.body)
|
25
|
+
|
26
|
+
response['iden'] = '<IDENTIFIER>' if response.has_key?('iden')
|
27
|
+
|
28
|
+
%w(devices contacts subscriptions).each do |key|
|
29
|
+
response[key] = response[key].map {|entity|
|
30
|
+
entity.merge!({'iden' => '<IDENTIFIER>'})
|
46
31
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
config.order = :random
|
32
|
+
if entity['fingerprint']
|
33
|
+
entity['fingerprint'] = JSON.parse(entity['fingerprint'])
|
34
|
+
entity['fingerprint'].merge!({'android_id' => '<ANDROID_ID>'})
|
35
|
+
end
|
52
36
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
# as the one that triggered the failure.
|
57
|
-
Kernel.srand config.seed
|
37
|
+
if entity['channel']
|
38
|
+
entity['channel'].merge!({'iden' => '<IDENTIFIER>'})
|
39
|
+
end
|
58
40
|
|
59
|
-
|
60
|
-
|
61
|
-
|
41
|
+
entity
|
42
|
+
} if response[key]
|
43
|
+
end
|
44
|
+
|
45
|
+
interaction.response.body = response.to_json
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
RSpec.configure do |config|
|
62
50
|
config.expect_with :rspec do |expectations|
|
63
|
-
|
64
|
-
# For more details, see:
|
65
|
-
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
66
|
-
expectations.syntax = :expect
|
51
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
67
52
|
end
|
68
53
|
|
69
|
-
# rspec-mocks config goes here. You can use an alternate test double
|
70
|
-
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
71
54
|
config.mock_with :rspec do |mocks|
|
72
|
-
# Enable only the newer, non-monkey-patching expect syntax.
|
73
|
-
# For more details, see:
|
74
|
-
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
75
|
-
mocks.syntax = :expect
|
76
|
-
|
77
|
-
# Prevents you from mocking or stubbing a method that does not exist on
|
78
|
-
# a real object. This is generally recommended.
|
79
55
|
mocks.verify_partial_doubles = true
|
80
56
|
end
|
81
|
-
|
57
|
+
|
58
|
+
config.filter_run :focus
|
59
|
+
config.run_all_when_everything_filtered = true
|
60
|
+
config.disable_monkey_patching!
|
61
|
+
config.warnings = true
|
82
62
|
end
|