discourse/app/services/push_notification_pusher.rb
Jeff Wong 91b31860a1
Feature: Push notifications for Android (#5792)
* Feature: Push notifications for Android

Notification config for desktop and mobile are merged.

Desktop notifications stay as they are for desktop views.

If mobile mode, push notifications are enabled.

Added push notification subscriptions in their own table, rather than through
custom fields.

Notification banner prompts appear for both mobile and desktop when enabled.
2018-05-04 15:31:48 -07:00

81 lines
2.5 KiB
Ruby

require_dependency 'webpush'
class PushNotificationPusher
def self.push(user, payload)
subscriptions(user).each do |subscription|
subscription = JSON.parse(subscription.data)
message = {
title: I18n.t(
"discourse_push_notifications.popup.#{Notification.types[payload[:notification_type]]}",
site_title: SiteSetting.title,
topic: payload[:topic_title],
username: payload[:username]
),
body: payload[:excerpt],
badge: get_badge,
icon: ActionController::Base.helpers.image_url("push-notifications/#{Notification.types[payload[:notification_type]]}.png"),
tag: "#{Discourse.current_hostname}-#{payload[:topic_id]}",
base_url: Discourse.base_url,
url: payload[:post_url],
hide_when_active: true
}
send_notification user, subscription, message
end
end
def self.subscriptions(user)
user.push_subscriptions
end
def self.clear_subscriptions(user)
user.push_subscriptions.clear
end
def self.subscribe(user, subscription, send_confirmation)
PushSubscription.create user: user, data: subscription.to_json
if send_confirmation == "true"
message = {
title: I18n.t("discourse_push_notifications.popup.confirm_title",
site_title: SiteSetting.title),
body: I18n.t("discourse_push_notifications.popup.confirm_body"),
icon: ActionController::Base.helpers.image_url("push-notifications/check.png"),
badge: get_badge,
tag: "#{Discourse.current_hostname}-subscription"
}
send_notification user, subscription, message
end
end
def self.unsubscribe(user, subscription)
PushSubscription.find_by(user: user, data: subscription.to_json)&.destroy
end
protected
def self.get_badge
return !SiteSetting.push_notifications_icon_url.blank? ?
SiteSetting.push_notifications_icon_url :
ActionController::Base.helpers.image_url("push-notifications/discourse.png")
end
def self.send_notification(user, subscription, message)
begin
response = Webpush.payload_send(
endpoint: subscription["endpoint"],
message: message.to_json,
p256dh: subscription.dig("keys", "p256dh"),
auth: subscription.dig("keys", "auth"),
vapid: {
subject: Discourse.base_url,
public_key: SiteSetting.vapid_public_key,
private_key: SiteSetting.vapid_private_key
}
)
rescue Webpush::InvalidSubscription => e
unsubscribe user, subscription
end
end
end