Created
February 13, 2012 18:09
-
-
Save papaver/1818741 to your computer and use it in GitHub Desktop.
Apple Push Notification Tester
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby -w | |
#------------------------------------------------------------------------------ | |
# requires | |
#------------------------------------------------------------------------------ | |
require 'json' | |
require 'openssl' | |
require 'socket' | |
require 'yaml' | |
#------------------------------------------------------------------------------ | |
# Default YAML Configuration | |
#------------------------------------------------------------------------------ | |
default_config = { | |
:message => 'This is a test of the notification broadcast system.', | |
:badge => 1, | |
:dev => { | |
:cert => '/some/path', | |
:phrase =>'', | |
:tokens => ['<4ebb7e88 4dcccb1c 8e407ae3 eaed0650 8919066d a1b8b6af 62298351 38801311>'], | |
}, | |
:prd => { | |
:cert => '/some/path', | |
:phrase => '', | |
:tokens => ['<4ebb7e88 4dcccb1c 8e407ae3 eaed0650 8919066d a1b8b6af 62298351 38801311>'], | |
} | |
} | |
#------------------------------------------------------------------------------ | |
# Apple Push Notification Tester | |
#------------------------------------------------------------------------------ | |
class Pusher | |
# apple push notification servers | |
@@apn_server = { | |
:dev => 'gateway.sandbox.push.apple.com', | |
:prd => 'gateway.push.apple.com', | |
:port => 2195 | |
} | |
def initialize(mode, cert, phrase) | |
@options = { | |
:host => @@apn_server[mode], | |
:port => @@apn_server[:port], | |
:cert => cert, | |
:passphrase => phrase | |
} | |
end | |
# build apple json payload | |
def build_payload(message, badge) | |
{ :aps => { :alert => message, | |
:badge => badge, | |
:sound => 'default' } }.to_json | |
end | |
# convert notification token into hex format | |
def token_hex(token) | |
[token.scan(/\<(.+)\>/).first.first.delete(' ')].pack('H*') | |
end | |
# build apple notification packet | |
def build_simple_packet(token_hex, json) | |
packet = "\0\0 #{token_hex}\0#{json.length.chr}#{json}" | |
raise 'packet too large' if packet.size.to_i > 256 | |
packet | |
end | |
# open a connection to the apple notification server | |
def open(options, &block) | |
# setup the ssl certificate | |
cert = File.read(options[:cert]) | |
ctx = OpenSSL::SSL::SSLContext.new | |
ctx.key = OpenSSL::PKey::RSA.new(cert, options[:passphrase]) | |
ctx.cert = OpenSSL::X509::Certificate.new(cert) | |
# open socket to server | |
sock = TCPSocket.new(options[:host], options[:port]) | |
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) | |
ssl.sync = true | |
ssl.connect | |
# run block | |
yield ssl | |
# cleanup | |
ssl.close | |
sock.close | |
end | |
# send notification to server | |
def send_notification(token, message, badge) | |
token_hex = self.token_hex(token) | |
payload = self.build_payload(message, badge) | |
packet = self.build_simple_packet(token_hex, payload) | |
self.open(@options) do |connection| | |
connection.write packet | |
end | |
end | |
end | |
#------------------------------------------------------------------------------ | |
# main | |
#------------------------------------------------------------------------------ | |
config_yml = 'config.yml' | |
# check if config file exists, if not create a default config and let user | |
# know they need to fill out the config to use the script | |
unless File.exists?(config_yml) | |
File.open(config_yml, 'w') { |f| f.write(default_config.to_yaml) } | |
puts 'Fill out the config.yml, and re-run the script.' | |
exit | |
end | |
# select mode to run in | |
puts "Select Mode:" | |
puts " 1) development" | |
puts " 2) production:" | |
print ">> " | |
until [1, 2].include?(choice = gets.strip.to_i) | |
puts "Invalid entry. Please pick a valid mode." | |
end | |
# set the correct mode to run in | |
mode = [:dev, :prd][choice - 1] | |
# read in the config file | |
config = YAML::load(File.open(config_yml)) | |
# send notifications out | |
pusher = Pusher.new(mode, config[mode][:cert], config[mode][:phrase]) | |
config[mode][:tokens].each do |token| | |
pusher.send_notification(token, config[:message], config[:badge]) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment