ass 0.0.2 → 0.0.9

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.
Files changed (5) hide show
  1. data/README.md +83 -15
  2. data/VERSION +1 -1
  3. data/ass.yml +1 -6
  4. data/lib/ass.rb +71 -42
  5. metadata +53 -5
data/README.md CHANGED
@@ -1,21 +1,18 @@
1
1
  ass
2
2
  =======
3
- Apple Service Server written with Sinatra and Sequel(Sqlite3) with apple push notification and in app purchase support.
3
+ ####Apple Service Server was written with Ruby/Sinatra and Sequel(Sqlite3), it provides push notification and in app purchase service.####
4
4
 
5
5
  Feature:
6
6
  =======
7
7
 
8
- 1. rubygem, simple to install.
9
- 2. provide pem file is the only requirement.
10
- 3. no need to setup database, using sqlite3.
8
+ 1. 'ass' is a rubygem, simple to install.
9
+ 2. only need to provide pem file.
10
+ 3. no need to setup database(using sqlite3).
11
11
  4. provide default config file(ass.yml) with default value.
12
12
 
13
- Requirement
13
+ Sqlite3 Installation
14
14
  =======
15
15
 
16
- Sqlite3
17
- -------
18
-
19
16
  CentOS/Redhat:
20
17
 
21
18
  $ yum install sqlite3
@@ -31,8 +28,8 @@ FreeBSD:
31
28
 
32
29
  Mac:
33
30
 
34
- $ brew install sqlite3 # Homebrew
35
- $ port install sqlite3 # Macport
31
+ $ brew install sqlite # Homebrew
32
+ $ port install sqlite # Macport
36
33
 
37
34
  Installation
38
35
  =======
@@ -41,16 +38,87 @@ Installation
41
38
 
42
39
  Usage
43
40
  =======
44
- 1. under the current directory, provide single pem file combined with certificate and key, HOWTO ([Check this link](http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12))
45
41
 
46
- 2. edit ass.yml. (when you run ass first time, it will generate this file) ([Check this link](https://raw.github.com/eiffelqiu/ass/master/ass.yml))
42
+ Prepare pem file:
43
+
44
+ under the current directory, provide single pem file combined with certificate and key(name pattern: appid_mode.pem), HOWTO ([Check this link](http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12))
45
+
46
+ cert.pem:
47
+ openssl x509 -in aps_development.cer -inform der -out cert.pem
48
+
49
+ key.pem:
50
+ $ openssl pkcs12 -nocerts -in key.p12 -out key.pem
51
+ $ Enter Import Password:
52
+ $ MAC verified OK
53
+ $ Enter PEM pass phrase:
54
+ $ Verifying - Enter PEM pass phrase:
55
+
56
+ Development Profile:
57
+ cat cert.pem key.pem > appid_development.pem
58
+
59
+ Distribution Profile:
60
+ cat cert.pem key.pem > appid_production.pem
47
61
 
48
- 3. provide a cron script under current directory, default named "cron" according to ass.yml
49
62
 
50
- 4. start ass server, default port is 4567(sinatra's default port)
63
+ * start ass server, default port is 4567 (sinatra's default port)
51
64
 
52
65
  ![ass usage](https://raw.github.com/eiffelqiu/ass/master/doc/capture1.png)
53
66
 
67
+ Configuration (ass.yml)
68
+ =======
69
+
70
+ when you run 'ass' first time, it will generate 'ass.yml' config file under current directory. ([Check this link](https://raw.github.com/eiffelqiu/ass/master/ass.yml))
71
+
72
+ port: 4567 ## ASS server port, default is sinatra's port number: 4567
73
+ mode: development ## 'development' or 'production' mode, you should provide pem file ({appid}_{mode}.pem) accordingly(such as, app1_development.pem, app1_production.pem).
74
+ cron: cron ## cron job file name, ASS server will generate a demo 'cron' file for demostration only under current directory.
75
+ timer: 0 # how often you run the cron job, unit: minute. when set with 0, means no cron job execute.
76
+ apps:
77
+ - app1 ## appid you want to supprt APNS, ASS Server can give push notification support for many iOS apps, just list the appid here.
78
+
79
+
80
+ FAQ:
81
+ =======
82
+
83
+ 1. How to register notification? (Client Side)
84
+ -------
85
+
86
+ In AppDelegate file, add methods below to register device token
87
+
88
+ - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
89
+ {
90
+ NSString * tokenAsString = [[[deviceToken description]
91
+ stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]
92
+ stringByReplacingOccurrencesOfString:@" " withString:@""];
93
+ NSString *urlAsString = [NSString stringWithFormat:@"http://serverIP:4567/v1/apps/app1/%@", token];
94
+ NSURL *url = [NSURL URLWithString:urlAsString];
95
+ NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
96
+ [urlRequest setTimeoutInterval:30.0f];
97
+ [urlRequest setHTTPMethod:@"GET"];
98
+ NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
99
+ [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:nil];
100
+ }
101
+
102
+ - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
103
+ {
104
+ NSLog(@"Failed to get token, error: %@", error);
105
+ }
106
+
107
+ 2. How to send push notification? (Server Side)
108
+ -------
109
+
110
+ run **curl** command to send push notification message, whatever shell.
111
+
112
+ $ curl http://localhost:4567/v1/apps/app1/push/{message}/{pid}
113
+
114
+ Note:
115
+
116
+ param1 (message): push notification message you want to send, remember the message should be html escaped
117
+
118
+ param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest
119
+
120
+
121
+
54
122
  Contributing to ass
55
123
  =======
56
124
 
@@ -65,5 +133,5 @@ Contributing to ass
65
133
  Copyright
66
134
  =======
67
135
 
68
- Copyright (c) 2012 Eiffel Qiu. See LICENSE.txt for further details.
136
+ #####Copyright (c) 2012 Eiffel Qiu. See LICENSE.txt for further details.#####
69
137
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.9
data/ass.yml CHANGED
@@ -1,11 +1,6 @@
1
1
  port: 4567
2
2
  mode: development
3
3
  cron: cron
4
- timer: 0 # minute
5
- development:
6
- - certificate : ck_dev.pem
7
- production:
8
- - certificate : ck_prod.pem
4
+ timer: 0
9
5
  apps:
10
6
  - app1
11
- - app2
data/lib/ass.rb CHANGED
@@ -15,20 +15,20 @@ require 'yaml'
15
15
  ############################################################
16
16
  ## Initilization Setup
17
17
  ############################################################
18
- lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
19
- root_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
20
- unless $LOAD_PATH.include?(lib_dir)
21
- $LOAD_PATH << lib_dir
18
+ LIBDIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
19
+ ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
20
+ unless $LOAD_PATH.include?(LIBDIR)
21
+ $LOAD_PATH << LIBDIR
22
22
  end
23
23
 
24
24
  unless File.exist?("#{Dir.pwd}/ass.yml") then
25
25
  puts 'create config file: ass.yml'
26
- system "cp #{root_dir}/ass.yml #{Dir.pwd}/ass.yml"
26
+ system "cp #{ROOTDIR}/ass.yml #{Dir.pwd}/ass.yml"
27
27
  end
28
28
 
29
29
  unless File.exist?("#{Dir.pwd}/cron") then
30
30
  puts "create a demo 'cron' script"
31
- system "cp #{root_dir}/cron #{Dir.pwd}/cron"
31
+ system "cp #{ROOTDIR}/cron #{Dir.pwd}/cron"
32
32
  end
33
33
 
34
34
  ############################################################
@@ -36,21 +36,37 @@ end
36
36
  ############################################################
37
37
  env = ENV['SINATRA_ENV'] || "development"
38
38
  config = YAML.load_file("#{Dir.pwd}/ass.yml")
39
- $timer = config['timer'] || 1
39
+ $timer = "#{config['timer']}".to_i
40
40
  $cron = config['cron'] || 'cron'
41
41
  $port = config['port'] || 4567
42
42
  $mode = config['mode'] || env
43
- $certificate = config["#{$mode}"][0]['certificate'] || 'ck.pem'
44
- ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
45
- VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
43
+ $VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
46
44
  $apps = config['apps'] || []
47
45
 
48
46
  ############################################################
49
47
  ## Certificate Key Setup
50
48
  ############################################################
51
49
 
52
- unless File.exist?("#{Dir.pwd}/#{$certificate}") then
53
- puts "1: please provide certificate key pem file under current directory"
50
+ $certkey = {}
51
+ def check_cert
52
+ $apps.each { |app|
53
+ unless File.exist?("#{Dir.pwd}/#{app}_#{$mode}.pem") then
54
+ puts "Please provide #{app}_#{$mode}.pem under '#{Dir.pwd}/' directory"
55
+ return false;
56
+ else
57
+ puts "'#{app}'s #{$mode} PEM: (#{app}_#{$mode}.pem)"
58
+ certfile = File.read("#{Dir.pwd}/#{app}_#{$mode}.pem")
59
+ openSSLContext = OpenSSL::SSL::SSLContext.new
60
+ openSSLContext.cert = OpenSSL::X509::Certificate.new(certfile)
61
+ openSSLContext.key = OpenSSL::PKey::RSA.new(certfile)
62
+ $certkey["#{app}"] = openSSLContext
63
+ end
64
+ }
65
+ return true
66
+ end
67
+
68
+ unless check_cert then
69
+ puts "1: please provide certificate key pem file under current directory, name should be: appid_dev.pem for development and appid_prod.pem for production"
54
70
  puts "2: edit your ass.yml under current directory"
55
71
  puts "3: run ass"
56
72
  puts "4: iOS Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access url below:"
@@ -61,91 +77,103 @@ unless File.exist?("#{Dir.pwd}/#{$certificate}") then
61
77
  exit
62
78
  else
63
79
  puts "*"*80
64
- puts "Simple Push Notification Server is Running (#{VERSION}) ..."
80
+ puts "Apple Service Server(#{$VERSION}) is Running ..."
81
+ puts "Push Notification Service: Enabled"
65
82
  puts "Mode: #{$mode}"
66
83
  puts "Port: #{$port}"
67
- puts "Certificate File: '#{Dir.pwd}/#{$certificate}'"
68
- puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".squeeze.strip == "0"
84
+ puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".to_i == 0
69
85
  puts "*"*80
70
86
  end
71
87
 
72
- $cert = File.read("#{Dir.pwd}/#{$certificate}")
73
- $openSSLContext = OpenSSL::SSL::SSLContext.new
74
- $openSSLContext.cert = OpenSSL::X509::Certificate.new($cert)
75
- $openSSLContext.key = OpenSSL::PKey::RSA.new($cert)
76
-
77
88
  ############################################################
78
89
  ## Sequel Database Setup
79
90
  ############################################################
80
91
 
81
- DB = nil;
82
-
83
- unless File.exist?("#{Dir.pwd}/push.db") then
84
- DB = Sequel.connect("sqlite://#{Dir.pwd}/push.db")
92
+ unless File.exist?("#{Dir.pwd}/ass.db") then
93
+ $DB = Sequel.connect("sqlite://#{Dir.pwd}/ass.db")
85
94
 
86
- DB.create_table :tokens do
95
+ $DB.create_table :tokens do
87
96
  primary_key :id
88
- String :app, :unique => true, :null => false
97
+ String :app, :unique => false, :null => false
89
98
  String :token, :unique => true, :null => false, :size => 100
90
99
  index [:app, :token]
91
100
  end
92
101
 
93
- DB.create_table :pushes do
102
+ $DB.create_table :pushes do
94
103
  primary_key :id
95
104
  String :pid, :unique => true, :null => false, :size => 100
96
105
  index :pid
97
106
  end
98
107
  else
99
- DB = Sequel.connect("sqlite://#{Dir.pwd}/push.db")
108
+ $DB = Sequel.connect("sqlite://#{Dir.pwd}/ass.db")
100
109
  end
101
110
 
102
- Token = DB[:tokens]
103
- Push = DB[:pushes]
111
+ Token = $DB[:tokens]
112
+ Push = $DB[:pushes]
104
113
 
105
114
  ############################################################
106
115
  ## Timer Job Setup
107
116
  ############################################################
108
117
  scheduler = Rufus::Scheduler.start_new
109
118
 
110
- unless "#{$timer}".squeeze.strip == "0"
119
+ unless $timer == 0 then
111
120
  scheduler.every "#{$timer}m" do
112
121
  puts "running job: '#{Dir.pwd}/#{$cron}' every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'}"
113
122
  system "./#{$cron}"
114
123
  end
115
124
  else
125
+ puts "1: How to register notification? (Client Side)"
116
126
  puts
117
- puts "*"*80
118
- puts "How to register notification?"
119
- puts
120
- puts "iOS Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access url below:"
127
+ puts "In AppDelegate file, inside didRegisterForRemoteNotificationsWithDeviceToken method access url below to register device token:"
121
128
  $apps.each { |app|
122
129
  puts "'#{app}'s registration url: http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken"
123
130
  }
124
131
  puts
125
- puts "How to send push notification?"
132
+ puts "2: How to send push notification? (Server Side)"
126
133
  puts
127
134
  $apps.each { |app|
128
135
  puts "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}"
129
136
  }
130
137
  puts
131
138
  puts "Note:"
132
- puts "message: notification message you want to send, remember the message should be html escaped"
133
- puts "pid: unique id that you mark the message, for example current timestamp"
139
+ puts "param1 (message): push notification message you want to send, remember the message should be html escaped"
140
+ puts "param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest"
134
141
  puts
135
142
  puts "*"*80
136
- puts
137
143
  end
138
144
 
139
145
  ############################################################
140
- ## Simple Push Notification Server based on Sinatra
146
+ ## Apple Service Server based on Sinatra
141
147
  ############################################################
142
148
 
143
149
  class App < Sinatra::Base
144
150
 
145
151
  set :port, "#{$port}".to_i
152
+
153
+ if "#{$mode}".strip == 'development' then
154
+ set :show_exceptions, true
155
+ set :dump_errors, true
156
+ else
157
+ set :show_exceptions, false
158
+ set :dump_errors, false
159
+ end
146
160
 
147
161
  get '/' do
148
- puts "Simple Push Notification Server"
162
+ o = "Apple Service Server #{$VERSION} <br/><br/>" +
163
+ "author: Eiffel(Q) <br/>email: eiffelqiu@gmail.com<br/><br/>"
164
+ o += "1: How to register notification? (Client Side)<br/><br/>"
165
+ o += "In AppDelegate file, inside didRegisterForRemoteNotificationsWithDeviceToken method access url below to register device token:<br/><br/>"
166
+ $apps.each { |app|
167
+ o += "'#{app}': http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken<br/>"
168
+ }
169
+ o += "<br/>2: How to send push notification? (Server Side)<br/><br/>"
170
+ $apps.each { |app|
171
+ o += "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}<br/>"
172
+ }
173
+ o += "<br/>Note:<br/>"
174
+ o += "param1 (message): push notification message you want to send, remember the message should be html escaped<br/>"
175
+ o += "param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest<br/>"
176
+ o
149
177
  end
150
178
 
151
179
  $apps.each { |app|
@@ -170,6 +198,7 @@ class App < Sinatra::Base
170
198
  @exist = Push.first(:pid => pid)
171
199
 
172
200
  unless @exist
201
+ openSSLContext = $certkey["#{app}"]
173
202
  # Connect to port 2195 on the server.
174
203
  sock = nil
175
204
  if $mode == 'production' then
@@ -178,7 +207,7 @@ class App < Sinatra::Base
178
207
  sock = TCPSocket.new('gateway.sandbox.push.apple.com', 2195)
179
208
  end
180
209
  # do our SSL handshaking
181
- sslSocket = OpenSSL::SSL::SSLSocket.new(sock, $openSSLContext)
210
+ sslSocket = OpenSSL::SSL::SSLSocket.new(sock, openSSLContext)
182
211
  sslSocket.connect
183
212
  #Push.create( :pid => pid )
184
213
  Push.insert(:pid => pid)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-12 00:00:00.000000000 Z
12
+ date: 2012-09-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sqlite3
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thin
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: sinatra
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -171,6 +187,38 @@ dependencies:
171
187
  - - ~>
172
188
  - !ruby/object:Gem::Version
173
189
  version: 1.8.4
190
+ - !ruby/object:Gem::Dependency
191
+ name: sqlite3
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ type: :runtime
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: thin
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :runtime
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
174
222
  - !ruby/object:Gem::Dependency
175
223
  name: sinatra
176
224
  requirement: !ruby/object:Gem::Requirement
@@ -251,7 +299,7 @@ dependencies:
251
299
  - - ! '>='
252
300
  - !ruby/object:Gem::Version
253
301
  version: 3.2.8
254
- description: Simple Push Notification Server written with Sinatra and Sequel(Sqlite3)
302
+ description: Apple Service Server written with Sinatra and Sequel(Sqlite3)
255
303
  email: eiffelqiu@gmail.com
256
304
  executables:
257
305
  - ass
@@ -283,7 +331,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
283
331
  version: '0'
284
332
  segments:
285
333
  - 0
286
- hash: -3175766109456070451
334
+ hash: -54990434379922484
287
335
  required_rubygems_version: !ruby/object:Gem::Requirement
288
336
  none: false
289
337
  requirements:
@@ -295,5 +343,5 @@ rubyforge_project: ass
295
343
  rubygems_version: 1.8.21
296
344
  signing_key:
297
345
  specification_version: 3
298
- summary: Simple Push Notification Server
346
+ summary: Apple Service Server
299
347
  test_files: []