From ed317c5bb3124e68fbb58688028645cc244efcb7 Mon Sep 17 00:00:00 2001 From: Pranav Raj S Date: Tue, 17 Aug 2021 01:44:16 +0530 Subject: [PATCH] feat: Use relay server for self-hosted mobile push notifications (#2757) --- .env.example | 4 ++++ .../notification/push_notification_service.rb | 13 +++++++++++++ lib/chatwoot_hub.rb | 12 +++++++++++- .../notification/push_notification_service_spec.rb | 7 +++++-- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index ea246c6f8..eb41a88f5 100644 --- a/.env.example +++ b/.env.example @@ -161,3 +161,7 @@ USE_INBOX_AVATAR_FOR_BOT=true # LETTER_OPENER=true # meant to be used in github codespaces # 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 diff --git a/app/services/notification/push_notification_service.rb b/app/services/notification/push_notification_service.rb index c3132f260..c98792ec7 100644 --- a/app/services/notification/push_notification_service.rb +++ b/app/services/notification/push_notification_service.rb @@ -9,6 +9,7 @@ class Notification::PushNotificationService notification_subscriptions.each do |subscription| send_browser_push(subscription) send_fcm_push(subscription) + send_push_via_chatwoot_hub(subscription) end end @@ -74,6 +75,18 @@ class Notification::PushNotificationService fcm = FCM.new(ENV['FCM_SERVER_KEY']) 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') end diff --git a/lib/chatwoot_hub.rb b/lib/chatwoot_hub.rb index b34d95bdb..c8ef38de0 100644 --- a/lib/chatwoot_hub.rb +++ b/lib/chatwoot_hub.rb @@ -2,6 +2,7 @@ class ChatwootHub BASE_URL = ENV['CHATWOOT_HUB_URL'] || 'https://hub.2.chatwoot.com' PING_URL = "#{BASE_URL}/ping".freeze REGISTRATION_URL = "#{BASE_URL}/instances".freeze + PUSH_NOTIFICATION_URL = "#{BASE_URL}/send_push".freeze EVENTS_URL = "#{BASE_URL}/events".freeze def self.installation_identifier @@ -51,7 +52,16 @@ class ChatwootHub rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e Rails.logger.info "Exception: #{e.message}" 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 def self.emit_event(event_name, event_data) diff --git a/spec/services/notification/push_notification_service_spec.rb b/spec/services/notification/push_notification_service_spec.rb index 44a5dbaf5..2e7911c84 100644 --- a/spec/services/notification/push_notification_service_spec.rb +++ b/spec/services/notification/push_notification_service_spec.rb @@ -20,17 +20,20 @@ describe Notification::PushNotificationService do described_class.new(notification: notification).perform expect(Webpush).to have_received(:payload_send) expect(FCM).not_to have_received(:new) - ENV['ENABLE_ACCOUNT_SIGNUP'] = nil + ENV['VAPID_PUBLIC_KEY'] = nil end it 'sends a fcm notification for firebase subscription' do ENV['FCM_SERVER_KEY'] = 'test' + ENV['ENABLE_PUSH_RELAY_SERVER'] = 'false' create(:notification_subscription, user: notification.user, subscription_type: 'fcm') described_class.new(notification: notification).perform expect(FCM).to have_received(:new) 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