feat: Use relay server for self-hosted mobile push notifications (#2757)

This commit is contained in:
Pranav Raj S
2021-08-17 01:44:16 +05:30
committed by GitHub
parent 319412f6dc
commit ed317c5bb3
4 changed files with 33 additions and 3 deletions

View File

@@ -161,3 +161,7 @@ USE_INBOX_AVATAR_FOR_BOT=true
# LETTER_OPENER=true # LETTER_OPENER=true
# meant to be used in github codespaces # meant to be used in github codespaces
# WEBPACKER_DEV_SERVER_PUBLIC= # WEBPACKER_DEV_SERVER_PUBLIC=
# If you want to use official mobile app,
# the notifications would be relayed via a Chatwoot server
ENABLE_PUSH_RELAY_SERVER=true

View File

@@ -9,6 +9,7 @@ class Notification::PushNotificationService
notification_subscriptions.each do |subscription| notification_subscriptions.each do |subscription|
send_browser_push(subscription) send_browser_push(subscription)
send_fcm_push(subscription) send_fcm_push(subscription)
send_push_via_chatwoot_hub(subscription)
end end
end end
@@ -74,6 +75,18 @@ class Notification::PushNotificationService
fcm = FCM.new(ENV['FCM_SERVER_KEY']) fcm = FCM.new(ENV['FCM_SERVER_KEY'])
response = fcm.send([subscription.subscription_attributes['push_token']], fcm_options) response = fcm.send([subscription.subscription_attributes['push_token']], fcm_options)
remove_subscription_if_error(subscription, response)
end
def send_push_via_chatwoot_hub(subscription)
return if ENV['FCM_SERVER_KEY']
return unless ActiveModel::Type::Boolean.new.cast(ENV.fetch('ENABLE_PUSH_RELAY_SERVER', true))
return unless subscription.fcm?
ChatwootHub.send_browser_push([subscription.subscription_attributes['push_token']], fcm_options)
end
def remove_subscription_if_error(subscription, response)
subscription.destroy! if JSON.parse(response[:body])['results']&.first&.keys&.include?('error') subscription.destroy! if JSON.parse(response[:body])['results']&.first&.keys&.include?('error')
end end

View File

@@ -2,6 +2,7 @@ class ChatwootHub
BASE_URL = ENV['CHATWOOT_HUB_URL'] || 'https://hub.2.chatwoot.com' BASE_URL = ENV['CHATWOOT_HUB_URL'] || 'https://hub.2.chatwoot.com'
PING_URL = "#{BASE_URL}/ping".freeze PING_URL = "#{BASE_URL}/ping".freeze
REGISTRATION_URL = "#{BASE_URL}/instances".freeze REGISTRATION_URL = "#{BASE_URL}/instances".freeze
PUSH_NOTIFICATION_URL = "#{BASE_URL}/send_push".freeze
EVENTS_URL = "#{BASE_URL}/events".freeze EVENTS_URL = "#{BASE_URL}/events".freeze
def self.installation_identifier def self.installation_identifier
@@ -51,7 +52,16 @@ class ChatwootHub
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
Rails.logger.info "Exception: #{e.message}" Rails.logger.info "Exception: #{e.message}"
rescue StandardError => e rescue StandardError => e
Raven.capture_exception(e) Sentry.capture_exception(e)
end
def self.send_browser_push(fcm_token_list, fcm_options)
info = { fcm_token_list: fcm_token_list, fcm_options: fcm_options }
RestClient.post(PUSH_NOTIFICATION_URL, info.merge(instance_config).to_json, { content_type: :json, accept: :json })
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
Rails.logger.info "Exception: #{e.message}"
rescue StandardError => e
Sentry.capture_exception(e)
end end
def self.emit_event(event_name, event_data) def self.emit_event(event_name, event_data)

View File

@@ -20,17 +20,20 @@ describe Notification::PushNotificationService do
described_class.new(notification: notification).perform described_class.new(notification: notification).perform
expect(Webpush).to have_received(:payload_send) expect(Webpush).to have_received(:payload_send)
expect(FCM).not_to have_received(:new) expect(FCM).not_to have_received(:new)
ENV['ENABLE_ACCOUNT_SIGNUP'] = nil ENV['VAPID_PUBLIC_KEY'] = nil
end end
it 'sends a fcm notification for firebase subscription' do it 'sends a fcm notification for firebase subscription' do
ENV['FCM_SERVER_KEY'] = 'test' ENV['FCM_SERVER_KEY'] = 'test'
ENV['ENABLE_PUSH_RELAY_SERVER'] = 'false'
create(:notification_subscription, user: notification.user, subscription_type: 'fcm') create(:notification_subscription, user: notification.user, subscription_type: 'fcm')
described_class.new(notification: notification).perform described_class.new(notification: notification).perform
expect(FCM).to have_received(:new) expect(FCM).to have_received(:new)
expect(Webpush).not_to have_received(:payload_send) expect(Webpush).not_to have_received(:payload_send)
ENV['ENABLE_ACCOUNT_SIGNUP'] = nil
ENV['FCM_SERVER_KEY'] = nil
ENV['ENABLE_PUSH_RELAY_SERVER'] = nil
end end
end end
end end