@@ -50,6 +50,7 @@ gem 'pg_search' | |||||
gem 'simple-navigation' | gem 'simple-navigation' | ||||
gem 'statsd-instrument' | gem 'statsd-instrument' | ||||
gem 'ruby-oembed', require: 'oembed' | gem 'ruby-oembed', require: 'oembed' | ||||
gem 'fcm' | |||||
gem 'react-rails' | gem 'react-rails' | ||||
gem 'browserify-rails' | gem 'browserify-rails' | ||||
@@ -127,6 +127,9 @@ GEM | |||||
execjs (2.7.0) | execjs (2.7.0) | ||||
fabrication (2.15.2) | fabrication (2.15.2) | ||||
fast_blank (1.0.0) | fast_blank (1.0.0) | ||||
fcm (0.0.2) | |||||
httparty | |||||
json | |||||
font-awesome-rails (4.6.3.1) | font-awesome-rails (4.6.3.1) | ||||
railties (>= 3.2, < 5.1) | railties (>= 3.2, < 5.1) | ||||
fuubar (2.1.1) | fuubar (2.1.1) | ||||
@@ -160,6 +163,8 @@ GEM | |||||
domain_name (~> 0.5) | domain_name (~> 0.5) | ||||
http-form_data (1.0.1) | http-form_data (1.0.1) | ||||
http_parser.rb (0.6.0) | http_parser.rb (0.6.0) | ||||
httparty (0.14.0) | |||||
multi_xml (>= 0.5.2) | |||||
httplog (0.3.2) | httplog (0.3.2) | ||||
colorize | colorize | ||||
i18n (0.7.0) | i18n (0.7.0) | ||||
@@ -207,6 +212,7 @@ GEM | |||||
mini_portile2 (2.1.0) | mini_portile2 (2.1.0) | ||||
minitest (5.10.1) | minitest (5.10.1) | ||||
multi_json (1.12.1) | multi_json (1.12.1) | ||||
multi_xml (0.6.0) | |||||
nio4r (1.2.1) | nio4r (1.2.1) | ||||
nokogiri (1.7.0.1) | nokogiri (1.7.0.1) | ||||
mini_portile2 (~> 2.1.0) | mini_portile2 (~> 2.1.0) | ||||
@@ -434,6 +440,7 @@ DEPENDENCIES | |||||
dotenv-rails | dotenv-rails | ||||
fabrication | fabrication | ||||
fast_blank | fast_blank | ||||
fcm | |||||
font-awesome-rails | font-awesome-rails | ||||
fuubar | fuubar | ||||
goldfinger | goldfinger | ||||
@@ -0,0 +1,18 @@ | |||||
# frozen_string_literal: true | |||||
class Api::V1::DevicesController < ApiController | |||||
before_action -> { doorkeeper_authorize! :read } | |||||
before_action :require_user! | |||||
respond_to :json | |||||
def register | |||||
Device.where(account: current_account, registration_id: params[:registration_id]).first_or_create!(account: current_account, registration_id: params[:registration_id]) | |||||
render_empty | |||||
end | |||||
def unregister | |||||
Device.where(account: current_account, registration_id: params[:registration_id]).delete_all | |||||
render_empty | |||||
end | |||||
end |
@@ -0,0 +1,7 @@ | |||||
# frozen_string_literal: true | |||||
class Device < ApplicationRecord | |||||
belongs_to :account | |||||
validates :account, :registration_id, presence: true | |||||
end |
@@ -10,6 +10,7 @@ class NotifyService < BaseService | |||||
create_notification | create_notification | ||||
send_email if email_enabled? | send_email if email_enabled? | ||||
send_push_notification | |||||
rescue ActiveRecord::RecordInvalid | rescue ActiveRecord::RecordInvalid | ||||
return | return | ||||
end | end | ||||
@@ -57,6 +58,10 @@ class NotifyService < BaseService | |||||
NotificationMailer.send(@notification.type, @recipient, @notification).deliver_later | NotificationMailer.send(@notification.type, @recipient, @notification).deliver_later | ||||
end | end | ||||
def send_push_notification | |||||
PushNotificationWorker.perform_async(@notification.id) | |||||
end | |||||
def email_enabled? | def email_enabled? | ||||
@recipient.user.settings.notification_emails[@notification.type] | @recipient.user.settings.notification_emails[@notification.type] | ||||
end | end | ||||
@@ -0,0 +1,28 @@ | |||||
# frozen_string_literal: true | |||||
class SendPushNotificationService < BaseService | |||||
def call(notification) | |||||
return if ENV['FCM_API_KEY'].blank? | |||||
devices = Device.where(account: notification.account).pluck(:registration_id) | |||||
fcm = FCM.new(ENV['FCM_API_KEY']) | |||||
response = fcm.send(devices, data: { notification_id: notification.id }, collapse_key: :notifications, priority: :high) | |||||
handle_response(response) | |||||
end | |||||
private | |||||
def handle_response(response) | |||||
update_canonical_ids(response[:canonical_ids]) if response[:canonical_ids] | |||||
remove_bad_ids(response[:not_registered_ids]) if response[:not_registered_ids] | |||||
end | |||||
def update_canonical_ids(ids) | |||||
ids.each { |pair| Device.find_by(registration_id: pair[:old]).update(registration_id: pair[:new]) } | |||||
end | |||||
def remove_bad_ids(bad_ids) | |||||
Device.where(registration_id: bad_ids).delete_all | |||||
end | |||||
end |
@@ -0,0 +1,11 @@ | |||||
# frozen_string_literal: true | |||||
class PushNotificationWorker | |||||
include Sidekiq::Worker | |||||
def perform(notification_id) | |||||
SendPushNotificationService.new.call(Notification.find(notification_id)) | |||||
rescue ActiveRecord::RecordNotFound | |||||
true | |||||
end | |||||
end |
@@ -118,6 +118,9 @@ Rails.application.routes.draw do | |||||
resources :blocks, only: [:index] | resources :blocks, only: [:index] | ||||
resources :favourites, only: [:index] | resources :favourites, only: [:index] | ||||
post '/devices/register', to: 'devices#register', as: :register_device | |||||
post '/devices/unregister', to: 'devices#unregister', as: :unregister_device | |||||
resources :follow_requests, only: [:index] do | resources :follow_requests, only: [:index] do | ||||
member do | member do | ||||
post :authorize | post :authorize | ||||
@@ -0,0 +1,13 @@ | |||||
class CreateDevices < ActiveRecord::Migration[5.0] | |||||
def change | |||||
create_table :devices do |t| | |||||
t.integer :account_id, null: false | |||||
t.string :registration_id, null: false, default: '' | |||||
t.timestamps | |||||
end | |||||
add_index :devices, :registration_id | |||||
add_index :devices, :account_id | |||||
end | |||||
end |
@@ -10,7 +10,7 @@ | |||||
# | # | ||||
# It's strongly recommended that you check this file into your version control system. | # It's strongly recommended that you check this file into your version control system. | ||||
ActiveRecord::Schema.define(version: 20170127165745) do | |||||
ActiveRecord::Schema.define(version: 20170129000348) do | |||||
# These are extensions that must be enabled in order to support this database | # These are extensions that must be enabled in order to support this database | ||||
enable_extension "plpgsql" | enable_extension "plpgsql" | ||||
@@ -54,6 +54,15 @@ ActiveRecord::Schema.define(version: 20170127165745) do | |||||
t.index ["account_id", "target_account_id"], name: "index_blocks_on_account_id_and_target_account_id", unique: true, using: :btree | t.index ["account_id", "target_account_id"], name: "index_blocks_on_account_id_and_target_account_id", unique: true, using: :btree | ||||
end | end | ||||
create_table "devices", force: :cascade do |t| | |||||
t.integer "account_id", null: false | |||||
t.string "registration_id", default: "", null: false | |||||
t.datetime "created_at", null: false | |||||
t.datetime "updated_at", null: false | |||||
t.index ["account_id"], name: "index_devices_on_account_id", using: :btree | |||||
t.index ["registration_id"], name: "index_devices_on_registration_id", using: :btree | |||||
end | |||||
create_table "domain_blocks", force: :cascade do |t| | create_table "domain_blocks", force: :cascade do |t| | ||||
t.string "domain", default: "", null: false | t.string "domain", default: "", null: false | ||||
t.datetime "created_at", null: false | t.datetime "created_at", null: false | ||||
@@ -0,0 +1,3 @@ | |||||
Fabricator(:device) do | |||||
registration_id "12345678" | |||||
end |
@@ -1,3 +1,3 @@ | |||||
Fabricator(:domain_block) do | Fabricator(:domain_block) do | ||||
domain "MyString" | |||||
domain "example.com" | |||||
end | end |
@@ -0,0 +1,5 @@ | |||||
require 'rails_helper' | |||||
RSpec.describe Device, type: :model do | |||||
end |