ghazel-em-gcm 0.0.1
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.
- checksums.yaml +7 -0
- data/README.md +58 -0
- data/em-gcm.gemspec +22 -0
- data/lib/em-gcm.rb +43 -0
- data/lib/em-gcm/client.rb +64 -0
- data/lib/em-gcm/log_message.rb +30 -0
- data/lib/em-gcm/notification.rb +60 -0
- data/lib/em-gcm/response.rb +76 -0
- data/lib/em-gcm/version.rb +5 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6111301e6d59ec7719dadce064d9080c566acd4b
|
4
|
+
data.tar.gz: 4e693f1b0ba08d6e80aed637226f0b15cdcb8b20
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fd2fefb61e21ff9a34bba5996fef11fec5332bf4895fdfe86fc5ede09f6eba5da6dba9a849f9b4f36b281c99085661bb4207a4d7985f76e03bd6eb38334f0cc6
|
7
|
+
data.tar.gz: 591504c0cc765b2ddf33a80ab91b423777b29d16b0d9d59842986a2e4c1c1dade7ae7e611cf1d7104703d62e9b341d6b2fa3b80ec42873969f64a064e136a8ab
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
em-gcm
|
2
|
+
======
|
3
|
+
|
4
|
+
Google Cloud Messaging for Android for Event Machine
|
5
|
+
|
6
|
+
See [Google's Documention](http://developer.android.com/guide/google/gcm/index.html) to learn more.
|
7
|
+
|
8
|
+
This project is based on groupme/em-c2dm and doesn't include spec yet
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
require "em-gcm"
|
13
|
+
|
14
|
+
EM::GCM.token = "abcedfg..."
|
15
|
+
|
16
|
+
EM.run do
|
17
|
+
#plain old c2dm compatible send
|
18
|
+
EM::GCM.push_plain(["registration_id"], :alert => "hi!", :collapse_key => "required")
|
19
|
+
#new json style send and support broadcase
|
20
|
+
EM::GCM.push_json(["registration_id1", "registration_id2"], :alert => "hi!", :collapse_key => "required")
|
21
|
+
end
|
22
|
+
|
23
|
+
### Custom Params
|
24
|
+
|
25
|
+
You can add custom params (which will be converted to `data.<KEY>`):
|
26
|
+
|
27
|
+
EM::GCM.push_plain(["registration_id"],
|
28
|
+
:alert => "Hello!",
|
29
|
+
:collapse_key => "required",
|
30
|
+
:custom => "data",
|
31
|
+
:awesome => true
|
32
|
+
)
|
33
|
+
|
34
|
+
|
35
|
+
### Response Callback
|
36
|
+
|
37
|
+
You can register a response callback to check success and handle errors:
|
38
|
+
|
39
|
+
EM::GCM.push_plain(["registration_id1"], :alert => "hi!") do |response|
|
40
|
+
if response.success?
|
41
|
+
puts "success! id=#{response.id}" # ID of sent message
|
42
|
+
else
|
43
|
+
case response.error
|
44
|
+
when "InvalidToken"
|
45
|
+
# reauthenticate
|
46
|
+
when "InvalidRegistration"
|
47
|
+
# clear our registration id
|
48
|
+
when "RetryAfter"
|
49
|
+
# pause sending for response.retry_after seconds
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
Please feel free to fork and update this!
|
data/em-gcm.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- mode: ruby; encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "em-gcm/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ghazel-em-gcm"
|
7
|
+
s.version = EventMachine::GCM::VERSION
|
8
|
+
s.authors = ["Zeng Xin"]
|
9
|
+
s.email = ["samuelzx@hotmail.com"]
|
10
|
+
s.homepage = "https://github.com/zengxin/em-gcm"
|
11
|
+
s.summary = %q{Google Cloud Messaging for Android for Event Machine}
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_dependency "eventmachine", ">= 1.0.0.beta.3"
|
19
|
+
s.add_dependency "em-http-request", ">= 1.0.0.beta.4"
|
20
|
+
s.add_dependency "uuid"
|
21
|
+
|
22
|
+
end
|
data/lib/em-gcm.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require "eventmachine"
|
4
|
+
require "em-http-request"
|
5
|
+
require "logger"
|
6
|
+
require "uuid"
|
7
|
+
require "em-gcm/client"
|
8
|
+
require "em-gcm/notification"
|
9
|
+
|
10
|
+
$uuid = UUID.new
|
11
|
+
|
12
|
+
module EventMachine
|
13
|
+
module GCM
|
14
|
+
class << self
|
15
|
+
def push_plain(registration_ids, options, &block)
|
16
|
+
notification = Notification.new(registration_ids, options)
|
17
|
+
Client.new(notification).deliver_plain(block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def push_json(registration_ids, options, &block)
|
21
|
+
notification = Notification.new(registration_ids, options)
|
22
|
+
Client.new(notification).deliver_json(block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def token=(token)
|
26
|
+
logger.info("setting new auth token")
|
27
|
+
@token = token
|
28
|
+
end
|
29
|
+
|
30
|
+
def token
|
31
|
+
@token
|
32
|
+
end
|
33
|
+
|
34
|
+
def logger
|
35
|
+
@logger ||= Logger.new(STDOUT)
|
36
|
+
end
|
37
|
+
|
38
|
+
def logger=(new_logger)
|
39
|
+
@logger = new_logger
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "em-gcm/response"
|
2
|
+
require "em-gcm/log_message"
|
3
|
+
|
4
|
+
module EventMachine
|
5
|
+
module GCM
|
6
|
+
class Client
|
7
|
+
URL = "https://android.googleapis.com/gcm/send"
|
8
|
+
|
9
|
+
def initialize(notification)
|
10
|
+
@notification = notification
|
11
|
+
end
|
12
|
+
|
13
|
+
def deliver_plain(block = nil)
|
14
|
+
verify_token
|
15
|
+
@start = Time.now.to_f
|
16
|
+
|
17
|
+
http = EventMachine::HttpRequest.new(URL).post(
|
18
|
+
:query => @notification.params,
|
19
|
+
:head => @notification.headers_plain
|
20
|
+
)
|
21
|
+
|
22
|
+
http.callback do
|
23
|
+
response = Response.new(http, @start)
|
24
|
+
LogMessage.new(@notification, response).log
|
25
|
+
block.call(response) if block
|
26
|
+
end
|
27
|
+
|
28
|
+
http.errback do |e|
|
29
|
+
EM::GCM.logger.error(e.inspect)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def deliver_json(block = nil)
|
34
|
+
verify_token
|
35
|
+
@start = Time.now.to_f
|
36
|
+
|
37
|
+
params = {:dry_run => "true"}
|
38
|
+
|
39
|
+
http = EventMachine::HttpRequest.new(URL).post(
|
40
|
+
#uncomment this if you want to test send and do not want receiver to receive message
|
41
|
+
#:query => params,
|
42
|
+
:body => @notification.body,
|
43
|
+
:head => @notification.headers_json
|
44
|
+
)
|
45
|
+
|
46
|
+
http.callback do
|
47
|
+
response = Response.new(http, @start, false)
|
48
|
+
LogMessage.new(@notification, response).log
|
49
|
+
block.call(response) if block
|
50
|
+
end
|
51
|
+
|
52
|
+
http.errback do |e|
|
53
|
+
EM::GCM.logger.error(e.inspect)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def verify_token
|
60
|
+
raise "token not set!" unless EM::GCM.token
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module GCM
|
3
|
+
class LogMessage
|
4
|
+
def initialize(notification, response)
|
5
|
+
@notification, @response = notification, response
|
6
|
+
end
|
7
|
+
|
8
|
+
def log
|
9
|
+
if @response.success?
|
10
|
+
EM::GCM.logger.info(message)
|
11
|
+
else
|
12
|
+
EM::GCM.logger.error(message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def message
|
19
|
+
parts = [
|
20
|
+
"CODE=#{@response.status}",
|
21
|
+
"GUID=#{@notification.uuid}",
|
22
|
+
"TIME=#{@response.duration}",
|
23
|
+
"TOKEN=#{@notification.registration_ids}"
|
24
|
+
]
|
25
|
+
parts << "ERROR=#{@response.error}" unless @response.success?
|
26
|
+
parts.join(" ")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module EventMachine
|
4
|
+
module GCM
|
5
|
+
class Notification
|
6
|
+
attr_reader :uuid, :options, :registration_ids
|
7
|
+
|
8
|
+
def initialize(registration_ids, options = {})
|
9
|
+
@registration_ids, @options = registration_ids, options
|
10
|
+
raise ArgumentError.new("missing options") if options.nil? || options.empty?
|
11
|
+
@uuid = $uuid.generate
|
12
|
+
end
|
13
|
+
|
14
|
+
def params
|
15
|
+
@params ||= generate_params
|
16
|
+
end
|
17
|
+
|
18
|
+
def body
|
19
|
+
@body ||= generate_body
|
20
|
+
end
|
21
|
+
|
22
|
+
def headers_plain
|
23
|
+
{
|
24
|
+
"Authorization" => "key=#{EM::GCM.token}",
|
25
|
+
"Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8",
|
26
|
+
"User-Agent" => "em-c2dm 1.0.0"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def headers_json
|
31
|
+
{
|
32
|
+
"Authorization" => "key=#{EM::GCM.token}",
|
33
|
+
"Content-Type" => "application/json",
|
34
|
+
"User-Agent" => "em-c2dm 1.0.0"
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def generate_params
|
42
|
+
params = { "registration_id" => @registration_ids[0] }
|
43
|
+
params["collapse_key"] = @options.delete(:collapse_key) || @options.delete("collapse_key")
|
44
|
+
@options.each do |k,v|
|
45
|
+
params["data.#{k}"] = v
|
46
|
+
end
|
47
|
+
params
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_body
|
51
|
+
body_hash = {}
|
52
|
+
body_hash[:collapse_key] = @options.delete(:collapse_key) || @options.delete("collapse_key")
|
53
|
+
body_hash[:data] = @options
|
54
|
+
body_hash[:registration_ids] = @registration_ids
|
55
|
+
body_hash.to_json
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module GCM
|
3
|
+
# Header errors
|
4
|
+
# InvalidToken - Authentication token is invalid. Reauthenticate.
|
5
|
+
# Retry_After - Service is down for maintenance. Call retry_after for seconds to wait.
|
6
|
+
#
|
7
|
+
# Body errors
|
8
|
+
# Quota_Exceeded - Too many messages sent by the sender. Retry after a while.
|
9
|
+
# Device_Quota_Exceeded - Too any messages sent by the sender to a specific device. Retry after a while.
|
10
|
+
# InvalidRegistration - Missing or bad registration_id. Sender should stop sending messages to this device.
|
11
|
+
# NotRegistered - The registration_id is no longer valid, for example user has uninstalled the application or turned off notifications. Sender should stop sending messages to this device.
|
12
|
+
# MessageTooBig - The payload of the message is too big, see the limitations. Reduce the size of the message.
|
13
|
+
# MissingCollapseKey - Collapse key is required. Include collapse key in the request.
|
14
|
+
class Response
|
15
|
+
# Common
|
16
|
+
attr_accessor :id
|
17
|
+
attr_accessor :status
|
18
|
+
attr_accessor :duration
|
19
|
+
attr_accessor :error
|
20
|
+
attr_accessor :body
|
21
|
+
|
22
|
+
# Service-specific
|
23
|
+
attr_accessor :retry_after
|
24
|
+
|
25
|
+
def initialize(http = {}, start = nil, is_plain = true)
|
26
|
+
@http = http
|
27
|
+
@duration = Time.now.to_f - start.to_f if start
|
28
|
+
if http.kind_of?(Hash)
|
29
|
+
@id = http[:id]
|
30
|
+
@status = http[:status]
|
31
|
+
@retry_after = http[:retry_after]
|
32
|
+
@error = http[:error]
|
33
|
+
else
|
34
|
+
parse_body(http.response)
|
35
|
+
parse_headers(http.response_header)
|
36
|
+
end
|
37
|
+
@is_plain = is_plain
|
38
|
+
end
|
39
|
+
|
40
|
+
def success?
|
41
|
+
@error.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def parse_body(body)
|
47
|
+
if @is_plain
|
48
|
+
body =~ (/^id=(.*)$/)
|
49
|
+
@id = $1
|
50
|
+
|
51
|
+
body =~ (/^Error=(.*)$/)
|
52
|
+
@error = $1
|
53
|
+
else
|
54
|
+
@body = body
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# These are messed up because of EM::HttpRequest's messed up parsing
|
59
|
+
def parse_headers(headers)
|
60
|
+
@status = headers.status
|
61
|
+
@retry_after = headers["RETRY_AFTER"].to_i
|
62
|
+
|
63
|
+
case @status
|
64
|
+
when 200
|
65
|
+
# noop
|
66
|
+
when 401
|
67
|
+
@error = "InvalidToken"
|
68
|
+
when 502, 503
|
69
|
+
@error = "RetryAfter"
|
70
|
+
else
|
71
|
+
@error = "Unknown error: #{headers.status} (#{@http.response})"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ghazel-em-gcm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zeng Xin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: eventmachine
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.0.beta.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.0.beta.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: em-http-request
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0.beta.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.0.beta.4
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: uuid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- samuelzx@hotmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- README.md
|
63
|
+
- em-gcm.gemspec
|
64
|
+
- lib/em-gcm.rb
|
65
|
+
- lib/em-gcm/client.rb
|
66
|
+
- lib/em-gcm/log_message.rb
|
67
|
+
- lib/em-gcm/notification.rb
|
68
|
+
- lib/em-gcm/response.rb
|
69
|
+
- lib/em-gcm/version.rb
|
70
|
+
homepage: https://github.com/zengxin/em-gcm
|
71
|
+
licenses: []
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.0.14
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Google Cloud Messaging for Android for Event Machine
|
93
|
+
test_files: []
|