fcm 0.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://badge.fury.io/rb/fcm.svg)](http://badge.fury.io/rb/fcm) [![Build Status](https://
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/fcm.svg)](http://badge.fury.io/rb/fcm) [![Build Status](https://github.com/decision-labs/fcm/workflows/Tests/badge.svg)](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
|