apn_on_rails 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -2
- data/generators/apn_migrations_generator.rb +17 -5
- data/generators/templates/apn_migrations/{create_apn_devices.rb → 001_create_apn_devices.rb} +0 -0
- data/generators/templates/apn_migrations/{create_apn_notifications.rb → 002_create_apn_notifications.rb} +0 -0
- data/lib/apn_on_rails/apn_on_rails.rb +12 -2
- data/lib/apn_on_rails/app/models/apn/connection.rb +65 -0
- data/lib/apn_on_rails/app/models/apn/notification.rb +8 -18
- metadata +5 -4
data/README
CHANGED
@@ -94,10 +94,15 @@ That's it, now you're ready to start creating notifications.
|
|
94
94
|
>> notification.sound = true
|
95
95
|
>> notification.alert = "foobar"
|
96
96
|
>> notification.save
|
97
|
-
>> APN::Notification.send_notifications
|
98
97
|
|
99
|
-
You can
|
98
|
+
You can use the following Rake task to deliver your notifications:
|
100
99
|
|
101
100
|
$ rake apn:notifications:deliver
|
102
101
|
|
102
|
+
The Rake task will find any unsent notifications in the database. If there aren't any notifications
|
103
|
+
it will simply do nothing. If there are notifications waiting to be delivered it will open a single connection
|
104
|
+
to Apple and push all the notifications through that one connection. Apple does not like people opening/closing
|
105
|
+
connections constantly, so it's pretty important that you are careful about batching up your notifications so
|
106
|
+
Apple doesn't shut you down.
|
107
|
+
|
103
108
|
Released under the MIT license.
|
@@ -4,10 +4,22 @@ class ApnMigrationsGenerator < Rails::Generator::Base
|
|
4
4
|
|
5
5
|
def manifest # :nodoc:
|
6
6
|
record do |m|
|
7
|
-
|
8
|
-
|
7
|
+
timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
8
|
+
db_migrate_path = File.join('db', 'migrate')
|
9
|
+
|
10
|
+
m.directory(db_migrate_path)
|
11
|
+
|
12
|
+
['001_create_apn_devices', '002_create_apn_notifications'].each_with_index do |f, i|
|
13
|
+
timestamp = timestamp.succ
|
14
|
+
if Dir.glob(File.join(db_migrate_path, "*_#{f}.rb")).empty?
|
15
|
+
m.file(File.join('apn_migrations', "#{f}.rb"),
|
16
|
+
File.join(db_migrate_path, "#{timestamp}_#{f}.rb"),
|
17
|
+
{:collision => :skip})
|
18
|
+
end
|
9
19
|
end
|
10
|
-
|
11
|
-
|
20
|
+
|
21
|
+
end # record
|
22
|
+
|
23
|
+
end # manifest
|
12
24
|
|
13
|
-
end
|
25
|
+
end # ApnMigrationsGenerator
|
data/generators/templates/apn_migrations/{create_apn_devices.rb → 001_create_apn_devices.rb}
RENAMED
File without changes
|
File without changes
|
@@ -14,12 +14,22 @@ end
|
|
14
14
|
|
15
15
|
configatron.apn.set_default(:passphrase, '')
|
16
16
|
configatron.apn.set_default(:port, 2195)
|
17
|
-
|
18
|
-
configatron.apn.set_default(:
|
17
|
+
|
18
|
+
configatron.apn.feedback.set_default(:passphrase, configatron.apn.passphrase)
|
19
|
+
configatron.apn.feedback.set_default(:port, 2196)
|
19
20
|
|
20
21
|
if rails_env == 'production'
|
21
22
|
configatron.apn.set_default(:host, 'gateway.push.apple.com')
|
22
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)
|
23
33
|
end
|
24
34
|
|
25
35
|
module APN # :nodoc:
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module APN
|
2
|
+
module Connection
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Yields up an SSL socket to write notifications to.
|
7
|
+
# The connections are close automatically.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# APN::Configuration.open_for_delivery do |conn|
|
11
|
+
# conn.write('my cool notification')
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# Configuration parameters are:
|
15
|
+
#
|
16
|
+
# configatron.apn.passphrase = ''
|
17
|
+
# configatron.apn.port = 2195
|
18
|
+
# configatron.apn.host = 'gateway.sandbox.push.apple.com' # Development
|
19
|
+
# configatron.apn.host = 'gateway.push.apple.com' # Production
|
20
|
+
# configatron.apn.cert = File.join(rails_root, 'config', 'apple_push_notification_development.pem')) # Development
|
21
|
+
# configatron.apn.cert = File.join(rails_root, 'config', 'apple_push_notification_production.pem')) # Production
|
22
|
+
def open_for_delivery(options = {}, &block)
|
23
|
+
open(options, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Yields up an SSL socket to receive feedback from.
|
27
|
+
# The connections are close automatically.
|
28
|
+
# Configuration parameters are:
|
29
|
+
#
|
30
|
+
# configatron.apn.feedback.passphrase = ''
|
31
|
+
# configatron.apn.feedback.port = 2196
|
32
|
+
# configatron.apn.feedback.host = 'feedback.sandbox.push.apple.com' # Development
|
33
|
+
# configatron.apn.feedback.host = 'feedback.push.apple.com' # Production
|
34
|
+
# configatron.apn.feedback.cert = File.join(rails_root, 'config', 'apple_push_notification_development.pem')) # Development
|
35
|
+
# configatron.apn.feedback.cert = File.join(rails_root, 'config', 'apple_push_notification_production.pem')) # Production
|
36
|
+
def open_for_feedback(options = {}, &block) # :nodoc:
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def open(options = {}, &block) # :nodoc:
|
42
|
+
options = {:cert => configatron.apn.cert,
|
43
|
+
:passphrase => configatron.apn.passphrase,
|
44
|
+
:host => configatron.apn.host,
|
45
|
+
:port => configatron.apn.port}.merge(options)
|
46
|
+
cert = File.read(options[:cert])
|
47
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
48
|
+
ctx.key = OpenSSL::PKey::RSA.new(cert, options[:passphrase])
|
49
|
+
ctx.cert = OpenSSL::X509::Certificate.new(cert)
|
50
|
+
|
51
|
+
s = TCPSocket.new(options[:host], options[:port])
|
52
|
+
ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
|
53
|
+
ssl.sync = true
|
54
|
+
ssl.connect
|
55
|
+
|
56
|
+
yield ssl if block_given?
|
57
|
+
|
58
|
+
ssl.close
|
59
|
+
s.close
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end # Connection
|
65
|
+
end # APN
|
@@ -86,25 +86,15 @@ class APN::Notification < ActiveRecord::Base
|
|
86
86
|
# so as to not be sent again.
|
87
87
|
def send_notifications(notifications = APN::Notification.all(:conditions => {:sent_at => nil}))
|
88
88
|
unless notifications.nil? || notifications.empty?
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
|
97
|
-
ssl.sync = true
|
98
|
-
ssl.connect
|
99
|
-
|
100
|
-
notifications.each do |noty|
|
101
|
-
ssl.write(noty.message_for_sending)
|
102
|
-
noty.sent_at = Time.now
|
103
|
-
noty.save
|
89
|
+
|
90
|
+
APN::Connection.open_for_delivery do |conn|
|
91
|
+
notifications.each do |noty|
|
92
|
+
conn.write(noty.message_for_sending)
|
93
|
+
noty.sent_at = Time.now
|
94
|
+
noty.save
|
95
|
+
end
|
104
96
|
end
|
105
|
-
|
106
|
-
ssl.close
|
107
|
-
s.close
|
97
|
+
|
108
98
|
end
|
109
99
|
end
|
110
100
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apn_on_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- markbates
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-30 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -33,6 +33,7 @@ extra_rdoc_files:
|
|
33
33
|
- LICENSE
|
34
34
|
files:
|
35
35
|
- lib/apn_on_rails/apn_on_rails.rb
|
36
|
+
- lib/apn_on_rails/app/models/apn/connection.rb
|
36
37
|
- lib/apn_on_rails/app/models/apn/device.rb
|
37
38
|
- lib/apn_on_rails/app/models/apn/notification.rb
|
38
39
|
- lib/apn_on_rails/tasks/apn.rake
|
@@ -42,8 +43,8 @@ files:
|
|
42
43
|
- README
|
43
44
|
- LICENSE
|
44
45
|
- generators/apn_migrations_generator.rb
|
45
|
-
- generators/templates/apn_migrations/
|
46
|
-
- generators/templates/apn_migrations/
|
46
|
+
- generators/templates/apn_migrations/001_create_apn_devices.rb
|
47
|
+
- generators/templates/apn_migrations/002_create_apn_notifications.rb
|
47
48
|
has_rdoc: true
|
48
49
|
homepage: http://www.metabates.com
|
49
50
|
licenses: []
|