fcm 0.0.2 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +4 -2
- data/README.md +95 -29
- data/fcm.gemspec +2 -3
- data/lib/fcm.rb +93 -17
- data/spec/fcm_spec.rb +100 -0
- metadata +10 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d92dc29d8a781ef45a9e3cd113fe834a3a41b63
|
4
|
+
data.tar.gz: e3413daa3b418bfbc0631ffdf79f653950599f25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 994687542f81b3d11b403d71dde8097a1990445c66249922215da103cff7737d44ee30d99537676cf2695f5606d2837cbb45cfdf59aed2b8c7649290450bf9a1
|
7
|
+
data.tar.gz: 1516e659f3c1d7180a77ac177e0f79e4f45d9d471d0f22434533657de07d9de4c29855baf66dcbee003cf9c3b1ac6976ac8a543ca9e75a07b1d9fd04297dfb59
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# Firebase Cloud Messaging (FCM) for Android and iOS
|
2
|
+
|
2
3
|
[![Gem Version](https://badge.fury.io/rb/fcm.svg)](http://badge.fury.io/rb/fcm) [![Build Status](https://secure.travis-ci.org/spacialdb/fcm.png?branch=master)](http://travis-ci.org/spacialdb/fcm)
|
3
4
|
|
4
5
|
The FCM gem lets your ruby backend send notifications to Android and iOS devices via [
|
5
6
|
Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/).
|
6
7
|
|
7
|
-
##Installation
|
8
|
+
## Installation
|
8
9
|
|
9
10
|
$ gem install fcm
|
10
11
|
|
@@ -14,53 +15,63 @@ or in your `Gemfile` just include it:
|
|
14
15
|
gem 'fcm'
|
15
16
|
```
|
16
17
|
|
17
|
-
##Requirements
|
18
|
+
## Requirements
|
18
19
|
|
19
20
|
For Android you will need a device running 2.3 (or newer) that also have the Google Play Store app installed, or an emulator running Android 2.3 with Google APIs. iOS devices are also supported.
|
20
21
|
|
21
22
|
One of the following, tested Ruby versions:
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
- `2.0.0`
|
25
|
+
- `2.1.9`
|
26
|
+
- `2.2.5`
|
27
|
+
- `2.3.1`
|
27
28
|
|
28
|
-
##Usage
|
29
|
+
## Usage
|
29
30
|
|
30
|
-
For your server to send a message to one or more devices, you must first initialise a new `FCM` class with your Firebase server
|
31
|
+
For your server to send a message to one or more devices, you must first initialise a new `FCM` class with your Firebase Cloud Messaging server key, and then call the `send` method on this and give it 1 or more (up to 1000) registration tokens as an array of strings. You can also optionally send further [HTTP message parameters](https://firebase.google.com/docs/cloud-messaging/http-server-ref) like `data` or `time_to_live` etc. as a hash via the second optional argument to `send`.
|
31
32
|
|
32
33
|
Example sending notifications:
|
33
34
|
|
34
35
|
```ruby
|
35
36
|
require 'fcm'
|
36
37
|
|
37
|
-
fcm = FCM.new("
|
38
|
+
fcm = FCM.new("my_server_key")
|
38
39
|
# you can set option parameters in here
|
39
40
|
# - all options are pass to HTTParty method arguments
|
40
41
|
# - ref: https://github.com/jnunemaker/httparty/blob/master/lib/httparty.rb#L29-L60
|
41
|
-
# fcm = FCM.new("
|
42
|
+
# fcm = FCM.new("my_server_key", timeout: 3)
|
42
43
|
|
43
44
|
registration_ids= ["12", "13"] # an array of one or more client registration tokens
|
44
|
-
|
45
|
+
|
46
|
+
# See https://developers.google.com/cloud-messaging/http for all available options.
|
47
|
+
options = { "notification": {
|
48
|
+
"title": "Portugal vs. Denmark",
|
49
|
+
"text": "5 to 1"
|
50
|
+
},
|
51
|
+
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
|
52
|
+
}
|
45
53
|
response = fcm.send(registration_ids, options)
|
46
54
|
```
|
47
55
|
|
48
|
-
Currently `response` is just a hash containing the response `body`, `headers` and `
|
56
|
+
Currently `response` is just a hash containing the response `body`, `headers` and `status_code`. Check [here](https://firebase.google.com/docs/cloud-messaging/server#response) to see how to interpret the responses.
|
49
57
|
|
50
58
|
## Device Group Messaging
|
51
59
|
|
52
60
|
With [device group messaging](https://firebase.google.com/docs/cloud-messaging/notifications), you can send a single message to multiple instance of an app running on devices belonging to a group. Typically, "group" refers a set of different devices that belong to a single user. However, a group could also represent a set of devices where the app instance functions in a highly correlated manner. To use this feature, you will first need an initialised `FCM` class.
|
53
61
|
|
54
62
|
### Generate a Notification Key for device group
|
55
|
-
|
63
|
+
|
64
|
+
Then you will need a notification key which you can create for a particular `key_name` which needs to be uniquely named per app in case you have multiple apps for the same `project_id`. This ensures that notifications only go to the intended target app. The `create` method will do this and return the token `notification_key`, that represents the device group, in the response:
|
56
65
|
|
57
66
|
```ruby
|
58
|
-
|
67
|
+
params = {key_name: "appUser-Chris",
|
59
68
|
project_id: "my_project_id",
|
60
|
-
registration_ids: ["4", "8", "15", "16", "23", "42"]
|
69
|
+
registration_ids: ["4", "8", "15", "16", "23", "42"]}
|
70
|
+
response = fcm.create(*params.values)
|
61
71
|
```
|
62
72
|
|
63
73
|
### Send to Notification Key
|
74
|
+
|
64
75
|
Now you can send a message to a particular `notification_key` via the `send_with_notification_key` method. This allows the server to send a single [data](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages) payload or/and [notification](https://firebase.google.com/docs/cloud-messaging/concept-options#notifications) payload to multiple app instances (typically on multiple devices) owned by a single user (instead of sending to some registration tokens). Note: the maximum number of members allowed for a `notification_key` is 20.
|
65
76
|
|
66
77
|
```ruby
|
@@ -74,31 +85,85 @@ response = fcm.send_with_notification_key("notification_key",
|
|
74
85
|
You can also add/remove registration Tokens to/from a particular `notification_key` of some `project_id`. For example:
|
75
86
|
|
76
87
|
```ruby
|
77
|
-
|
88
|
+
params = { key_name: "appUser-Chris",
|
78
89
|
project_id: "my_project_id",
|
79
90
|
notification_key:"appUser-Chris-key",
|
80
|
-
registration_ids:["7", "3"]
|
91
|
+
registration_ids:["7", "3"] }
|
92
|
+
response = fcm.add(*params.values)
|
81
93
|
|
82
|
-
|
94
|
+
params = { key_name: "appUser-Chris",
|
83
95
|
project_id: "my_project_id",
|
84
96
|
notification_key:"appUser-Chris-key",
|
85
|
-
registration_ids:["8", "15"]
|
97
|
+
registration_ids:["8", "15"] }
|
98
|
+
response = fcm.remove(*params.values)
|
86
99
|
```
|
87
100
|
|
88
101
|
## Send Messages to Topics
|
89
102
|
|
90
|
-
FCM [topic messaging](https://firebase.google.com/docs/cloud-messaging/topic-messaging) allows your app server to send a message to multiple devices that have opted in to a particular topic. Based on the publish/subscribe model, topic messaging supports unlimited subscriptions per app. Sending to a topic is very similar to sending to an individual device or to a user group, in the sense that you can use the `fcm.send_with_notification_key()` method where the `
|
103
|
+
FCM [topic messaging](https://firebase.google.com/docs/cloud-messaging/topic-messaging) allows your app server to send a message to multiple devices that have opted in to a particular topic. Based on the publish/subscribe model, topic messaging supports unlimited subscriptions per app. Sending to a topic is very similar to sending to an individual device or to a user group, in the sense that you can use the `fcm.send_with_notification_key()` method where the `notification_key` matches the regular expression `"/topics/[a-zA-Z0-9-_.~%]+"`:
|
91
104
|
|
92
105
|
```ruby
|
93
106
|
response = fcm.send_with_notification_key("/topics/yourTopic",
|
94
|
-
data: {message: "This is a FCM Topic Message!")
|
107
|
+
data: {message: "This is a FCM Topic Message!"})
|
95
108
|
```
|
96
109
|
|
97
110
|
Or you can use the helper:
|
98
111
|
|
99
112
|
```ruby
|
100
113
|
response = fcm.send_to_topic("yourTopic",
|
101
|
-
data: {message: "This is a FCM Topic Message!")
|
114
|
+
data: {message: "This is a FCM Topic Message!"})
|
115
|
+
```
|
116
|
+
|
117
|
+
### Sending to Multiple Topics
|
118
|
+
|
119
|
+
To send to combinations of multiple topics, the FCM [docs](https://firebase.google.com/docs/cloud-messaging/send-message#send_messages_to_topics_2) require that you set a **condition** key (instead of the `to:` key) to a boolean condition that specifies the target topics. For example, to send messages to devices that subscribed to _TopicA_ and either _TopicB_ or _TopicC_:
|
120
|
+
|
121
|
+
```
|
122
|
+
'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)
|
123
|
+
```
|
124
|
+
|
125
|
+
FCM first evaluates any conditions in parentheses, and then evaluates the expression from left to right. In the above expression, a user subscribed to any single topic does not receive the message. Likewise, a user who does not subscribe to TopicA does not receive the message. These combinations do receive it:
|
126
|
+
|
127
|
+
- TopicA and TopicB
|
128
|
+
- TopicA and TopicC
|
129
|
+
|
130
|
+
You can include up to five topics in your conditional expression, and parentheses are supported. Supported operators: `&&`, `||`, `!`. Note the usage for !:
|
131
|
+
|
132
|
+
```
|
133
|
+
!('TopicA' in topics)
|
134
|
+
```
|
135
|
+
|
136
|
+
With this expression, any app instances that are not subscribed to TopicA, including app instances that are not subscribed to any topic, receive the message.
|
137
|
+
|
138
|
+
The `send_to_topic_condition` method within this library allows you to specicy a condition of multiple topics to which to send to the data payload.
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
response = fcm.send_to_topic_condition(
|
142
|
+
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)",
|
143
|
+
data: {
|
144
|
+
message: "This is an FCM Topic Message sent to a condition!"
|
145
|
+
}
|
146
|
+
)
|
147
|
+
```
|
148
|
+
|
149
|
+
## Subscribe the client app to a topic
|
150
|
+
|
151
|
+
Given a registration token and a topic name, you can add the token to the topic using the [Google Instance ID server API](https://developers.google.com/instance-id/reference/server).
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
topic = "YourTopic"
|
155
|
+
registration_id= "12" # a client registration tokens
|
156
|
+
response = fcm.topic_subscription(topic, registration_id)
|
157
|
+
```
|
158
|
+
|
159
|
+
Or you can manage relationship maps for multiple app instances [Google Instance ID server API. Manage relationship](https://developers.google.com/instance-id/reference/server#manage_relationship_maps_for_multiple_app_instances)
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
topic = "YourTopic"
|
163
|
+
registration_ids= ["4", "8", "15", "16", "23", "42"] # an array of one or more client registration tokens
|
164
|
+
response = fcm.batch_topic_subscription(topic, registration_ids)
|
165
|
+
# or unsubscription
|
166
|
+
response = fcm.batch_topic_unsubscription(topic, registration_ids)
|
102
167
|
```
|
103
168
|
|
104
169
|
## Mobile Clients
|
@@ -111,22 +176,23 @@ The guide to set up an iOS app to get notifications is here: [Setting up a FCM C
|
|
111
176
|
|
112
177
|
### 0.0.2
|
113
178
|
|
114
|
-
|
115
|
-
|
179
|
+
- Fixed group messaging url.
|
180
|
+
- Added API to `recover_notification_key`.
|
116
181
|
|
117
182
|
### 0.0.1
|
118
183
|
|
119
|
-
|
184
|
+
- Initial version.
|
120
185
|
|
121
|
-
##MIT License
|
186
|
+
## MIT License
|
122
187
|
|
123
|
-
|
188
|
+
- Copyright (c) 2016 Kashif Rasul and Shoaib Burq. See LICENSE.txt for details.
|
124
189
|
|
125
|
-
##Many thanks to all the contributors
|
190
|
+
## Many thanks to all the contributors
|
126
191
|
|
127
|
-
|
192
|
+
- [Contributors](https://github.com/spacialdb/fcm/contributors)
|
128
193
|
|
129
194
|
## Donations
|
195
|
+
|
130
196
|
We accept tips through [Gratipay](https://gratipay.com/spacialdb/).
|
131
197
|
|
132
198
|
[![Gratipay](https://img.shields.io/gratipay/spacialdb.svg)](https://www.gittip.com/spacialdb/)
|
data/fcm.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "fcm"
|
6
|
-
s.version = "0.0.
|
6
|
+
s.version = "0.0.6"
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ["Kashif Rasul", "Shoaib Burq"]
|
9
9
|
s.email = ["kashif@spacialdb.com", "shoaib@spacialdb.com"]
|
@@ -21,6 +21,5 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
22
|
s.require_paths = ["lib"]
|
23
23
|
|
24
|
-
s.
|
25
|
-
s.add_dependency('json')
|
24
|
+
s.add_runtime_dependency('httparty', '~> 0.10', '>= 0.10.0')
|
26
25
|
end
|
data/lib/fcm.rb
CHANGED
@@ -10,6 +10,8 @@ class FCM
|
|
10
10
|
|
11
11
|
# constants
|
12
12
|
GROUP_NOTIFICATION_BASE_URI = 'https://android.googleapis.com/gcm'
|
13
|
+
INSTANCE_ID_API = 'https://iid.googleapis.com/iid/v1'
|
14
|
+
TOPIC_REGEX = /[a-zA-Z0-9\-_.~%]+/
|
13
15
|
|
14
16
|
attr_accessor :timeout, :api_key
|
15
17
|
|
@@ -18,18 +20,18 @@ class FCM
|
|
18
20
|
@client_options = client_options
|
19
21
|
end
|
20
22
|
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# "score": "5x1",
|
28
|
-
# "time": "15:10"
|
29
|
-
# }
|
23
|
+
# See https://developers.google.com/cloud-messaging/http for more details.
|
24
|
+
# { "notification": {
|
25
|
+
# "title": "Portugal vs. Denmark",
|
26
|
+
# "text": "5 to 1"
|
27
|
+
# },
|
28
|
+
# "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
|
30
29
|
# }
|
31
30
|
# fcm = FCM.new("API_KEY")
|
32
|
-
# fcm.send(
|
31
|
+
# fcm.send(
|
32
|
+
# ["4sdsx", "8sdsd"], # registration_ids
|
33
|
+
# { "notification": { "title": "Portugal vs. Denmark", "text": "5 to 1" }, "to" : "bk3RNwTe3HdFQ3P1..." }
|
34
|
+
# )
|
33
35
|
def send_notification(registration_ids, options = {})
|
34
36
|
post_body = build_post_body(registration_ids, options)
|
35
37
|
|
@@ -129,32 +131,75 @@ class FCM
|
|
129
131
|
response = nil
|
130
132
|
|
131
133
|
for_uri(GROUP_NOTIFICATION_BASE_URI) do
|
132
|
-
response = self.class.
|
134
|
+
response = self.class.get('/notification', params.merge(@client_options))
|
133
135
|
end
|
134
136
|
build_response(response)
|
135
137
|
end
|
136
138
|
|
137
139
|
def send_with_notification_key(notification_key, options = {})
|
138
140
|
body = { to: notification_key }.merge(options)
|
141
|
+
execute_notification(body)
|
142
|
+
end
|
139
143
|
|
144
|
+
def topic_subscription(topic, registration_id)
|
140
145
|
params = {
|
141
|
-
body: body.to_json,
|
142
146
|
headers: {
|
143
|
-
|
144
|
-
|
147
|
+
'Authorization' => "key=#{@api_key}",
|
148
|
+
'Content-Type' => 'application/json'
|
145
149
|
}
|
146
150
|
}
|
147
151
|
|
148
|
-
response =
|
152
|
+
response = nil
|
153
|
+
|
154
|
+
for_uri(INSTANCE_ID_API) do
|
155
|
+
response = self.class.post("/#{registration_id}/rel/topics/#{topic}", params)
|
156
|
+
end
|
157
|
+
|
158
|
+
build_response(response)
|
159
|
+
end
|
160
|
+
|
161
|
+
def batch_topic_subscription(topic, registration_ids)
|
162
|
+
manage_topics_relationship(topic, registration_ids, 'Add')
|
163
|
+
end
|
164
|
+
|
165
|
+
def batch_topic_unsubscription(topic, registration_ids)
|
166
|
+
manage_topics_relationship(topic, registration_ids, 'Remove')
|
167
|
+
end
|
168
|
+
|
169
|
+
def manage_topics_relationship(topic, registration_ids, action)
|
170
|
+
body = { to: "/topics/#{topic}", registration_tokens: registration_ids }
|
171
|
+
params = {
|
172
|
+
body: body.to_json,
|
173
|
+
headers: {
|
174
|
+
'Authorization' => "key=#{@api_key}",
|
175
|
+
'Content-Type' => 'application/json'
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
response = nil
|
180
|
+
|
181
|
+
for_uri(INSTANCE_ID_API) do
|
182
|
+
response = self.class.post("/:batch#{action}", params)
|
183
|
+
end
|
184
|
+
|
149
185
|
build_response(response)
|
150
186
|
end
|
151
187
|
|
188
|
+
|
189
|
+
|
152
190
|
def send_to_topic(topic, options = {})
|
153
|
-
if topic
|
191
|
+
if topic.gsub(TOPIC_REGEX, "").length == 0
|
154
192
|
send_with_notification_key('/topics/' + topic, options)
|
155
193
|
end
|
156
194
|
end
|
157
195
|
|
196
|
+
def send_to_topic_condition(condition, options = {})
|
197
|
+
if validate_condition?(condition)
|
198
|
+
body = { condition: condition }.merge(options)
|
199
|
+
execute_notification(body)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
158
203
|
private
|
159
204
|
|
160
205
|
def for_uri(uri)
|
@@ -165,7 +210,8 @@ class FCM
|
|
165
210
|
end
|
166
211
|
|
167
212
|
def build_post_body(registration_ids, options = {})
|
168
|
-
|
213
|
+
ids = registration_ids.is_a?(String) ? [registration_ids] : registration_ids
|
214
|
+
{ registration_ids: ids }.merge(options)
|
169
215
|
end
|
170
216
|
|
171
217
|
def build_response(response, registration_ids = [])
|
@@ -213,6 +259,19 @@ class FCM
|
|
213
259
|
not_registered_ids
|
214
260
|
end
|
215
261
|
|
262
|
+
def execute_notification(body)
|
263
|
+
params = {
|
264
|
+
body: body.to_json,
|
265
|
+
headers: {
|
266
|
+
'Authorization' => "key=#{@api_key}",
|
267
|
+
'Content-Type' => 'application/json'
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
response = self.class.post('/send', params.merge(@client_options))
|
272
|
+
build_response(response)
|
273
|
+
end
|
274
|
+
|
216
275
|
def has_canonical_id?(result)
|
217
276
|
!result['registration_id'].nil?
|
218
277
|
end
|
@@ -220,4 +279,21 @@ class FCM
|
|
220
279
|
def is_not_registered?(result)
|
221
280
|
result['error'] == 'NotRegistered'
|
222
281
|
end
|
282
|
+
|
283
|
+
def validate_condition?(condition)
|
284
|
+
validate_condition_format?(condition) && validate_condition_topics?(condition)
|
285
|
+
end
|
286
|
+
|
287
|
+
def validate_condition_format?(condition)
|
288
|
+
bad_characters = condition.gsub(
|
289
|
+
/(topics|in|\s|\(|\)|(&&)|[!]|(\|\|)|'([a-zA-Z0-9\-_.~%]+)')/,
|
290
|
+
""
|
291
|
+
)
|
292
|
+
bad_characters.length == 0
|
293
|
+
end
|
294
|
+
|
295
|
+
def validate_condition_topics?(condition)
|
296
|
+
topics = condition.scan(/(?:^|\S|\s)'([^']*?)'(?:$|\S|\s)/).flatten
|
297
|
+
topics.all? { |topic| topic.gsub(TOPIC_REGEX, "").length == 0 }
|
298
|
+
end
|
223
299
|
end
|
data/spec/fcm_spec.rb
CHANGED
@@ -4,10 +4,16 @@ describe FCM do
|
|
4
4
|
let(:send_url) { "#{FCM.base_uri}/send" }
|
5
5
|
let(:group_notification_base_uri) { "https://android.googleapis.com/gcm/notification" }
|
6
6
|
let(:api_key) { 'AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA' }
|
7
|
+
let(:registration_id) { '42' }
|
7
8
|
let(:registration_ids) { ['42'] }
|
8
9
|
let(:key_name) { 'appUser-Chris' }
|
9
10
|
let(:project_id) { "123456789" } # https://developers.google.com/cloud-messaging/gcm#senderid
|
10
11
|
let(:notification_key) { "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ" }
|
12
|
+
let(:valid_topic) { "TopicA" }
|
13
|
+
let(:invalid_topic) { "TopicA$" }
|
14
|
+
let(:valid_condition) { "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)" }
|
15
|
+
let(:invalid_condition) { "'TopicA' in topics and some other text ('TopicB' in topics || 'TopicC' in topics)" }
|
16
|
+
let(:invalid_condition_topic) { "'TopicA$' in topics" }
|
11
17
|
|
12
18
|
it 'should raise an error if the api key is not provided' do
|
13
19
|
expect { FCM.new }.to raise_error(ArgumentError)
|
@@ -21,6 +27,9 @@ describe FCM do
|
|
21
27
|
let(:valid_request_body) do
|
22
28
|
{ registration_ids: registration_ids }
|
23
29
|
end
|
30
|
+
let(:valid_request_body_with_string) do
|
31
|
+
{ registration_ids: registration_id }
|
32
|
+
end
|
24
33
|
let(:valid_request_headers) do
|
25
34
|
{
|
26
35
|
'Content-Type' => 'application/json',
|
@@ -40,6 +49,17 @@ describe FCM do
|
|
40
49
|
)
|
41
50
|
end
|
42
51
|
|
52
|
+
let(:stub_fcm_send_request_with_string) do
|
53
|
+
stub_request(:post, send_url).with(
|
54
|
+
body: valid_request_body_with_string.to_json,
|
55
|
+
headers: valid_request_headers
|
56
|
+
).to_return(
|
57
|
+
body: '{}',
|
58
|
+
headers: {},
|
59
|
+
status: 200
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
43
63
|
let(:stub_fcm_send_request_with_basic_auth) do
|
44
64
|
uri = URI.parse(send_url)
|
45
65
|
uri.user = 'a'
|
@@ -49,6 +69,7 @@ describe FCM do
|
|
49
69
|
|
50
70
|
before(:each) do
|
51
71
|
stub_fcm_send_request
|
72
|
+
stub_fcm_send_request_with_string
|
52
73
|
stub_fcm_send_request_with_basic_auth
|
53
74
|
end
|
54
75
|
|
@@ -58,6 +79,12 @@ describe FCM do
|
|
58
79
|
stub_fcm_send_request.should have_been_made.times(1)
|
59
80
|
end
|
60
81
|
|
82
|
+
it 'should send notification using POST to FCM if id provided as string' do
|
83
|
+
fcm = FCM.new(api_key)
|
84
|
+
fcm.send(registration_id).should eq(response: 'success', body: '{}', headers: {}, status_code: 200, canonical_ids: [], not_registered_ids: [])
|
85
|
+
stub_fcm_send_request.should have_been_made.times(1)
|
86
|
+
end
|
87
|
+
|
61
88
|
context 'send notification with data' do
|
62
89
|
let!(:stub_with_data) do
|
63
90
|
stub_request(:post, send_url)
|
@@ -74,6 +101,76 @@ describe FCM do
|
|
74
101
|
end
|
75
102
|
end
|
76
103
|
|
104
|
+
context "sending notification to a topic" do
|
105
|
+
let!(:stub_with_valid_topic) do
|
106
|
+
stub_request(:post, send_url)
|
107
|
+
.with(body: '{"to":"/topics/TopicA","data":{"score":"5x1","time":"15:10"}}',
|
108
|
+
headers: valid_request_headers)
|
109
|
+
.to_return(status: 200, body: '', headers: {})
|
110
|
+
end
|
111
|
+
let!(:stub_with_invalid_topic) do
|
112
|
+
stub_request(:post, send_url)
|
113
|
+
.with(body: '{"condition":"/topics/TopicA$","data":{"score":"5x1","time":"15:10"}}',
|
114
|
+
headers: valid_request_headers)
|
115
|
+
.to_return(status: 200, body: '', headers: {})
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#send_to_topic" do
|
119
|
+
it 'should send the data in a post request to fcm' do
|
120
|
+
fcm = FCM.new(api_key)
|
121
|
+
fcm.send_to_topic(valid_topic, data: { score: '5x1', time: '15:10' })
|
122
|
+
stub_with_valid_topic.should have_been_requested
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should not send to invalid topics' do
|
126
|
+
fcm = FCM.new(api_key)
|
127
|
+
fcm.send_to_topic(invalid_topic, data: { score: '5x1', time: '15:10' })
|
128
|
+
stub_with_invalid_topic.should_not have_been_requested
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "sending notification to a topic condition" do
|
134
|
+
let!(:stub_with_valid_condition) do
|
135
|
+
stub_request(:post, send_url)
|
136
|
+
.with(body: '{"condition":"\'TopicA\' in topics && (\'TopicB\' in topics || \'TopicC\' in topics)","data":{"score":"5x1","time":"15:10"}}',
|
137
|
+
headers: valid_request_headers)
|
138
|
+
.to_return(status: 200, body: '', headers: {})
|
139
|
+
end
|
140
|
+
let!(:stub_with_invalid_condition) do
|
141
|
+
stub_request(:post, send_url)
|
142
|
+
.with(body: '{"condition":"\'TopicA\' in topics and some other text (\'TopicB\' in topics || \'TopicC\' in topics)","data":{"score":"5x1","time":"15:10"}}',
|
143
|
+
headers: valid_request_headers)
|
144
|
+
.to_return(status: 200, body: '', headers: {})
|
145
|
+
end
|
146
|
+
let!(:stub_with_invalid_condition_topic) do
|
147
|
+
stub_request(:post, send_url)
|
148
|
+
.with(body: '{"condition":"\'TopicA$\' in topics","data":{"score":"5x1","time":"15:10"}}',
|
149
|
+
headers: valid_request_headers)
|
150
|
+
.to_return(status: 200, body: '', headers: {})
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "#send_to_topic_condition" do
|
154
|
+
it 'should send the data in a post request to fcm' do
|
155
|
+
fcm = FCM.new(api_key)
|
156
|
+
fcm.send_to_topic_condition(valid_condition, data: { score: '5x1', time: '15:10' })
|
157
|
+
stub_with_valid_condition.should have_been_requested
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should not send to invalid conditions' do
|
161
|
+
fcm = FCM.new(api_key)
|
162
|
+
fcm.send_to_topic_condition(invalid_condition, data: { score: '5x1', time: '15:10' })
|
163
|
+
stub_with_invalid_condition.should_not have_been_requested
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should not send to invalid topics in a condition' do
|
167
|
+
fcm = FCM.new(api_key)
|
168
|
+
fcm.send_to_topic_condition(invalid_condition_topic, data: { score: '5x1', time: '15:10' })
|
169
|
+
stub_with_invalid_condition_topic.should_not have_been_requested
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
77
174
|
context 'when send_notification responds with failure' do
|
78
175
|
let(:mock_request_attributes) do
|
79
176
|
{
|
@@ -373,6 +470,9 @@ describe FCM do
|
|
373
470
|
)
|
374
471
|
end
|
375
472
|
end # remove context
|
473
|
+
end
|
376
474
|
|
475
|
+
describe 'subscribing to a topic' do
|
476
|
+
# TODO
|
377
477
|
end
|
378
478
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fcm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kashif Rasul
|
@@ -9,36 +9,28 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-11-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '0'
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
20
|
+
version: '0.10'
|
25
21
|
- - ">="
|
26
22
|
- !ruby/object:Gem::Version
|
27
|
-
version:
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: json
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - ">="
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
23
|
+
version: 0.10.0
|
35
24
|
type: :runtime
|
36
25
|
prerelease: false
|
37
26
|
version_requirements: !ruby/object:Gem::Requirement
|
38
27
|
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0.10'
|
39
31
|
- - ">="
|
40
32
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
33
|
+
version: 0.10.0
|
42
34
|
description: fcm provides ruby bindings to Firebase Cloud Messaging (FCM) a cross-platform
|
43
35
|
messaging solution that lets you reliably deliver messages and notifications at
|
44
36
|
no cost to Android, iOS or Web browsers.
|
@@ -80,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
72
|
version: '0'
|
81
73
|
requirements: []
|
82
74
|
rubyforge_project: fcm
|
83
|
-
rubygems_version: 2.6.
|
75
|
+
rubygems_version: 2.6.13
|
84
76
|
signing_key:
|
85
77
|
specification_version: 4
|
86
78
|
summary: Reliably deliver messages and notifications via FCM
|