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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4200d68170fc0c8cee514824e77244e51fc68802dc8ad6a34a1c592c11f36a71
4
- data.tar.gz: a70490fb7e92cf2ea66e53ba1cb58a5c8caad45b8d6bbbf1335bc13c3e49c774
3
+ metadata.gz: 16615f79f5432e2a352dc3c26e42d48efed7727a86f04f2b9d2bf93cca47aae6
4
+ data.tar.gz: d2fe30204d7ef51288014fbcc2df5f211ea8d8b4dbbc28cb9af0d9fadc54d6c7
5
5
  SHA512:
6
- metadata.gz: a5d276a776ddd9eed746f16e129c1820e27361e99fa3e6c6f8be14af04561a8f4dd520d4296bf632d31bb1269b4a8817e18bb3938d8992d736503e310dfbd8cb
7
- data.tar.gz: 7049ded384b5df8a097addbd96cce01ca559ddb6a61b8ec27e2f5fe06d7d4d70d0009b4d7bfa240dfe84598acfb917ce735ec4b8c6a71e072108d4ed1d6cc629
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
@@ -48,4 +48,4 @@ specifications
48
48
  Gemfile.lock
49
49
  .rvmrc
50
50
  spec/reports
51
- *.gem
51
+ *.gem
data/Gemfile CHANGED
@@ -5,3 +5,4 @@ gem 'rake'
5
5
  gem 'rspec'
6
6
  gem 'webmock'
7
7
  gem 'ci_reporter_rspec'
8
+ gem 'googleauth'
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://secure.travis-ci.org/spacialdb/fcm.png?branch=master)](http://travis-ci.org/spacialdb/fcm)
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
- One of the following, tested Ruby versions:
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/reference/fcm/rest/v1/projects.messages for all available options.
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
- data: {message: "This is a FCM Topic Message!"})
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
- data: {message: "This is a FCM Topic Message!"})
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
- data: {
145
- message: "This is an FCM Topic Message sent to a condition!"
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
- ## Donations
260
+ ## Cutting a release
200
261
 
201
- We accept tips through [Gratipay](https://gratipay.com/spacialdb/).
262
+ Update version in `fcm.gemspec` with `VERSION` and update `README.md` `## ChangeLog` section.
202
263
 
203
- [![Gratipay](https://img.shields.io/gratipay/spacialdb.svg)](https://www.gittip.com/spacialdb/)
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 = "fcm"
6
- s.version = "0.0.7"
7
- s.platform = Gem::Platform::RUBY
8
- s.authors = ["Kashif Rasul", "Shoaib Burq"]
9
- s.email = ["kashif@spacialdb.com", "shoaib@spacialdb.com"]
10
- s.homepage = "https://github.com/spacialdb/fcm"
11
- s.summary = %q{Reliably deliver messages and notifications via FCM}
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 = "MIT"
13
+ s.license = "MIT"
14
14
 
15
- s.required_ruby_version = '>= 2.0.0'
15
+ s.required_ruby_version = ">= 2.4.0"
16
16
 
17
- s.rubyforge_project = "fcm"
18
-
19
- s.files = `git ls-files`.split("\n")
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('faraday','0.15.4')
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 'faraday'
2
- require 'cgi'
3
- require 'json'
1
+ require "faraday"
2
+ require "cgi"
3
+ require "json"
4
+ require "googleauth"
4
5
 
5
6
  class FCM
6
- BASE_URI = 'https://fcm.googleapis.com'
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 = 'https://android.googleapis.com'
12
- INSTANCE_ID_API = 'https://iid.googleapis.com'
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('/fcm/send', post_body.to_json)
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: 'create',
46
- notification_key_name: key_name)
93
+ post_body = build_post_body(registration_ids, operation: "create",
94
+ notification_key_name: key_name)
47
95
 
48
96
  extra_headers = {
49
- 'project_id' => project_id
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('/gcm/notification', post_body.to_json)
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: 'add',
61
- notification_key_name: key_name,
62
- notification_key: notification_key)
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
- 'project_id' => project_id
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('/gcm/notification', post_body.to_json)
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: 'remove',
77
- notification_key_name: key_name,
78
- notification_key: notification_key)
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
- 'project_id' => project_id
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('/gcm/notification', post_body.to_json)
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
- query: {
94
- notification_key_name: key_name
95
- }
96
- }
97
-
143
+ params = { notification_key_name: key_name }
144
+
98
145
  extra_headers = {
99
- 'project_id' => project_id
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('/gcm/notification', params)
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, 'Add')
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, 'Remove')
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('/topics/' + topic, options)
186
+ send_with_notification_key("/topics/" + topic, options)
140
187
  end
141
188
  end
142
189
 
143
- def get_instance_id_info iid_token, options={}
144
- params = {
145
- query: options
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('/iid/info/'+iid_token, params)
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 iid_token, topic_name
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 iid_token, topic_name
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 instance_ids, topic_name
163
- manage_topics_relationship(topic_name, instance_ids, 'Add')
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 instance_ids, topic_name
167
- manage_topics_relationship(topic_name, instance_ids, 'Remove')
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(:url => uri) do |faraday|
181
- faraday.adapter Faraday.default_adapter
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] = 'success'
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] = 'Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields.'
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] = 'There was an error authenticating the sender account.'
256
+ response_hash[:response] = "There was an error authenticating the sender account."
209
257
  when 503
210
- response_hash[:response] = 'Server is temporarily unavailable.'
258
+ response_hash[:response] = "Server is temporarily unavailable."
211
259
  when 500..599
212
- response_hash[:response] = 'There was an internal error in the FCM server while trying to process the request.'
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['canonical_ids'] > 0
221
- body['results'].each_with_index do |result, index|
222
- canonical_ids << { old: registration_ids[index], new: result['registration_id'] } if has_canonical_id?(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['failure'] > 0
233
- body['results'].each_with_index do |result, index|
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('/fcm/send', body.to_json)
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['registration_id'].nil?
297
+ !result["registration_id"].nil?
250
298
  end
251
299
 
252
300
  def is_not_registered?(result)
253
- result['error'] == 'NotRegistered'
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