c2dm_on_rails 0.1.5
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.
- data/CHANGELOG +1 -0
- data/LICENSE +21 -0
- data/Manifest +17 -0
- data/README.textile +153 -0
- data/Rakefile +12 -0
- data/c2dm_on_rails.gemspec +36 -0
- data/generators/c2dm_migrations_generator.rb +31 -0
- data/generators/templates/c2dm_migrations/001_create_c2dm_devices.rb +16 -0
- data/generators/templates/c2dm_migrations/002_create_c2dm_notifications.rb +21 -0
- data/lib/c2dm_on_rails.rb +4 -0
- data/lib/c2dm_on_rails/app/models/c2dm/base.rb +9 -0
- data/lib/c2dm_on_rails/app/models/c2dm/device.rb +30 -0
- data/lib/c2dm_on_rails/app/models/c2dm/notification.rb +82 -0
- data/lib/c2dm_on_rails/c2dm_on_rails.rb +139 -0
- data/lib/c2dm_on_rails/libs/connection.rb +36 -0
- data/lib/c2dm_on_rails/tasks/c2dm.rake +11 -0
- data/lib/c2dm_on_rails_tasks.rb +3 -0
- metadata +130 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.5 Initial release
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2009 Julius de Bruijn, Digia Plc
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
LICENSE
|
3
|
+
Manifest
|
4
|
+
README.textile
|
5
|
+
Rakefile
|
6
|
+
c2dm_on_rails.gemspec
|
7
|
+
generators/c2dm_migrations_generator.rb
|
8
|
+
generators/templates/c2dm_migrations/001_create_c2dm_devices.rb
|
9
|
+
generators/templates/c2dm_migrations/002_create_c2dm_notifications.rb
|
10
|
+
lib/c2dm_on_rails.rb
|
11
|
+
lib/c2dm_on_rails/app/models/c2dm/base.rb
|
12
|
+
lib/c2dm_on_rails/app/models/c2dm/device.rb
|
13
|
+
lib/c2dm_on_rails/app/models/c2dm/notification.rb
|
14
|
+
lib/c2dm_on_rails/c2dm_on_rails.rb
|
15
|
+
lib/c2dm_on_rails/libs/connection.rb
|
16
|
+
lib/c2dm_on_rails/tasks/c2dm.rake
|
17
|
+
lib/c2dm_on_rails_tasks.rb
|
data/README.textile
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
h1. C2dm on Rails (Android push notifications on Rails)
|
2
|
+
|
3
|
+
APN on Rails is a Ruby on Rails gem that allows you to easily add Apple Push Notification (iPhone)
|
4
|
+
support to your Rails application.
|
5
|
+
|
6
|
+
C2dm on Rails is a Ruby on Rails gem that allows you to easily add Android push notification
|
7
|
+
(Android 2.2> devices) to your Rails application.
|
8
|
+
|
9
|
+
h2. Acknowledgements:
|
10
|
+
|
11
|
+
This gem is under construction and is forked from our project. The developer
|
12
|
+
has some allocated hours for developing the gem further. The gem is tested
|
13
|
+
quite lightly and not in production environment yet.
|
14
|
+
|
15
|
+
This gem is a re-write of a plugin that was written by Fabien Penso and Sam Soffes.
|
16
|
+
Their plugin was a great start, but it just didn't quite reach the level I hoped it would.
|
17
|
+
I've re-written, as a gem, added a ton of tests, and I would like to think that I made it
|
18
|
+
a little nicer and easier to use.
|
19
|
+
|
20
|
+
This gem is a re-write of a apn_on_rails gem that was written by Mark Bates and
|
21
|
+
before he made it a gem, it was started by Fabien Penso and Sam Soffes. The gem
|
22
|
+
installation, migration generation and usage is copied from the original apn_on_rails
|
23
|
+
gem. This is also my first rubygem, so please feel free to fix some oditties and please
|
24
|
+
comment also.
|
25
|
+
|
26
|
+
h2. Requirements:
|
27
|
+
|
28
|
+
First it is necessary to sign up to Android Cloud to Device Messaging service.
|
29
|
+
You need a role account email, it's password and the name of your Android app for
|
30
|
+
configuring the c2dm gem.
|
31
|
+
|
32
|
+
Sign up here:
|
33
|
+
|
34
|
+
"http://code.google.com/android/c2dm/signup.html":http://code.google.com/android/c2dm/signup.html
|
35
|
+
|
36
|
+
h2. Installing:
|
37
|
+
|
38
|
+
h3. Stable (RubyForge):
|
39
|
+
|
40
|
+
<pre><code>
|
41
|
+
$ sudo gem install c2dm_on_rails
|
42
|
+
</code></pre>
|
43
|
+
|
44
|
+
h3. Rails Gem Management:
|
45
|
+
|
46
|
+
If you like to use the built in Rails gem management:
|
47
|
+
|
48
|
+
<pre><code>
|
49
|
+
config.gem 'c2dm_on_rails'
|
50
|
+
</code></pre>
|
51
|
+
|
52
|
+
h2. Setup and Configuration:
|
53
|
+
|
54
|
+
Once you have the gem installed via your favorite gem installation, you need to require it so you can
|
55
|
+
start to use it:
|
56
|
+
|
57
|
+
Add the following require, wherever it makes sense to you:
|
58
|
+
|
59
|
+
<pre><code>
|
60
|
+
require 'c2dm_on_rails'
|
61
|
+
</code></pre>
|
62
|
+
|
63
|
+
You also need to add the following to your Rakefile so you can use the
|
64
|
+
Rake tasks that ship with C2dm on Rails:
|
65
|
+
|
66
|
+
<pre><code>
|
67
|
+
begin
|
68
|
+
require 'c2dm_on_rails_tasks'
|
69
|
+
rescue MissingSourceFile => e
|
70
|
+
puts e.message
|
71
|
+
end
|
72
|
+
</code></pre>
|
73
|
+
|
74
|
+
Now, to create the tables you need for C2dm on Rails, run the following task:
|
75
|
+
|
76
|
+
<pre><code>
|
77
|
+
$ ruby script/generate c2dm_migrations
|
78
|
+
</code></pre>
|
79
|
+
|
80
|
+
C2dm on Rails uses the Configatron gem, "http://github.com/markbates/configatron/tree/master":http://github.com/markbates/configatron/tree/master,
|
81
|
+
to configure itself. C2dm on Rails has the following default configurations that you change as you
|
82
|
+
see fit:
|
83
|
+
|
84
|
+
<pre><code>
|
85
|
+
configatron.c2dm.api_url = 'https://android.apis.google.com/c2dm/send'
|
86
|
+
</code></pre>
|
87
|
+
|
88
|
+
C2dm on Rails uses also the gdata gem for connecting a Google account. The
|
89
|
+
config file for Google Connect (config/c2dm.yml) should look like this:
|
90
|
+
|
91
|
+
<pre><code>
|
92
|
+
development:
|
93
|
+
username: your_user_name
|
94
|
+
password: password_for_the_account
|
95
|
+
app_name: your_applications_name
|
96
|
+
|
97
|
+
production:
|
98
|
+
... etc
|
99
|
+
</code></pre>
|
100
|
+
|
101
|
+
That's it, now you're ready to start creating notifications.
|
102
|
+
|
103
|
+
h3. Upgrade Notes:
|
104
|
+
|
105
|
+
If you are upgrading to a new version of APN on Rails you should always run:
|
106
|
+
|
107
|
+
<pre><code>
|
108
|
+
$ ruby script/generate c2dm_migrations
|
109
|
+
</code></pre>
|
110
|
+
|
111
|
+
That way you ensure you have the latest version of the database tables needed.
|
112
|
+
|
113
|
+
h2. Example:
|
114
|
+
|
115
|
+
More information about C2dm services should be read from "http://code.google.com/android/c2dm/":http://code.google.com/android/c2dm/
|
116
|
+
|
117
|
+
<pre><code>
|
118
|
+
$ ./script/console
|
119
|
+
>> device = C2dm::Device.create(:registration_id => "XXXXXXXXXXXXXXXXXXXXXX")
|
120
|
+
>> notification = C2dm::Notification.new
|
121
|
+
>> notification.device = device
|
122
|
+
>> notification.collapse_key = "private_message"
|
123
|
+
>> notification.delay_while_idle = true
|
124
|
+
>> notification.data = {"sender_id" => "420", "message_text" => "Wanna go for a ride?"}
|
125
|
+
>> notification.save
|
126
|
+
</code></pre>
|
127
|
+
|
128
|
+
You can use the following Rake task to deliver your notifications:
|
129
|
+
|
130
|
+
<pre><code>
|
131
|
+
$ rake c2dm:notifications:deliver
|
132
|
+
</code></pre>
|
133
|
+
|
134
|
+
The Rake task will find any unsent notifications in the database. If there aren't any notifications
|
135
|
+
it will simply do nothing. If there are notifications waiting to be delivered it will login with the provided
|
136
|
+
login data and send notifications using HTTP POST to Google. The client can get an error from Google. There are
|
137
|
+
several possibilities:
|
138
|
+
|
139
|
+
|code 200| |
|
140
|
+
| |Error: QuotaExceeded. It will cancel the notification sending and user should try to send them again after a while.|
|
141
|
+
| |Error: DeviceQuotaExceeded. It will cancel the notification sending for the current device and continue from the other devices.|
|
142
|
+
| |Error: InvalidRegistration. The devices registration_id is missing or invalid. The device and all its notifications will be deleted.|
|
143
|
+
| |Error: NotRegistred. The registration_id is no longer valid. The device and all its notifications will be deleted.|
|
144
|
+
| |Error: MessageTooBig. The maximum size of a c2dm push notification is 1024 bytes. User should reduce the size and try again.|
|
145
|
+
| |Error: MissingCollapseKey. Google uses a property called collapse_key to collapse a group of like messages when the device is online, so that only the last message is sent to the client. It is required.|
|
146
|
+
|
147
|
+
|code 503| |
|
148
|
+
| |The server is currently unavailable. The sending process is stopped and sender must retry later. Senders that retry too often and too fast risk being blacklisted.|
|
149
|
+
|
150
|
+
|code 401| |
|
151
|
+
| |The ClientLogin auth is invalid. Check the config file.|
|
152
|
+
|
153
|
+
Released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('c2dm_on_rails', '0.1.5') do |p|
|
6
|
+
p.description = "Android push notifications on Rails."
|
7
|
+
p.url = "http://github.com/pimeys/c2dm_on_rails"
|
8
|
+
p.author = "Julius de Bruijn"
|
9
|
+
p.email = "julius.debruijn@digia.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
11
|
+
p.development_dependencies = ["gdata >=1.1.1", "configatron >=2.6.3"]
|
12
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{c2dm_on_rails}
|
5
|
+
s.version = "0.1.5"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Julius de Bruijn"]
|
9
|
+
s.date = %q{2010-12-09}
|
10
|
+
s.description = %q{Android push notifications on Rails.}
|
11
|
+
s.email = %q{julius.debruijn@digia.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.textile", "lib/c2dm_on_rails.rb", "lib/c2dm_on_rails/app/models/c2dm/base.rb", "lib/c2dm_on_rails/app/models/c2dm/device.rb", "lib/c2dm_on_rails/app/models/c2dm/notification.rb", "lib/c2dm_on_rails/c2dm_on_rails.rb", "lib/c2dm_on_rails/libs/connection.rb", "lib/c2dm_on_rails/tasks/c2dm.rake", "lib/c2dm_on_rails_tasks.rb"]
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.textile", "Rakefile", "c2dm_on_rails.gemspec", "generators/c2dm_migrations_generator.rb", "generators/templates/c2dm_migrations/001_create_c2dm_devices.rb", "generators/templates/c2dm_migrations/002_create_c2dm_notifications.rb", "lib/c2dm_on_rails.rb", "lib/c2dm_on_rails/app/models/c2dm/base.rb", "lib/c2dm_on_rails/app/models/c2dm/device.rb", "lib/c2dm_on_rails/app/models/c2dm/notification.rb", "lib/c2dm_on_rails/c2dm_on_rails.rb", "lib/c2dm_on_rails/libs/connection.rb", "lib/c2dm_on_rails/tasks/c2dm.rake", "lib/c2dm_on_rails_tasks.rb"]
|
14
|
+
s.homepage = %q{http://github.com/pimeys/c2dm_on_rails}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "C2dm_on_rails", "--main", "README.textile"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{c2dm_on_rails}
|
18
|
+
s.rubygems_version = %q{1.3.7}
|
19
|
+
s.summary = %q{Android push notifications on Rails.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_development_dependency(%q<gdata>, [">= 1.1.1"])
|
27
|
+
s.add_development_dependency(%q<configatron>, [">= 2.6.3"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<gdata>, [">= 1.1.1"])
|
30
|
+
s.add_dependency(%q<configatron>, [">= 2.6.3"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<gdata>, [">= 1.1.1"])
|
34
|
+
s.add_dependency(%q<configatron>, [">= 2.6.3"])
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rails_generator'
|
2
|
+
# Generates the migrations necessary for C2dm on Rails.
|
3
|
+
# This should be run upon install and upgrade of the
|
4
|
+
# C2dm on Rails gem.
|
5
|
+
#
|
6
|
+
# $ ruby script/generate c2dm_migrations
|
7
|
+
class C2dmMigrationsGenerator < Rails::Generator::Base
|
8
|
+
|
9
|
+
def manifest # :nodoc:
|
10
|
+
record do |m|
|
11
|
+
timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
12
|
+
db_migrate_path = File.join('db', 'migrate')
|
13
|
+
|
14
|
+
m.directory(db_migrate_path)
|
15
|
+
|
16
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'templates', 'c2dm_migrations', '*.rb')).sort.each_with_index do |f, i|
|
17
|
+
f = File.basename(f)
|
18
|
+
f.match(/\d+\_(.+)/)
|
19
|
+
timestamp = timestamp.succ
|
20
|
+
if Dir.glob(File.join(db_migrate_path, "*_#{$1}")).empty?
|
21
|
+
m.file(File.join('c2dm_migrations', f),
|
22
|
+
File.join(db_migrate_path, "#{timestamp}_#{$1}"),
|
23
|
+
{:collision => :skip})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end # record
|
28
|
+
|
29
|
+
end # manifest
|
30
|
+
|
31
|
+
end # C2dmMigrationsGenerator
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateC2dmDevices < ActiveRecord::Migration # :nodoc:
|
2
|
+
def self.up
|
3
|
+
create_table :c2dm_devices do |t|
|
4
|
+
t.string :registration_id, :size => 120, :null => false
|
5
|
+
t.datetime :last_registered_at
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :c2dm_devices, :registration_id, :unique => true
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :c2dm_devices
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateC2dmNotifications < ActiveRecord::Migration # :nodoc:
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
|
5
|
+
create_table :c2dm_notifications do |t|
|
6
|
+
t.integer :device_id, :null => false
|
7
|
+
t.string :collapse_key, :null => false
|
8
|
+
t.text :data
|
9
|
+
t.boolean :delay_while_idle
|
10
|
+
t.datetime :sent_at
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
add_index :c2dm_notifications, :device_id
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.down
|
18
|
+
drop_table :c2dm_notifications
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Represents an Android phone.
|
2
|
+
# An C2dm::Device can have many C2dm::Notification.
|
3
|
+
#
|
4
|
+
# In order for the C2dm::Feedback system to work properly you *MUST*
|
5
|
+
# touch the <tt>last_registered_at</tt> column everytime someone opens
|
6
|
+
# your application. If you do not, then it is possible, and probably likely,
|
7
|
+
# that their device will be removed and will no longer receive notifications.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# Device.create(:registration_id => 'FOOBAR')
|
11
|
+
class C2dm::Device < C2dm::Base
|
12
|
+
|
13
|
+
has_many :notifications, :class_name => 'C2dm::Notification', :dependent => :destroy
|
14
|
+
|
15
|
+
validates_presence_of :registration_id
|
16
|
+
validates_uniqueness_of :registration_id
|
17
|
+
|
18
|
+
before_save :set_last_registered_at
|
19
|
+
|
20
|
+
# The <tt>feedback_at</tt> accessor is set when the
|
21
|
+
# device is marked as potentially disconnected from your
|
22
|
+
# application by Google.
|
23
|
+
attr_accessor :feedback_at
|
24
|
+
|
25
|
+
private
|
26
|
+
def set_last_registered_at
|
27
|
+
self.last_registered_at = Time.now if self.last_registered_at.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
# Represents the message you wish to send.
|
5
|
+
# An C2dm::Notification belongs to an C2dm::Device.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# c2dm = C2dm::Notification.new
|
9
|
+
# c2dm.key = "value"
|
10
|
+
# c2dm.device = APN::Device.find(1)
|
11
|
+
# c2dm.save
|
12
|
+
#
|
13
|
+
# To deliver call the following method:
|
14
|
+
# C2dm::Notification.send_notifications
|
15
|
+
#
|
16
|
+
# As each C2dm::Notification is sent the <tt>sent_at</tt> column will be timestamped,
|
17
|
+
# so as to not be sent again.
|
18
|
+
class C2dm::Notification < C2dm::Base
|
19
|
+
include ::ActionView::Helpers::TextHelper
|
20
|
+
extend ::ActionView::Helpers::TextHelper
|
21
|
+
serialize :data
|
22
|
+
|
23
|
+
belongs_to :device, :class_name => 'C2dm::Device'
|
24
|
+
|
25
|
+
class << self
|
26
|
+
|
27
|
+
# Opens a connection to the Google C2dm server and attempts to batch deliver
|
28
|
+
# an Array of notifications.
|
29
|
+
#
|
30
|
+
# This method expects an Array of C2dm::Notifications. If no parameter is passed
|
31
|
+
# in then it will use the following:
|
32
|
+
# C2dm::Notification.all(:conditions => {:sent_at => nil})
|
33
|
+
#
|
34
|
+
# As each C2dm::Notification is sent the <tt>sent_at</tt> column will be timestamped,
|
35
|
+
# so as to not be sent again.
|
36
|
+
#
|
37
|
+
# This can be run from the following Rake task:
|
38
|
+
# $ rake c2dm:notifications:deliver
|
39
|
+
def send_notifications(notifications = C2dm::Notification.all(:conditions => {:sent_at => nil}))
|
40
|
+
unless notifications.nil? || notifications.empty?
|
41
|
+
C2dm::Connection.open do |token|
|
42
|
+
notifications.each do |noty|
|
43
|
+
response = C2dm::Connection.send_notification(noty, token)
|
44
|
+
if response[:code] == 200
|
45
|
+
case response[:message]
|
46
|
+
when "Error=QuotaExceeded"
|
47
|
+
raise C2dm::Errors::QuotaExceeded.new(response[:message])
|
48
|
+
when "Error=DeviceQuotaExceeded"
|
49
|
+
ex = C2dm::Errors::DeviceQuotaExceeded.new(response[:message])
|
50
|
+
logger.warn(ex.message)
|
51
|
+
when "Error=InvalidRegistration"
|
52
|
+
ex = C2dm::Errors::InvalidRegistration.new(response[:message])
|
53
|
+
logger.warn("#{ex.message}, destroying c2dm_device with id #{noty.device.id}")
|
54
|
+
noty.device.destroy
|
55
|
+
when "Error=NotRegistered"
|
56
|
+
ex = C2dm::Errors::NotRegistered.new(response[:message])
|
57
|
+
logger.warn("#{ex.message}, destroying c2dm_device with id #{noty.device.id}")
|
58
|
+
noty.device.destroy
|
59
|
+
when "Error=MessageTooBig"
|
60
|
+
ex = C2dm::Errors::MessageTooBig.new(response[:message])
|
61
|
+
logger.warn(ex.message)
|
62
|
+
when "Error=MissingCollapseKey"
|
63
|
+
ex = C2dm::Errors::MissingCollapseKey.new(response[:message])
|
64
|
+
logger.warn(ex.message)
|
65
|
+
else
|
66
|
+
noty.sent_at = Time.now
|
67
|
+
noty.save!
|
68
|
+
end
|
69
|
+
elsif response[:code] == 503
|
70
|
+
raise C2dm::Errors:ServiceUnavailable.new(response[:message])
|
71
|
+
elsif response[:code] == 401
|
72
|
+
raise C2dm::Errors::InvalidAuthToken.new(response[:message])
|
73
|
+
else
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end # class << self
|
81
|
+
|
82
|
+
end # C2dm::Notification
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'configatron'
|
2
|
+
require 'gdata'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
rails_root = File.join(FileUtils.pwd, 'rails_root')
|
6
|
+
if defined?(RAILS_ROOT)
|
7
|
+
rails_root = RAILS_ROOT
|
8
|
+
end
|
9
|
+
|
10
|
+
rails_env = 'development'
|
11
|
+
if defined?(RAILS_ENV)
|
12
|
+
rails_env = RAILS_ENV
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/c2dm.yml")[rails_env]
|
17
|
+
rescue ex
|
18
|
+
raise C2dm::Errors.ConfigFileNotFound.new(ex.message)
|
19
|
+
end
|
20
|
+
|
21
|
+
begin
|
22
|
+
configatron.c2dm.api_url = URI.parse('https://android.apis.google.com/c2dm/send')
|
23
|
+
configatron.c2dm.username = APP_CONFIG['username']
|
24
|
+
configatron.c2dm.password = APP_CONFIG['password']
|
25
|
+
configatron.c2dm.app_name = APP_CONFIG['app_name']
|
26
|
+
rescue ex
|
27
|
+
raise C2dm::Errors.ConfigFileMissingAttributes.new(ex.message)
|
28
|
+
end
|
29
|
+
|
30
|
+
module C2dm # :nodoc:
|
31
|
+
|
32
|
+
module Errors # :nodoc:
|
33
|
+
|
34
|
+
# The payload of the message is too big, the limit is currently 1024
|
35
|
+
# bytes. Reduce the size of the message.
|
36
|
+
class MessageTooBig < StandardError
|
37
|
+
|
38
|
+
def initialize(message) # :nodoc:
|
39
|
+
super("The maximum size allowed for a notification payload is 1024 bytes: '#{message}'")
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# Too many messages sent by the sender. Retry after a while.
|
45
|
+
class QuotaExceeded < StandardError
|
46
|
+
|
47
|
+
def initialize(message) # :nodoc:
|
48
|
+
super("Too many messages sent by the sender: '#{message}'")
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
# Too many messages sent by the sender to a specific device. Retry after a
|
54
|
+
# while.
|
55
|
+
class DeviceQuotaExceeded < StandardError
|
56
|
+
|
57
|
+
def initialize(message) # :nodoc:
|
58
|
+
super("Too many messages sent by the sender to a specific device: '#{message}'")
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
# Missing or bad registration_id. Sender should stop sending messages to
|
64
|
+
# this device.
|
65
|
+
class InvalidRegistration < StandardError
|
66
|
+
|
67
|
+
def initialize(message) # :nodoc:
|
68
|
+
super("Missing or bad registration_id: '#{message}'")
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# The registration_id is no longer valid, for example user has uninstalled
|
74
|
+
# the application or turned off notifications. Sender should stop sending
|
75
|
+
# messages to this device.
|
76
|
+
class NotRegistered < StandardError
|
77
|
+
|
78
|
+
def initialize(message) # :nodoc:
|
79
|
+
super("The registration_id is no longer valid: '#{message}'")
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# Collapse key is required. Include collapse key in the request.
|
85
|
+
class MissingCollapseKey < StandardError
|
86
|
+
|
87
|
+
def initialize(message) # :nodoc:
|
88
|
+
super("Collapse key is required: '#{message}'")
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# ClientLogin AUTH_TOKEN is invalid. Check the config
|
94
|
+
class InvalidAuthToken < StandardError
|
95
|
+
|
96
|
+
def initialize(message)
|
97
|
+
super("Invalid auth token: '#{message}'")
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
class ConfigFileNotFound < StandardError
|
103
|
+
|
104
|
+
def initialize(message)
|
105
|
+
super("The config file c2dm.yml not found from config/ directory or contains errors: '#{message}'")
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class ConfigFileMissingAttributes < StandardError
|
111
|
+
|
112
|
+
def initialize(message)
|
113
|
+
super("Config file doesn't contain username, password or app_name: '#{message}'")
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
class ServiceUnavailable < StandardError
|
119
|
+
|
120
|
+
def initialize(message)
|
121
|
+
super("Service is currently unavailable. Try again later: '#{message}'")
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end # Errors
|
126
|
+
|
127
|
+
end # APN
|
128
|
+
|
129
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'app', 'models', 'c2dm', '*.rb')).sort.each do |f|
|
130
|
+
require f
|
131
|
+
end
|
132
|
+
|
133
|
+
%w{ models controllers helpers }.each do |dir|
|
134
|
+
path = File.join(File.dirname(__FILE__), 'app', dir)
|
135
|
+
$LOAD_PATH << path
|
136
|
+
# puts "Adding #{path}"
|
137
|
+
ActiveSupport::Dependencies.load_paths << path
|
138
|
+
ActiveSupport::Dependencies.load_once_paths.delete(path)
|
139
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'gdata'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
module C2dm
|
5
|
+
module Connection
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def send_notification(noty, token)
|
9
|
+
headers = { "Content-Type" => "application/x-www-form-urlencoded",
|
10
|
+
"Authorization" => "GoogleLogin auth=#{token}" }
|
11
|
+
|
12
|
+
message_data = noty.data.map{|k, v| "&data.#{k}=#{v}"}.reduce{|k, v| k + v}
|
13
|
+
data = "registration_id=#{noty.device.registration_id}&collapse_key=#{noty.collapse_key}#{message_data}"
|
14
|
+
|
15
|
+
data = data + "&delay_while_idle" if noty.delay_while_idle
|
16
|
+
|
17
|
+
url = configatron.c2dm.api_url
|
18
|
+
http = Net::HTTP.new(url.host, url.port)
|
19
|
+
http.use_ssl = true
|
20
|
+
|
21
|
+
resp, dat = http.post(url.path, data, headers)
|
22
|
+
|
23
|
+
return {:code => resp.code.to_i, :message => dat}
|
24
|
+
end
|
25
|
+
|
26
|
+
def open
|
27
|
+
client_login_handler = GData::Auth::ClientLogin.new('ac2dm', :account_type => 'HOSTED_OR_GOOGLE')
|
28
|
+
token = client_login_handler.get_token(configatron.c2dm.username,
|
29
|
+
configatron.c2dm.password,
|
30
|
+
configatron.c2dm.app_name)
|
31
|
+
|
32
|
+
yield token
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end # Connection
|
36
|
+
end # C2dm
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: c2dm_on_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 5
|
10
|
+
version: 0.1.5
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Julius de Bruijn
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-09 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: gdata
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 17
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 1
|
33
|
+
- 1
|
34
|
+
version: 1.1.1
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: configatron
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 17
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 6
|
49
|
+
- 3
|
50
|
+
version: 2.6.3
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
description: Android push notifications on Rails.
|
54
|
+
email: julius.debruijn@digia.com
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files:
|
60
|
+
- CHANGELOG
|
61
|
+
- LICENSE
|
62
|
+
- README.textile
|
63
|
+
- lib/c2dm_on_rails.rb
|
64
|
+
- lib/c2dm_on_rails/app/models/c2dm/base.rb
|
65
|
+
- lib/c2dm_on_rails/app/models/c2dm/device.rb
|
66
|
+
- lib/c2dm_on_rails/app/models/c2dm/notification.rb
|
67
|
+
- lib/c2dm_on_rails/c2dm_on_rails.rb
|
68
|
+
- lib/c2dm_on_rails/libs/connection.rb
|
69
|
+
- lib/c2dm_on_rails/tasks/c2dm.rake
|
70
|
+
- lib/c2dm_on_rails_tasks.rb
|
71
|
+
files:
|
72
|
+
- CHANGELOG
|
73
|
+
- LICENSE
|
74
|
+
- Manifest
|
75
|
+
- README.textile
|
76
|
+
- Rakefile
|
77
|
+
- c2dm_on_rails.gemspec
|
78
|
+
- generators/c2dm_migrations_generator.rb
|
79
|
+
- generators/templates/c2dm_migrations/001_create_c2dm_devices.rb
|
80
|
+
- generators/templates/c2dm_migrations/002_create_c2dm_notifications.rb
|
81
|
+
- lib/c2dm_on_rails.rb
|
82
|
+
- lib/c2dm_on_rails/app/models/c2dm/base.rb
|
83
|
+
- lib/c2dm_on_rails/app/models/c2dm/device.rb
|
84
|
+
- lib/c2dm_on_rails/app/models/c2dm/notification.rb
|
85
|
+
- lib/c2dm_on_rails/c2dm_on_rails.rb
|
86
|
+
- lib/c2dm_on_rails/libs/connection.rb
|
87
|
+
- lib/c2dm_on_rails/tasks/c2dm.rake
|
88
|
+
- lib/c2dm_on_rails_tasks.rb
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: http://github.com/pimeys/c2dm_on_rails
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options:
|
95
|
+
- --line-numbers
|
96
|
+
- --inline-source
|
97
|
+
- --title
|
98
|
+
- C2dm_on_rails
|
99
|
+
- --main
|
100
|
+
- README.textile
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 11
|
118
|
+
segments:
|
119
|
+
- 1
|
120
|
+
- 2
|
121
|
+
version: "1.2"
|
122
|
+
requirements: []
|
123
|
+
|
124
|
+
rubyforge_project: c2dm_on_rails
|
125
|
+
rubygems_version: 1.3.7
|
126
|
+
signing_key:
|
127
|
+
specification_version: 3
|
128
|
+
summary: Android push notifications on Rails.
|
129
|
+
test_files: []
|
130
|
+
|