firebase_cloud_messenger 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df760f55ce074ae2ec5f8e45d43ba2f0446e94f2
4
+ data.tar.gz: f7aef2b712e689775f41d30d55897d27dc9ce3a6
5
+ SHA512:
6
+ metadata.gz: 71ae814f893ee647dc1149219787ba06481e536b35134e94f24ad82f86100e2833da1d5c789c1e70c31bf7080795ed0cb0c336c46ab2e75fedba7635c1ddcfd1
7
+ data.tar.gz: b12035cc991df505d0a7196a01e37a18a0574e88a2bd9a823910f54b3937861aefee4830dd9cb1bc279127391f2b2e5020835a666d3627f20a19442edce81c0f
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in firebase_cloud_messenger.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 PatientsLikeMe
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # firebase-cloud-messenger
2
+
3
+ firebase-cloud-messenger wraps Google's API to make sending push notifications to iOS, android, and
4
+ web push notifications from your server easy.
5
+
6
+ NB: Google released the [FCM HTTP v1 API](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages)
7
+ in November 2017, giving legacy status to the older but still supported HTTP and XMPP apis.
8
+ This gem only targets the [FCM HTTP v1 API], which Google [recommends using for new projects](https://firebase.google.com/docs/cloud-messaging/server),
9
+ because it is the most up-to-date and secure.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'firebase_cloud_messenger'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install firebase_cloud_messenger
26
+
27
+ In order for google to authenticate requests to Firebase Cloud Messenger, you must have your
28
+ credentials file in a place that's accessible. You can tell firebase-cloud-messenger where it is in
29
+ two ways:
30
+
31
+ 1. `FirebaseCloudMessenger.credentials_path = "path/to/credentials/file.json"`
32
+ 2. `export GOOGLE_APPLICATION_CREDENTIALS = "path/to/credentials/file.json"`
33
+
34
+ ## Usage
35
+
36
+ ### Sending a Message
37
+
38
+ You can see how your message should be structured [here](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages)
39
+ firebase-cloud-messenger provides built-in data classes for each json object type in the FCM API
40
+ specification, but you can also build up a hash message on your own, or use some combination of the
41
+ two.
42
+
43
+ Send messages with built-in data objects, which can be built through a hash argument to the
44
+ initializer or via writer methods:
45
+ ```ruby
46
+ android_notification = FirebaseCloudMessenger::Android::Notification.new(title: "title")
47
+ android_config = FirebaseCloudMessenger::Android::AndroidConfig.new(notification: android_notification)
48
+ message = FirebaseCloudMessenger::Message.new(android: android_config, token "a_device_token")
49
+
50
+ FirebaseCloudMessenger.send(message: message) # => { "name" => "name_from_fcm" }
51
+
52
+ # OR
53
+
54
+ android_notification = FirebaseCloudMessenger::Android::Notification.new
55
+ android_notification.title = "title"
56
+
57
+ android_config = FirebaseCloudMessenger::Android::AndroidConfig.new
58
+ android_config.notification = android_notification
59
+
60
+ message = FirebaseCloudMessenger::Message.new
61
+ message.android = android_config
62
+ message.token = "a_device_token"
63
+
64
+ FirebaseCloudMessenger.send(message: message) # => { "name" => "name_from_fcm" }
65
+ ```
66
+
67
+ or with just a hash:
68
+
69
+ ```ruby
70
+ message = {
71
+ android: {
72
+ notification: {
73
+ title: "title"
74
+ }
75
+ },
76
+ token: "a_device_token"
77
+ }
78
+
79
+ FirebaseCloudMessenger.send(message: message) # => { "name" => "name_from_fcm" }
80
+ ```
81
+
82
+ or some combination of the two:
83
+
84
+ ```ruby
85
+ message = FirebaseCloudMessenger::Message.new(android: { notification: { title: "title" }, token: "a_device_token" })
86
+ FirebaseCloudMessenger.send(message: message) # => { "name" => "name_from_fcm" }
87
+ ```
88
+
89
+ ### Error Handling
90
+
91
+ If something goes wrong, `::send` will raise an instance of a subclass of `FirebaseCloudMessenger::Error` with
92
+ helpful info on what went wrong:
93
+ ```ruby
94
+ message = FirebaseCloudMessenger::Message.new(android: { bad: "data" }, token: "a_device_token"})
95
+ begin
96
+ FirebaseCloudMessenger.send(message: message)
97
+ rescue FirebaseCloudMessenger::Error => e
98
+ e.class # => FirebaseCloudMessenger::BadRequest
99
+ e.message # => A message from fcm about what's wrong with the request
100
+ e.status # => 400
101
+ e.details # => An array of error details from fcm
102
+ end
103
+ ```
104
+
105
+ ### Message Validation
106
+
107
+ Many errors can be caught before sending by validating a message before sending it.
108
+
109
+ Validate your message either by via the Firebase Cloud Messenger API:
110
+ ```ruby
111
+ message = FirebaseCloudMessenger.new(android: { bad: "data" })
112
+ message.valid?(against_api: true) # => false
113
+ message.errors # => [<error_msg>]
114
+ ```
115
+
116
+ or client-side, via json-schema:
117
+ ```ruby
118
+ message = FirebaseCloudMessenger.new(android: { bad: "data" }, token: "a_device_token")
119
+ message.valid? # => false
120
+ message.errors # => ["The property '#/android' contains additional properties [\"bad\"] outside of the schema when none are allowed in schema..."]
121
+ ```
122
+
123
+ Validate your hash message (returns only true or false):
124
+ ```ruby
125
+ message = {
126
+ android: { bad: "data" },
127
+ token: "a_device_token"
128
+ }
129
+
130
+ #api-side
131
+ FirebaseCloudMessenger.validate_message(message, against_api: true) # => false
132
+
133
+ #OR
134
+
135
+ #client-side
136
+ FirebaseCloudMessenger.validate_message(message) # => false
137
+
138
+ ```
139
+
140
+
141
+ ## Development
142
+
143
+ After checking out the repo, run `bundle` to install dependencies. Then, run `rake test` to run the tests.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'firebase_cloud_messenger/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "firebase_cloud_messenger"
8
+ spec.version = FirebaseCloudMessenger::VERSION
9
+ spec.license = "MIT"
10
+ spec.authors = ["Vince DeVendra"]
11
+ spec.email = ["vdevendra@patientslikeme.com"]
12
+ spec.homepage = "https://github.com/patientslikeme/firebase_cloud_messenger"
13
+
14
+ spec.summary = %q{A ruby api wrapper for the FirebaseCloudMesenger API}
15
+ spec.description = spec.summary
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "googleauth", "~> 0.6"
22
+ spec.add_runtime_dependency "json-schema", "~> 2.8"
23
+
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "minitest"
26
+ spec.add_development_dependency "mocha"
27
+ spec.add_development_dependency "pry"
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'net/http'
2
+ require 'googleauth'
3
+ require 'json'
4
+
5
+ require 'firebase_cloud_messenger/auth_client'
6
+ require 'firebase_cloud_messenger/error'
7
+ require 'firebase_cloud_messenger/client'
8
+ require 'firebase_cloud_messenger/firebase_object'
9
+ require 'firebase_cloud_messenger/message'
10
+ require 'firebase_cloud_messenger/notification'
11
+ require 'firebase_cloud_messenger/android'
12
+ require 'firebase_cloud_messenger/apns'
13
+ require 'firebase_cloud_messenger/webpush'
14
+
15
+
16
+ module FirebaseCloudMessenger
17
+ class << self
18
+ attr_accessor :credentials_path
19
+ end
20
+
21
+ def self.send(message: {}, validate_only: false, conn: nil)
22
+ Client.new(credentials_path).send(message, validate_only, conn)
23
+ end
24
+
25
+ def self.validate_message(message, conn = nil, against_api: false)
26
+ message = Message.new(message) if message.is_a?(Hash)
27
+
28
+ message.valid?(conn, against_api: against_api)
29
+ end
30
+ end
@@ -0,0 +1,2 @@
1
+ require 'firebase_cloud_messenger/android/config'
2
+ require 'firebase_cloud_messenger/android/notification'
@@ -0,0 +1,12 @@
1
+ module FirebaseCloudMessenger
2
+ module Android
3
+ class Config < FirebaseObject
4
+ FIELDS = %i(collapse_key priority ttl restricted_package_name data notification).freeze
5
+ attr_accessor(*FIELDS)
6
+
7
+ def initialize(data)
8
+ super(data, FIELDS)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module FirebaseCloudMessenger
2
+ module Android
3
+ class Notification < FirebaseObject
4
+ FIELDS = %i(title body icon color sound tag click_action body_loc_key body_loc_args title_loc_key title_loc_args).freeze
5
+ attr_accessor(*FIELDS)
6
+
7
+ def initialize(data)
8
+ super(data, FIELDS)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ require 'firebase_cloud_messenger/apns/apns_object'
2
+ require 'firebase_cloud_messenger/apns/payload'
3
+ require 'firebase_cloud_messenger/apns/alert'
4
+ require 'firebase_cloud_messenger/apns/config'
5
+
@@ -0,0 +1,12 @@
1
+ module FirebaseCloudMessenger
2
+ module Apns
3
+ class Alert < ApnsObject
4
+ FIELDS = %i(title body title_loc_key title_loc_args action_loc_key loc_key loc_args launch_image).freeze
5
+ attr_accessor(*FIELDS)
6
+
7
+ def initialize(data)
8
+ super(data, FIELDS)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module FirebaseCloudMessenger
2
+ module Apns
3
+ class ApnsObject < FirebaseObject
4
+ def to_h
5
+ fields.each_with_object({}) do |field, object_hash|
6
+ val = send(field)
7
+ next if val.nil?
8
+ val = val.to_h if val.is_a?(FirebaseObject)
9
+
10
+ object_hash[field.to_s.gsub("_", "-").to_sym] = val
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ module FirebaseCloudMessenger
2
+ module Apns
3
+ class Config < ApnsObject
4
+ FIELDS = %i(headers payload).freeze
5
+ attr_accessor(*FIELDS)
6
+
7
+ def initialize(data)
8
+ super(data, FIELDS)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module FirebaseCloudMessenger
2
+ module Apns
3
+ class Payload < ApnsObject
4
+ FIELDS = %i(alert badge sound content_available category thread_id).freeze
5
+
6
+ attr_accessor(*FIELDS)
7
+
8
+ def initialize(data)
9
+ super(data, FIELDS)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module FirebaseCloudMessenger
2
+ class AuthClient
3
+ attr_reader :credentials_path
4
+
5
+ AUTH_SCOPE = "https://www.googleapis.com/auth/firebase.messaging".freeze
6
+
7
+ def initialize(credentials_path)
8
+ @credentials_path = credentials_path
9
+ @authorizer = get_authorizer
10
+ end
11
+
12
+ def fetch_access_token_info
13
+ authorizer.fetch_access_token!
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :authorizer
19
+
20
+ def get_authorizer
21
+ begin
22
+ file = File.open(credentials_path)
23
+ Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: file, scope: AUTH_SCOPE)
24
+ ensure
25
+ file.close
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,96 @@
1
+ require 'firebase_cloud_messenger/error'
2
+
3
+ module FirebaseCloudMessenger
4
+ class Client
5
+ attr_writer :max_retry_count, :project_id, :access_token
6
+ attr_accessor :credentials_path
7
+
8
+ def initialize(credentials_path = nil)
9
+ @credentials_path = credentials_path || ENV['GOOGLE_APPLICATION_CREDENTIALS']
10
+ end
11
+
12
+ def send(message, validate_only, conn)
13
+ retry_count = 0
14
+
15
+ loop do
16
+ response = make_fcm_request(message, validate_only, conn || request_conn)
17
+
18
+ retry_count += 1
19
+ if response_successful?(response) || retry_count > max_retry_count
20
+ return message_from_response(response)
21
+ elsif response.code == "401"
22
+ refresh_access_token_info
23
+ else
24
+ raise Error.from_response(response)
25
+ end
26
+ end
27
+ end
28
+
29
+ def request_conn
30
+ conn = Net::HTTP.new(send_url.host, 443)
31
+ conn.use_ssl = true
32
+ conn
33
+ end
34
+
35
+ def request_headers
36
+ {
37
+ "Content-Type" => "application/json",
38
+ "Authorization" => "Bearer #{access_token}"
39
+ }
40
+ end
41
+
42
+ def request_body(message, validate_only)
43
+ {
44
+ message: message.to_h,
45
+ validateOnly: validate_only
46
+ }.to_json
47
+ end
48
+
49
+ def access_token
50
+ @access_token ||= access_token_info["access_token"]
51
+ end
52
+
53
+ def auth_client
54
+ @auth_client ||= AuthClient.new(credentials_path)
55
+ end
56
+
57
+ def access_token_info
58
+ @access_token_info ||= auth_client.fetch_access_token_info
59
+ end
60
+
61
+ def refresh_access_token_info
62
+ self.access_token = nil
63
+ self.access_token_info = auth_client.fetch_access_token_info
64
+ end
65
+
66
+ def project_id
67
+ @project_id ||= JSON.parse(File.read(credentials_path)).fetch("project_id")
68
+ end
69
+
70
+ def send_url
71
+ URI "https://fcm.googleapis.com/v1/projects/#{project_id}/messages:send"
72
+ end
73
+
74
+ def max_retry_count
75
+ @max_retry_count ||= 1
76
+ end
77
+
78
+ private
79
+
80
+ attr_writer :access_token_info
81
+
82
+ def make_fcm_request(message, validate_only, conn = request_conn)
83
+ conn.post(send_url.path,
84
+ request_body(message, validate_only),
85
+ request_headers)
86
+ end
87
+
88
+ def message_from_response(response)
89
+ JSON.parse(response.body)
90
+ end
91
+
92
+ def response_successful?(response)
93
+ ("200".."299").include?(response.code)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,56 @@
1
+ module FirebaseCloudMessenger
2
+ class Error < StandardError
3
+ attr_reader :response
4
+
5
+ def self.from_response(response)
6
+ status = response.code
7
+
8
+ klass = case status.to_i
9
+ when 400 then FirebaseCloudMessenger::BadRequest
10
+ when 401 then FirebaseCloudMessenger::Unauthorized
11
+ when 403 then FirebaseCloudMessenger::Forbidden
12
+ else self
13
+ end
14
+
15
+ klass.new(response)
16
+ end
17
+
18
+ def initialize(response = nil)
19
+ @response = response
20
+
21
+ super(error_message)
22
+ end
23
+
24
+ def response_status
25
+ response.code.to_i
26
+ end
27
+
28
+ def response_body
29
+ response.body
30
+ end
31
+
32
+ def parsed_response
33
+ JSON.parse(response_body)
34
+ end
35
+
36
+ def details
37
+ parsed_response["error"]["details"]
38
+ end
39
+
40
+ private
41
+
42
+ def error_message
43
+ return nil if response.nil?
44
+
45
+ <<-MSG
46
+ Status: #{response_status}
47
+
48
+ #{parsed_response["error"]["message"]}
49
+ MSG
50
+ end
51
+ end
52
+
53
+ class BadRequest < Error; end
54
+ class Unauthorized < Error; end
55
+ class Forbidden < Error; end
56
+ end
@@ -0,0 +1,29 @@
1
+ module FirebaseCloudMessenger
2
+ class FirebaseObject
3
+ def initialize(data, fields)
4
+ @fields = fields
5
+
6
+ fields.each do |field|
7
+ send(:"#{field}=", data.delete(field))
8
+ end
9
+
10
+ if data.any?
11
+ raise ArgumentError, "Keys must be one on #{fields.inspect}"
12
+ end
13
+ end
14
+
15
+ def to_h
16
+ fields.each_with_object({}) do |field, object_hash|
17
+ val = send(field)
18
+ next if val.nil?
19
+ val = val.to_h if val.is_a?(FirebaseObject)
20
+
21
+ object_hash[field] = val
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :fields
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require 'firebase_cloud_messenger/schema'
2
+ require 'json-schema'
3
+
4
+ module FirebaseCloudMessenger
5
+ class Message < FirebaseObject
6
+ FIELDS = %i(name data notification android webpush apns token topic condition).freeze
7
+ attr_accessor(*FIELDS)
8
+
9
+ attr_writer :errors
10
+
11
+ def initialize(data)
12
+ super(data, FIELDS)
13
+ end
14
+
15
+ def valid?(conn = nil, against_api: false)
16
+ if against_api
17
+ validate_against_api!(conn)
18
+ else
19
+ validate_against_schema
20
+ end
21
+
22
+ errors.none?
23
+ end
24
+
25
+ def errors
26
+ @errors ||= []
27
+ end
28
+
29
+ private
30
+
31
+ def validate_against_api!(conn)
32
+ begin
33
+ FirebaseCloudMessenger.send(message: self, validate_only: true, conn: conn)
34
+ rescue FirebaseCloudMessenger::Error => e
35
+ if e.details
36
+ self.errors += e.details
37
+ else
38
+ self.errors << e.parsed_response["error"]["message"]
39
+ end
40
+ end
41
+ end
42
+
43
+ def validate_against_schema
44
+ self.errors += JSON::Validator.fully_validate(FirebaseCloudMessenger::SCHEMA, to_h)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,10 @@
1
+ module FirebaseCloudMessenger
2
+ class Notification < FirebaseObject
3
+ FIELDS = %i(title body)
4
+ attr_accessor(*FIELDS)
5
+
6
+ def initialize(data)
7
+ super(data, FIELDS)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,121 @@
1
+ module FirebaseCloudMessenger
2
+ SCHEMA = {
3
+ "definitions" => {
4
+ "data" => {
5
+ "type" => "object",
6
+ "additionalProperties" => { "type" => "string" }
7
+ },
8
+ "notification" => {
9
+ "type" => "object",
10
+ "properties" => {
11
+ "title" => { "type" => "string" },
12
+ "body" => { "type" => "string" }
13
+ },
14
+ "additionalProperties" => false
15
+ },
16
+ "android_config" => {
17
+ "type" => "object",
18
+ "properties" => {
19
+ "collapse_key" => { "type" => "string" },
20
+ "priority" => { "type" => "string", "enum" => ["NORMAL", "HIGH"] },
21
+ "ttl" => { "type" => "string", "format" => "^[0-9]+\.[0-9]+s$" },
22
+ "restricted_package_name" => { "type" => "string" },
23
+ "data" => { "$ref" => "#/definitions/data" },
24
+ "notification" => { "$ref" => "#/definitions/android_notification" }
25
+ },
26
+ "additionalProperties" => false
27
+ },
28
+ "android_notification" => {
29
+ "type" => "object",
30
+ "properties" => {
31
+ "title" => { "type" => "string" },
32
+ "body" => { "type" => "string" },
33
+ "icon" => { "type" => "string" },
34
+ "color" => { "type" => "string" },
35
+ "sound" => { "type" => "string" },
36
+ "tag" => { "type" => "string" },
37
+ "click_action" => { "type" => "string" },
38
+ "body_loc_key" => { "type" => "string" },
39
+ "body_loc_args" => { "type" => "array", "items" => { "type" => "string" } },
40
+ "title_loc_key" => { "type" => "string" },
41
+ "title_loc_args" => { "type" => "array", "items" => { "type" => "string" } }
42
+ },
43
+ "additionalProperties" => false
44
+ },
45
+ "webpush_config" => {
46
+ "type" => "object",
47
+ "properties" => {
48
+ "headers" => { "$ref" => "#/definitions/data" },
49
+ "data" => { "$ref" => "#/definitions/data" },
50
+ "notification" => { "$ref" => "#/definitions/webpush_notification" }
51
+ },
52
+ "additionalProperties" => false
53
+ },
54
+ "webpush_notification" => {
55
+ "type" => "object",
56
+ "properties" => {
57
+ "title" => { "type" => "string" },
58
+ "body" => { "type" => "string" },
59
+ "icon" => { "type" => "string" }
60
+ },
61
+ "additionalProperties" => false
62
+ },
63
+ "apns" => {
64
+ "type" => "object",
65
+ "properties" => {
66
+ "headers" => { "$ref" => "#/definitions/data" },
67
+ "payload" => { "$ref" => "#/definitions/apns_payload" }
68
+ },
69
+ "additionalProperties" => false
70
+ },
71
+ "apns_alert" => {
72
+ "anyOf" => [
73
+ { "type" => "string" },
74
+ {
75
+ "type" => "object",
76
+ "properties" => {
77
+ "title" => { "type" => "string" },
78
+ "body" => { "type" => "string" },
79
+ "title-loc-key " => { "anyOf" => [ { "type" => "string" }, { "type" => "null" } ] },
80
+ "title-loc-args" => { "anyOf" => [ { "type" => "array", "items" => { "type" => "string" } }, { "type" => "null" }] },
81
+ "action-loc-key" => { "anyOf" => [ { "type" => "string" }, { "type" => "null" } ] },
82
+ "loc-key" => { "type" => "string" },
83
+ "loc-args" => { "type" => "array", "items" => { "type" => "string" } },
84
+ "launch-image" => { "type" => "string" }
85
+ },
86
+ "additionalProperties" => false
87
+ }
88
+ ]
89
+ },
90
+ "apns_payload" => {
91
+ "type" => "object",
92
+ "properties" => {
93
+ "alert" => { "$ref" => "#/definitions/apns_alert" },
94
+ "badge" => { "type" => "number" },
95
+ "sound" => { "type" => "string" },
96
+ "content-available" => { "type" => "number" },
97
+ "category" => { "type" => "string" },
98
+ "thread-id" => { "type" => "string" }
99
+ },
100
+ "additionalProperties" => false
101
+ }
102
+ },
103
+ "type" => "object",
104
+ "properties" => {
105
+ "data" => { "$ref" => "#/definitions/data" },
106
+ "notification" => { "$ref" => "#/definitions/notification" },
107
+ "android" => { "$ref" => "#/definitions/android_config" },
108
+ "webpush" => { "$ref" => "#/definitions/webpush_config" },
109
+ "apns" => { "$ref" => "#/definitions/apns" },
110
+ "token" => { "type" => "string" },
111
+ "topic" => { "type" => "string" },
112
+ "condition" => { "type" => "string" }
113
+ },
114
+ "additionalProperties" => false,
115
+ "oneOf" => [
116
+ { "required" => ["token"] },
117
+ { "required" => ["topic"] },
118
+ { "required" => ["condition"] }
119
+ ]
120
+ }
121
+ end
@@ -0,0 +1,3 @@
1
+ module FirebaseCloudMessenger
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ require 'firebase_cloud_messenger/webpush/config'
2
+ require 'firebase_cloud_messenger/webpush/notification'
@@ -0,0 +1,12 @@
1
+ module FirebaseCloudMessenger
2
+ module Webpush
3
+ class Config < FirebaseObject
4
+ FIELDS = %i(headers data notification).freeze
5
+ attr_accessor(*FIELDS)
6
+
7
+ def initialize(data)
8
+ super(data, FIELDS)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module FirebaseCloudMessenger
2
+ module Webpush
3
+ class Notification < FirebaseObject
4
+ FIELDS = %i(title body icon).freeze
5
+ attr_accessor(*FIELDS)
6
+
7
+ def initialize(data)
8
+ super(data, FIELDS)
9
+ end
10
+ end
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: firebase_cloud_messenger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Vince DeVendra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: googleauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json-schema
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: A ruby api wrapper for the FirebaseCloudMesenger API
98
+ email:
99
+ - vdevendra@patientslikeme.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - firebase_cloud_messenger.gemspec
110
+ - lib/firebase_cloud_messenger.rb
111
+ - lib/firebase_cloud_messenger/android.rb
112
+ - lib/firebase_cloud_messenger/android/config.rb
113
+ - lib/firebase_cloud_messenger/android/notification.rb
114
+ - lib/firebase_cloud_messenger/apns.rb
115
+ - lib/firebase_cloud_messenger/apns/alert.rb
116
+ - lib/firebase_cloud_messenger/apns/apns_object.rb
117
+ - lib/firebase_cloud_messenger/apns/config.rb
118
+ - lib/firebase_cloud_messenger/apns/payload.rb
119
+ - lib/firebase_cloud_messenger/auth_client.rb
120
+ - lib/firebase_cloud_messenger/client.rb
121
+ - lib/firebase_cloud_messenger/error.rb
122
+ - lib/firebase_cloud_messenger/firebase_object.rb
123
+ - lib/firebase_cloud_messenger/message.rb
124
+ - lib/firebase_cloud_messenger/notification.rb
125
+ - lib/firebase_cloud_messenger/schema.rb
126
+ - lib/firebase_cloud_messenger/version.rb
127
+ - lib/firebase_cloud_messenger/webpush.rb
128
+ - lib/firebase_cloud_messenger/webpush/config.rb
129
+ - lib/firebase_cloud_messenger/webpush/notification.rb
130
+ homepage: https://github.com/patientslikeme/firebase_cloud_messenger
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.5.2
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: A ruby api wrapper for the FirebaseCloudMesenger API
154
+ test_files: []