1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
require "googleauth"
module Noticed
module DeliveryMethods
class Fcm < DeliveryMethod
required_option :credentials, :device_tokens, :json
def deliver
evaluate_option(:device_tokens).each do |device_token|
send_notification device_token
end
end
def send_notification(device_token)
post_request("https://fcm.googleapis.com/v1/projects/#{credentials[:project_id]}/messages:send",
headers: {authorization: "Bearer #{access_token}"},
json: format_notification(device_token))
rescue Noticed::ResponseUnsuccessful => exception
if bad_token?(exception.response) && config[:invalid_token]
notification.instance_exec(device_token, &config[:invalid_token])
elsif config[:error_handler]
notification.instance_exec(exception.response, &config[:error_handler])
else
raise
end
end
def format_notification(device_token)
method = config[:json]
if method.is_a?(Symbol) && event.respond_to?(method, true)
event.send(method, device_token)
else
notification.instance_exec(device_token, &method)
end
end
def bad_token?(response)
response.code == "404" || response.code == "400"
end
def credentials
@credentials ||= begin
value = evaluate_option(:credentials)
case value
when Hash
value
when Pathname
load_json(value)
when String
load_json(Rails.root.join(value))
else
raise ArgumentError, "FCM credentials must be a Hash, String, Pathname, or Symbol"
end
end
end
def load_json(path)
JSON.parse(File.read(path), symbolize_names: true)
end
def access_token
@authorizer ||= (evaluate_option(:authorizer) || Google::Auth::ServiceAccountCredentials).make_creds(
json_key_io: StringIO.new(credentials.to_json),
scope: "https://www.googleapis.com/auth/firebase.messaging"
)
@authorizer.fetch_access_token!["access_token"]
end
end
end
end
ActiveSupport.run_load_hooks :noticed_delivery_methods_fcm, Noticed::DeliveryMethods::Fcm
|