speedy_c2dm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use "ruby-1.9.2-p290@speedy_c2dm"
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in speedy_c2dm.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem "shoulda"
8
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Amro Mousa, (c) 2011 Brandon Keene, (c) 2011 Sandeep Ghael
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.markdown ADDED
@@ -0,0 +1,34 @@
1
+ # c2dm
2
+
3
+ c2dm sends push notifications to Android devices via google [c2dm](http://code.google.com/android/c2dm/index.html).
4
+
5
+ # How is this GEM different than other C2DM gems?
6
+
7
+ To use C2DM the server needs to fetch and store authenticaion tokens from Google. This token will periodically expire, and the recommendation from Google is that "the server should store the token and have a policy to refresh it periodically." Other C2DM gems take a brute force method around this issue, by requesting a new authenticaion token from Google for *each* notification request they send. This effectively doubles the number of HTTP calls being made for each notification.
8
+
9
+ This GEM will request the token when the SpeedyC2DM::API class is first initialized. From then on, it will use the auth token stored as an instance variable. On subsequent notification calls, it will check for 'Update-Client-Auth' or check for status 401 (auth failed). When it detects either of these, it will then request new tokens from Google servers. In the case of status 503 (service unavailable), a return message indicating 503 is returned. It is suggested that you retry after exponential back-off in the case of 503 (using something like resque-retry).
10
+
11
+ ##Installation
12
+
13
+ $ gem install speedy_c2dm
14
+
15
+ ##Requirements
16
+
17
+ An Android device running 2.2 or newer, its registration token, and a google account registered for c2dm.
18
+
19
+ ##Usage
20
+
21
+ c2dm = SpeedyC2DM::API.new(TEST_EMAIL, TEST_PASSWORD)
22
+
23
+ options = {
24
+ :registration_id => TEST_REGISTRATION_ID,
25
+ :message => "Hi!",
26
+ :extra_data => 42,
27
+ :collapse_key => "some-collapse-key"
28
+ }
29
+
30
+ response = c2dm.send_notification(options)
31
+
32
+ ##Copyrights
33
+
34
+ * See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,3 @@
1
+ module SpeedyC2dm
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,110 @@
1
+ require "speedy_c2dm/version"
2
+ require 'typhoeus'
3
+
4
+ module SpeedyC2DM
5
+
6
+ class API
7
+ AUTH_URL = 'https://www.google.com/accounts/ClientLogin'
8
+ PUSH_URL = 'https://android.apis.google.com/c2dm/send'
9
+
10
+ # Initialize with an API key and config options
11
+ def initialize(email, password)
12
+ @email = email
13
+ @password = password
14
+
15
+ @auth_token = get_auth_token(@email, @password)
16
+ end
17
+
18
+ def get_auth_token(email, password)
19
+ post_body = "accountType=HOSTED_OR_GOOGLE&Email=#{email}&Passwd=#{password}&service=ac2dm"
20
+ params = {
21
+ :body => post_body,
22
+ :headers => {
23
+ 'Content-type' => 'application/x-www-form-urlencoded',
24
+ 'Content-length' => "#{post_body.length}"
25
+ }
26
+ }
27
+ response = Typhoeus::Request.post(AUTH_URL, params)
28
+ return response.body.split("\n")[2].gsub("Auth=", "")
29
+ end
30
+
31
+ # Send a notification
32
+ #
33
+ # :registration_id is required.
34
+ # :collapse_key is optional.
35
+ #
36
+ # Other +options+ will be sent as "data.<key>=<value>"
37
+ #
38
+ # +options+ = {
39
+ # :registration_id => "...",
40
+ # :message => "Hi!",
41
+ # :extra_data => 42,
42
+ # :collapse_key => "some-collapse-key"
43
+ # }
44
+ def send_notification(options)
45
+ request = requestObject(options)
46
+
47
+ hydra = Typhoeus::Hydra.new
48
+ hydra.queue request
49
+ hydra.run # this is a blocking call that returns once all requests are complete
50
+
51
+ # the response object will be set after the request is run
52
+ response = request.response
53
+
54
+ # the response can be one of three codes:
55
+ # 200 (success)
56
+ # 401 (auth failed)
57
+ # 503 (retry later with exponential backoff)
58
+ # see more documentation here: http://code.google.com/android/c2dm/#testing
59
+ if response.code.eql? 200
60
+
61
+ # look for the header 'Update-Client-Auth'
62
+ # in the response you get after sending a message. It indicates that
63
+ # this is the token to be used for the next message to send.
64
+ if response.headers_hash['Update-Client-Auth']
65
+ @auth_token = get_auth_token(@email, @password)
66
+ end
67
+ return "success: 200"
68
+
69
+ elsif response.code.eql? 401
70
+
71
+ # auth failed. Refresh auth key and requeue
72
+ @auth_token = get_auth_token(@email, @password)
73
+ hydra.queue request(options)
74
+ hydra.run # this is a blocking call that returns once all requests are complete
75
+
76
+ response_inner = request.response
77
+ if response_inner.code.eql? 200
78
+ return "success"
79
+ elsif response_inner.code.eql? 401
80
+ return "failed: 401 - auth failed"
81
+ elsif response_inner.code.eql? 503
82
+ return "failed: 503 - service unavailable"
83
+ end
84
+
85
+ elsif response.code.eql? 503
86
+
87
+ # service un-available.
88
+ return "failed: 503 - service unavailable"
89
+
90
+ end
91
+ end
92
+
93
+ def requestObject(options)
94
+ payload = {}
95
+ payload[:registration_id] = options.delete(:registration_id)
96
+ payload[:collapse_key] = options.delete(:collapse_key)
97
+ options.each {|key, value| payload["data.#{key}"] = value}
98
+
99
+ Typhoeus::Request.new(PUSH_URL, {
100
+ :method => :post,
101
+ :params => payload,
102
+ :headers => {
103
+ 'Authorization' => "GoogleLogin auth=#{@auth_token}"
104
+ }
105
+ })
106
+ end
107
+
108
+ end
109
+
110
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "speedy_c2dm/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "speedy_c2dm"
7
+ s.version = SpeedyC2dm::VERSION
8
+ s.authors = ["Sandeep Ghael"]
9
+ s.email = ["sghael@ravidapp.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Speedy C2DM is an intelligent gem for sending push notifications to Android devices via Google C2DM.}
12
+ s.description = %q{Speedy C2DM sends push notifications to Android devices via google c2dm.}
13
+
14
+ s.rubyforge_project = "speedy_c2dm"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "typhoeus"
22
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'speedy_c2dm'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,38 @@
1
+ current_dir = File.expand_path(File.dirname(__FILE__))
2
+ require File.join(current_dir, 'helper')
3
+
4
+ class TestSpeedyC2DM < Test::Unit::TestCase
5
+
6
+ TEST_EMAIL = "TODO - Fill me"
7
+ TEST_PASSWORD = "TODO - Fill me"
8
+ INVALID_TEST_EMAIL = "foo-bar.com"
9
+ TEST_REGISTRATION_ID = "TODO - Fill me"
10
+
11
+ should "not raise an error if the API key is valid" do
12
+ assert_nothing_raised do
13
+ SpeedyC2DM::API.new(TEST_EMAIL, TEST_PASSWORD)
14
+ end
15
+ end
16
+
17
+ should "raise an error if the email/password is not provided" do
18
+ assert_raise(ArgumentError) do
19
+ SpeedyC2DM::API.new()
20
+ end
21
+ end
22
+
23
+ should "not raise an error if a send notification call succeeds" do
24
+ assert_nothing_raised do
25
+ speedyC2DM = SpeedyC2DM::API.new(TEST_EMAIL, TEST_PASSWORD)
26
+
27
+ options = {
28
+ :registration_id => TEST_REGISTRATION_ID,
29
+ :message => "Hi!",
30
+ :extra_data => 42,
31
+ :collapse_key => "some-collapse-key"
32
+ }
33
+
34
+ response = speedyC2DM.send_notification(options)
35
+ end
36
+ end
37
+
38
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: speedy_c2dm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sandeep Ghael
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-01 00:00:00.000000000 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: typhoeus
17
+ requirement: &2157328800 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2157328800
26
+ description: Speedy C2DM sends push notifications to Android devices via google c2dm.
27
+ email:
28
+ - sghael@ravidapp.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - .rvmrc
35
+ - Gemfile
36
+ - LICENSE.txt
37
+ - README.markdown
38
+ - Rakefile
39
+ - lib/speedy_c2dm.rb
40
+ - lib/speedy_c2dm/version.rb
41
+ - speedy_c2dm.gemspec
42
+ - test/helper.rb
43
+ - test/test_speedy_c2dm.rb
44
+ has_rdoc: true
45
+ homepage: ''
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project: speedy_c2dm
65
+ rubygems_version: 1.6.2
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Speedy C2DM is an intelligent gem for sending push notifications to Android
69
+ devices via Google C2DM.
70
+ test_files:
71
+ - test/helper.rb
72
+ - test/test_speedy_c2dm.rb