gcm_rails_mongo_mapper 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -0
- data/Gemfile.lock +26 -0
- data/LICENSE.txt +20 -0
- data/README.textile +129 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/lib/gcm_rails_mongo_mapper/app/models/gcm/base.rb +5 -0
- data/lib/gcm_rails_mongo_mapper/app/models/gcm/device.rb +37 -0
- data/lib/gcm_rails_mongo_mapper/app/models/gcm/notification.rb +103 -0
- data/lib/gcm_rails_mongo_mapper/gcm_rails_mongo_mapper.rb +88 -0
- data/lib/gcm_rails_mongo_mapper/libs/connection.rb +44 -0
- data/lib/gcm_rails_mongo_mapper/tasks/gcm.rake +9 -0
- data/lib/gcm_rails_mongo_mapper.rb +3 -0
- data/lib/gcm_rails_mongo_mapper_tasks.rb +3 -0
- data/lib/generators/gcm_migrations_generator.rb +32 -0
- data/lib/generators/templates/gcm_migrations/create_gcm_devices.rb +16 -0
- data/lib/generators/templates/gcm_migrations/create_gcm_notifications.rb +21 -0
- metadata +146 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
configatron (2.9.1)
|
5
|
+
yamler (>= 0.1.0)
|
6
|
+
git (1.2.5)
|
7
|
+
jeweler (1.8.4)
|
8
|
+
bundler (~> 1.0)
|
9
|
+
git (>= 1.2.5)
|
10
|
+
rake
|
11
|
+
rdoc
|
12
|
+
json (1.7.3)
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rdoc (3.12)
|
15
|
+
json (~> 1.4)
|
16
|
+
yamler (0.1.0)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
bundler (~> 1.0.0)
|
23
|
+
configatron
|
24
|
+
jeweler (~> 1.8.4)
|
25
|
+
json
|
26
|
+
rdoc (~> 3.12)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Dennis Ondeng
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
h1. Gcm on Rails (Google Cloud Messaging for Android on Rails)
|
2
|
+
|
3
|
+
Gcm on Rails (gcm_on_rails) is a Ruby on Rails gem that allows you to easily incorporate Google's 'Google Cloud Messaging for Android' into your Rails application. This gem was derived from c2dm_on_rails (https://github.com/pimeys/c2dm_on_rails) after Google deprecated C2DM on June 27, 2012
|
4
|
+
|
5
|
+
h2. Acknowledgements:
|
6
|
+
|
7
|
+
This gem was derived from Julius de Bruijn's gem c2dm_on_rails which according to him, was originally a rewrite of the gem
|
8
|
+
apn_on_rails written by Mark Bates and before him Fabien Penso and Sam Soffes. Thanks to all the above who were involved in
|
9
|
+
earlier versions or derivatives of the gem. I originally wanted to use the c2dm_on_rails gem for a project at Kopo Kopo, Inc
|
10
|
+
and the rug was pulled from under me when Google deprecated C2DM in favor of GCM (Google Cloud Messaging). I thus decided to
|
11
|
+
create an updated gem. This is also my first rubygem so please feel free to fix or add on anything you may see fit.
|
12
|
+
|
13
|
+
h2. Requirements:
|
14
|
+
|
15
|
+
You will have to sign up to GCM first via the Google APIs Console page (https://code.google.com/apis/console).
|
16
|
+
When you create an new API project, the browser url will change to something like:
|
17
|
+
<pre><code>
|
18
|
+
https://code.google.com/apis/console/#project:4815162342
|
19
|
+
</code></pre>
|
20
|
+
|
21
|
+
The value after #project (4815162342) in this example is the project ID and will be used later on as the GCM sender
|
22
|
+
ID. You will also need to obtain an Api Key and for detailed instructions on how to get one, follow the instructions
|
23
|
+
here:-
|
24
|
+
|
25
|
+
"http://developer.android.com/guide/google/gcm/gs.html":http://developer.android.com/guide/google/gcm/gs.html
|
26
|
+
|
27
|
+
GCM is designed to work on Android version 2.2 or greater, so only Android 2.2> devices are eligible. The device must
|
28
|
+
also have an active Google Account if the Android version is less than version 4.1
|
29
|
+
|
30
|
+
h2. Installing:
|
31
|
+
|
32
|
+
Installation is by simply adding the following to your Gemfile:
|
33
|
+
<pre><code>
|
34
|
+
gem 'gcm_on_rails'
|
35
|
+
</code></pre>
|
36
|
+
|
37
|
+
h2. Setup and Configuration
|
38
|
+
|
39
|
+
The following needs to be added to your Rakefile so that you can use the the Rake tasks that ship with gcm_on_rails:
|
40
|
+
<pre><code>
|
41
|
+
begin
|
42
|
+
require 'gcm_on_rails_tasks'
|
43
|
+
rescue MissingSourceFile => e
|
44
|
+
puts e.message
|
45
|
+
end
|
46
|
+
</code></pre>
|
47
|
+
|
48
|
+
To create the tables needed for Gcm on Rails, run the following task:
|
49
|
+
<pre><code>
|
50
|
+
$ rails generate gcm_migrations
|
51
|
+
</code></pre>
|
52
|
+
|
53
|
+
Gcm on Rails like its predecessor uses the Configatron gem, "http://github.com/markbates/configatron/tree/master":http://github.com/markbates/configatron/tree/master,
|
54
|
+
Some settings need to be loaded for configuration purposes. An initialzer script that can be put in config/initializers/gcm_on_rails.rb
|
55
|
+
will suffice. Below is an example of such a script.
|
56
|
+
<pre><code>
|
57
|
+
configatron.gcm_on_rails.api_url = 'https://android.googleapis.com/gcm/send'
|
58
|
+
configatron.gcm_on_rails.api_key = 'AAAAAAPPPPPPPIIIIIIIKKKKKEEEEYYYYY'
|
59
|
+
configatron.gcm_on_rails.app_name = 'com.yourapppackage.com'
|
60
|
+
configatron.gcm_on_rails.delivery_format = 'json'
|
61
|
+
</code></pre>
|
62
|
+
|
63
|
+
A couple of notes:
|
64
|
+
- The api_key is the api key that you received from Google when signing up for GCM
|
65
|
+
- Note that unlike the old C2dm on Rails, GCM on Rails switches to a simple API key for authentication. ClientLogin or OAuth2 tokens will NOT work.
|
66
|
+
- The app_name is simply the name of the pacakge of your Android app.
|
67
|
+
- GCM on Rails message requests can be either be sent in plain text or JSON format. Specify 'json' for JSON and 'plain_text' for plain text format.
|
68
|
+
|
69
|
+
That's it, you are now ready to start creating notifications.
|
70
|
+
|
71
|
+
h2. Upgrade Notes:
|
72
|
+
|
73
|
+
When upgrading to a new version of Gcm on Rails, you should alwasy run:
|
74
|
+
<pre><code>
|
75
|
+
$ rails generate gcm_migrations
|
76
|
+
</code></pre>
|
77
|
+
|
78
|
+
That way you are ensured to have the latest version of the database tables needed.
|
79
|
+
|
80
|
+
h2. Example:
|
81
|
+
|
82
|
+
Please note that a more detailed introduction to GCM is located at "http://developer.android.com/guide/google/gcm/index.html":http://developer.android.com/guide/google/gcm/index.html
|
83
|
+
<pre><code>
|
84
|
+
$ rails console
|
85
|
+
>> device = Gcm::Device.create(:registration_id => "XXXXXXXXXXXXXXXXXXXXXX")
|
86
|
+
>> notification = Gcm::Notification.new
|
87
|
+
>> notification.device = device
|
88
|
+
>> notification.collapse_key = "updates_available"
|
89
|
+
>> notification.delay_while_idle = true
|
90
|
+
>> notification.data = {:registration_ids => ["RegistrationID"], :data => {:message_text => "Get on cloud nine"}}
|
91
|
+
>> notification.save
|
92
|
+
</code></pre>
|
93
|
+
|
94
|
+
The following Rake task can then be used to deliver notifications:
|
95
|
+
<pre><code>
|
96
|
+
$ rake gcm:notifications:deliver
|
97
|
+
</code></pre>
|
98
|
+
|
99
|
+
The rake task will look for any unsent notifications in the database. If found, the notifications will then be dispatched
|
100
|
+
for delivery. If no unsent notifications exist, the Rake task simply does nothing. As described by Google, possible errors
|
101
|
+
from the GCM servers are:
|
102
|
+
|
103
|
+
|Code 200| |
|
104
|
+
| |Error: MissingRegistration. Happens when the request did not actually contain a registration_id parameter when in plain text format or registration_ids when in json format.|
|
105
|
+
| |Error: InvalidRegistration. The registration_id passed is not on the GCM servers. The device and all of its notifications will be deleted.|
|
106
|
+
| |Error: MismatchedSenderId. The sender Id that was passed is not one that the application specified as an allowed sender.|
|
107
|
+
| |Error: NotRegistered. An existing registration Id has ceased to be valid. The device and all of tis notifications will be deleted.|
|
108
|
+
| |Error: MessageTooBig. The total payload data that is in the message exceeds 4096 bytes.|
|
109
|
+
|
110
|
+
|Code 401| |
|
111
|
+
| |API Key is Invalid. Check the configuration file|
|
112
|
+
|
113
|
+
|Code 503| |
|
114
|
+
| |Service is unavailable and you should retry later. However, you must honor the 'Retry-After' header if it is included in the response from the GCM server.
|
115
|
+
Exponential backoff should be implemented in your retry mechanism.|
|
116
|
+
|
117
|
+
|Code 500| |
|
118
|
+
| |Internal server error. Retry again while still honoring 'Retry-After' header and using exponential backoff.|
|
119
|
+
|
120
|
+
|
121
|
+
h2. To-Do's:
|
122
|
+
|
123
|
+
- Tests, tests then some more tests. These need to be implemented.
|
124
|
+
- Implement "broadcasting" sending and processing responses to multiple registration id's within one request. Currently only one message to a single registration id is implemented.
|
125
|
+
|
126
|
+
|
127
|
+
Released under the MIT license.
|
128
|
+
Copyright (c) 2012 Dennis Ondeng. See LICENSE.txt for further details.
|
129
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "gcm_rails_mongo_mapper"
|
18
|
+
gem.homepage = "http://github.com/kkelani/gcm_rails_mongo_mapper"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Google Cloud Messaging for Android on Rails using MongoMapper}
|
21
|
+
gem.description = %Q{gcm_rails_mongo_mapper is a Ruby on Rails gem based on dondeng's gcm_on_rails gem (https://github.com/dondeng/gcm_on_rails). Same funcionality except this gem works with MongoMapper. This is my first gem so any feedback is greatly appreciated!}
|
22
|
+
gem.email = "kkelani@gmail.com"
|
23
|
+
gem.authors = ["Kevin Kelani"]
|
24
|
+
gem.version = "0.0.1"
|
25
|
+
# dependencies defined in Gemfile
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
|
30
|
+
require 'rdoc/task'
|
31
|
+
Rake::RDocTask.new do |rdoc|
|
32
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
33
|
+
|
34
|
+
rdoc.rdoc_dir = 'rdoc'
|
35
|
+
rdoc.title = "gcm_on_rails #{version}"
|
36
|
+
rdoc.rdoc_files.include('README*')
|
37
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.2
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Represents an Android phone.
|
2
|
+
# An Gcm::Device can have many Gcm::Notification.
|
3
|
+
#
|
4
|
+
# In order for the Gcm::Feedback system to work properly you *MUST*
|
5
|
+
# touch the <tt>last_registered_at</tt> column every time 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 Gcm::Device < Gcm::Base
|
12
|
+
#self.table_name = "gcm_devices"
|
13
|
+
set_collection_name "gcm_devices"
|
14
|
+
|
15
|
+
# Fields
|
16
|
+
key :registration_id, String
|
17
|
+
key :last_registered_at, DateTime
|
18
|
+
timestamps!
|
19
|
+
|
20
|
+
#has_many :notifications, :class_name => 'Gcm::Notification', :dependent => :destroy
|
21
|
+
many :notifications, :class_name => 'Gcm::Notification', :dependent => :destroy
|
22
|
+
|
23
|
+
validates_presence_of :registration_id
|
24
|
+
validates_uniqueness_of :registration_id
|
25
|
+
|
26
|
+
before_save :set_last_registered_at
|
27
|
+
|
28
|
+
# The <tt>feedback_at</tt> accessor is set when the
|
29
|
+
# device is marked as potentially disconnected from your
|
30
|
+
# application by Google.
|
31
|
+
attr_accessor :feedback_at
|
32
|
+
|
33
|
+
private
|
34
|
+
def set_last_registered_at
|
35
|
+
self.last_registered_at = Time.now if self.last_registered_at.nil?
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class Gcm::Notification < Gcm::Base
|
2
|
+
#self.table_name = "gcm_notifications"
|
3
|
+
set_collection_name "gcm_notifications"
|
4
|
+
|
5
|
+
key :collapse_key, String
|
6
|
+
key :delay_while_idle, Boolean
|
7
|
+
key :sent_at, DateTime
|
8
|
+
key :time_to_live, Integer
|
9
|
+
key :data, Hash
|
10
|
+
key :date, String
|
11
|
+
key :park_id, String
|
12
|
+
key :sport_id, String
|
13
|
+
timestamps!
|
14
|
+
|
15
|
+
include ::ActionView::Helpers::TextHelper
|
16
|
+
extend ::ActionView::Helpers::TextHelper
|
17
|
+
#serialize :data
|
18
|
+
|
19
|
+
belongs_to :device, :class_name => 'Gcm::Device'
|
20
|
+
validates_presence_of :collapse_key if :time_to_live?
|
21
|
+
|
22
|
+
class << self
|
23
|
+
# Opens a connection to the Google GCM server and attempts to batch deliver
|
24
|
+
# an Array of notifications.
|
25
|
+
#
|
26
|
+
# This method expects an Array of Gcm::Notifications. If no parameter is passed
|
27
|
+
# in then it will use the following:
|
28
|
+
# Gcm::Notification.all(:conditions => {:sent_at => nil})
|
29
|
+
#
|
30
|
+
# As each Gcm::Notification is sent the <tt>sent_at</tt> column will be timestamped,
|
31
|
+
# so as to not be sent again.
|
32
|
+
#
|
33
|
+
# This can be run from the following Rake task:
|
34
|
+
# $ rake gcm:notifications:deliver
|
35
|
+
def send_notifications(notifications = Gcm::Notification.all(:conditions => {:sent_at => nil}, :joins => :device, :readonly => false))
|
36
|
+
|
37
|
+
if configatron.gcm_on_rails.delivery_format and configatron.gcm_on_rails.delivery_format == 'plain_text'
|
38
|
+
format = "plain_text"
|
39
|
+
else
|
40
|
+
format = "json"
|
41
|
+
end
|
42
|
+
|
43
|
+
unless notifications.nil? || notifications.empty?
|
44
|
+
api_key = Gcm::Connection.open
|
45
|
+
if api_key
|
46
|
+
notifications.each do |notification|
|
47
|
+
#puts "sending notification #{notification.id} to device #{notification.device.registration_id}"
|
48
|
+
response = Gcm::Connection.send_notification(notification, api_key, format)
|
49
|
+
#puts "response: #{response[:code]}; #{response.inspect}"
|
50
|
+
if response[:code] == 200
|
51
|
+
if format == "json"
|
52
|
+
error = ""
|
53
|
+
message_data = JSON.parse response[:message]
|
54
|
+
success = message_data['success']
|
55
|
+
error = message_data['results'][0]['error'] if success == 0
|
56
|
+
else #format is plain text
|
57
|
+
message_data = response[:message]
|
58
|
+
error = response[:message].split('=')[1]
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
case error
|
63
|
+
when "MissingRegistration"
|
64
|
+
ex = Gcm::Errors::MissingRegistration.new(response[:message])
|
65
|
+
#logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}")
|
66
|
+
puts "#{ex.message}, destroying gcm_device with id #{notification.device.id}"
|
67
|
+
notification.device.destroy
|
68
|
+
when "InvalidRegistration"
|
69
|
+
ex = Gcm::Errors::InvalidRegistration.new(response[:message])
|
70
|
+
#logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}")
|
71
|
+
puts "#{ex.message}, destroying gcm_device with id #{notification.device.id}"
|
72
|
+
notification.device.destroy
|
73
|
+
when "MismatchedSenderId"
|
74
|
+
ex = Gcm::Errors::MismatchSenderId.new(response[:message])
|
75
|
+
#logger.warn(ex.message)
|
76
|
+
puts ex.message
|
77
|
+
when "NotRegistered"
|
78
|
+
ex = Gcm::Errors::NotRegistered.new(response[:message])
|
79
|
+
#logger.warn("#{ex.message}, destroying gcm_device with id #{notification.device.id}")
|
80
|
+
puts "#{ex.message}, destroying gcm_device with id #{notification.device.id}"
|
81
|
+
notification.device.destroy
|
82
|
+
when "MessageTooBig"
|
83
|
+
ex = Gcm::Errors::MessageTooBig.new(response[:message])
|
84
|
+
#logger.warn(ex.message)
|
85
|
+
puts ex.message
|
86
|
+
else
|
87
|
+
notification.sent_at = Time.now
|
88
|
+
notification.save!
|
89
|
+
end
|
90
|
+
elsif response[:code] == 401
|
91
|
+
raise Gcm::Errors::InvalidAuthToken.new(message_data)
|
92
|
+
elsif response[:code] == 503
|
93
|
+
raise Gcm::Errors::ServiceUnavailable.new(message_data)
|
94
|
+
elsif response[:code] == 500
|
95
|
+
raise Gcm::Errors::InternalServerError.new(message_data)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'configatron'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Gcm
|
5
|
+
module Errors
|
6
|
+
|
7
|
+
# Missing registration_id.
|
8
|
+
class MissingRegistration < StandardError
|
9
|
+
def initialize(message) # :nodoc:
|
10
|
+
super("Missing registration_id: '#{message}'")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Invalid registration_id. Check the formatting of the registration ID that is passed to the server. Make sure
|
15
|
+
# it matches the the registration ID the phone receives in the com.google.android.c2dm.intent.REGISTRATION intent
|
16
|
+
# and that it is not being truncated or additional characters being appended
|
17
|
+
class InvalidRegistration < StandardError
|
18
|
+
def initialize(message) # :nodoc:
|
19
|
+
super("Invalid registration_id: '#{message}'")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# A registration ID is tied to a certain group of senders. When an application registers for GCM usage, it must
|
24
|
+
# specify which senders are allowed to send messages.
|
25
|
+
class MismatchSenderId < StandardError
|
26
|
+
def initialize(message) # :nodoc
|
27
|
+
super("Mismatched Sender Id: '#{message}'")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# From Google:-
|
32
|
+
# An existing registration ID may cease to be valid in a number of scenarios, including:
|
33
|
+
# - If the application manually unregisters
|
34
|
+
# - If the application is automatically unregistered which can (but not guaranteed) to happen if the user
|
35
|
+
# uninstalls the application
|
36
|
+
# - If the registration ID expires. Google might decide to refresh registration IDs
|
37
|
+
#
|
38
|
+
# For all cases above, it is recommended that this registration ID is removed from the 3rd party server
|
39
|
+
class NotRegistered < StandardError
|
40
|
+
def initialize(message) # :nodoc
|
41
|
+
super("The registration_id is no longer valid: '#{message}'")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# The payload of the message is too big, the limit is currently 4096
|
46
|
+
# bytes. Reduce the size of the message.
|
47
|
+
class MessageTooBig < StandardError
|
48
|
+
def initialize(message) # :nodoc:
|
49
|
+
super("The maximum size allowed for a notification payload is 4096 bytes: '#{message}'")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# ClientLogin AUTH_TOKEN is invalid. Check the config
|
54
|
+
class InvalidAuthToken < StandardError
|
55
|
+
def initialize(message)
|
56
|
+
super("Invalid auth token: '#{message}'")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Indicates that server is temporarily unavailable (i.e because of timeouts, etc.)
|
61
|
+
# Sender must retry later, honoring any Retry-After header included in the response.
|
62
|
+
# Application servers must implement exponential back-off
|
63
|
+
class ServiceUnavailable < StandardError
|
64
|
+
def initialize(message)
|
65
|
+
super("Service is currently unavailable. Try again later: '#{message}'")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Indicates an internal server error with the GCM server
|
70
|
+
class InternalServerError < StandardError
|
71
|
+
def initialize(message)
|
72
|
+
super("The was an internal error in the GCM server while trying to process the request: '#{message}'")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'app', 'models', 'gcm', '*.rb')).sort.each do |f|
|
78
|
+
require f
|
79
|
+
end
|
80
|
+
|
81
|
+
%w{ models controllers helpers }.each do |dir|
|
82
|
+
path = File.join(File.dirname(__FILE__), 'app', dir)
|
83
|
+
$LOAD_PATH << path
|
84
|
+
# puts "Adding #{path}"
|
85
|
+
#ActiveSupport::Dependencies.autoload_paths << path
|
86
|
+
#ActiveSupport::Dependencies.autoload_once_paths.delete(path)
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Gcm
|
5
|
+
module Connection
|
6
|
+
class << self
|
7
|
+
def send_notification(notification, api_key, format)
|
8
|
+
|
9
|
+
if format == 'json'
|
10
|
+
headers = {"Content-Type" => "application/json",
|
11
|
+
"Authorization" => "key=#{api_key}"}
|
12
|
+
|
13
|
+
data = notification.data.merge({:collapse_key => notification.collapse_key}) unless notification.collapse_key.nil?
|
14
|
+
data = data.merge({:delay_while_idle => notification.delay_while_idle}) unless notification.delay_while_idle.nil?
|
15
|
+
data = data.merge({:time_to_live => notification.time_to_live}) unless notification.time_to_live.nil?
|
16
|
+
data = data.to_json
|
17
|
+
else #plain text format
|
18
|
+
headers = {"Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8",
|
19
|
+
"Authorization" => "key=#{api_key}"}
|
20
|
+
|
21
|
+
post_data = notification.data[:data].map{|k, v| "&data.#{k}=#{URI.escape(v)}".reduce{|k, v| k + v}}[0]
|
22
|
+
extra_data = "registration_id=#{notification.data[:registration_ids][0]}"
|
23
|
+
extra_data = "#{extra_data}&collapse_key=#{notification.collapse_key}" unless notification.collapse_key.nil?
|
24
|
+
extra_data = "#{extra_data}&delay_while_idle=1" if notification.delay_while_idle
|
25
|
+
data = "#{extra_data}#{post_data}"
|
26
|
+
end
|
27
|
+
|
28
|
+
url_string = configatron.gcm_on_rails.api_url
|
29
|
+
url = URI.parse url_string
|
30
|
+
http = Net::HTTP.new(url.host, url.port)
|
31
|
+
http.use_ssl = true
|
32
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
33
|
+
|
34
|
+
resp, dat = http.post(url.path, data, headers)
|
35
|
+
|
36
|
+
return {:code => resp.code.to_i, :message => dat }
|
37
|
+
end
|
38
|
+
|
39
|
+
def open
|
40
|
+
configatron.gcm_on_rails.api_key
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
# Generates the migrations necessary for Gcm on Rails.
|
3
|
+
# This should be run upon install and upgrade of the
|
4
|
+
# Gcm on Rails gem.
|
5
|
+
#
|
6
|
+
# $ ruby script/generate gcm_migrations
|
7
|
+
class GcmMigrationsGenerator < Rails::Generators::Base
|
8
|
+
include Rails::Generators::Migration
|
9
|
+
extend ActiveRecord::Generators::Migration
|
10
|
+
|
11
|
+
# Set the current directory as base for the inherited generators.
|
12
|
+
def self.base_root
|
13
|
+
File.dirname(__FILE__)
|
14
|
+
end
|
15
|
+
|
16
|
+
source_root File.expand_path('../templates/gcm_migrations', __FILE__)
|
17
|
+
|
18
|
+
def create_migrations
|
19
|
+
templates = {
|
20
|
+
'create_gcm_devices.rb' => 'db/migrate/create_gcm_devices.rb',
|
21
|
+
'create_gcm_notifications.rb' => 'db/migrate/create_gcm_notifications.rb'
|
22
|
+
}
|
23
|
+
|
24
|
+
templates.each_pair do |name, path|
|
25
|
+
begin
|
26
|
+
migration_template(name, path)
|
27
|
+
rescue => err
|
28
|
+
puts "WARNING: #{err.message}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end # GcmMigrationsGenerator
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateGcmDevices < ActiveRecord::Migration # :nodoc:
|
2
|
+
def self.up
|
3
|
+
create_table :gcm_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 :gcm_devices, :registration_id, :unique => true
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :gcm_devices
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateGcmNotifications < ActiveRecord::Migration # :nodoc:
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
|
5
|
+
create_table :gcm_notifications do |t|
|
6
|
+
t.integer :device_id, :null => false
|
7
|
+
t.string :collapse_key
|
8
|
+
t.text :data
|
9
|
+
t.boolean :delay_while_idle
|
10
|
+
t.datetime :sent_at
|
11
|
+
t.integer :time_to_live
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :gcm_notifications, :device_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.down
|
19
|
+
drop_table :gcm_notifications
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gcm_rails_mongo_mapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kevin Kelani
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: configatron
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: json
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.12'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.12'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.0.0
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: jeweler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.8.4
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.8.4
|
94
|
+
description: gcm_rails_mongo_mapper is a Ruby on Rails gem based on dondeng's gcm_on_rails
|
95
|
+
gem (https://github.com/dondeng/gcm_on_rails). Same funcionality except this gem
|
96
|
+
works with MongoMapper. This is my first gem so any feedback is greatly appreciated!
|
97
|
+
email: kkelani@gmail.com
|
98
|
+
executables: []
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files:
|
101
|
+
- LICENSE.txt
|
102
|
+
- README.textile
|
103
|
+
files:
|
104
|
+
- Gemfile
|
105
|
+
- Gemfile.lock
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.textile
|
108
|
+
- Rakefile
|
109
|
+
- VERSION
|
110
|
+
- lib/gcm_rails_mongo_mapper.rb
|
111
|
+
- lib/gcm_rails_mongo_mapper/app/models/gcm/base.rb
|
112
|
+
- lib/gcm_rails_mongo_mapper/app/models/gcm/device.rb
|
113
|
+
- lib/gcm_rails_mongo_mapper/app/models/gcm/notification.rb
|
114
|
+
- lib/gcm_rails_mongo_mapper/gcm_rails_mongo_mapper.rb
|
115
|
+
- lib/gcm_rails_mongo_mapper/libs/connection.rb
|
116
|
+
- lib/gcm_rails_mongo_mapper/tasks/gcm.rake
|
117
|
+
- lib/gcm_rails_mongo_mapper_tasks.rb
|
118
|
+
- lib/generators/gcm_migrations_generator.rb
|
119
|
+
- lib/generators/templates/gcm_migrations/create_gcm_devices.rb
|
120
|
+
- lib/generators/templates/gcm_migrations/create_gcm_notifications.rb
|
121
|
+
homepage: http://github.com/kkelani/gcm_rails_mongo_mapper
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.8.24
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: Google Cloud Messaging for Android on Rails using MongoMapper
|
146
|
+
test_files: []
|