spns 0.2.4 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/README.md +14 -24
  2. data/VERSION +1 -1
  3. data/bin/spns +2 -2
  4. data/cron +10 -3
  5. data/lib/spns.rb +77 -53
  6. data/spns.yml +4 -1
  7. metadata +2 -2
data/README.md CHANGED
@@ -3,23 +3,12 @@ spns
3
3
  Simple Push Notification Server written with Sinatra and Sequel(Sqlite3)
4
4
 
5
5
  Feature:
6
- 1: rubygem, simple to install.
7
- 2: provide pem file is the only requirement.
8
- 3: no need to setup database, using sqlite3.
9
- 4: provide default config file(spns.yml) with default value.
6
+ * rubygem, simple to install.
7
+ * provide pem file is the only requirement.
8
+ * no need to setup database, using sqlite3.
9
+ * provide default config file(spns.yml) with default value.
10
10
 
11
- Prerequisites
12
- =======
13
-
14
- Ruby
15
- -------
16
- spns is a ruby gem, require ruby installed on your mac machine. Since now all Mac OSX system preinstalled ruby enviroment, that's not a big issue.
17
-
18
- Rubygem(latest)
19
- -------
20
- spns require latest rubygem installed, so you need to update your rubygem to latest version, run command below to update your rubygem to the latest one.
21
-
22
- $ sudo gem update --system # double dash option
11
+ Requirement
23
12
 
24
13
  Sqlite3
25
14
  -------
@@ -36,17 +25,18 @@ Installation
36
25
 
37
26
  Usage
38
27
  =======
39
- 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))
28
+ * 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))
40
29
 
41
- 2. edit spns.yml. (when you run spns first time, it will generate this file) ([Check this link](https://raw.github.com/eiffelqiu/spns/master/spns.yml))
30
+ * edit spns.yml. (when you run spns first time, it will generate this file) ([Check this link](https://raw.github.com/eiffelqiu/spns/master/spns.yml))
42
31
 
43
- 3. provide a cron script under current directory, default named "cron" according to spns.yml
32
+ * provide a cron script under current directory, default named "cron" according to spns.yml
44
33
 
45
- 4. start spns server, default port is 4567(sinatra's default port)
34
+ * start spns server, default port is 4567(sinatra's default port)
46
35
 
47
36
  ![spns usage](https://raw.github.com/eiffelqiu/spns/master/doc/capture1.png)
48
37
 
49
- == Contributing to spns
38
+ Contributing to spns
39
+ =======
50
40
 
51
41
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
52
42
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
@@ -56,8 +46,8 @@ Usage
56
46
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
57
47
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
58
48
 
59
- == Copyright
49
+ Copyright
50
+ ==
60
51
 
61
- Copyright (c) 2012 Eiffel Qiu. See LICENSE.txt for
62
- further details.
52
+ Copyright (c) 2012 Eiffel Qiu. See LICENSE.txt for further details.
63
53
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.2.6
data/bin/spns CHANGED
@@ -1,5 +1,5 @@
1
- # -*- coding: utf-8 -*-
2
1
  #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
3
 
4
4
  require 'rubygems' unless defined?(Gem)
5
5
  require 'sinatra/base'
@@ -23,7 +23,7 @@ unless File.exist?("#{Dir.pwd}/spns.yml") then
23
23
  end
24
24
 
25
25
  unless File.exist?("#{Dir.pwd}/cron") then
26
- puts "create a demo 'cron' script under current directory"
26
+ puts "create a demo 'cron' script"
27
27
  system "cp #{root_dir}/cron #{Dir.pwd}/cron"
28
28
  end
29
29
 
data/cron CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'yaml'
5
5
  require 'cgi'
6
+ require 'digest/sha2'
6
7
 
7
8
  ###########################################################################
8
9
  ####
@@ -17,13 +18,19 @@ require 'cgi'
17
18
  env = ENV['SINATRA_ENV'] || "development"
18
19
  config = YAML.load_file("#{Dir.pwd}/spns.yml")
19
20
  $port = config['port'] || 4567
20
-
21
+ $apps = config['apps'] || []
22
+
21
23
  ############################################################
22
24
  ## Using curl command to send push notification message
23
25
  ############################################################
24
26
 
25
27
  @message = CGI::escape("sample push notification message")
28
+
29
+ #@pid = Digest::SHA2.hexdigest("#{Time.now.to_i}")
26
30
  @pid = "#{Time.now.to_i}"
27
31
 
28
- puts "curl http://localhost:#{$port}/v1/app/push/#{@message}/#{@pid}"
29
- system "curl http://localhost:#{$port}/v1/app/push/#{@message}/#{@pid}"
32
+ $apps.each { |app|
33
+ sleep 1
34
+ puts "curl http://localhost:#{$port}/v1/apps/#{app}/push/#{@message}/#{@pid}"
35
+ system "curl http://localhost:#{$port}/v1/apps/#{app}/push/#{@message}/#{@pid}"
36
+ }
data/lib/spns.rb CHANGED
@@ -22,8 +22,9 @@ $cron = config['cron'] || 'cron'
22
22
  $port = config['port'] || 4567
23
23
  $mode = config['mode'] || env
24
24
  $certificate = config["#{$mode}"][0]['certificate'] || 'ck.pem'
25
- ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__),'..'))
25
+ ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
26
26
  VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
27
+ $apps = config['apps'] || []
27
28
 
28
29
  ############################################################
29
30
  ## Certificate Key Setup
@@ -31,7 +32,7 @@ VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
31
32
 
32
33
  unless File.exist?("#{Dir.pwd}/#{$certificate}") then
33
34
  puts "1: please provide certificate key pem file under current directory"
34
- puts "2: edit your spns.yml under current directory first"
35
+ puts "2: edit your spns.yml under current directory"
35
36
  puts "3: run spns"
36
37
  puts "4: Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access this url: http://serverIP:#{$port}/v1/app/DeviceToken"
37
38
  puts "5: Server: cron should access 'curl http://localhost:#{$port}/v1/app/push/#{messages}/#{pid}' to send push message"
@@ -42,7 +43,7 @@ else
42
43
  puts "Mode: #{$mode}"
43
44
  puts "Port: #{$port}"
44
45
  puts "Certificate File: '#{Dir.pwd}/#{$certificate}'"
45
- puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} "
46
+ puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".squeeze.strip == "0"
46
47
  puts "*"*80
47
48
  end
48
49
 
@@ -78,68 +79,91 @@ Push = DB[:pushes]
78
79
  ############################################################
79
80
  scheduler = Rufus::Scheduler.start_new
80
81
 
81
- scheduler.every "#{$timer}m" do
82
- puts "running job: '#{Dir.pwd}/#{$cron}' every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'}"
83
- system "./#{$cron}"
84
- end
82
+ unless "#{$timer}".squeeze.strip == "0"
83
+ scheduler.every "#{$timer}m" do
84
+ puts "running job: '#{Dir.pwd}/#{$cron}' every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'}"
85
+ system "./#{$cron}"
86
+ end
87
+ else
88
+ puts
89
+ puts "*"*80
90
+ puts
91
+ puts "How to send push notification?"
92
+ puts
93
+ $apps.each { |app|
94
+ puts "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}"
95
+ }
96
+ puts
97
+ puts "Note:"
98
+ puts "message: notification message you want to send, remember the message should be html escaped"
99
+ puts "pid: unique id that you mark the message, for example current timestamp"
100
+ puts
101
+ puts "*"*80
102
+ puts
103
+ end
85
104
 
86
105
  ############################################################
87
106
  ## Simple Push Notification Server based on Sinatra
88
107
  ############################################################
89
108
 
90
109
  class App < Sinatra::Base
91
-
92
- set :port, "#{$port}".to_i
93
-
110
+
111
+ set :port, "#{$port}".to_i
112
+
94
113
  get '/' do
95
114
  puts "Simple Push Notification Server"
96
115
  end
97
116
 
98
- get '/v1/app/:token' do
99
- o = Token.first(:token => params[:token])
100
- unless o
101
- Token.insert(
102
- :app => 'app',
103
- :token => params[:token]
104
- )
117
+ $apps.each { |app|
118
+ get "/v1/apps/#{app}/:token" do
119
+ puts "#{:token} was added to #{app}"
120
+ o = Token.first(:token => params[:token])
121
+ unless o
122
+ Token.insert(
123
+ :app => app,
124
+ :token => params[:token]
125
+ )
126
+ end
105
127
  end
106
- end
107
128
 
108
- get '/v1/app/push/:message/:pid' do
109
- message = CGI::unescape(params[:message])
110
- pid = params[:pid]
111
- @push = Token.where(:app => 'app')
112
- @exist = Push.first(:pid => pid )
113
-
114
- unless @exist
115
- # Connect to port 2195 on the server.
116
- sock = nil
117
- if $mode == 'production' then
118
- sock = TCPSocket.new('gateway.push.apple.com', 2195)
119
- else
120
- sock = TCPSocket.new('gateway.sandbox.push.apple.com', 2195)
129
+ get "/v1/apps/#{app}/push/:message/:pid" do
130
+ message = CGI::unescape(params[:message])
131
+ pid = params[:pid]
132
+
133
+ puts "'#{message}' was sent to (#{app}) with pid: [#{pid}]"
134
+
135
+ @push = Token.where(:app => app)
136
+ @exist = Push.first(:pid => pid)
137
+
138
+ unless @exist
139
+ # Connect to port 2195 on the server.
140
+ sock = nil
141
+ if $mode == 'production' then
142
+ sock = TCPSocket.new('gateway.push.apple.com', 2195)
143
+ else
144
+ sock = TCPSocket.new('gateway.sandbox.push.apple.com', 2195)
145
+ end
146
+ # do our SSL handshaking
147
+ sslSocket = OpenSSL::SSL::SSLSocket.new(sock, $openSSLContext)
148
+ sslSocket.connect
149
+ #Push.create( :pid => pid )
150
+ Push.insert(:pid => pid)
151
+ # write our packet to the stream
152
+ @push.each do |o|
153
+ tokenText = o[:token]
154
+ # pack the token to convert the ascii representation back to binary
155
+ tokenData = [tokenText].pack('H*')
156
+ # construct the payload
157
+ payload = "{\"aps\":{\"alert\":\"#{message}\", \"badge\":1}}"
158
+ # construct the packet
159
+ packet = [0, 0, 32, tokenData, 0, payload.length, payload].pack("ccca*cca*")
160
+ # read our certificate and set up our SSL context
161
+ sslSocket.write(packet)
162
+ end
163
+ # cleanup
164
+ sslSocket.close
165
+ sock.close
121
166
  end
122
- # do our SSL handshaking
123
- sslSocket = OpenSSL::SSL::SSLSocket.new(sock, $openSSLContext)
124
- sslSocket.connect
125
- #Push.create( :pid => pid )
126
- Push.insert( :pid => pid )
127
- # write our packet to the stream
128
- @push.each do |o|
129
- tokenText = o[:token]
130
- # pack the token to convert the ascii representation back to binary
131
- tokenData = [tokenText].pack('H*')
132
- # construct the payload
133
- payload = "{\"aps\":{\"alert\":\"#{message}\", \"badge\":1}}"
134
- # construct the packet
135
- packet = [0, 0, 32, tokenData, 0, payload.length, payload].pack("ccca*cca*")
136
- # read our certificate and set up our SSL context
137
- sslSocket.write(packet)
138
- end
139
- # cleanup
140
- sslSocket.close
141
- sock.close
142
167
  end
143
- end
144
-
168
+ }
145
169
  end
data/spns.yml CHANGED
@@ -1,8 +1,11 @@
1
1
  port: 4567
2
2
  mode: development
3
3
  cron: cron
4
- timer: 1 # minute
4
+ timer: 0 # minute
5
5
  development:
6
6
  - certificate : ck_dev.pem
7
7
  production:
8
8
  - certificate : ck_prod.pem
9
+ apps:
10
+ - app1
11
+ - app2
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -315,7 +315,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
315
315
  version: '0'
316
316
  segments:
317
317
  - 0
318
- hash: 1770229218471308952
318
+ hash: -4363883423968780376
319
319
  required_rubygems_version: !ruby/object:Gem::Requirement
320
320
  none: false
321
321
  requirements: