fcm 0.0.7 → 1.0.8
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/.github/workflows/ci.yml +30 -0
- data/.gitignore +1 -1
- data/Gemfile +1 -0
- data/README.md +89 -21
- data/fcm.gemspec +14 -15
- data/lib/fcm.rb +127 -61
- data/spec/fcm_spec.rb +177 -108
- metadata +35 -15
- data/.travis.yml +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16615f79f5432e2a352dc3c26e42d48efed7727a86f04f2b9d2bf93cca47aae6
|
|
4
|
+
data.tar.gz: d2fe30204d7ef51288014fbcc2df5f211ea8d8b4dbbc28cb9af0d9fadc54d6c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06c32340bae1ab25e1d66c06d63fa5d7276214604902218a1a9f5cf06774a60a08ab4bc700616f63ed5563a8b106227ef073168fcbfa29798348fadec2480767
|
|
7
|
+
data.tar.gz: ffa28e382feba7728e496318ea546237c9c5070ccc175d71a2dc83e9adf0a58efa932336a729549599978b6a2406ec01e80bd060997f779631d3a53122660b59
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches:
|
|
6
|
+
- '*'
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- master
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
tests:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
ruby: ['2.7', '3.0', '3.1']
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@master
|
|
20
|
+
|
|
21
|
+
- name: Set up Ruby
|
|
22
|
+
uses: ruby/setup-ruby@v1
|
|
23
|
+
with:
|
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
|
25
|
+
bundler: default
|
|
26
|
+
bundler-cache: true
|
|
27
|
+
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: |
|
|
30
|
+
bundle exec rspec
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Firebase Cloud Messaging (FCM) for Android and iOS
|
|
2
2
|
|
|
3
|
-
[](http://badge.fury.io/rb/fcm) [](http://badge.fury.io/rb/fcm) [](https://github.com/decision-labs/fcm/actions)
|
|
4
4
|
|
|
5
5
|
The FCM gem lets your ruby backend send notifications to Android and iOS devices via [
|
|
6
6
|
Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/).
|
|
@@ -19,17 +19,56 @@ gem 'fcm'
|
|
|
19
19
|
|
|
20
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.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- `2.0.0`
|
|
25
|
-
- `2.1.10`
|
|
26
|
-
- `2.2.10`
|
|
27
|
-
- `2.3.8`
|
|
28
|
-
- `2.4.5`
|
|
29
|
-
- `2.5.3`
|
|
22
|
+
A version of supported Ruby, currently:
|
|
23
|
+
`ruby >= 2.4`
|
|
30
24
|
|
|
31
25
|
## Usage
|
|
32
26
|
|
|
27
|
+
## HTTP v1 API
|
|
28
|
+
|
|
29
|
+
To migrate to HTTP v1 see: https://firebase.google.com/docs/cloud-messaging/migrate-v1
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
fcm = FCM.new(
|
|
33
|
+
API_TOKEN,
|
|
34
|
+
GOOGLE_APPLICATION_CREDENTIALS_PATH,
|
|
35
|
+
FIREBASE_PROJECT_ID
|
|
36
|
+
)
|
|
37
|
+
message = {
|
|
38
|
+
'topic': "89023", # OR token if you want to send to a specific device
|
|
39
|
+
# 'token': "000iddqd",
|
|
40
|
+
'data': {
|
|
41
|
+
payload: {
|
|
42
|
+
data: {
|
|
43
|
+
id: 1
|
|
44
|
+
}
|
|
45
|
+
}.to_json
|
|
46
|
+
},
|
|
47
|
+
'notification': {
|
|
48
|
+
title: notification.title_th,
|
|
49
|
+
body: notification.body_th,
|
|
50
|
+
},
|
|
51
|
+
'android': {},
|
|
52
|
+
'apns': {
|
|
53
|
+
payload: {
|
|
54
|
+
aps: {
|
|
55
|
+
sound: "default",
|
|
56
|
+
category: "#{Time.zone.now.to_i}"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
'fcm_options': {
|
|
61
|
+
analytics_label: 'Label'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fcm.send_v1(message)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## HTTP Legacy Version
|
|
69
|
+
|
|
70
|
+
To migrate to HTTP v1 see: https://firebase.google.com/docs/cloud-messaging/migrate-v1
|
|
71
|
+
|
|
33
72
|
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`.
|
|
34
73
|
|
|
35
74
|
Example sending notifications:
|
|
@@ -38,14 +77,10 @@ Example sending notifications:
|
|
|
38
77
|
require 'fcm'
|
|
39
78
|
|
|
40
79
|
fcm = FCM.new("my_server_key")
|
|
41
|
-
# you can set option parameters in here
|
|
42
|
-
# - all options are pass to HTTParty method arguments
|
|
43
|
-
# - ref: https://github.com/jnunemaker/httparty/blob/master/lib/httparty.rb#L29-L60
|
|
44
|
-
# fcm = FCM.new("my_server_key", timeout: 3)
|
|
45
80
|
|
|
46
81
|
registration_ids= ["12", "13"] # an array of one or more client registration tokens
|
|
47
82
|
|
|
48
|
-
# See https://firebase.google.com/docs/
|
|
83
|
+
# See https://firebase.google.com/docs/cloud-messaging/http-server-ref for all available options.
|
|
49
84
|
options = { "notification": {
|
|
50
85
|
"title": "Portugal vs. Denmark",
|
|
51
86
|
"body": "5 to 1"
|
|
@@ -105,14 +140,14 @@ FCM [topic messaging](https://firebase.google.com/docs/cloud-messaging/topic-mes
|
|
|
105
140
|
|
|
106
141
|
```ruby
|
|
107
142
|
response = fcm.send_with_notification_key("/topics/yourTopic",
|
|
108
|
-
|
|
143
|
+
notification: {body: "This is a FCM Topic Message!"})
|
|
109
144
|
```
|
|
110
145
|
|
|
111
146
|
Or you can use the helper:
|
|
112
147
|
|
|
113
148
|
```ruby
|
|
114
149
|
response = fcm.send_to_topic("yourTopic",
|
|
115
|
-
|
|
150
|
+
notification: {body: "This is a FCM Topic Message!"})
|
|
116
151
|
```
|
|
117
152
|
|
|
118
153
|
### Sending to Multiple Topics
|
|
@@ -141,8 +176,8 @@ The `send_to_topic_condition` method within this library allows you to specicy a
|
|
|
141
176
|
```ruby
|
|
142
177
|
response = fcm.send_to_topic_condition(
|
|
143
178
|
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)",
|
|
144
|
-
|
|
145
|
-
|
|
179
|
+
notification: {
|
|
180
|
+
body: "This is an FCM Topic Message sent to a condition!"
|
|
146
181
|
}
|
|
147
182
|
)
|
|
148
183
|
```
|
|
@@ -175,6 +210,31 @@ The guide to set up an iOS app to get notifications is here: [Setting up a FCM C
|
|
|
175
210
|
|
|
176
211
|
## ChangeLog
|
|
177
212
|
|
|
213
|
+
### 1.0.8
|
|
214
|
+
- caches calls to `Google::Auth::ServiceAccountCredentials` #103
|
|
215
|
+
- Allow `faraday` versions from 1 up to 2 #101
|
|
216
|
+
|
|
217
|
+
### 1.0.7
|
|
218
|
+
|
|
219
|
+
- Fix passing `DEFAULT_TIMEOUT` to `faraday` [#96](https://github.com/decision-labs/fcm/pull/96)
|
|
220
|
+
- Fix issue with `get_instance_id_info` option params [#98](https://github.com/decision-labs/fcm/pull/98)
|
|
221
|
+
- Accept any IO object for credentials [#95](https://github.com/decision-labs/fcm/pull/94)
|
|
222
|
+
|
|
223
|
+
Huge thanks to @excid3 @jsparling @jensljungblad
|
|
224
|
+
|
|
225
|
+
### 1.0.3
|
|
226
|
+
|
|
227
|
+
- Fix overly strict faraday dependency
|
|
228
|
+
|
|
229
|
+
### 1.0.2
|
|
230
|
+
|
|
231
|
+
- Bug fix: retrieve notification key" params: https://github.com/spacialdb/fcm/commit/b328a75c11d779a06d0ceda83527e26aa0495774
|
|
232
|
+
|
|
233
|
+
### 1.0.0
|
|
234
|
+
|
|
235
|
+
- Bumped supported ruby to `>= 2.4`
|
|
236
|
+
- Fix deprecation warnings from `faraday` by changing dependency version to `faraday 1.0.0`
|
|
237
|
+
|
|
178
238
|
### 0.0.7
|
|
179
239
|
|
|
180
240
|
- replace `httparty` with `faraday`
|
|
@@ -184,6 +244,7 @@ The guide to set up an iOS app to get notifications is here: [Setting up a FCM C
|
|
|
184
244
|
- Fixed group messaging url.
|
|
185
245
|
- Added API to `recover_notification_key`.
|
|
186
246
|
|
|
247
|
+
|
|
187
248
|
### 0.0.1
|
|
188
249
|
|
|
189
250
|
- Initial version.
|
|
@@ -196,8 +257,15 @@ The guide to set up an iOS app to get notifications is here: [Setting up a FCM C
|
|
|
196
257
|
|
|
197
258
|
- [Contributors](https://github.com/spacialdb/fcm/contributors)
|
|
198
259
|
|
|
199
|
-
##
|
|
260
|
+
## Cutting a release
|
|
200
261
|
|
|
201
|
-
|
|
262
|
+
Update version in `fcm.gemspec` with `VERSION` and update `README.md` `## ChangeLog` section.
|
|
202
263
|
|
|
203
|
-
|
|
264
|
+
```bash
|
|
265
|
+
# set the version
|
|
266
|
+
# VERSION="1.0.7"
|
|
267
|
+
gem build fcm.gemspec
|
|
268
|
+
git tag -a v${VERSION} -m "Releasing version v${VERSION}"
|
|
269
|
+
git push origin --tags
|
|
270
|
+
gem push fcm-${VERSION}.gem
|
|
271
|
+
```
|
data/fcm.gemspec
CHANGED
|
@@ -2,24 +2,23 @@
|
|
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
|
-
s.name
|
|
6
|
-
s.version
|
|
7
|
-
s.platform
|
|
8
|
-
s.authors
|
|
9
|
-
s.email
|
|
10
|
-
s.homepage
|
|
11
|
-
s.summary
|
|
5
|
+
s.name = "fcm"
|
|
6
|
+
s.version = "1.0.8"
|
|
7
|
+
s.platform = Gem::Platform::RUBY
|
|
8
|
+
s.authors = ["Kashif Rasul", "Shoaib Burq"]
|
|
9
|
+
s.email = ["kashif@decision-labs.com", "shoaib@decision-labs.com"]
|
|
10
|
+
s.homepage = "https://github.com/decision-labs/fcm"
|
|
11
|
+
s.summary = %q{Reliably deliver messages and notifications via FCM}
|
|
12
12
|
s.description = %q{fcm provides ruby bindings to Firebase Cloud Messaging (FCM) a cross-platform messaging solution that lets you reliably deliver messages and notifications at no cost to Android, iOS or Web browsers.}
|
|
13
|
-
s.license
|
|
13
|
+
s.license = "MIT"
|
|
14
14
|
|
|
15
|
-
s.required_ruby_version
|
|
15
|
+
s.required_ruby_version = ">= 2.4.0"
|
|
16
16
|
|
|
17
|
-
s.
|
|
18
|
-
|
|
19
|
-
s.
|
|
20
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
21
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
17
|
+
s.files = `git ls-files`.split("\n")
|
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
22
20
|
s.require_paths = ["lib"]
|
|
23
21
|
|
|
24
|
-
s.add_runtime_dependency(
|
|
22
|
+
s.add_runtime_dependency("faraday", ">= 1.0.0", "< 3.0")
|
|
23
|
+
s.add_runtime_dependency("googleauth", "~> 1")
|
|
25
24
|
end
|
data/lib/fcm.rb
CHANGED
|
@@ -1,24 +1,71 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
1
|
+
require "faraday"
|
|
2
|
+
require "cgi"
|
|
3
|
+
require "json"
|
|
4
|
+
require "googleauth"
|
|
4
5
|
|
|
5
6
|
class FCM
|
|
6
|
-
BASE_URI =
|
|
7
|
+
BASE_URI = "https://fcm.googleapis.com"
|
|
8
|
+
BASE_URI_V1 = "https://fcm.googleapis.com/v1/projects/"
|
|
7
9
|
DEFAULT_TIMEOUT = 30
|
|
8
10
|
FORMAT = :json
|
|
9
11
|
|
|
10
12
|
# constants
|
|
11
|
-
GROUP_NOTIFICATION_BASE_URI =
|
|
12
|
-
INSTANCE_ID_API =
|
|
13
|
+
GROUP_NOTIFICATION_BASE_URI = "https://android.googleapis.com"
|
|
14
|
+
INSTANCE_ID_API = "https://iid.googleapis.com"
|
|
13
15
|
TOPIC_REGEX = /[a-zA-Z0-9\-_.~%]+/
|
|
14
16
|
|
|
15
|
-
attr_accessor :timeout, :api_key
|
|
17
|
+
attr_accessor :timeout, :api_key, :json_key_path, :project_base_uri
|
|
16
18
|
|
|
17
|
-
def initialize(api_key, client_options = {})
|
|
19
|
+
def initialize(api_key, json_key_path = "", project_name = "", client_options = {})
|
|
18
20
|
@api_key = api_key
|
|
19
21
|
@client_options = client_options
|
|
22
|
+
@json_key_path = json_key_path
|
|
23
|
+
@project_base_uri = BASE_URI_V1 + project_name.to_s
|
|
20
24
|
end
|
|
21
25
|
|
|
26
|
+
# See https://firebase.google.com/docs/cloud-messaging/send-message
|
|
27
|
+
# {
|
|
28
|
+
# "token": "4sdsx",
|
|
29
|
+
# "notification": {
|
|
30
|
+
# "title": "Breaking News",
|
|
31
|
+
# "body": "New news story available."
|
|
32
|
+
# },
|
|
33
|
+
# "data": {
|
|
34
|
+
# "story_id": "story_12345"
|
|
35
|
+
# },
|
|
36
|
+
# "android": {
|
|
37
|
+
# "notification": {
|
|
38
|
+
# "click_action": "TOP_STORY_ACTIVITY",
|
|
39
|
+
# "body": "Check out the Top Story"
|
|
40
|
+
# }
|
|
41
|
+
# },
|
|
42
|
+
# "apns": {
|
|
43
|
+
# "payload": {
|
|
44
|
+
# "aps": {
|
|
45
|
+
# "category" : "NEW_MESSAGE_CATEGORY"
|
|
46
|
+
# }
|
|
47
|
+
# }
|
|
48
|
+
# }
|
|
49
|
+
# }
|
|
50
|
+
# fcm = FCM.new(api_key, json_key_path, project_name)
|
|
51
|
+
# fcm.send(
|
|
52
|
+
# { "token": "4sdsx",, "to" : "notification": {}.. }
|
|
53
|
+
# )
|
|
54
|
+
def send_notification_v1(message)
|
|
55
|
+
return if @project_base_uri.empty?
|
|
56
|
+
|
|
57
|
+
post_body = { 'message': message }
|
|
58
|
+
|
|
59
|
+
response = Faraday.post("#{@project_base_uri}/messages:send") do |req|
|
|
60
|
+
req.headers["Content-Type"] = "application/json"
|
|
61
|
+
req.headers["Authorization"] = "Bearer #{jwt_token}"
|
|
62
|
+
req.body = post_body.to_json
|
|
63
|
+
end
|
|
64
|
+
build_response(response)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
alias send_v1 send_notification_v1
|
|
68
|
+
|
|
22
69
|
# See https://developers.google.com/cloud-messaging/http for more details.
|
|
23
70
|
# { "notification": {
|
|
24
71
|
# "title": "Portugal vs. Denmark",
|
|
@@ -35,72 +82,72 @@ class FCM
|
|
|
35
82
|
post_body = build_post_body(registration_ids, options)
|
|
36
83
|
|
|
37
84
|
for_uri(BASE_URI) do |connection|
|
|
38
|
-
response = connection.post(
|
|
85
|
+
response = connection.post("/fcm/send", post_body.to_json)
|
|
39
86
|
build_response(response, registration_ids)
|
|
40
87
|
end
|
|
41
88
|
end
|
|
89
|
+
|
|
42
90
|
alias send send_notification
|
|
43
91
|
|
|
44
92
|
def create_notification_key(key_name, project_id, registration_ids = [])
|
|
45
|
-
post_body = build_post_body(registration_ids, operation:
|
|
46
|
-
|
|
93
|
+
post_body = build_post_body(registration_ids, operation: "create",
|
|
94
|
+
notification_key_name: key_name)
|
|
47
95
|
|
|
48
96
|
extra_headers = {
|
|
49
|
-
|
|
97
|
+
"project_id" => project_id,
|
|
50
98
|
}
|
|
51
99
|
|
|
52
100
|
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
|
|
53
|
-
response = connection.post(
|
|
101
|
+
response = connection.post("/gcm/notification", post_body.to_json)
|
|
54
102
|
build_response(response)
|
|
55
103
|
end
|
|
56
104
|
end
|
|
105
|
+
|
|
57
106
|
alias create create_notification_key
|
|
58
107
|
|
|
59
108
|
def add_registration_ids(key_name, project_id, notification_key, registration_ids)
|
|
60
|
-
post_body = build_post_body(registration_ids, operation:
|
|
61
|
-
|
|
62
|
-
|
|
109
|
+
post_body = build_post_body(registration_ids, operation: "add",
|
|
110
|
+
notification_key_name: key_name,
|
|
111
|
+
notification_key: notification_key)
|
|
63
112
|
|
|
64
113
|
extra_headers = {
|
|
65
|
-
|
|
114
|
+
"project_id" => project_id,
|
|
66
115
|
}
|
|
67
116
|
|
|
68
117
|
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
|
|
69
|
-
response = connection.post(
|
|
118
|
+
response = connection.post("/gcm/notification", post_body.to_json)
|
|
70
119
|
build_response(response)
|
|
71
120
|
end
|
|
72
121
|
end
|
|
122
|
+
|
|
73
123
|
alias add add_registration_ids
|
|
74
124
|
|
|
75
125
|
def remove_registration_ids(key_name, project_id, notification_key, registration_ids)
|
|
76
|
-
post_body = build_post_body(registration_ids, operation:
|
|
77
|
-
|
|
78
|
-
|
|
126
|
+
post_body = build_post_body(registration_ids, operation: "remove",
|
|
127
|
+
notification_key_name: key_name,
|
|
128
|
+
notification_key: notification_key)
|
|
79
129
|
|
|
80
130
|
extra_headers = {
|
|
81
|
-
|
|
131
|
+
"project_id" => project_id,
|
|
82
132
|
}
|
|
83
133
|
|
|
84
134
|
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
|
|
85
|
-
response = connection.post(
|
|
135
|
+
response = connection.post("/gcm/notification", post_body.to_json)
|
|
86
136
|
build_response(response)
|
|
87
137
|
end
|
|
88
138
|
end
|
|
139
|
+
|
|
89
140
|
alias remove remove_registration_ids
|
|
90
141
|
|
|
91
142
|
def recover_notification_key(key_name, project_id)
|
|
92
|
-
params = {
|
|
93
|
-
|
|
94
|
-
notification_key_name: key_name
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
143
|
+
params = { notification_key_name: key_name }
|
|
144
|
+
|
|
98
145
|
extra_headers = {
|
|
99
|
-
|
|
146
|
+
"project_id" => project_id,
|
|
100
147
|
}
|
|
101
148
|
|
|
102
149
|
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
|
|
103
|
-
response = connection.get(
|
|
150
|
+
response = connection.get("/gcm/notification", params)
|
|
104
151
|
build_response(response)
|
|
105
152
|
end
|
|
106
153
|
end
|
|
@@ -118,11 +165,11 @@ class FCM
|
|
|
118
165
|
end
|
|
119
166
|
|
|
120
167
|
def batch_topic_subscription(topic, registration_ids)
|
|
121
|
-
manage_topics_relationship(topic, registration_ids,
|
|
168
|
+
manage_topics_relationship(topic, registration_ids, "Add")
|
|
122
169
|
end
|
|
123
170
|
|
|
124
171
|
def batch_topic_unsubscription(topic, registration_ids)
|
|
125
|
-
manage_topics_relationship(topic, registration_ids,
|
|
172
|
+
manage_topics_relationship(topic, registration_ids, "Remove")
|
|
126
173
|
end
|
|
127
174
|
|
|
128
175
|
def manage_topics_relationship(topic, registration_ids, action)
|
|
@@ -136,35 +183,33 @@ class FCM
|
|
|
136
183
|
|
|
137
184
|
def send_to_topic(topic, options = {})
|
|
138
185
|
if topic.gsub(TOPIC_REGEX, "").length == 0
|
|
139
|
-
send_with_notification_key(
|
|
186
|
+
send_with_notification_key("/topics/" + topic, options)
|
|
140
187
|
end
|
|
141
188
|
end
|
|
142
189
|
|
|
143
|
-
def get_instance_id_info
|
|
144
|
-
params =
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
190
|
+
def get_instance_id_info(iid_token, options = {})
|
|
191
|
+
params = options
|
|
192
|
+
|
|
148
193
|
for_uri(INSTANCE_ID_API) do |connection|
|
|
149
|
-
response = connection.get(
|
|
194
|
+
response = connection.get("/iid/info/" + iid_token, params)
|
|
150
195
|
build_response(response)
|
|
151
196
|
end
|
|
152
197
|
end
|
|
153
198
|
|
|
154
|
-
def subscribe_instance_id_to_topic
|
|
199
|
+
def subscribe_instance_id_to_topic(iid_token, topic_name)
|
|
155
200
|
batch_subscribe_instance_ids_to_topic([iid_token], topic_name)
|
|
156
201
|
end
|
|
157
202
|
|
|
158
|
-
def unsubscribe_instance_id_from_topic
|
|
203
|
+
def unsubscribe_instance_id_from_topic(iid_token, topic_name)
|
|
159
204
|
batch_unsubscribe_instance_ids_from_topic([iid_token], topic_name)
|
|
160
205
|
end
|
|
161
206
|
|
|
162
|
-
def batch_subscribe_instance_ids_to_topic
|
|
163
|
-
manage_topics_relationship(topic_name, instance_ids,
|
|
207
|
+
def batch_subscribe_instance_ids_to_topic(instance_ids, topic_name)
|
|
208
|
+
manage_topics_relationship(topic_name, instance_ids, "Add")
|
|
164
209
|
end
|
|
165
210
|
|
|
166
|
-
def batch_unsubscribe_instance_ids_from_topic
|
|
167
|
-
manage_topics_relationship(topic_name, instance_ids,
|
|
211
|
+
def batch_unsubscribe_instance_ids_from_topic(instance_ids, topic_name)
|
|
212
|
+
manage_topics_relationship(topic_name, instance_ids, "Remove")
|
|
168
213
|
end
|
|
169
214
|
|
|
170
215
|
def send_to_topic_condition(condition, options = {})
|
|
@@ -177,8 +222,11 @@ class FCM
|
|
|
177
222
|
private
|
|
178
223
|
|
|
179
224
|
def for_uri(uri, extra_headers = {})
|
|
180
|
-
connection = ::Faraday.new(
|
|
181
|
-
|
|
225
|
+
connection = ::Faraday.new(
|
|
226
|
+
url: uri,
|
|
227
|
+
request: { timeout: DEFAULT_TIMEOUT }
|
|
228
|
+
) do |faraday|
|
|
229
|
+
faraday.adapter Faraday.default_adapter
|
|
182
230
|
faraday.headers["Content-Type"] = "application/json"
|
|
183
231
|
faraday.headers["Authorization"] = "key=#{api_key}"
|
|
184
232
|
extra_headers.each do |key, value|
|
|
@@ -198,18 +246,18 @@ class FCM
|
|
|
198
246
|
response_hash = { body: body, headers: response.headers, status_code: response.status }
|
|
199
247
|
case response.status
|
|
200
248
|
when 200
|
|
201
|
-
response_hash[:response] =
|
|
249
|
+
response_hash[:response] = "success"
|
|
202
250
|
body = JSON.parse(body) unless body.empty?
|
|
203
251
|
response_hash[:canonical_ids] = build_canonical_ids(body, registration_ids) unless registration_ids.empty?
|
|
204
252
|
response_hash[:not_registered_ids] = build_not_registered_ids(body, registration_ids) unless registration_ids.empty?
|
|
205
253
|
when 400
|
|
206
|
-
response_hash[:response] =
|
|
254
|
+
response_hash[:response] = "Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields."
|
|
207
255
|
when 401
|
|
208
|
-
response_hash[:response] =
|
|
256
|
+
response_hash[:response] = "There was an error authenticating the sender account."
|
|
209
257
|
when 503
|
|
210
|
-
response_hash[:response] =
|
|
258
|
+
response_hash[:response] = "Server is temporarily unavailable."
|
|
211
259
|
when 500..599
|
|
212
|
-
response_hash[:response] =
|
|
260
|
+
response_hash[:response] = "There was an internal error in the FCM server while trying to process the request."
|
|
213
261
|
end
|
|
214
262
|
response_hash
|
|
215
263
|
end
|
|
@@ -217,9 +265,9 @@ class FCM
|
|
|
217
265
|
def build_canonical_ids(body, registration_ids)
|
|
218
266
|
canonical_ids = []
|
|
219
267
|
unless body.empty?
|
|
220
|
-
if body[
|
|
221
|
-
body[
|
|
222
|
-
canonical_ids << { old: registration_ids[index], new: result[
|
|
268
|
+
if body["canonical_ids"] > 0
|
|
269
|
+
body["results"].each_with_index do |result, index|
|
|
270
|
+
canonical_ids << { old: registration_ids[index], new: result["registration_id"] } if has_canonical_id?(result)
|
|
223
271
|
end
|
|
224
272
|
end
|
|
225
273
|
end
|
|
@@ -229,8 +277,8 @@ class FCM
|
|
|
229
277
|
def build_not_registered_ids(body, registration_id)
|
|
230
278
|
not_registered_ids = []
|
|
231
279
|
unless body.empty?
|
|
232
|
-
if body[
|
|
233
|
-
body[
|
|
280
|
+
if body["failure"] > 0
|
|
281
|
+
body["results"].each_with_index do |result, index|
|
|
234
282
|
not_registered_ids << registration_id[index] if is_not_registered?(result)
|
|
235
283
|
end
|
|
236
284
|
end
|
|
@@ -240,17 +288,17 @@ class FCM
|
|
|
240
288
|
|
|
241
289
|
def execute_notification(body)
|
|
242
290
|
for_uri(BASE_URI) do |connection|
|
|
243
|
-
response = connection.post(
|
|
291
|
+
response = connection.post("/fcm/send", body.to_json)
|
|
244
292
|
build_response(response)
|
|
245
293
|
end
|
|
246
294
|
end
|
|
247
295
|
|
|
248
296
|
def has_canonical_id?(result)
|
|
249
|
-
!result[
|
|
297
|
+
!result["registration_id"].nil?
|
|
250
298
|
end
|
|
251
299
|
|
|
252
300
|
def is_not_registered?(result)
|
|
253
|
-
result[
|
|
301
|
+
result["error"] == "NotRegistered"
|
|
254
302
|
end
|
|
255
303
|
|
|
256
304
|
def validate_condition?(condition)
|
|
@@ -269,4 +317,22 @@ class FCM
|
|
|
269
317
|
topics = condition.scan(/(?:^|\S|\s)'([^']*?)'(?:$|\S|\s)/).flatten
|
|
270
318
|
topics.all? { |topic| topic.gsub(TOPIC_REGEX, "").length == 0 }
|
|
271
319
|
end
|
|
320
|
+
|
|
321
|
+
def jwt_token
|
|
322
|
+
scope = "https://www.googleapis.com/auth/firebase.messaging"
|
|
323
|
+
@authorizer ||= Google::Auth::ServiceAccountCredentials.make_creds(
|
|
324
|
+
json_key_io: json_key,
|
|
325
|
+
scope: scope,
|
|
326
|
+
)
|
|
327
|
+
token = @authorizer.fetch_access_token!
|
|
328
|
+
token["access_token"]
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def json_key
|
|
332
|
+
@json_key ||= if @json_key_path.respond_to?(:read)
|
|
333
|
+
@json_key_path
|
|
334
|
+
else
|
|
335
|
+
File.open(@json_key_path)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
272
338
|
end
|