presskit-apn_on_rails 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +2 -0
- data/.specification +80 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +47 -0
- data/LICENSE +21 -0
- data/README +179 -0
- data/README.textile +209 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/autotest/discover.rb +1 -0
- data/generators/apn_migrations_generator.rb +31 -0
- data/generators/templates/apn_migrations/001_create_apn_devices.rb +13 -0
- data/generators/templates/apn_migrations/002_create_apn_notifications.rb +23 -0
- data/generators/templates/apn_migrations/003_alter_apn_devices.rb +25 -0
- data/generators/templates/apn_migrations/004_create_apn_apps.rb +18 -0
- data/generators/templates/apn_migrations/005_create_groups.rb +23 -0
- data/generators/templates/apn_migrations/006_alter_apn_groups.rb +11 -0
- data/generators/templates/apn_migrations/007_create_device_groups.rb +27 -0
- data/generators/templates/apn_migrations/008_create_apn_group_notifications.rb +23 -0
- data/generators/templates/apn_migrations/009_create_pull_notifications.rb +16 -0
- data/generators/templates/apn_migrations/010_alter_apn_notifications.rb +21 -0
- data/generators/templates/apn_migrations/011_make_device_token_index_nonunique.rb +11 -0
- data/generators/templates/apn_migrations/012_add_launch_notification_to_apn_pull_notifications.rb +9 -0
- data/lib/apn_on_rails.rb +4 -0
- data/lib/apn_on_rails/apn_on_rails.rb +81 -0
- data/lib/apn_on_rails/app/models/apn/app.rb +152 -0
- data/lib/apn_on_rails/app/models/apn/base.rb +9 -0
- data/lib/apn_on_rails/app/models/apn/device.rb +50 -0
- data/lib/apn_on_rails/app/models/apn/device_grouping.rb +16 -0
- data/lib/apn_on_rails/app/models/apn/group.rb +12 -0
- data/lib/apn_on_rails/app/models/apn/group_notification.rb +79 -0
- data/lib/apn_on_rails/app/models/apn/notification.rb +93 -0
- data/lib/apn_on_rails/app/models/apn/pull_notification.rb +28 -0
- data/lib/apn_on_rails/libs/connection.rb +70 -0
- data/lib/apn_on_rails/libs/feedback.rb +39 -0
- data/lib/apn_on_rails/tasks/apn.rake +30 -0
- data/lib/apn_on_rails/tasks/db.rake +19 -0
- data/lib/apn_on_rails_tasks.rb +3 -0
- data/presskit-apn_on_rails.gemspec +144 -0
- data/spec/active_record/setup_ar.rb +19 -0
- data/spec/apn_on_rails/app/models/apn/app_spec.rb +230 -0
- data/spec/apn_on_rails/app/models/apn/device_spec.rb +60 -0
- data/spec/apn_on_rails/app/models/apn/group_notification_spec.rb +66 -0
- data/spec/apn_on_rails/app/models/apn/notification_spec.rb +71 -0
- data/spec/apn_on_rails/app/models/apn/pull_notification_spec.rb +100 -0
- data/spec/apn_on_rails/libs/connection_spec.rb +40 -0
- data/spec/apn_on_rails/libs/feedback_spec.rb +43 -0
- data/spec/extensions/string.rb +10 -0
- data/spec/factories/app_factory.rb +27 -0
- data/spec/factories/device_factory.rb +29 -0
- data/spec/factories/device_grouping_factory.rb +22 -0
- data/spec/factories/group_factory.rb +27 -0
- data/spec/factories/group_notification_factory.rb +22 -0
- data/spec/factories/notification_factory.rb +22 -0
- data/spec/factories/pull_notification_factory.rb +22 -0
- data/spec/fixtures/hexa.bin +1 -0
- data/spec/fixtures/message_for_sending.bin +0 -0
- data/spec/rails_root/config/apple_push_notification_development.pem +19 -0
- data/spec/spec_helper.rb +55 -0
- metadata +282 -0
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "fireinc-apn_on_rails"
|
16
|
+
gem.summary = %Q{Apple Push Notifications on Rails}
|
17
|
+
|
18
|
+
gem.description = %Q{APN on Rails is a Ruby on Rails gem that allows you to
|
19
|
+
easily add Apple Push Notification (iPhone) support to your Rails application.
|
20
|
+
This version includes an association between an assumed User model and APN::Device
|
21
|
+
}
|
22
|
+
|
23
|
+
gem.email = "caleb@fire.coop"
|
24
|
+
gem.homepage = "http://github.com/calebhaye/apn_on_rails"
|
25
|
+
gem.authors = ["markbates", "Rebecca Nesson", "Caleb Adam Haye"]
|
26
|
+
end
|
27
|
+
#Jeweler::RubygemsDotOrgsTasks.new
|
28
|
+
|
29
|
+
require 'rspec/core'
|
30
|
+
require 'rspec/core/rake_task'
|
31
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
32
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
33
|
+
end
|
34
|
+
|
35
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
36
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
37
|
+
spec.rcov = true
|
38
|
+
end
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "apn #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.2.5
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rails_generator'
|
2
|
+
# Generates the migrations necessary for APN on Rails.
|
3
|
+
# This should be run upon install and upgrade of the
|
4
|
+
# APN on Rails gem.
|
5
|
+
#
|
6
|
+
# $ ruby script/generate apn_migrations
|
7
|
+
class ApnMigrationsGenerator < Rails::Generator::Base
|
8
|
+
|
9
|
+
def manifest # :nodoc:
|
10
|
+
record do |m|
|
11
|
+
timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
12
|
+
db_migrate_path = File.join('db', 'migrate')
|
13
|
+
|
14
|
+
m.directory(db_migrate_path)
|
15
|
+
|
16
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'templates', 'apn_migrations', '*.rb')).sort.each_with_index do |f, i|
|
17
|
+
f = File.basename(f)
|
18
|
+
f.match(/\d+\_(.+)/)
|
19
|
+
timestamp = timestamp.succ
|
20
|
+
if Dir.glob(File.join(db_migrate_path, "*_#{$1}")).empty?
|
21
|
+
m.file(File.join('apn_migrations', f),
|
22
|
+
File.join(db_migrate_path, "#{timestamp}_#{$1}"),
|
23
|
+
{:collision => :skip})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end # record
|
28
|
+
|
29
|
+
end # manifest
|
30
|
+
|
31
|
+
end # ApnMigrationsGenerator
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateApnNotifications < ActiveRecord::Migration # :nodoc:
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
|
5
|
+
create_table :apn_notifications do |t|
|
6
|
+
t.integer :device_id, :null => false
|
7
|
+
t.integer :errors_nb, :default => 0 # used for storing errors from apple feedbacks
|
8
|
+
t.string :device_language, :size => 5 # if you don't want to send localized strings
|
9
|
+
t.string :sound
|
10
|
+
t.string :alert, :size => 150
|
11
|
+
t.integer :badge
|
12
|
+
t.datetime :sent_at
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :apn_notifications, :device_id
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.down
|
20
|
+
drop_table :apn_notifications
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class AlterApnDevices < ActiveRecord::Migration # :nodoc:
|
2
|
+
|
3
|
+
module APN # :nodoc:
|
4
|
+
class Device < ActiveRecord::Base # :nodoc:
|
5
|
+
set_table_name 'apn_devices'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.up
|
10
|
+
add_column :apn_devices, :last_registered_at, :datetime
|
11
|
+
|
12
|
+
APN::Device.all.each do |device|
|
13
|
+
device.last_registered_at = device.created_at
|
14
|
+
device.save!
|
15
|
+
end
|
16
|
+
change_column :apn_devices, :token, :string, :size => 100, :null => false
|
17
|
+
add_index :apn_devices, :token, :unique => true
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.down
|
21
|
+
change_column :apn_devices, :token, :string
|
22
|
+
remove_index :apn_devices, :column => :token
|
23
|
+
remove_column :apn_devices, :last_registered_at
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateApnApps < ActiveRecord::Migration # :nodoc:
|
2
|
+
def self.up
|
3
|
+
create_table :apn_apps do |t|
|
4
|
+
t.text :apn_dev_cert
|
5
|
+
t.text :apn_prod_cert
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_column :apn_devices, :app_id, :integer
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
drop_table :apn_apps
|
16
|
+
remove_column :apn_devices, :app_id
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateGroups < ActiveRecord::Migration # :nodoc:
|
2
|
+
def self.up
|
3
|
+
create_table :apn_groups do |t|
|
4
|
+
t.column :name, :string
|
5
|
+
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :apn_devices_apn_groups, :id => false do |t|
|
10
|
+
t.column :group_id, :integer
|
11
|
+
t.column :device_id, :integer
|
12
|
+
end
|
13
|
+
|
14
|
+
add_index :apn_devices_apn_groups, [:group_id, :device_id]
|
15
|
+
add_index :apn_devices_apn_groups, :device_id
|
16
|
+
add_index :apn_devices_apn_groups, :group_id
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.down
|
20
|
+
drop_table :apn_groups
|
21
|
+
drop_table :apn_devices_apn_groups
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class CreateDeviceGroups < ActiveRecord::Migration # :nodoc:
|
2
|
+
def self.up
|
3
|
+
drop_table :apn_devices_apn_groups
|
4
|
+
|
5
|
+
create_table :apn_device_groupings do |t|
|
6
|
+
t.column :group_id, :integer
|
7
|
+
t.column :device_id, :integer
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :apn_device_groupings, [:group_id, :device_id]
|
11
|
+
add_index :apn_device_groupings, :device_id
|
12
|
+
add_index :apn_device_groupings, :group_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :apn_device_groupings
|
17
|
+
|
18
|
+
create_table :apn_devices_apn_groups, :id => false do |t|
|
19
|
+
t.column :group_id, :integer
|
20
|
+
t.column :device_id, :integer
|
21
|
+
end
|
22
|
+
|
23
|
+
add_index :apn_devices_apn_groups, [:group_id, :device_id]
|
24
|
+
add_index :apn_devices_apn_groups, :device_id
|
25
|
+
add_index :apn_devices_apn_groups, :group_id
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateApnGroupNotifications < ActiveRecord::Migration # :nodoc:
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
|
5
|
+
create_table :apn_group_notifications do |t|
|
6
|
+
t.integer :group_id, :null => false
|
7
|
+
t.string :device_language, :size => 5 # if you don't want to send localized strings
|
8
|
+
t.string :sound
|
9
|
+
t.string :alert, :size => 150
|
10
|
+
t.integer :badge
|
11
|
+
t.text :custom_properties
|
12
|
+
t.datetime :sent_at
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :apn_group_notifications, :group_id
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.down
|
20
|
+
drop_table :apn_group_notifications
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreatePullNotifications < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :apn_pull_notifications do |t|
|
4
|
+
t.integer :app_id
|
5
|
+
t.string :title
|
6
|
+
t.string :content
|
7
|
+
t.string :link
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :apn_pull_notifications
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class AlterApnNotifications < ActiveRecord::Migration # :nodoc:
|
2
|
+
|
3
|
+
module APN # :nodoc:
|
4
|
+
class Notification < ActiveRecord::Base # :nodoc:
|
5
|
+
set_table_name 'apn_notifications'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.up
|
10
|
+
unless APN::Notification.column_names.include?("custom_properties")
|
11
|
+
add_column :apn_notifications, :custom_properties, :text
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
if APN::Notification.column_names.include?("custom_properties")
|
17
|
+
remove_column :apn_notifications, :custom_properties
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class MakeDeviceTokenIndexNonunique < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
remove_index :apn_devices, :column => :token
|
4
|
+
add_index :apn_devices, :token
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_index :apn_devices, :column => :token
|
9
|
+
add_index :apn_devices, :token, :unique => true
|
10
|
+
end
|
11
|
+
end
|
data/lib/apn_on_rails.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'openssl'
|
3
|
+
require 'configatron'
|
4
|
+
|
5
|
+
rails_root = File.join(FileUtils.pwd, 'rails_root')
|
6
|
+
if defined?(RAILS_ROOT)
|
7
|
+
rails_root = RAILS_ROOT
|
8
|
+
end
|
9
|
+
|
10
|
+
rails_env = 'development'
|
11
|
+
if defined?(RAILS_ENV)
|
12
|
+
rails_env = RAILS_ENV
|
13
|
+
end
|
14
|
+
|
15
|
+
configatron.apn.set_default(:passphrase, '')
|
16
|
+
configatron.apn.set_default(:port, 2195)
|
17
|
+
|
18
|
+
configatron.apn.feedback.set_default(:passphrase, configatron.apn.passphrase)
|
19
|
+
configatron.apn.feedback.set_default(:port, 2196)
|
20
|
+
|
21
|
+
if rails_env == 'production'
|
22
|
+
configatron.apn.set_default(:host, 'gateway.push.apple.com')
|
23
|
+
configatron.apn.set_default(:cert, File.join(rails_root, 'config', 'apple_push_notification_production.pem'))
|
24
|
+
|
25
|
+
configatron.apn.feedback.set_default(:host, 'feedback.push.apple.com')
|
26
|
+
configatron.apn.feedback.set_default(:cert, configatron.apn.cert)
|
27
|
+
else
|
28
|
+
configatron.apn.set_default(:host, 'gateway.sandbox.push.apple.com')
|
29
|
+
configatron.apn.set_default(:cert, File.join(rails_root, 'config', 'apple_push_notification_development.pem'))
|
30
|
+
|
31
|
+
configatron.apn.feedback.set_default(:host, 'feedback.sandbox.push.apple.com')
|
32
|
+
configatron.apn.feedback.set_default(:cert, configatron.apn.cert)
|
33
|
+
end
|
34
|
+
|
35
|
+
module APN # :nodoc:
|
36
|
+
|
37
|
+
module Errors # :nodoc:
|
38
|
+
|
39
|
+
# Raised when a notification message to Apple is longer than 256 bytes.
|
40
|
+
class ExceededMessageSizeError < StandardError
|
41
|
+
|
42
|
+
def initialize(message) # :nodoc:
|
43
|
+
super("The maximum size allowed for a notification payload is 256 bytes: '#{message}'")
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
class MissingCertificateError < StandardError
|
49
|
+
def initialize
|
50
|
+
super("This app has no certificate")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end # Errors
|
55
|
+
|
56
|
+
end # APN
|
57
|
+
|
58
|
+
base = File.join(File.dirname(__FILE__), 'app', 'models', 'apn', 'base.rb')
|
59
|
+
require base
|
60
|
+
|
61
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'app', 'models', 'apn', '*.rb')).sort.each do |f|
|
62
|
+
require f
|
63
|
+
end
|
64
|
+
|
65
|
+
%w{ models controllers helpers }.each do |dir|
|
66
|
+
path = File.join(File.dirname(__FILE__), 'app', dir)
|
67
|
+
$LOAD_PATH << path
|
68
|
+
# puts "Adding #{path}"
|
69
|
+
begin
|
70
|
+
if ActiveSupport::Dependencies.respond_to? :autoload_paths
|
71
|
+
ActiveSupport::Dependencies.autoload_paths << path
|
72
|
+
ActiveSupport::Dependencies.autoload_once_paths.delete(path)
|
73
|
+
else
|
74
|
+
ActiveSupport::Dependencies.load_paths << path
|
75
|
+
ActiveSupport::Dependencies.load_once_paths.delete(path)
|
76
|
+
end
|
77
|
+
rescue NameError
|
78
|
+
Dependencies.load_paths << path
|
79
|
+
Dependencies.load_once_paths.delete(path)
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
class APN::App < APN::Base
|
2
|
+
|
3
|
+
has_many :groups, :class_name => 'APN::Group', :dependent => :destroy
|
4
|
+
has_many :devices, :class_name => 'APN::Device', :dependent => :destroy
|
5
|
+
has_many :notifications, :through => :devices, :dependent => :destroy
|
6
|
+
has_many :unsent_notifications, :through => :devices
|
7
|
+
has_many :group_notifications, :through => :groups
|
8
|
+
has_many :unsent_group_notifications, :through => :groups
|
9
|
+
|
10
|
+
def cert
|
11
|
+
(RAILS_ENV == 'production' ? apn_prod_cert : apn_dev_cert)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Opens a connection to the Apple APN server and attempts to batch deliver
|
15
|
+
# an Array of group notifications.
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# As each APN::GroupNotification is sent the <tt>sent_at</tt> column will be timestamped,
|
19
|
+
# so as to not be sent again.
|
20
|
+
#
|
21
|
+
def send_notifications
|
22
|
+
if self.cert.nil?
|
23
|
+
raise APN::Errors::MissingCertificateError.new
|
24
|
+
return
|
25
|
+
end
|
26
|
+
APN::App.send_notifications_for_cert(self.cert, self.id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.send_notifications
|
30
|
+
apps = APN::App.all
|
31
|
+
apps.each do |app|
|
32
|
+
app.send_notifications
|
33
|
+
end
|
34
|
+
if !configatron.apn.cert.blank?
|
35
|
+
global_cert = File.read(configatron.apn.cert)
|
36
|
+
send_notifications_for_cert(global_cert, nil)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.send_notifications_for_cert(the_cert, app_id)
|
41
|
+
# unless self.unsent_notifications.nil? || self.unsent_notifications.empty?
|
42
|
+
if (app_id == nil)
|
43
|
+
conditions = "app_id is null"
|
44
|
+
else
|
45
|
+
conditions = ["app_id = ?", app_id]
|
46
|
+
end
|
47
|
+
begin
|
48
|
+
APN::Device.find_each(:conditions => conditions) do |dev|
|
49
|
+
APN::Connection.open_for_delivery({:cert => the_cert}) do |conn, sock|
|
50
|
+
dev.unsent_notifications.each do |noty|
|
51
|
+
conn.write(noty.message_for_sending)
|
52
|
+
noty.sent_at = Time.now
|
53
|
+
noty.save
|
54
|
+
end
|
55
|
+
end
|
56
|
+
sleep(1)
|
57
|
+
end
|
58
|
+
rescue Exception => e
|
59
|
+
log_connection_exception(e)
|
60
|
+
end
|
61
|
+
# end
|
62
|
+
end
|
63
|
+
|
64
|
+
def send_group_notifications
|
65
|
+
if self.cert.nil?
|
66
|
+
raise APN::Errors::MissingCertificateError.new
|
67
|
+
return
|
68
|
+
end
|
69
|
+
unless self.unsent_group_notifications.nil? || self.unsent_group_notifications.empty?
|
70
|
+
APN::Connection.open_for_delivery({:cert => self.cert}) do |conn, sock|
|
71
|
+
unsent_group_notifications.each do |gnoty|
|
72
|
+
gnoty.devices.find_each do |device|
|
73
|
+
conn.write(gnoty.message_for_sending(device))
|
74
|
+
end
|
75
|
+
gnoty.sent_at = Time.now
|
76
|
+
gnoty.save
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_group_notification(gnoty)
|
83
|
+
if self.cert.nil?
|
84
|
+
raise APN::Errors::MissingCertificateError.new
|
85
|
+
return
|
86
|
+
end
|
87
|
+
unless gnoty.nil?
|
88
|
+
APN::Connection.open_for_delivery({:cert => self.cert}) do |conn, sock|
|
89
|
+
gnoty.devices.find_each do |device|
|
90
|
+
conn.write(gnoty.message_for_sending(device))
|
91
|
+
end
|
92
|
+
gnoty.sent_at = Time.now
|
93
|
+
gnoty.save
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.send_group_notifications
|
99
|
+
apps = APN::App.all
|
100
|
+
apps.each do |app|
|
101
|
+
app.send_group_notifications
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Retrieves a list of APN::Device instnces from Apple using
|
106
|
+
# the <tt>devices</tt> method. It then checks to see if the
|
107
|
+
# <tt>last_registered_at</tt> date of each APN::Device is
|
108
|
+
# before the date that Apple says the device is no longer
|
109
|
+
# accepting notifications then the device is deleted. Otherwise
|
110
|
+
# it is assumed that the application has been re-installed
|
111
|
+
# and is available for notifications.
|
112
|
+
#
|
113
|
+
# This can be run from the following Rake task:
|
114
|
+
# $ rake apn:feedback:process
|
115
|
+
def process_devices
|
116
|
+
if self.cert.nil?
|
117
|
+
raise APN::Errors::MissingCertificateError.new
|
118
|
+
return
|
119
|
+
end
|
120
|
+
APN::App.process_devices_for_cert(self.cert)
|
121
|
+
end # process_devices
|
122
|
+
|
123
|
+
def self.process_devices
|
124
|
+
apps = APN::App.all
|
125
|
+
apps.each do |app|
|
126
|
+
app.process_devices
|
127
|
+
end
|
128
|
+
if !configatron.apn.cert.blank?
|
129
|
+
global_cert = File.read(configatron.apn.cert)
|
130
|
+
APN::App.process_devices_for_cert(global_cert)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.process_devices_for_cert(the_cert)
|
135
|
+
puts "in APN::App.process_devices_for_cert"
|
136
|
+
APN::Feedback.devices(the_cert).each do |device|
|
137
|
+
if device.last_registered_at < device.feedback_at
|
138
|
+
puts "device #{device.id} -> #{device.last_registered_at} < #{device.feedback_at}"
|
139
|
+
device.destroy
|
140
|
+
else
|
141
|
+
puts "device #{device.id} -> #{device.last_registered_at} not < #{device.feedback_at}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
protected
|
148
|
+
def self.log_connection_exception(ex)
|
149
|
+
puts ex.message
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|