maia 2.0.0 → 4.0.3

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
- SHA1:
3
- metadata.gz: 0200a5ab7f43a82c921bc7a3dbadbece312e129b
4
- data.tar.gz: 5dd079e1820935f9de05e4ce9ab7e8907058e280
2
+ SHA256:
3
+ metadata.gz: 1164306f881ef2bbcafa53947387cd80389f0f41c7b7cc3b1b5c685ac2d52ad3
4
+ data.tar.gz: a0b5faf5699c23b693c161906ab14546e0a96656a88307e8d96cac82d81ff78e
5
5
  SHA512:
6
- metadata.gz: 5ac7fbcdb52b2db18d12021a946c4343bd645576587cdc5095a81c9dc7bc869e99245ad18ea7c6e3ce5c4ebeda6e49f116d8b688205054a2c07834649f1d364c
7
- data.tar.gz: f4f06d7362e26f54fbf548ad342424daa98594c992b8aa8e4516ecc1bec642200ee4262627bec2f1417d9d416781e700ef006855b33b505d04116dede020538a
6
+ metadata.gz: 7b2b6a594dafbd284acfed06d67714910f04ee2795bd40b261260366ebd930334b649a2b4ed28a12a7cf9610a7931963445a2e32156ed11a930216c2ee773845
7
+ data.tar.gz: f8c80d2f8f1cfcb57cbad64db76b7cfc6600f161141982285221157fb0540f899b8950f03485089504e02b2f4796df6fe6011a9abacd80afed7de2432c2182d0
data/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # Maia
2
+
3
+ This project maintains a `Maia::Device` model and facilitates the delivery of push notifications for iOS and Android through FCM (Firebase Cloud Messaging).
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ gem 'maia'
9
+ bundle
10
+ bin/rake railties:install:migrations
11
+ bin/rake db:migrate
12
+ ```
13
+
14
+ This will copy the `maia_devices` table into your project.
15
+
16
+ ## Setup
17
+
18
+ Maia relies on [ActiveJob](https://github.com/rails/rails/tree/master/activejob) to enqueue messages. Ensure your application is properly setup with ActiveJob!
19
+
20
+ Set your FCM key in an initializer, such as `config/initializers/maia.rb`:
21
+
22
+ ```ruby
23
+ Maia::FCM.key = Rails.application.secrets[:fcm][:key]
24
+ ```
25
+
26
+ Alternatively, you can set `ENV['FCM_KEY']`, which Maia will check first.
27
+
28
+ Include `Maia::Model` into your User model. This will attach the `has_many` relationship you need with `Maia::Device`:
29
+
30
+ ```ruby
31
+ class User
32
+ include Maia::Model
33
+ # ...
34
+ end
35
+ ```
36
+
37
+ Create a Devices controller where you need it, which is most likely an API. The controller itself will be generated within your application so that Maia does not make any assumptions about your method of authentication, `respond_with` mimetypes, etc. The only requirement is that `current_user` exists and returns whatever model included `Maia::Model`.
38
+
39
+ Here's an example of getting setup with an API Devices controller that mobile apps can register with:
40
+
41
+ `bin/rails g controller api/devices`
42
+
43
+ After the controller is generated, include `Maia::Controller`:
44
+
45
+ ```ruby
46
+ class API::DevicesController
47
+ include Maia::Controller
48
+ # ...
49
+ ```
50
+
51
+ Maia provides the `create` method for you, so devices can now register themselves by POSTing to that controller. If you'd like to add any other actions, feel free.
52
+
53
+ ## Device Registration
54
+
55
+ Devices can register with your application by submitting a POST to your devices controller with these params:
56
+
57
+ ```
58
+ { "device": { "token": "<TOKEN>" } }
59
+ ```
60
+
61
+ Where `<TOKEN>` is the token from FCM registration.
62
+
63
+ ## Device Management
64
+
65
+ When FCM responds with an invalid or unregistered device token, the device record will be destroyed from the database.
66
+
67
+ When FCM responds with a canonical ID, the device record will be updated so that it's `token` field will be equal to the canonical ID given by FCM.
68
+
69
+ ## Device Expiration
70
+
71
+ Devices will expire after 14 days. This is to ensure user's who sell or otherwise give away their device will not be tied to that device forever. Each time a POST to Devices is received, the token expiration will be refreshed.
72
+
73
+ ## Defining Messages
74
+
75
+ Maia provides a `Maia::Message` class that provides an interface for defining push messages and sending them. To define a message, inherit from `Maia::Message` and override whatever you need to:
76
+
77
+ ```ruby
78
+ class ExampleMessage < Maia::Message
79
+ # Required
80
+ def title
81
+ 'Something happened!'
82
+ end
83
+
84
+ # Required, the body of the message on Android, alert on iOS
85
+ def body
86
+ 'Something very important has happened, check it out!'
87
+ end
88
+
89
+ # Determines the icon to load on Android phones
90
+ def icon
91
+ 'icn_maia'
92
+ end
93
+
94
+ # Will use 'default' by default. Overriding to nil will prevent sound
95
+ def sound
96
+ 'default'
97
+ end
98
+
99
+ # Badge to use on iOS
100
+ def badge
101
+ 1
102
+ end
103
+
104
+ # #RRGGBB formatted color to use for the Android notification icon
105
+ def color
106
+ '#ffffff'
107
+ end
108
+
109
+ # click_action on Android, category on iOS
110
+ def on_click
111
+ 'SOMETHING_HAPPENED'
112
+ end
113
+
114
+ # Any additional data to send with the payload
115
+ def data
116
+ { foo: :bar }
117
+ end
118
+
119
+ # :normal or :high (:normal by default)
120
+ def priority
121
+ :normal
122
+ end
123
+
124
+ # Override to true in order to send the iOS content-available flag
125
+ def content_available?
126
+ false
127
+ end
128
+
129
+ # Override to true in order to send a dry run push. This can help debug any device errors without actually sending a push message
130
+ def dry_run?
131
+ false
132
+ end
133
+ end
134
+ ```
135
+
136
+ This message will generate the following FCM payload:
137
+
138
+ ```json
139
+ {
140
+ "priority": "normal",
141
+ "dry_run": false,
142
+ "content_available": false,
143
+ "data": {
144
+ "foo": "bar"
145
+ },
146
+ "notification": {
147
+ "title": "Something happened!",
148
+ "body": "'Something very important has happened, check it out!'",
149
+ "icon": "icn_maia",
150
+ "sound": "default",
151
+ "badge": 1,
152
+ "color": "#ffffff",
153
+ "click_action": "SOMETHING_HAPPENED",
154
+ },
155
+ "registration_ids": ["<TOKEN1>", "<TOKEN2>"]
156
+ }
157
+ ```
158
+
159
+ `Maia::Message` does not define a constructor so you can construct your message however you want.
160
+
161
+ ## Sending messages
162
+
163
+ `Maia::Message` provides a `send_to` that pushes the message out to a user (or collection of users). The argument to `send_to` should be a single record or relation of records.
164
+
165
+ For example:
166
+
167
+ ```ruby
168
+ ExampleMessage.new(...).send_to User.first
169
+ ExampleMessage.new(...).send_to User.where(beta: true)
170
+ ```
171
+
172
+ `send_to` will batch users in groups of 999 tokens (FCM limitation) and send them via ActiveJob.
173
+
174
+ ## Specifying job options (`wait`, `queue`, etc)
175
+
176
+ The `send_to` method passes it's last argument into [ActiveJob's `set` method](http://apidock.com/rails/ActiveJob/Core/ClassMethods/set), for example:
177
+
178
+ ```ruby
179
+ ExampleMessage.new(...).send_to User.first, wait: 10.seconds, queue: :maia
180
+ ```
181
+
182
+ ## Sending a test push
183
+
184
+ Maia comes with a built-in message to use to test your configuration out:
185
+
186
+ ```ruby
187
+ Maia::Poke.new.send_to user
188
+ ```
@@ -25,7 +25,7 @@ module Maia
25
25
  end
26
26
 
27
27
  def find_device(token = params[:device][:token])
28
- current_user.devices.find_by token: token
28
+ current_user.devices.find_by! token: token
29
29
  end
30
30
 
31
31
  def update_device(device)
data/lib/maia.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'rails'
2
+ require 'active_support/core_ext/enumerable'
3
+
2
4
  require 'maia/engine'
3
5
  require 'maia/message'
4
6
  require 'maia/messenger'
@@ -6,5 +8,15 @@ require 'maia/poke'
6
8
  require 'maia/dry_run'
7
9
  require 'maia/error'
8
10
 
11
+ require 'maia/fcm'
12
+ require 'maia/fcm/connection'
13
+ require 'maia/fcm/notification'
14
+ require 'maia/fcm/response_collection'
15
+ require 'maia/fcm/response'
16
+ require 'maia/fcm/result_collection'
17
+ require 'maia/fcm/result'
18
+ require 'maia/fcm/service'
19
+
9
20
  module Maia
21
+ BATCH_SIZE = 999
10
22
  end
data/lib/maia/engine.rb CHANGED
@@ -2,7 +2,6 @@ module Maia
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Maia
4
4
 
5
- require 'mercurius'
6
5
  require 'responders'
7
6
  end
8
7
  end
data/lib/maia/fcm.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Maia
2
+ module FCM
3
+ class << self
4
+ attr_accessor :key
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ module Maia
2
+ module FCM
3
+ class Connection
4
+ URL = 'https://fcm.googleapis.com/fcm/send'.freeze
5
+
6
+ def initialize(key)
7
+ @key = key
8
+ end
9
+
10
+ def write(payload = {})
11
+ request = Net::HTTP::Post.new uri, headers
12
+ request.body = payload.to_json
13
+ http.request request
14
+ end
15
+
16
+ def uri
17
+ URI(URL)
18
+ end
19
+
20
+ def headers
21
+ {
22
+ 'Content-Type' => 'application/json',
23
+ 'Authorization' => "key=#{@key}"
24
+ }
25
+ end
26
+
27
+ def http
28
+ @_http ||= Net::HTTP.new(uri.host, uri.port).tap do |h|
29
+ h.use_ssl = true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ module Maia
2
+ module FCM
3
+ class Notification
4
+ attr_accessor :attributes
5
+
6
+ def initialize(attributes = {})
7
+ @attributes = attributes
8
+ end
9
+
10
+ def to_h
11
+ @attributes
12
+ end
13
+
14
+ def ==(other)
15
+ attributes == other.attributes
16
+ end
17
+
18
+ def method_missing(method_name, *args, &block)
19
+ @attributes.fetch(method_name) { super }
20
+ end
21
+
22
+ def respond_to_missing?(method_name)
23
+ @attributes.include? method_name
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,55 @@
1
+ module Maia
2
+ module FCM
3
+ class Response
4
+ attr_reader :http_response, :tokens
5
+
6
+ def initialize(http_response, tokens = [])
7
+ @http_response = http_response
8
+ @tokens = tokens
9
+ end
10
+
11
+ def status
12
+ http_response.code
13
+ end
14
+
15
+ def success?
16
+ (200..399).cover? status
17
+ end
18
+
19
+ def fail?
20
+ !success?
21
+ end
22
+
23
+ def results
24
+ @_results ||= begin
25
+ results = to_h.fetch 'results', []
26
+ results.map!.with_index do |attributes, i|
27
+ Result.new attributes, tokens[i]
28
+ end
29
+ ResultCollection.new(results)
30
+ end
31
+ end
32
+
33
+ def error
34
+ case status
35
+ when 400
36
+ 'Invalid JSON was sent to FCM.'
37
+ when 401
38
+ 'Authentication error with FCM. Check the server whitelist and the validity of your project key.'
39
+ when 500..599
40
+ 'FCM Internal server error.'
41
+ end
42
+ end
43
+
44
+ def retry_after
45
+ http_response.headers['Retry-After']
46
+ end
47
+
48
+ def to_h
49
+ JSON.parse http_response.body
50
+ rescue JSON::ParserError
51
+ {}
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module Maia
2
+ module FCM
3
+ class ResponseCollection
4
+ include Enumerable
5
+
6
+ def initialize(notification, responses = [])
7
+ @notification = notification
8
+ @responses = responses
9
+ end
10
+
11
+ def results
12
+ collection = ResultCollection.new
13
+ @responses.each do |response|
14
+ response.results.each do |result|
15
+ collection << result
16
+ end
17
+ end
18
+ collection
19
+ end
20
+
21
+ def [](index)
22
+ @responses[index]
23
+ end
24
+
25
+ def <<(response)
26
+ @responses.concat Array(response).flatten
27
+ end
28
+
29
+ def each(&block)
30
+ @responses.each(&block)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ module Maia
2
+ module FCM
3
+ class Result
4
+ include ActiveModel::Model
5
+
6
+ attr_accessor :message_id, :registration_id, :error
7
+ attr_reader :token
8
+
9
+ def initialize(attributes, token)
10
+ super attributes
11
+ @token = token
12
+ end
13
+
14
+ def success?
15
+ message_id.present?
16
+ end
17
+
18
+ def fail?
19
+ !success?
20
+ end
21
+
22
+ def canonical_id
23
+ registration_id
24
+ end
25
+
26
+ def has_canonical_id?
27
+ canonical_id.present?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ module Maia
2
+ module FCM
3
+ class ResultCollection
4
+ include Enumerable
5
+
6
+ def initialize(results = [])
7
+ @results = results
8
+ end
9
+
10
+ def succeeded
11
+ @results.select(&:success?)
12
+ end
13
+
14
+ def failed
15
+ @results.select(&:fail?)
16
+ end
17
+
18
+ def with_canonical_ids
19
+ @results.select(&:has_canonical_id?)
20
+ end
21
+
22
+ def [](index)
23
+ @results[index]
24
+ end
25
+
26
+ def <<(result)
27
+ @results << result
28
+ end
29
+
30
+ def each(&block)
31
+ @results.each(&block)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,48 @@
1
+ module Maia
2
+ module FCM
3
+ class Service
4
+ def initialize
5
+ @connection ||= FCM::Connection.new key
6
+ end
7
+
8
+ def key
9
+ ENV.fetch 'FCM_KEY', Maia::FCM.key
10
+ end
11
+
12
+ def deliver(notification, *tokens, topic: nil)
13
+ responses = ResponseCollection.new notification
14
+ responses << deliver_all(notification, tokens)
15
+ responses << deliver_all(notification, "/topics/#{topic}") if topic
16
+ responses
17
+ end
18
+
19
+ private
20
+ def deliver_all(notification, tokens)
21
+ batch(tokens).map do |batch|
22
+ if batch.one?
23
+ unicast notification, batch.first
24
+ elsif batch.many?
25
+ multicast notification, batch
26
+ end
27
+ end
28
+ end
29
+
30
+ def unicast(notification, recipient)
31
+ deliver! notification, recipient, to: recipient
32
+ end
33
+
34
+ def multicast(notification, recipients)
35
+ deliver! notification, recipients, registration_ids: recipients
36
+ end
37
+
38
+ def deliver!(notification, recipients, params = {})
39
+ payload = notification.to_h.merge params
40
+ Response.new @connection.write(payload), Array(recipients)
41
+ end
42
+
43
+ def batch(recipients, batch_size: Maia::BATCH_SIZE)
44
+ Array(recipients).flatten.compact.each_slice batch_size
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/maia/message.rb CHANGED
@@ -1,19 +1,17 @@
1
1
  module Maia
2
2
  class Message
3
- MAX_TOKENS_AT_ONCE = 999
4
-
5
3
  def send_to(pushable, job_options = {})
6
4
  devices = Device.owned_by pushable
7
- worker = Maia::Messenger.set job_options
5
+ worker = Messenger.set job_options
8
6
 
9
- enqueue worker, devices.android, to_h(notify: notify?(:android))
10
- enqueue worker, devices.ios, to_h(notify: notify?(:ios))
11
- enqueue worker, devices.unknown, to_h(notify: notify?(:unknown))
7
+ enqueue worker, devices.android
8
+ enqueue worker, devices.ios
9
+ enqueue worker, devices.unknown
12
10
  end
13
11
 
14
- def enqueue(worker, devices, payload)
15
- devices.pluck(:token).each_slice MAX_TOKENS_AT_ONCE do |tokens|
16
- worker.perform_later tokens, payload.deep_stringify_keys
12
+ def enqueue(worker, devices)
13
+ devices.in_batches(of: Maia::BATCH_SIZE) do |devices|
14
+ worker.perform_later devices.pluck(:token), to_h.deep_stringify_keys
17
15
  end
18
16
  end
19
17
 
@@ -23,11 +21,14 @@ module Maia
23
21
  def body
24
22
  end
25
23
 
24
+ def on_click
25
+ end
26
+
26
27
  def icon
27
28
  end
28
29
 
29
30
  def sound
30
- 'default'
31
+ :default
31
32
  end
32
33
 
33
34
  def badge
@@ -36,17 +37,6 @@ module Maia
36
37
  def color
37
38
  end
38
39
 
39
- def action
40
- end
41
-
42
- def title_i18n
43
- []
44
- end
45
-
46
- def body_i18n
47
- []
48
- end
49
-
50
40
  def data
51
41
  end
52
42
 
@@ -58,12 +48,12 @@ module Maia
58
48
  false
59
49
  end
60
50
 
61
- def dry_run?
51
+ def content_mutable?
62
52
  false
63
53
  end
64
54
 
65
- def notify?(_platform = :unknown)
66
- true
55
+ def dry_run?
56
+ false
67
57
  end
68
58
 
69
59
  def notification
@@ -71,51 +61,22 @@ module Maia
71
61
  title: title,
72
62
  body: body,
73
63
  icon: icon,
74
- sound: sound,
64
+ sound: sound.to_s,
75
65
  badge: badge,
76
66
  color: color,
77
- click_action: action
78
- }.merge(i18n).compact
67
+ click_action: on_click
68
+ }.compact
79
69
  end
80
70
 
81
- def to_h(notify: true)
82
- payload = {
71
+ def to_h
72
+ {
83
73
  priority: priority.to_s,
84
74
  dry_run: dry_run?,
85
75
  content_available: content_available?,
86
- data: data
87
- }
88
-
89
- payload[:notification] = notification if notify
90
- payload.compact
76
+ mutable_content: content_mutable?,
77
+ data: data,
78
+ notification: notification
79
+ }.compact
91
80
  end
92
-
93
- private
94
- def i18n
95
- {}.tap do |hash|
96
- hash[:body_loc_key] = body_i18n.first
97
- hash[:body_loc_args] = body_i18n_args
98
- hash[:title_loc_key] = title_i18n_key
99
- hash[:title_loc_args] = title_i18n_args
100
- end.compact
101
- end
102
-
103
- def body_i18n_key
104
- body_i18n.first
105
- end
106
-
107
- def body_i18n_args
108
- args = body_i18n.drop 1
109
- args if args.any?
110
- end
111
-
112
- def title_i18n_key
113
- title_i18n.first
114
- end
115
-
116
- def title_i18n_args
117
- args = title_i18n.drop 1
118
- args if args.any?
119
- end
120
81
  end
121
82
  end
@@ -4,46 +4,48 @@ module Maia
4
4
  logger.info "Pushing to #{tokens.size} token(s)..."
5
5
  logger.info "Payload: #{payload}"
6
6
 
7
- notification = GCM::Notification.new(payload)
8
- responses = gcm.deliver(notification, tokens)
7
+ notification = FCM::Notification.new payload
8
+ responses = fcm.deliver notification, tokens
9
9
 
10
10
  responses.each do |response|
11
- if error = response.error
12
- raise Maia::Error, error
13
- else
14
- handle_failed_tokens response.results.failed
15
- update_devices_to_use_canonical_ids response.results.with_canonical_ids
16
- end
11
+ raise Maia::Error, response.error if response.error
12
+ handle_errors response.results.failed
13
+ update_devices_to_use_canonical_ids response.results.with_canonical_ids
17
14
  end
18
15
  end
19
16
 
20
17
  private
21
- def gcm
22
- @_service ||= GCM::Service.new connection: connection
23
- end
24
-
25
- def connection
26
- nil # use the default
18
+ def fcm
19
+ @_service ||= FCM::Service.new
27
20
  end
28
21
 
29
- def handle_failed_tokens(results)
22
+ def handle_errors(results)
30
23
  results.each do |result|
31
- device = Maia::Device.find_by(token: result.token)
32
- if device
33
- if device_unrecoverable?(result.error)
34
- log_error "Destroying device #{device.id}", result, device
35
- device.destroy
36
- else
37
- log_error "Push to device #{device.id} failed", result, device
38
- end
24
+ device = Maia::Device.find_by token: result.token
25
+ next unless device.present?
26
+
27
+ if device_unrecoverable? result.error
28
+ log_error "Destroying device #{device.id}", result, device
29
+ device.destroy
30
+ else
31
+ log_error "Push to device #{device.id} failed", result, device
39
32
  end
40
33
  end
41
34
  end
42
35
 
36
+ def device_unrecoverable?(error)
37
+ error =~ /InvalidRegistration|NotRegistered|MismatchSenderId/
38
+ end
39
+
40
+ def log_error(message, result, device)
41
+ logger.info "#{message} (error: #{result.error}, token: #{device.token})"
42
+ end
43
+
43
44
  def update_devices_to_use_canonical_ids(results)
44
45
  results.each do |result|
45
46
  device = Maia::Device.find_by token: result.token
46
47
  next if device.nil?
48
+
47
49
  if user_already_has_token_registered?(device.pushable, result.canonical_id)
48
50
  device.destroy
49
51
  else
@@ -52,16 +54,8 @@ module Maia
52
54
  end
53
55
  end
54
56
 
55
- def device_unrecoverable?(error)
56
- error =~ /InvalidRegistration|NotRegistered|MismatchSenderId/
57
- end
58
-
59
57
  def user_already_has_token_registered?(user, token)
60
58
  user.devices.exists? token: token
61
59
  end
62
-
63
- def log_error(message, result, device)
64
- logger.info "#{message} (error: #{result.error}, token: #{device.token})"
65
- end
66
60
  end
67
61
  end
data/lib/maia/poke.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  module Maia
2
2
  class Poke < Message
3
3
  def title
4
- 'Poke'
4
+ 'Poke!'
5
5
  end
6
6
 
7
7
  def body
8
- 'Poke'
8
+ 'This is a test push, please ignore me.'
9
9
  end
10
10
  end
11
11
  end
data/lib/maia/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Maia
2
- VERSION = '2.0.0'.freeze
2
+ VERSION = '4.0.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 4.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Logan Serman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-08 00:00:00.000000000 Z
11
+ date: 2019-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,78 +16,48 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.0.2
19
+ version: '5'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: 5.0.2
29
+ version: '5'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: activejob
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: 5.0.2
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 5.0.2
41
- - !ruby/object:Gem::Dependency
42
- name: responders
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
39
+ version: '5'
40
+ - - "<"
46
41
  - !ruby/object:Gem::Version
47
- version: '2.0'
42
+ version: '7'
48
43
  type: :runtime
49
44
  prerelease: false
50
45
  version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.0'
55
- - !ruby/object:Gem::Dependency
56
- name: mercurius
57
- requirement: !ruby/object:Gem::Requirement
58
46
  requirements:
59
47
  - - ">="
60
48
  - !ruby/object:Gem::Version
61
- version: 0.2.1
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
49
+ version: '5'
50
+ - - "<"
67
51
  - !ruby/object:Gem::Version
68
- version: 0.2.1
52
+ version: '7'
69
53
  - !ruby/object:Gem::Dependency
70
- name: sqlite3
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: rspec-rails
54
+ name: responders
85
55
  requirement: !ruby/object:Gem::Requirement
86
56
  requirements:
87
57
  - - ">="
88
58
  - !ruby/object:Gem::Version
89
59
  version: '0'
90
- type: :development
60
+ type: :runtime
91
61
  prerelease: false
92
62
  version_requirements: !ruby/object:Gem::Requirement
93
63
  requirements:
@@ -95,7 +65,7 @@ dependencies:
95
65
  - !ruby/object:Gem::Version
96
66
  version: '0'
97
67
  - !ruby/object:Gem::Dependency
98
- name: capybara
68
+ name: sqlite3
99
69
  requirement: !ruby/object:Gem::Requirement
100
70
  requirements:
101
71
  - - ">="
@@ -109,7 +79,7 @@ dependencies:
109
79
  - !ruby/object:Gem::Version
110
80
  version: '0'
111
81
  - !ruby/object:Gem::Dependency
112
- name: capybara-webkit
82
+ name: rspec-rails
113
83
  requirement: !ruby/object:Gem::Requirement
114
84
  requirements:
115
85
  - - ">="
@@ -123,7 +93,7 @@ dependencies:
123
93
  - !ruby/object:Gem::Version
124
94
  version: '0'
125
95
  - !ruby/object:Gem::Dependency
126
- name: launchy
96
+ name: webmock
127
97
  requirement: !ruby/object:Gem::Requirement
128
98
  requirements:
129
99
  - - ">="
@@ -137,7 +107,7 @@ dependencies:
137
107
  - !ruby/object:Gem::Version
138
108
  version: '0'
139
109
  - !ruby/object:Gem::Dependency
140
- name: webmock
110
+ name: webmock-rspec-helper
141
111
  requirement: !ruby/object:Gem::Requirement
142
112
  requirements:
143
113
  - - ">="
@@ -150,7 +120,7 @@ dependencies:
150
120
  - - ">="
151
121
  - !ruby/object:Gem::Version
152
122
  version: '0'
153
- description: Manage device tokens and push messaging with Rails and Mercurius.
123
+ description: Manage device tokens and push messaging with Rails and FCM.
154
124
  email:
155
125
  - loganserman@gmail.com
156
126
  executables: []
@@ -158,6 +128,7 @@ extensions: []
158
128
  extra_rdoc_files: []
159
129
  files:
160
130
  - MIT-LICENSE
131
+ - README.md
161
132
  - Rakefile
162
133
  - app/controllers/concerns/maia/controller.rb
163
134
  - app/models/concerns/maia/model.rb
@@ -171,6 +142,14 @@ files:
171
142
  - lib/maia/dry_run.rb
172
143
  - lib/maia/engine.rb
173
144
  - lib/maia/error.rb
145
+ - lib/maia/fcm.rb
146
+ - lib/maia/fcm/connection.rb
147
+ - lib/maia/fcm/notification.rb
148
+ - lib/maia/fcm/response.rb
149
+ - lib/maia/fcm/response_collection.rb
150
+ - lib/maia/fcm/result.rb
151
+ - lib/maia/fcm/result_collection.rb
152
+ - lib/maia/fcm/service.rb
174
153
  - lib/maia/message.rb
175
154
  - lib/maia/messenger.rb
176
155
  - lib/maia/poke.rb
@@ -195,8 +174,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
174
  version: '0'
196
175
  requirements: []
197
176
  rubyforge_project:
198
- rubygems_version: 2.6.12
177
+ rubygems_version: 2.7.7
199
178
  signing_key:
200
179
  specification_version: 4
201
- summary: Manage device tokens and push messaging with Rails and Mercurius.
180
+ summary: Manage device tokens and push messaging with Rails and FCM.
202
181
  test_files: []