Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit.

  • Loading branch information...
commit d1670e724bcfaa8e9c14b7006d22325f1a75fa6f 0 parents
Mark Bates markbates authored
15 .gitignore
@@ -0,0 +1,15 @@
+*.log
+.DS_Store
+doc
+tmp
+pkg
+*.gem
+*.pid
+coverage
+coverage.data
+build/*
+*.pbxuser
+*.mode1v3
+.svn
+profile
+spec/active_record/test.db
21 LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2009 markbates
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
3  README
@@ -0,0 +1,3 @@
+README
+========================================================================
+apn_on_rails was developed by: markbates
14 Rakefile
@@ -0,0 +1,14 @@
+require 'rubygems'
+require 'gemstub'
+
+Gemstub.test_framework = :rspec
+
+Gemstub.gem_spec do |s|
+ # s.version = "0.0.1"
+ # s.rubyforge_project = "apn_on_rails"
+ # s.add_dependency('')
+end
+
+Gemstub.rdoc do |rd|
+ rd.title = "apn_on_rails"
+end
3  lib/apn_on_rails.rb
@@ -0,0 +1,3 @@
+Dir.glob(File.join(File.dirname(__FILE__), 'apn_on_rails', '**/*.rb')).each do |f|
+ require File.expand_path(f)
+end
18 lib/apn_on_rails/apn_on_rails.rb
@@ -0,0 +1,18 @@
+require 'socket'
+require 'openssl'
+require 'configatron'
+
+module APN
+end
+
+Dir.glob(File.join(File.dirname(__FILE__), 'app', 'models', 'apn', '*.rb')).sort.each do |f|
+ require f
+end
+
+%w{ models controllers helpers }.each do |dir|
+ path = File.join(File.dirname(__FILE__), 'app', dir)
+ $LOAD_PATH << path
+ # puts "Adding #{path}"
+ ActiveSupport::Dependencies.load_paths << path
+ ActiveSupport::Dependencies.load_once_paths.delete(path)
+end
29 lib/apn_on_rails/app/models/apn/device.rb
@@ -0,0 +1,29 @@
+class APN::Device < ActiveRecord::Base
+ set_table_name 'apn_devices'
+
+ has_many :notifications, :class_name => 'APN::Notification'
+
+ validates_uniqueness_of :token
+
+ def token=(token)
+ res = token.scan(/\<(.+)\>/).first
+ unless res.nil? || res.empty?
+ # self.token = res.first
+ token = res.first
+ end
+ write_attribute('token', token)
+ end
+
+ before_validation :clean_token
+
+ private
+ def clean_token
+ if self.token && self.token_changed?
+ res = self.token.scan(/\<(.+)\>/).first
+ unless res.nil? || res.empty?
+ self.token = res.first
+ end
+ end
+ end
+
+end
6 lib/apn_on_rails/app/models/apn/notification.rb
@@ -0,0 +1,6 @@
+class APN::Notification < ActiveRecord::Base
+ set_table_name 'apn_notifications'
+
+ belongs_to :device, :class_name => 'APN::Device'
+
+end
94 lib/apn_on_rails/app/models/apple_push_notification.rb
@@ -0,0 +1,94 @@
+# #
+# # Fabien Penso <fabien.penso@conovae.com>
+# # April 6th, 2009.
+# #
+#
+# require 'socket'
+# require 'openssl'
+#
+# class ApplePushNotification < ActiveRecord::Base
+#
+# HOST = "gateway.sandbox.push.apple.com"
+# PATH = '/'
+# PORT = 2195
+# path = File.join(RAILS_ROOT, 'config', 'apple_push_notification_development.pem')
+# CERT = File.read(path) if File.exists?(path)
+# PASSPHRASE = "foobar"
+# CACERT = File.expand_path(File.dirname(__FILE__) + "certs/ca.gateway.sandbox.push.apple.com.crt")
+# USERAGENT = 'Mozilla/5.0 (apple_push_notification Ruby on Rails 0.1)'
+#
+# # attr_accessor :paylod, :sound, :badge, :alert, :appdata
+# attr_accessible :device_token
+#
+# # validates_uniqueness_of :device_token
+#
+# # def send_notification
+# #
+# # ctx = OpenSSL::SSL::SSLContext.new
+# # ctx.key = OpenSSL::PKey::RSA.new(CERT, PASSPHRASE)
+# # ctx.cert = OpenSSL::X509::Certificate.new(CERT)
+# #
+# # s = TCPSocket.new(HOST, PORT)
+# # ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
+# # ssl.sync = true
+# # ssl.connect
+# #
+# # ssl.write(self.apn_message_for_sending)
+# #
+# # ssl.close
+# # s.close
+# #
+# # rescue SocketError => error
+# # raise "Error while sending notifications: #{error}"
+# # end
+#
+# def self.send_notifications(notifications)
+# ctx = OpenSSL::SSL::SSLContext.new
+# ctx.key = OpenSSL::PKey::RSA.new(CERT, PASSPHRASE)
+# ctx.cert = OpenSSL::X509::Certificate.new(CERT)
+#
+# s = TCPSocket.new(HOST, PORT)
+# ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
+# ssl.sync = true
+# ssl.connect
+#
+# for notif in notifications do
+# ssl.write(notif.apn_message_for_sending)
+# notif.sent_at = Time.now
+# notif.save
+# end
+#
+# ssl.close
+# s.close
+# rescue SocketError => error
+# raise "Error while sending notifications: #{error}"
+# end
+#
+# def to_apple_json
+# logger.debug "Sending #{self.apple_array.to_json}"
+# self.apple_array.to_json
+# end
+#
+# def apn_message_for_sending
+# json = self.to_apple_json
+# message = "\0\0 #{self.device_token_hexa}\0#{json.length.chr}#{json}"
+# raise "The maximum size allowed for a notification payload is 256 bytes." if message.size.to_i > 256
+# message
+# end
+#
+# def device_token_hexa
+# [self.device_token.delete(' ')].pack('H*')
+# end
+#
+# def apple_array
+# result = {}
+# result['aps'] = {}
+# result['aps']['alert'] = alert if alert
+# result['aps']['badge'] = badge.to_i if badge
+# result['aps']['sound'] = sound if sound and sound.is_a? String
+# result['aps']['sound'] = "1.aiff" if sound and sound.is_a?(TrueClass)
+# result.merge appdata if appdata
+#
+# result
+# end
+# end
13 lib/apn_on_rails/db/migrate/20090723132058_create_apn_devices.rb
@@ -0,0 +1,13 @@
+class CreateApnDevices < ActiveRecord::Migration
+ def self.up
+ create_table :apn_devices do |t|
+ t.text :token, :size => 71, :null => false
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :apn_devices
+ end
+end
32 lib/apn_on_rails/db/migrate/20090723132059_create_apn_notifications.rb
@@ -0,0 +1,32 @@
+class CreateApnNotifications < ActiveRecord::Migration
+
+ def self.up
+
+ create_table :apn_notifications do |t|
+ t.integer :device_id, :null => false
+ t.integer :errors_nb, :default => 0 # used for storing errors from apple feedbacks
+ t.string :device_language, :size => 5 # if you don't want to send localized strings
+ t.text :payload
+ t.string :sound
+ t.integer :badge
+ t.text :app_data
+ t.datetime :sent_at
+ t.timestamps
+ end
+
+ add_index :apn_notifications, :device_id
+ end
+
+ def self.down
+ drop_table :apn_notifications
+ end
+
+end
+
+# add_column :apple_push_notifications, :payload, :text
+# add_column :apple_push_notifications, :sound, :string
+# add_column :apple_push_notifications, :badge, :integer
+# add_column :apple_push_notifications, :alert, :string
+# add_column :apple_push_notifications, :appdata, :text
+# add_column :apple_push_notifications, :sent_at, :datetime
+# add_column :apple_push_notifications, :device_id, :integer
16 spec/active_record/setup_ar.rb
@@ -0,0 +1,16 @@
+require 'rubygems'
+require 'activerecord'
+
+logger = Logger.new(STDOUT)
+logger.level = Logger::INFO
+ActiveRecord::Base.logger = logger
+
+db_file = File.join(File.dirname(__FILE__), 'test.db')
+FileUtils.rm(db_file) if File.exists?(db_file)
+
+ActiveRecord::Base.establish_connection({
+ :adapter => 'sqlite3',
+ :dbfile => db_file
+})
+
+ActiveRecord::Migrator.up(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'apn_on_rails', 'db', 'migrate'))
25 spec/apn_on_rails/app/models/apn/device_spec.rb
@@ -0,0 +1,25 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper.rb')
+
+describe APN::Device do
+
+ describe 'token' do
+
+ it 'should be unique' do
+ device = DeviceFactory.new(:token => APN::Device.first.token)
+ device.should_not be_valid
+ device.errors['token'].should include('has already been taken')
+
+ device = DeviceFactory.new(:token => device.token.succ)
+ device.should be_valid
+ end
+
+ it 'should get cleansed if it contains brackets' do
+ token = DeviceFactory.random_token
+ device = DeviceFactory.new(:token => "<#{token}>")
+ device.token.should == token
+ device.token.should_not == "<#{token}>"
+ end
+
+ end
+
+end
7 spec/apn_on_rails/app/models/apn/notification_spec.rb
@@ -0,0 +1,7 @@
+require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper.rb')
+
+describe APN::Notification do
+
+ it 'should do something'
+
+end
10 spec/extensions/string.rb
@@ -0,0 +1,10 @@
+class String
+
+ def self.randomize(length = 10)
+ chars = ("A".."H").to_a + ("J".."N").to_a + ("P".."T").to_a + ("W".."Z").to_a + ("3".."9").to_a
+ newpass = ""
+ 1.upto(length) { |i| newpass << chars[rand(chars.size-1)] }
+ return newpass.upcase
+ end
+
+end
28 spec/factories/device_factory.rb
@@ -0,0 +1,28 @@
+module DeviceFactory
+
+ class << self
+
+ def new(options = {})
+ options = {:token => DeviceFactory.random_token}.merge(options)
+ return APN::Device.new(options)
+ end
+
+ def create(options = {})
+ device = DeviceFactory.new(options)
+ device.save
+ return device
+ end
+
+ def random_token
+ tok = []
+ 8.times do
+ tok << String.randomize(8)
+ end
+ tok.join(' ').downcase
+ end
+
+ end
+
+end
+
+DeviceFactory.create
0  spec/factories/notification_factory.rb
No changes.
2  spec/spec.opts
@@ -0,0 +1,2 @@
+--format specdoc
+--colour
34 spec/spec_helper.rb
@@ -0,0 +1,34 @@
+require 'rubygems'
+require 'spec'
+
+Dir.glob(File.join(File.dirname(__FILE__), 'extensions', '*.rb')).sort.each do |f|
+ require f
+end
+
+require File.join(File.dirname(__FILE__), 'active_record', 'setup_ar.rb')
+
+require File.join(File.dirname(__FILE__), '..', 'lib', 'apn_on_rails')
+
+Dir.glob(File.join(File.dirname(__FILE__), 'factories', '*.rb')).sort.each do |f|
+ require f
+end
+
+Spec::Runner.configure do |config|
+
+ config.before(:all) do
+
+ end
+
+ config.after(:all) do
+
+ end
+
+ config.before(:each) do
+
+ end
+
+ config.after(:each) do
+
+ end
+
+end
Please sign in to comment.
Something went wrong with that request. Please try again.