./lib/houston.rb in houston-0.0.1 vs ./lib/houston.rb in houston-0.1.0

- old
+ new

@@ -1,147 +1,7 @@ -require 'uri' -require 'socket' -require 'openssl' -require 'json' - module Houston - Version = "0.0.1" - - APPLE_PRODUCTION_GATEWAY_URI = "apn://gateway.push.apple.com:2195" - APPLE_PRODUCTION_FEEDBACK_URI = "apn://feedback.push.apple.com:2196" - - APPLE_DEVELOPMENT_GATEWAY_URI = "apn://gateway.sandbox.push.apple.com:2195" - APPLE_DEVELOPMENT_FEEDBACK_URI = "apn://feedback.push.apple.com:2196" - - class Client - attr_accessor :gateway_uri, :feedback_uri, :certificate, :passphrase - - def initialize - @gateway_uri = ENV['APN_GATEWAY_URI'] - @feedback_uri = ENV['APN_FEEDBACK_URI'] - @certificate = ENV['APN_CERTIFICATE'] - @passphrase = ENV['APN_CERTIFICATE_PASSPHRASE'] - end - - def self.development - client = self.new - client.gateway_uri = APPLE_DEVELOPMENT_GATEWAY_URI - client.feedback_uri = APPLE_DEVELOPMENT_FEEDBACK_URI - client - end - - def self.production - client = self.new - client.gateway_uri = APPLE_PRODUCTION_GATEWAY_URI - client.feedback_uri = APPLE_PRODUCTION_FEEDBACK_URI - client - end - - def push(*notifications) - Connection.open(connection_options_for_endpoint(:gateway)) do |connection, socket| - notifications.each do |notification| - next if notification.sent? - - connection.write(notification.message) - notification.mark_as_sent! - end - end - end - - def devices - devices = [] - - Connection.open(connection_options_for_endpoint(:feedback)) do |connection, socket| - while line = connection.read(38) - feedback = line.unpack('N1n1H140') - token = feedback[2].scan(/.{0,8}/).join(' ').strip - devices << token if token - end - end - - devices - end - - private - - def connection_options_for_endpoint(endpoint = :gateway) - uri = case endpoint - when :gateway then URI(@gateway_uri) - when :feedback then URI(@feedback_uri) - else - raise ArgumentError - end - - { - certificate: @certificate, - passphrase: @passphrase, - host: uri.host, - port: uri.port - } - end - end - - class Notification - attr_accessor :device, :alert, :badge, :sound, :custom_data - attr_reader :sent_at - - def initialize(options = {}) - @device = options.delete(:device) - @alert = options.delete(:alert) - @badge = options.delete(:badge) - @sound = options.delete(:sound) - - @custom_data = options - end - - def payload - json = {}.merge(@custom_data || {}) - json['aps'] = {} - json['aps']['alert'] = @alert - json['aps']['badge'] = @badge.to_i rescue 0 - json['aps']['sound'] = @sound - - json - end - - def message - json = payload.to_json - - "\0\0 #{[@device.gsub(/[<\s>]/, '')].pack('H*')}\0#{json.length.chr}#{json}" - end - - def mark_as_sent! - @sent_at = Time.now - end - - def sent? - !!@sent_at - end - end - - class Connection - class << self - def open(options = {}) - return unless block_given? - - [:certificate, :passphrase, :host, :port].each do |option| - raise ArgumentError, "Missing connection parameter: #{option}" unless option - end - - socket = TCPSocket.new(options[:host], options[:port]) - - context = OpenSSL::SSL::SSLContext.new - context.key = OpenSSL::PKey::RSA.new(options[:certificate], options[:passphrase]) - context.cert = OpenSSL::X509::Certificate.new(options[:certificate]) - - ssl = OpenSSL::SSL::SSLSocket.new(socket, context) - ssl.sync = true - ssl.connect - - yield ssl, socket - - ssl.close - socket.close - end - end - end + VERSION = "0.1.0" end + +require 'houston/client' +require 'houston/notification' +require 'houston/connection'