exponent-server-sdk 0.0.2 → 0.0.3
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 +2 -0
- data/.travis.yml +7 -0
- data/README.md +36 -3
- data/Rakefile +9 -0
- data/exponent-server-sdk.gemspec +10 -9
- data/lib/exponent-server-sdk.rb +97 -18
- data/lib/exponent-server-sdk/version.rb +1 -1
- data/test/exponent-server-sdk-test.rb +130 -0
- metadata +28 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88ec6ffe5bd4602818f88d05b6ce235631cd4951
|
4
|
+
data.tar.gz: b5cf4200640d97ca8136dbe2788c60b1a28d1531
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51937e0397c547c37f7a6da6dc0b94897cf578ef47ca4271f5ee2b15c216cea04a9071893cd45e2a3ca2f729feffa60bc1b0c893640fdd72a15d4e8605caa04f
|
7
|
+
data.tar.gz: 15b4e65065e9526a407b9f274f7bb9d56427cd2ee7dd842962d1be4f0ff9812f3e65d9f6c4e6bad8b9ef45047543a6ee401ef7a0698deece9cb0de44da90ffec
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,17 +1,50 @@
|
|
1
1
|
# Exponent Server SDK Ruby
|
2
|
+
[](https://travis-ci.org/expo/exponent-server-sdk-ruby)
|
2
3
|
|
3
4
|
Use to send push notifications to Exponent Experiences from a Ruby server.
|
4
5
|
|
6
|
+
If you have problems with the code in this repository, please file issues & bug reports at https://github.com/expo/expo. Thanks!
|
7
|
+
|
5
8
|
## Installation
|
6
9
|
|
7
10
|
Add this line to your application's Gemfile:
|
8
11
|
|
9
|
-
|
12
|
+
```ruby
|
13
|
+
gem 'exponent-server-sdk'
|
14
|
+
```
|
10
15
|
|
11
16
|
And then execute:
|
12
17
|
|
13
|
-
|
18
|
+
```shell
|
19
|
+
$ bundle
|
20
|
+
```
|
14
21
|
|
15
22
|
Or install it yourself as:
|
16
23
|
|
17
|
-
|
24
|
+
```shell
|
25
|
+
$ gem install exponent-server-sdk
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Client
|
31
|
+
|
32
|
+
The push client is the preferred way. This hits the latest version of the api.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
exponent = Exponent::Push::Client.new
|
36
|
+
|
37
|
+
messages = [{
|
38
|
+
to: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
|
39
|
+
sound: "default",
|
40
|
+
body: "Hello world!"
|
41
|
+
}, {
|
42
|
+
to: "ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]",
|
43
|
+
badge: 1,
|
44
|
+
body: "You've got mail"
|
45
|
+
}]
|
46
|
+
|
47
|
+
exponent.publish messages
|
48
|
+
```
|
49
|
+
|
50
|
+
The complete format of the messages can be found [here.](https://docs.expo.io/versions/v16.0.0/guides/push-notifications.html#http2-api)
|
data/Rakefile
CHANGED
data/exponent-server-sdk.gemspec
CHANGED
@@ -4,22 +4,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'exponent-server-sdk/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'exponent-server-sdk'
|
8
8
|
spec.version = Exponent::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Jesse Ruder', 'Pablo Gomez']
|
10
|
+
spec.email = ['jesse@sixfivezero.net', 'pablonahuelgomez@gmail.com']
|
11
11
|
spec.summary = %q{Exponent Server SDK}
|
12
12
|
spec.description = %q{Exponent Server SDK}
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency
|
21
|
+
spec.add_dependency 'typhoeus'
|
22
22
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
23
|
+
spec.add_development_dependency 'bundler'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'minitest'
|
25
26
|
end
|
data/lib/exponent-server-sdk.rb
CHANGED
@@ -1,32 +1,111 @@
|
|
1
1
|
require 'exponent-server-sdk/version'
|
2
|
-
|
3
|
-
require '
|
2
|
+
require 'typhoeus'
|
3
|
+
require 'json'
|
4
4
|
|
5
5
|
module Exponent
|
6
|
+
def self.is_exponent_push_token?(token)
|
7
|
+
token.start_with?('ExponentPushToken')
|
8
|
+
end
|
9
|
+
|
6
10
|
module Push
|
7
|
-
|
8
|
-
token.start_with?('ExponentPushToken')
|
9
|
-
end
|
11
|
+
Error = Class.new(StandardError)
|
10
12
|
|
11
13
|
class Client
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
|
15
|
+
def initialize(new_http_client = nil)
|
16
|
+
@http_client = new_http_client || Typhoeus
|
17
|
+
end
|
18
|
+
|
19
|
+
def publish(messages)
|
20
|
+
handle_response(push_notifications(messages))
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :http_client
|
26
|
+
|
27
|
+
def handle_response(response)
|
28
|
+
case response.code.to_s
|
29
|
+
when /(^4|^5)/
|
30
|
+
raise Error, build_error_from_failure(parse_json(response))
|
31
|
+
else
|
32
|
+
handle_success(parse_json(response))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_json(response)
|
37
|
+
JSON.parse(response.body)
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_error_from_failure(response)
|
41
|
+
build_error_with_handling(response) do
|
42
|
+
extract_error_from_response(response)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def extract_error_from_response(response)
|
47
|
+
error = response.fetch('errors').first { unknown_error_format(response) }
|
48
|
+
"#{error.fetch('code')} -> #{error.fetch('message')}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_error_with_handling(response)
|
52
|
+
yield(response)
|
53
|
+
rescue KeyError
|
54
|
+
unknown_error_format(response)
|
55
|
+
end
|
56
|
+
|
57
|
+
def push_notifications(messages)
|
58
|
+
http_client.post(
|
59
|
+
push_url,
|
60
|
+
body: messages.to_json,
|
61
|
+
headers: headers
|
19
62
|
)
|
63
|
+
end
|
20
64
|
|
21
|
-
|
22
|
-
|
23
|
-
|
65
|
+
def push_url
|
66
|
+
'https://exp.host/--/api/v2/push/send'
|
67
|
+
end
|
68
|
+
|
69
|
+
def headers
|
70
|
+
{
|
71
|
+
'Content-Type' => 'application/json',
|
72
|
+
'Accept' => 'application/json',
|
73
|
+
'Accept-Encoding' => 'gzip, deflate'
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def handle_success(response)
|
78
|
+
data = extract_data(response)
|
79
|
+
if data.fetch('status') == 'ok'
|
80
|
+
data
|
81
|
+
else
|
82
|
+
raise Error, build_error_from_success(response)
|
24
83
|
end
|
25
84
|
end
|
26
|
-
end
|
27
85
|
|
28
|
-
|
29
|
-
|
86
|
+
def build_error_from_success(response)
|
87
|
+
build_error_with_handling(response) do
|
88
|
+
extract_error_from_success(response)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def extract_error_from_success(response)
|
93
|
+
data = extract_data(response)
|
94
|
+
message = data.fetch('message')
|
95
|
+
|
96
|
+
if data['details']
|
97
|
+
"#{data.fetch('details').fetch('error')} -> #{message}"
|
98
|
+
else
|
99
|
+
"#{data.fetch('status')} -> #{message}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def extract_data(response)
|
104
|
+
response.fetch('data').first
|
105
|
+
end
|
106
|
+
|
107
|
+
def unknown_error_format(response)
|
108
|
+
"Unknown error format: #{response}"
|
30
109
|
end
|
31
110
|
end
|
32
111
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'exponent-server-sdk'
|
3
|
+
|
4
|
+
class ExponentServerSdkTest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@mock = MiniTest::Mock.new
|
7
|
+
@response_mock = MiniTest::Mock.new
|
8
|
+
@exponent = Exponent::Push::Client.new(@mock)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_publish_with_success
|
12
|
+
@response_mock.expect(:code, 200)
|
13
|
+
@response_mock.expect(:body, success_body.to_json)
|
14
|
+
|
15
|
+
@mock.expect(:post, @response_mock, client_args)
|
16
|
+
|
17
|
+
@exponent.publish(messages)
|
18
|
+
|
19
|
+
@mock.verify
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_publish_with_error
|
23
|
+
@response_mock.expect(:code, 400)
|
24
|
+
@response_mock.expect(:body, error_body.to_json)
|
25
|
+
message = 'INTERNAL_SERVER_ERROR -> An unknown error occurred.'
|
26
|
+
|
27
|
+
@mock.expect(:post, @response_mock, client_args)
|
28
|
+
|
29
|
+
exception = assert_raises Exponent::Push::Error do
|
30
|
+
@exponent.publish(messages)
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_equal(message, exception.message)
|
34
|
+
|
35
|
+
@mock.verify
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_publish_with_success_and_errors
|
39
|
+
@response_mock.expect(:code, 200)
|
40
|
+
@response_mock.expect(:body, success_with_error_body.to_json)
|
41
|
+
message = 'DeviceNotRegistered -> "ExponentPushToken[42]" is not a registered push notification recipient'
|
42
|
+
|
43
|
+
@mock.expect(:post, @response_mock, client_args)
|
44
|
+
|
45
|
+
exception = assert_raises Exponent::Push::Error do
|
46
|
+
@exponent.publish(messages)
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_equal(message, exception.message)
|
50
|
+
|
51
|
+
@mock.verify
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_publish_with_success_and_apn_error
|
55
|
+
@response_mock.expect(:code, 200)
|
56
|
+
@response_mock.expect(:body, success_with_apn_error_body.to_json)
|
57
|
+
message = 'error -> Could not find APNs credentials for you (your_app). Check whether you are trying to send a notification to a detached app.'
|
58
|
+
|
59
|
+
@mock.expect(:post, @response_mock, client_args)
|
60
|
+
|
61
|
+
exception = assert_raises Exponent::Push::Error do
|
62
|
+
@exponent.publish(messages)
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal(message, exception.message)
|
66
|
+
|
67
|
+
@mock.verify
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def success_body
|
73
|
+
{ 'data' => [{ 'status' => 'ok' }] }
|
74
|
+
end
|
75
|
+
|
76
|
+
def error_body
|
77
|
+
{
|
78
|
+
'errors' => [{
|
79
|
+
'code' => 'INTERNAL_SERVER_ERROR',
|
80
|
+
'message' => 'An unknown error occurred.'
|
81
|
+
}]
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def success_with_error_body
|
86
|
+
{
|
87
|
+
'data' => [{
|
88
|
+
'status' => 'error',
|
89
|
+
'message' => '"ExponentPushToken[42]" is not a registered push notification recipient',
|
90
|
+
'details' => { 'error' => 'DeviceNotRegistered' }
|
91
|
+
}]
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def success_with_apn_error_body
|
96
|
+
{
|
97
|
+
'data' => [{
|
98
|
+
'status' => 'error',
|
99
|
+
'message' =>
|
100
|
+
'Could not find APNs credentials for you (your_app). Check whether you are trying to send a notification to a detached app.'
|
101
|
+
}]
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def client_args
|
106
|
+
[
|
107
|
+
'https://exp.host/--/api/v2/push/send',
|
108
|
+
{
|
109
|
+
body: messages.to_json,
|
110
|
+
headers: {
|
111
|
+
'Content-Type' => 'application/json',
|
112
|
+
'Accept' => 'application/json',
|
113
|
+
'Accept-Encoding' => 'gzip, deflate'
|
114
|
+
}
|
115
|
+
}
|
116
|
+
]
|
117
|
+
end
|
118
|
+
|
119
|
+
def messages
|
120
|
+
[{
|
121
|
+
to: 'ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]',
|
122
|
+
sound: 'default',
|
123
|
+
body: 'Hello world!'
|
124
|
+
}, {
|
125
|
+
to: 'ExponentPushToken[yyyyyyyyyyyyyyyyyyyyyy]',
|
126
|
+
badge: 1,
|
127
|
+
body: "You've got mail"
|
128
|
+
}]
|
129
|
+
end
|
130
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exponent-server-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Ruder
|
8
|
+
- Pablo Gomez
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2018-02-13 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: typhoeus
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
18
|
- - ">="
|
@@ -28,16 +29,16 @@ dependencies:
|
|
28
29
|
name: bundler
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- - "
|
32
|
+
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
+
version: '0'
|
34
35
|
type: :development
|
35
36
|
prerelease: false
|
36
37
|
version_requirements: !ruby/object:Gem::Requirement
|
37
38
|
requirements:
|
38
|
-
- - "
|
39
|
+
- - ">="
|
39
40
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
41
|
+
version: '0'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
43
|
name: rake
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,14 +53,30 @@ dependencies:
|
|
52
53
|
- - ">="
|
53
54
|
- !ruby/object:Gem::Version
|
54
55
|
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: minitest
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
55
70
|
description: Exponent Server SDK
|
56
71
|
email:
|
57
72
|
- jesse@sixfivezero.net
|
73
|
+
- pablonahuelgomez@gmail.com
|
58
74
|
executables: []
|
59
75
|
extensions: []
|
60
76
|
extra_rdoc_files: []
|
61
77
|
files:
|
62
78
|
- ".gitignore"
|
79
|
+
- ".travis.yml"
|
63
80
|
- Gemfile
|
64
81
|
- LICENSE.txt
|
65
82
|
- README.md
|
@@ -68,6 +85,7 @@ files:
|
|
68
85
|
- lib/exponent-server-sdk.rb
|
69
86
|
- lib/exponent-server-sdk/version.rb
|
70
87
|
- manual-testing.txt
|
88
|
+
- test/exponent-server-sdk-test.rb
|
71
89
|
homepage: ''
|
72
90
|
licenses:
|
73
91
|
- MIT
|
@@ -88,8 +106,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
106
|
version: '0'
|
89
107
|
requirements: []
|
90
108
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.
|
109
|
+
rubygems_version: 2.6.11
|
92
110
|
signing_key:
|
93
111
|
specification_version: 4
|
94
112
|
summary: Exponent Server SDK
|
95
|
-
test_files:
|
113
|
+
test_files:
|
114
|
+
- test/exponent-server-sdk-test.rb
|