From d4ba7679dad980594bdf4752bb955b6876865cc2 Mon Sep 17 00:00:00 2001 From: Sebastian Sierra Date: Sat, 8 Dec 2012 01:33:04 -0200 Subject: [PATCH 1/5] Sending and processing responses to multiple registration ids --- README.textile | 2 +- gcm_on_rails.gemspec | 1 + lib/gcm_on_rails/app/models/gcm/device.rb | 4 ++-- lib/gcm_on_rails/app/models/gcm/notification.rb | 6 +++--- lib/gcm_on_rails/libs/connection.rb | 5 +++-- lib/generators/gcm_migrations_generator.rb | 5 +++-- .../create_gcm_devices_notifications.rb | 16 ++++++++++++++++ .../gcm_migrations/create_gcm_notifications.rb | 4 +--- 8 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb diff --git a/README.textile b/README.textile index c6426b1..c1705c2 100644 --- a/README.textile +++ b/README.textile @@ -84,7 +84,7 @@ Please note that a more detailed introduction to GCM is located at "http://devel $ rails console >> device = Gcm::Device.create(:registration_id => "XXXXXXXXXXXXXXXXXXXXXX") >> notification = Gcm::Notification.new - >> notification.device = device + >> notification.devices << device >> notification.collapse_key = "updates_available" >> notification.delay_while_idle = true >> notification.data = {:registration_ids => ["RegistrationID"], :data => {:message_text => "Get on cloud nine"}} diff --git a/gcm_on_rails.gemspec b/gcm_on_rails.gemspec index 5fc23ee..e452f37 100644 --- a/gcm_on_rails.gemspec +++ b/gcm_on_rails.gemspec @@ -35,6 +35,7 @@ Gem::Specification.new do |s| "lib/gcm_on_rails_tasks.rb", "lib/generators/gcm_migrations_generator.rb", "lib/generators/templates/gcm_migrations/create_gcm_devices.rb", + "lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb", "lib/generators/templates/gcm_migrations/create_gcm_notifications.rb" ] s.homepage = "http://github.com/dondeng/gcm_on_rails" diff --git a/lib/gcm_on_rails/app/models/gcm/device.rb b/lib/gcm_on_rails/app/models/gcm/device.rb index 165aeaa..579624d 100644 --- a/lib/gcm_on_rails/app/models/gcm/device.rb +++ b/lib/gcm_on_rails/app/models/gcm/device.rb @@ -13,7 +13,7 @@ class Gcm::Device < Gcm::Base attr_accessible :registration_id - has_many :notifications, :class_name => 'Gcm::Notification', :dependent => :destroy + has_and_belongs_to_many :notifications, :class_name => 'Gcm::Notification', :join_table => :gcm_devices_notifications validates_presence_of :registration_id validates_uniqueness_of :registration_id @@ -28,4 +28,4 @@ class Gcm::Device < Gcm::Base def set_last_registered_at self.last_registered_at = Time.now if self.last_registered_at.nil? end -end \ No newline at end of file +end diff --git a/lib/gcm_on_rails/app/models/gcm/notification.rb b/lib/gcm_on_rails/app/models/gcm/notification.rb index 8b144ac..7fc690b 100644 --- a/lib/gcm_on_rails/app/models/gcm/notification.rb +++ b/lib/gcm_on_rails/app/models/gcm/notification.rb @@ -5,7 +5,7 @@ class Gcm::Notification < Gcm::Base extend ::ActionView::Helpers::TextHelper serialize :data - belongs_to :device, :class_name => 'Gcm::Device' + has_and_belongs_to_many :devices, :class_name => 'Gcm::Device', :join_table => :gcm_devices_notifications validates_presence_of :collapse_key if :time_to_live? class << self @@ -28,7 +28,7 @@ class << self # {:message=>"{\"multicast_id\":6085691036338669615,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\":\"0:1349723376618187%d702725e98d39af3\"}]}", :code=>200} # # - def send_notifications(notifications = Gcm::Notification.all(:conditions => {:sent_at => nil}, :joins => :device, :readonly => false)) + def send_notifications(notifications = Gcm::Notification.all(:conditions => {:sent_at => nil}, :include => :devices, :readonly => false)) if configatron.gcm_on_rails.delivery_format and configatron.gcm_on_rails.delivery_format == 'plain_text' format = "plain_text" @@ -97,4 +97,4 @@ def send_notifications(notifications = Gcm::Notification.all(:conditions => {:se end end end -end \ No newline at end of file +end diff --git a/lib/gcm_on_rails/libs/connection.rb b/lib/gcm_on_rails/libs/connection.rb index c240329..bb5f6fc 100644 --- a/lib/gcm_on_rails/libs/connection.rb +++ b/lib/gcm_on_rails/libs/connection.rb @@ -12,13 +12,14 @@ def send_notification(notification, api_key, format) data = notification.data.merge({:collapse_key => notification.collapse_key}) unless notification.collapse_key.nil? data = data.merge({:delay_while_idle => notification.delay_while_idle}) unless notification.delay_while_idle.nil? data = data.merge({:time_to_live => notification.time_to_live}) unless notification.time_to_live.nil? + data = data.merge({:registration_ids => notification.devices.map{ |d| d.registration_id } }) data = data.to_json else #plain text format headers = {"Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8", "Authorization" => "key=#{api_key}"} post_data = notification.data[:data].map{|k, v| "&data.#{k}=#{URI.escape(v)}".reduce{|k, v| k + v}}[0] - extra_data = "registration_id=#{notification.data[:registration_ids][0]}" + extra_data = "registration_ids=#{notification.devices.map{ |d| d.registration_id }}" extra_data = "#{extra_data}&collapse_key=#{notification.collapse_key}" unless notification.collapse_key.nil? extra_data = "#{extra_data}&delay_while_idle=1" if notification.delay_while_idle data = "#{extra_data}#{post_data}" @@ -40,4 +41,4 @@ def open end end end -end \ No newline at end of file +end diff --git a/lib/generators/gcm_migrations_generator.rb b/lib/generators/gcm_migrations_generator.rb index a8d95a3..0b43c9e 100644 --- a/lib/generators/gcm_migrations_generator.rb +++ b/lib/generators/gcm_migrations_generator.rb @@ -18,7 +18,8 @@ def self.base_root def create_migrations templates = { 'create_gcm_devices.rb' => 'db/migrate/create_gcm_devices.rb', - 'create_gcm_notifications.rb' => 'db/migrate/create_gcm_notifications.rb' + 'create_gcm_notifications.rb' => 'db/migrate/create_gcm_notifications.rb', + 'create_gcm_devices_notifications.rb' => 'db/migrate/create_gcm_devices_notifications.rb' } templates.each_pair do |name, path| @@ -29,4 +30,4 @@ def create_migrations end end end -end # GcmMigrationsGenerator \ No newline at end of file +end # GcmMigrationsGenerator diff --git a/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb b/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb new file mode 100644 index 0000000..1abb1ff --- /dev/null +++ b/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb @@ -0,0 +1,16 @@ +class CreateGcmDevicesNotifications < ActiveRecord::Migration # :nodoc: + + def self.up + + create_table :gcm_devices_notifications, :id => false do |t| + t.integer :device_id, :null => false + t.integer :notification_id, :null => false + end + + add_index :gcm_devices_notifications, [:device_id, :notification_id], :unique => true + end + + def self.down + drop_table :gcm_devices_notifications + end +end diff --git a/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb b/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb index 72b49ab..fb34be0 100644 --- a/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb +++ b/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb @@ -3,7 +3,6 @@ class CreateGcmNotifications < ActiveRecord::Migration # :nodoc: def self.up create_table :gcm_notifications do |t| - t.integer :device_id, :null => false t.string :collapse_key t.text :data t.boolean :delay_while_idle @@ -12,10 +11,9 @@ def self.up t.timestamps end - add_index :gcm_notifications, :device_id end def self.down drop_table :gcm_notifications end -end \ No newline at end of file +end From e2a3a93a96723ef564596badfcbdb524bfeb9089 Mon Sep 17 00:00:00 2001 From: Sebastian Sierra Date: Sun, 24 Feb 2013 21:50:59 -0200 Subject: [PATCH 2/5] Updated rake task in order to deliver only some type of notifications --- README.textile | 17 ++- VERSION | 2 +- gcm_on_rails.gemspec | 2 +- .../app/models/gcm/notification.rb | 122 ++++++++++-------- lib/gcm_on_rails/tasks/gcm.rake | 9 +- .../create_gcm_notifications.rb | 1 + 6 files changed, 90 insertions(+), 63 deletions(-) diff --git a/README.textile b/README.textile index c1705c2..54a76ee 100644 --- a/README.textile +++ b/README.textile @@ -87,11 +87,22 @@ Please note that a more detailed introduction to GCM is located at "http://devel >> notification.devices << device >> notification.collapse_key = "updates_available" >> notification.delay_while_idle = true - >> notification.data = {:registration_ids => ["RegistrationID"], :data => {:message_text => "Get on cloud nine"}} + >> notification.data = {:data => {:message_text => "Get on cloud nine"}} + >> notification.notification_type = "urgent" >> notification.save +In this version you don't have to add the registration ids of the devices you're going to send the notifications. You just add them to notifications_devices relation by doing: +

+  >> notification.devices << device
+
+as it was shown in the previous example. + +The following Rake task can then be used to deliver urgent notifications: +

+  $ rake gcm:notifications:deliver["urgent"]
+
-The following Rake task can then be used to deliver notifications: +If you want to deliver every notification that wasn't delivered yet:

   $ rake gcm:notifications:deliver
 
@@ -128,7 +139,7 @@ h2. To-Do's: in the message object of the return json. - Tests, tests then some more tests. These need to be implemented. -- Implement "broadcasting" sending and processing responses to multiple registration id's within one request. Currently only one message to a single registration id is implemented. +- Implement some sort of mechanism to update from previous versions Released under the MIT license. diff --git a/VERSION b/VERSION index 7693c96..845639e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.3 \ No newline at end of file +0.1.4 diff --git a/gcm_on_rails.gemspec b/gcm_on_rails.gemspec index e452f37..082e025 100644 --- a/gcm_on_rails.gemspec +++ b/gcm_on_rails.gemspec @@ -5,7 +5,7 @@ Gem::Specification.new do |s| s.name = "gcm_on_rails" - s.version = "0.1.3" + s.version = "0.1.4" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Dennis Ondeng"] diff --git a/lib/gcm_on_rails/app/models/gcm/notification.rb b/lib/gcm_on_rails/app/models/gcm/notification.rb index 7fc690b..4c3d8c7 100644 --- a/lib/gcm_on_rails/app/models/gcm/notification.rb +++ b/lib/gcm_on_rails/app/models/gcm/notification.rb @@ -28,73 +28,83 @@ class << self # {:message=>"{\"multicast_id\":6085691036338669615,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\":\"0:1349723376618187%d702725e98d39af3\"}]}", :code=>200} # # + def send_notifications_by_type(notification_type, notifications = Gcm::Notification.all(:conditions => {:sent_at => nil, notification_type: notification_type}, :include => :devices, :readonly => false)) + notify(notifications) + end + def send_notifications(notifications = Gcm::Notification.all(:conditions => {:sent_at => nil}, :include => :devices, :readonly => false)) + notify(notifications) + end - if configatron.gcm_on_rails.delivery_format and configatron.gcm_on_rails.delivery_format == 'plain_text' - format = "plain_text" - else - format = "json" - end + private - unless notifications.nil? || notifications.empty? - api_key = Gcm::Connection.open - if api_key - notifications.each do |notification| + def notify notifications - logger.info "notification = #{notification.inspect}" - response = Gcm::Connection.send_notification(notification, api_key, format) - logger.info "response = #{response.inspect}" + if configatron.gcm_on_rails.delivery_format and configatron.gcm_on_rails.delivery_format == 'plain_text' + format = "plain_text" + else + format = "json" + end - if response[:code] == 200 - if response[:message].nil? - # TODO - Making this assumption might not be right. HTTP status code 200 does not really signify success - # if Gcm servers returned nil for the message - error = "success" - elsif format == "json" - error = "" - message_data = JSON.parse response[:message] - success = message_data['success'] - error = message_data['results'][0]['error'] if success == 0 - elsif format == "plain_text" #format is plain text - message_data = response[:message] - error = response[:message].split('=')[1] - end + unless notifications.nil? || notifications.empty? + api_key = Gcm::Connection.open + if api_key + notifications.each do |notification| + logger.info "notification = #{notification.inspect}" + response = Gcm::Connection.send_notification(notification, api_key, format) + logger.info "response = #{response.inspect}" - case error - when "MissingRegistration" - ex = Gcm::Errors::MissingRegistration.new(response[:message]) - logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}") - notification.device.destroy - when "InvalidRegistration" - ex = Gcm::Errors::InvalidRegistration.new(response[:message]) - logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}") - notification.device.destroy - when "MismatchedSenderId" - ex = Gcm::Errors::MismatchSenderId.new(response[:message]) - logger.warn(ex.message) - when "NotRegistered" - ex = Gcm::Errors::NotRegistered.new(response[:message]) - logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}") - notification.device.destroy - when "MessageTooBig" - ex = Gcm::Errors::MessageTooBig.new(response[:message]) - logger.warn(ex.message) - else - notification.sent_at = Time.now - notification.save! + if response[:code] == 200 + if response[:message].nil? + # TODO - Making this assumption might not be right. HTTP status code 200 does not really signify success + # if Gcm servers returned nil for the message + error = "success" + elsif format == "json" + error = "" + message_data = JSON.parse response[:message] + success = message_data['success'] + error = message_data['results'][0]['error'] if success == 0 + elsif format == "plain_text" #format is plain text + message_data = response[:message] + error = response[:message].split('=')[1] + end + + + case error + when "MissingRegistration" + ex = Gcm::Errors::MissingRegistration.new(response[:message]) + logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}") + notification.device.destroy + when "InvalidRegistration" + ex = Gcm::Errors::InvalidRegistration.new(response[:message]) + logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}") + notification.device.destroy + when "MismatchedSenderId" + ex = Gcm::Errors::MismatchSenderId.new(response[:message]) + logger.warn(ex.message) + when "NotRegistered" + ex = Gcm::Errors::NotRegistered.new(response[:message]) + logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}") + notification.device.destroy + when "MessageTooBig" + ex = Gcm::Errors::MessageTooBig.new(response[:message]) + logger.warn(ex.message) + else + #notification.sent_at = Time.now + notification.save! + end + elsif response[:code] == 401 + raise Gcm::Errors::InvalidAuthToken.new(message_data) + elsif response[:code] == 503 + raise Gcm::Errors::ServiceUnavailable.new(message_data) + elsif response[:code] == 500 + raise Gcm::Errors::InternalServerError.new(message_data) end - elsif response[:code] == 401 - raise Gcm::Errors::InvalidAuthToken.new(message_data) - elsif response[:code] == 503 - raise Gcm::Errors::ServiceUnavailable.new(message_data) - elsif response[:code] == 500 - raise Gcm::Errors::InternalServerError.new(message_data) - end + end end end end - end end end diff --git a/lib/gcm_on_rails/tasks/gcm.rake b/lib/gcm_on_rails/tasks/gcm.rake index 1df4faa..a645282 100644 --- a/lib/gcm_on_rails/tasks/gcm.rake +++ b/lib/gcm_on_rails/tasks/gcm.rake @@ -2,8 +2,13 @@ namespace :gcm do namespace :notifications do desc "Deliver all unsent Gcm notifications." - task :deliver => [:environment] do - Gcm::Notification.send_notifications + task :deliver, [:type] => [:environment] do |t, args| + if args.type.nil? + Gcm::Notification.send_notifications + else + Gcm::Notification.send_notifications_by_type(args.type) + end end + end end diff --git a/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb b/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb index fb34be0..fda6e58 100644 --- a/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb +++ b/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb @@ -8,6 +8,7 @@ def self.up t.boolean :delay_while_idle t.datetime :sent_at t.integer :time_to_live + t.string :notification_type t.timestamps end From c9a43851bbd47a0d762e453092539ddc60e4d84f Mon Sep 17 00:00:00 2001 From: Sebastian Sierra Date: Mon, 25 Feb 2013 19:01:26 -0200 Subject: [PATCH 3/5] Create generator to upgrade from previous versions --- README.textile | 13 +++++--- lib/gcm_on_rails/tasks/gcm.rake | 2 +- lib/generators/gcm_upgrade_generator.rb | 31 +++++++++++++++++++ .../add_notification_type_column.rb | 9 ++++++ .../create_gcm_devices_notifications.rb | 1 - .../remove_device_notifications_column.rb | 9 ++++++ 6 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 lib/generators/gcm_upgrade_generator.rb create mode 100644 lib/generators/templates/gcm_migrations/add_notification_type_column.rb create mode 100644 lib/generators/templates/gcm_migrations/remove_device_notifications_column.rb diff --git a/README.textile b/README.textile index 54a76ee..b0914f6 100644 --- a/README.textile +++ b/README.textile @@ -70,10 +70,15 @@ That's it, you are now ready to start creating notifications. h2. Upgrade Notes: -When upgrading to a new version of Gcm on Rails, you should alwasy run: -

-  $ rails generate gcm_migrations
-
+h3. Upgrading to 0.1.4 + +When upgrading from version 0.1.3 to 0.1.4 you should run: +
$ rails generate gcm_upgrade
+ +h3. Upgrading to <= 0.1.3 + +When upgrading to a new version of Gcm on Rails, you should always run: +
$ rails generate gcm_migrations
That way you are ensured to have the latest version of the database tables needed. diff --git a/lib/gcm_on_rails/tasks/gcm.rake b/lib/gcm_on_rails/tasks/gcm.rake index a645282..efeaa15 100644 --- a/lib/gcm_on_rails/tasks/gcm.rake +++ b/lib/gcm_on_rails/tasks/gcm.rake @@ -1,7 +1,7 @@ namespace :gcm do namespace :notifications do - desc "Deliver all unsent Gcm notifications." + desc "Deliver unsent Gcm notifications of the specified type." task :deliver, [:type] => [:environment] do |t, args| if args.type.nil? Gcm::Notification.send_notifications diff --git a/lib/generators/gcm_upgrade_generator.rb b/lib/generators/gcm_upgrade_generator.rb new file mode 100644 index 0000000..0875854 --- /dev/null +++ b/lib/generators/gcm_upgrade_generator.rb @@ -0,0 +1,31 @@ +require 'rails/generators/active_record' +# Generates the migrations necessary for upgrading Gcm on Rails. +# +# $ ruby script/generate gcm_upgrade +class GcmUpgradeGenerator < Rails::Generators::Base + include Rails::Generators::Migration + extend ActiveRecord::Generators::Migration + + # Set the current directory as base for the inherited generators. + def self.base_root + File.dirname(__FILE__) + end + + source_root File.expand_path('../templates/gcm_migrations', __FILE__) + + def create_migrations + templates = { + 'remove_device_notifications_column.rb' => 'db/migrate/remove_device_notifications_column.rb', + 'create_gcm_devices_notifications.rb' => 'db/migrate/create_gcm_devices_notifications.rb', + 'add_notification_type_column.rb' => 'db/migrate/add_notification_type_column.rb' + } + + templates.each_pair do |name, path| + begin + migration_template(name, path) + rescue => err + puts "WARNING: #{err.message}" + end + end + end +end # GcmUpgradeGenerator diff --git a/lib/generators/templates/gcm_migrations/add_notification_type_column.rb b/lib/generators/templates/gcm_migrations/add_notification_type_column.rb new file mode 100644 index 0000000..332d07d --- /dev/null +++ b/lib/generators/templates/gcm_migrations/add_notification_type_column.rb @@ -0,0 +1,9 @@ +class AddNotificationTypeColumn < ActiveRecord::Migration # :nodoc: + def self.up + add_column :gcm_notifications, :notification_type, :string + end + + def self.down + remove_column :gcm_notifications, :notification_type + end +end diff --git a/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb b/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb index 1abb1ff..9bf3791 100644 --- a/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb +++ b/lib/generators/templates/gcm_migrations/create_gcm_devices_notifications.rb @@ -1,7 +1,6 @@ class CreateGcmDevicesNotifications < ActiveRecord::Migration # :nodoc: def self.up - create_table :gcm_devices_notifications, :id => false do |t| t.integer :device_id, :null => false t.integer :notification_id, :null => false diff --git a/lib/generators/templates/gcm_migrations/remove_device_notifications_column.rb b/lib/generators/templates/gcm_migrations/remove_device_notifications_column.rb new file mode 100644 index 0000000..4425d45 --- /dev/null +++ b/lib/generators/templates/gcm_migrations/remove_device_notifications_column.rb @@ -0,0 +1,9 @@ +class RemoveDeviceNotificationsColumn < ActiveRecord::Migration # :nodoc: + def self.up + remove_column :gcm_notifications, :device_id + end + + def self.down + add_column :gcm_notifications, :device_id, :null => false + end +end From 16b29d08fc08805817016d971bb6e195a7ce7aaf Mon Sep 17 00:00:00 2001 From: Sebastian Sierra Date: Mon, 25 Feb 2013 19:18:50 -0200 Subject: [PATCH 4/5] Updated README --- README.textile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.textile b/README.textile index b0914f6..4191677 100644 --- a/README.textile +++ b/README.textile @@ -73,11 +73,14 @@ h2. Upgrade Notes: h3. Upgrading to 0.1.4 When upgrading from version 0.1.3 to 0.1.4 you should run: +
$ rails generate gcm_upgrade
+ h3. Upgrading to <= 0.1.3 When upgrading to a new version of Gcm on Rails, you should always run: +
$ rails generate gcm_migrations
That way you are ensured to have the latest version of the database tables needed. From d2597f7ad2aba46f765d81b400b082ad3180e498 Mon Sep 17 00:00:00 2001 From: Waclaw Luczak Date: Mon, 11 Mar 2013 15:48:11 +0100 Subject: [PATCH 5/5] Update notification.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uncomment notification.sent_at = Time.now --- lib/gcm_on_rails/app/models/gcm/notification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gcm_on_rails/app/models/gcm/notification.rb b/lib/gcm_on_rails/app/models/gcm/notification.rb index 4c3d8c7..4733510 100644 --- a/lib/gcm_on_rails/app/models/gcm/notification.rb +++ b/lib/gcm_on_rails/app/models/gcm/notification.rb @@ -91,7 +91,7 @@ def notify notifications ex = Gcm::Errors::MessageTooBig.new(response[:message]) logger.warn(ex.message) else - #notification.sent_at = Time.now + notification.sent_at = Time.now notification.save! end elsif response[:code] == 401