Skip to content

Commit b31378f

Browse files
committed
format and update readme with send_v1 HTTP v1
1 parent 7691238 commit b31378f

File tree

4 files changed

+228
-175
lines changed

4 files changed

+228
-175
lines changed

README.md

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,56 @@ gem 'fcm'
1919

2020
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.
2121

22-
2322
A version of supported Ruby, currently:
2423
`ruby >= 2.4`
2524

26-
2725
## Usage
2826

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+
2972
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`.
3073

3174
Example sending notifications:
@@ -166,6 +209,7 @@ You can find a guide to implement an Android Client app to receive notifications
166209
The guide to set up an iOS app to get notifications is here: [Setting up a FCM Client App on iOS](https://firebase.google.com/docs/cloud-messaging/ios/client).
167210

168211
## ChangeLog
212+
169213
### 1.0.3
170214

171215
- Fix overly strict faraday depenecy

fcm.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
1919
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
2020
s.require_paths = ["lib"]
2121

22-
# s.add_runtime_dependency('faraday', '~> 1')
22+
s.add_runtime_dependency('faraday', '~> 1')
2323
end

lib/fcm.rb

Lines changed: 65 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
require 'faraday'
2-
require 'cgi'
3-
require 'json'
4-
require 'googleauth'
1+
require "faraday"
2+
require "cgi"
3+
require "json"
4+
require "googleauth"
55

66
class FCM
7-
BASE_URI = 'https://fcm.googleapis.com'
8-
BASE_URI_V1 = 'https://fcm.googleapis.com/v1/projects/'
7+
BASE_URI = "https://fcm.googleapis.com"
8+
BASE_URI_V1 = "https://fcm.googleapis.com/v1/projects/"
99
DEFAULT_TIMEOUT = 30
1010
FORMAT = :json
1111

1212
# constants
13-
GROUP_NOTIFICATION_BASE_URI = 'https://android.googleapis.com'
14-
INSTANCE_ID_API = 'https://iid.googleapis.com'
13+
GROUP_NOTIFICATION_BASE_URI = "https://android.googleapis.com"
14+
INSTANCE_ID_API = "https://iid.googleapis.com"
1515
TOPIC_REGEX = /[a-zA-Z0-9\-_.~%]+/
1616

1717
attr_accessor :timeout, :api_key, :json_key_path, :project_base_uri
1818

19-
def initialize(api_key, json_key_path = '', project_name = '', client_options = {})
19+
def initialize(api_key, json_key_path = "", project_name = "", client_options = {})
2020
@api_key = api_key
2121
@client_options = client_options
2222
@json_key_path = json_key_path
@@ -57,12 +57,13 @@ def send_notification_v1(message)
5757
post_body = { 'message': message }
5858

5959
response = Faraday.post("#{@project_base_uri}/messages:send") do |req|
60-
req.headers['Content-Type'] = 'application/json'
61-
req.headers['Authorization'] = "Bearer #{jwt_token}"
60+
req.headers["Content-Type"] = "application/json"
61+
req.headers["Authorization"] = "Bearer #{jwt_token}"
6262
req.body = post_body.to_json
6363
end
6464
build_response(response)
6565
end
66+
6667
alias send_v1 send_notification_v1
6768

6869
# See https://developers.google.com/cloud-messaging/http for more details.
@@ -81,68 +82,72 @@ def send_notification(registration_ids, options = {})
8182
post_body = build_post_body(registration_ids, options)
8283

8384
for_uri(BASE_URI) do |connection|
84-
response = connection.post('/fcm/send', post_body.to_json)
85+
response = connection.post("/fcm/send", post_body.to_json)
8586
build_response(response, registration_ids)
8687
end
8788
end
89+
8890
alias send send_notification
8991

9092
def create_notification_key(key_name, project_id, registration_ids = [])
91-
post_body = build_post_body(registration_ids, operation: 'create',
92-
notification_key_name: key_name)
93+
post_body = build_post_body(registration_ids, operation: "create",
94+
notification_key_name: key_name)
9395

9496
extra_headers = {
95-
'project_id' => project_id
97+
"project_id" => project_id,
9698
}
9799

98100
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
99-
response = connection.post('/gcm/notification', post_body.to_json)
101+
response = connection.post("/gcm/notification", post_body.to_json)
100102
build_response(response)
101103
end
102104
end
105+
103106
alias create create_notification_key
104107

105108
def add_registration_ids(key_name, project_id, notification_key, registration_ids)
106-
post_body = build_post_body(registration_ids, operation: 'add',
107-
notification_key_name: key_name,
108-
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)
109112

110113
extra_headers = {
111-
'project_id' => project_id
114+
"project_id" => project_id,
112115
}
113116

114117
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
115-
response = connection.post('/gcm/notification', post_body.to_json)
118+
response = connection.post("/gcm/notification", post_body.to_json)
116119
build_response(response)
117120
end
118121
end
122+
119123
alias add add_registration_ids
120124

121125
def remove_registration_ids(key_name, project_id, notification_key, registration_ids)
122-
post_body = build_post_body(registration_ids, operation: 'remove',
123-
notification_key_name: key_name,
124-
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)
125129

126130
extra_headers = {
127-
'project_id' => project_id
131+
"project_id" => project_id,
128132
}
129133

130134
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
131-
response = connection.post('/gcm/notification', post_body.to_json)
135+
response = connection.post("/gcm/notification", post_body.to_json)
132136
build_response(response)
133137
end
134138
end
139+
135140
alias remove remove_registration_ids
136141

137142
def recover_notification_key(key_name, project_id)
138-
params = {notification_key_name: key_name}
139-
143+
params = { notification_key_name: key_name }
144+
140145
extra_headers = {
141-
'project_id' => project_id
146+
"project_id" => project_id,
142147
}
143148

144149
for_uri(GROUP_NOTIFICATION_BASE_URI, extra_headers) do |connection|
145-
response = connection.get('/gcm/notification', params)
150+
response = connection.get("/gcm/notification", params)
146151
build_response(response)
147152
end
148153
end
@@ -160,11 +165,11 @@ def topic_subscription(topic, registration_id)
160165
end
161166

162167
def batch_topic_subscription(topic, registration_ids)
163-
manage_topics_relationship(topic, registration_ids, 'Add')
168+
manage_topics_relationship(topic, registration_ids, "Add")
164169
end
165170

166171
def batch_topic_unsubscription(topic, registration_ids)
167-
manage_topics_relationship(topic, registration_ids, 'Remove')
172+
manage_topics_relationship(topic, registration_ids, "Remove")
168173
end
169174

170175
def manage_topics_relationship(topic, registration_ids, action)
@@ -178,35 +183,35 @@ def manage_topics_relationship(topic, registration_ids, action)
178183

179184
def send_to_topic(topic, options = {})
180185
if topic.gsub(TOPIC_REGEX, "").length == 0
181-
send_with_notification_key('/topics/' + topic, options)
186+
send_with_notification_key("/topics/" + topic, options)
182187
end
183188
end
184189

185-
def get_instance_id_info iid_token, options={}
190+
def get_instance_id_info(iid_token, options = {})
186191
params = {
187-
query: options
192+
query: options,
188193
}
189-
194+
190195
for_uri(INSTANCE_ID_API) do |connection|
191-
response = connection.get('/iid/info/'+iid_token, params)
196+
response = connection.get("/iid/info/" + iid_token, params)
192197
build_response(response)
193198
end
194199
end
195200

196-
def subscribe_instance_id_to_topic iid_token, topic_name
201+
def subscribe_instance_id_to_topic(iid_token, topic_name)
197202
batch_subscribe_instance_ids_to_topic([iid_token], topic_name)
198203
end
199204

200-
def unsubscribe_instance_id_from_topic iid_token, topic_name
205+
def unsubscribe_instance_id_from_topic(iid_token, topic_name)
201206
batch_unsubscribe_instance_ids_from_topic([iid_token], topic_name)
202207
end
203208

204-
def batch_subscribe_instance_ids_to_topic instance_ids, topic_name
205-
manage_topics_relationship(topic_name, instance_ids, 'Add')
209+
def batch_subscribe_instance_ids_to_topic(instance_ids, topic_name)
210+
manage_topics_relationship(topic_name, instance_ids, "Add")
206211
end
207212

208-
def batch_unsubscribe_instance_ids_from_topic instance_ids, topic_name
209-
manage_topics_relationship(topic_name, instance_ids, 'Remove')
213+
def batch_unsubscribe_instance_ids_from_topic(instance_ids, topic_name)
214+
manage_topics_relationship(topic_name, instance_ids, "Remove")
210215
end
211216

212217
def send_to_topic_condition(condition, options = {})
@@ -220,7 +225,7 @@ def send_to_topic_condition(condition, options = {})
220225

221226
def for_uri(uri, extra_headers = {})
222227
connection = ::Faraday.new(:url => uri) do |faraday|
223-
faraday.adapter Faraday.default_adapter
228+
faraday.adapter Faraday.default_adapter
224229
faraday.headers["Content-Type"] = "application/json"
225230
faraday.headers["Authorization"] = "key=#{api_key}"
226231
extra_headers.each do |key, value|
@@ -240,28 +245,28 @@ def build_response(response, registration_ids = [])
240245
response_hash = { body: body, headers: response.headers, status_code: response.status }
241246
case response.status
242247
when 200
243-
response_hash[:response] = 'success'
248+
response_hash[:response] = "success"
244249
body = JSON.parse(body) unless body.empty?
245250
response_hash[:canonical_ids] = build_canonical_ids(body, registration_ids) unless registration_ids.empty?
246251
response_hash[:not_registered_ids] = build_not_registered_ids(body, registration_ids) unless registration_ids.empty?
247252
when 400
248-
response_hash[:response] = 'Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields.'
253+
response_hash[:response] = "Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields."
249254
when 401
250-
response_hash[:response] = 'There was an error authenticating the sender account.'
255+
response_hash[:response] = "There was an error authenticating the sender account."
251256
when 503
252-
response_hash[:response] = 'Server is temporarily unavailable.'
257+
response_hash[:response] = "Server is temporarily unavailable."
253258
when 500..599
254-
response_hash[:response] = 'There was an internal error in the FCM server while trying to process the request.'
259+
response_hash[:response] = "There was an internal error in the FCM server while trying to process the request."
255260
end
256261
response_hash
257262
end
258263

259264
def build_canonical_ids(body, registration_ids)
260265
canonical_ids = []
261266
unless body.empty?
262-
if body['canonical_ids'] > 0
263-
body['results'].each_with_index do |result, index|
264-
canonical_ids << { old: registration_ids[index], new: result['registration_id'] } if has_canonical_id?(result)
267+
if body["canonical_ids"] > 0
268+
body["results"].each_with_index do |result, index|
269+
canonical_ids << { old: registration_ids[index], new: result["registration_id"] } if has_canonical_id?(result)
265270
end
266271
end
267272
end
@@ -271,8 +276,8 @@ def build_canonical_ids(body, registration_ids)
271276
def build_not_registered_ids(body, registration_id)
272277
not_registered_ids = []
273278
unless body.empty?
274-
if body['failure'] > 0
275-
body['results'].each_with_index do |result, index|
279+
if body["failure"] > 0
280+
body["results"].each_with_index do |result, index|
276281
not_registered_ids << registration_id[index] if is_not_registered?(result)
277282
end
278283
end
@@ -282,17 +287,17 @@ def build_not_registered_ids(body, registration_id)
282287

283288
def execute_notification(body)
284289
for_uri(BASE_URI) do |connection|
285-
response = connection.post('/fcm/send', body.to_json)
290+
response = connection.post("/fcm/send", body.to_json)
286291
build_response(response)
287292
end
288293
end
289294

290295
def has_canonical_id?(result)
291-
!result['registration_id'].nil?
296+
!result["registration_id"].nil?
292297
end
293298

294299
def is_not_registered?(result)
295-
result['error'] == 'NotRegistered'
300+
result["error"] == "NotRegistered"
296301
end
297302

298303
def validate_condition?(condition)
@@ -313,12 +318,12 @@ def validate_condition_topics?(condition)
313318
end
314319

315320
def jwt_token
316-
scope = 'https://www.googleapis.com/auth/firebase.messaging'
321+
scope = "https://www.googleapis.com/auth/firebase.messaging"
317322
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
318323
json_key_io: File.open(@json_key_path),
319-
scope: scope
324+
scope: scope,
320325
)
321326
token = authorizer.fetch_access_token!
322-
token['access_token']
327+
token["access_token"]
323328
end
324329
end

0 commit comments

Comments
 (0)