ruby-mpns 1.1.2 → 1.2.0
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.md +5 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +5 -3
- data/VERSION +1 -1
- data/lib/ruby-mpns.rb +76 -114
- data/ruby-mpns.gemspec +5 -5
- data/test/test_ruby-mpns.rb +98 -2
- metadata +3 -3
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
builder (3.0.4)
|
4
5
|
git (1.2.5)
|
5
|
-
htmlentities (4.3.1)
|
6
6
|
jeweler (1.8.3)
|
7
7
|
bundler (~> 1.0)
|
8
8
|
git (>= 1.2.5)
|
@@ -27,8 +27,8 @@ PLATFORMS
|
|
27
27
|
ruby
|
28
28
|
|
29
29
|
DEPENDENCIES
|
30
|
+
builder
|
30
31
|
bundler (>= 1.0.0)
|
31
|
-
htmlentities
|
32
32
|
jeweler (~> 1.8.3)
|
33
33
|
rdoc (~> 3.12)
|
34
34
|
shoulda
|
data/README.md
CHANGED
@@ -14,7 +14,7 @@ Or in your gemfile:
|
|
14
14
|
|
15
15
|
## Usage
|
16
16
|
|
17
|
-
To use it
|
17
|
+
To use it just use the singleton `MicrosoftPushNotificationService` like the following:
|
18
18
|
|
19
19
|
uri = "http://my-uri.com/to/the-windows-phone-i-am-targetting"
|
20
20
|
|
@@ -73,10 +73,12 @@ For general information about Push Notification on Windows Phone check the [MSDN
|
|
73
73
|
|
74
74
|
### Missing features
|
75
75
|
|
76
|
-
* Add unit tests
|
77
|
-
* Add support for multi-level hash for raw notifications
|
78
76
|
* Add an ActiveRecord extension (acts_as_microsoft_pushable)
|
79
77
|
|
78
|
+
### Contributors
|
79
|
+
|
80
|
+
* [Dmitry Medvinsky](https://github.com/dmedvinsky)
|
81
|
+
|
80
82
|
## License
|
81
83
|
|
82
84
|
Copyright (c) 2012 [Nicolas VERINAUD](http://www.nverinaud.com). Released under the MIT license.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/lib/ruby-mpns.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'builder'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
4
|
|
5
5
|
module MicrosoftPushNotificationService
|
6
6
|
|
7
|
-
|
7
|
+
def self.extended(base)
|
8
8
|
unless base.respond_to?(:device_uri)
|
9
9
|
base.class.class_eval do
|
10
10
|
attr_accessor :device_uri
|
@@ -12,94 +12,51 @@ module MicrosoftPushNotificationService
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
def self.send_notification
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def self.send_notification(uri, type, options = {})
|
16
|
+
device = Object.new
|
17
|
+
device.extend MicrosoftPushNotificationService
|
18
|
+
device.device_uri = uri
|
19
|
+
device.send_notification type, options
|
20
20
|
end
|
21
21
|
|
22
|
-
def send_notification
|
23
|
-
type = safe_type_to_sym
|
24
|
-
|
25
|
-
|
26
|
-
notification = nil
|
27
|
-
notification_class = nil
|
28
|
-
|
29
|
-
if type == :tile
|
30
|
-
notification = tile_notification_with_options options
|
31
|
-
notification_class = "1"
|
32
|
-
elsif type == :toast
|
33
|
-
notification = toast_notification_with_options options
|
34
|
-
notification_class = "2"
|
35
|
-
else
|
36
|
-
notification = raw_notification_with_options options
|
37
|
-
notification_class = "3"
|
38
|
-
end
|
39
|
-
|
40
|
-
# HTTP connection
|
22
|
+
def send_notification(type, options = {})
|
23
|
+
type = safe_type_to_sym(type)
|
24
|
+
notification, notification_class = build_notification(type, options)
|
41
25
|
uri = URI.parse(self.device_uri)
|
42
26
|
|
43
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
44
27
|
request = Net::HTTP::Post.new(uri.request_uri)
|
45
|
-
request.content_type =
|
46
|
-
|
47
|
-
|
48
|
-
request["X-WindowsPhone-Target"] = type.to_s
|
49
|
-
end
|
50
|
-
request["X-NotificationClass"] = notification_class
|
28
|
+
request.content_type = 'text/xml'
|
29
|
+
request['X-WindowsPhone-Target'] = type.to_s if type.to_sym != :raw
|
30
|
+
request['X-NotificationClass'] = notification_class
|
51
31
|
request.body = notification
|
52
32
|
request.content_length = notification.length
|
53
|
-
|
54
|
-
response = Net::HTTP.start(uri.host, uri.port) do |http|
|
55
|
-
http.request(request)
|
56
|
-
end
|
57
33
|
|
58
|
-
|
34
|
+
Net::HTTP.start(uri.host, uri.port) { |http| http.request request }
|
59
35
|
end
|
60
36
|
|
61
37
|
|
62
38
|
protected
|
63
39
|
|
64
|
-
def safe_type_to_sym
|
65
|
-
sym = nil
|
66
|
-
|
67
|
-
|
68
|
-
sym = type.to_sym
|
69
|
-
else
|
70
|
-
sym = :raw
|
71
|
-
end
|
72
|
-
|
73
|
-
if sym != :tile && sym != :toast
|
74
|
-
sym = :raw
|
75
|
-
end
|
76
|
-
|
77
|
-
return sym
|
40
|
+
def safe_type_to_sym(type)
|
41
|
+
sym = type.to_sym unless type.nil?
|
42
|
+
sym = :raw unless [:tile, :toast].include?(sym)
|
43
|
+
sym
|
78
44
|
end
|
79
45
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
46
|
+
def notification_builder_for_type(type)
|
47
|
+
case type
|
48
|
+
when :tile
|
49
|
+
:tile_notification_with_options
|
50
|
+
when :toast
|
51
|
+
:toast_notification_with_options
|
52
|
+
else
|
53
|
+
:raw_notification_with_options
|
84
54
|
end
|
85
55
|
end
|
86
56
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# - params : hash
|
91
|
-
def toast_notification_with_options options = {}
|
92
|
-
coder = HTMLEntities.new
|
93
|
-
|
94
|
-
notification = '<?xml version="1.0" encoding="utf-8"?>'
|
95
|
-
notification << '<wp:Notification xmlns:wp="WPNotification">'
|
96
|
-
notification << '<wp:Toast>'
|
97
|
-
notification << '<wp:Text1>' << coder.encode(options[:title]) << '</wp:Text1>'
|
98
|
-
notification << '<wp:Text2>' << coder.encode(options[:content]) << '</wp:Text2>'
|
99
|
-
notification << '<wp:Param>' << coder.encode(format_params(options[:params])) << '</wp:Param>'
|
100
|
-
notification << '</wp:Toast>'
|
101
|
-
notification << '</wp:Notification>'
|
102
|
-
return notification
|
57
|
+
def build_notification(type, options = {})
|
58
|
+
notification_builder = notification_builder_for_type(type)
|
59
|
+
send(notification_builder, options)
|
103
60
|
end
|
104
61
|
|
105
62
|
# Tile options :
|
@@ -110,54 +67,59 @@ protected
|
|
110
67
|
# - back_background_image : string, path to local image embedded in the app or accessible via HTTP (.jpg or .png, 173x137px, max 80kb)
|
111
68
|
# - back_content : string
|
112
69
|
# - (optional) navigation_uri : string, the exact navigation URI for the tile to update, only needed if you wish to update a secondary tile
|
113
|
-
def tile_notification_with_options
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
70
|
+
def tile_notification_with_options(options = {})
|
71
|
+
uri = options[:navigation_uri]
|
72
|
+
xml = Builder::XmlMarkup.new
|
73
|
+
xml.instruct!
|
74
|
+
xml.tag!('wp:Notification', 'xmlns:wp' => 'WPNotification') do
|
75
|
+
xml.tag!('wp:Tile', uri.nil? ? {} : {'Id' => uri}) do
|
76
|
+
xml.tag!('wp:BackgroundImage') { xml.text!(options[:background_image] || '') }
|
77
|
+
xml.tag!('wp:Count') { xml.text!(options[:count].to_s || '') }
|
78
|
+
xml.tag!('wp:Title') { xml.text!(options[:title] || '') }
|
79
|
+
xml.tag!('wp:BackBackgroundImage') { xml.text!(options[:back_background_image] || '') }
|
80
|
+
xml.tag!('wp:BackTitle') { xml.text!(options[:back_title] || '') }
|
81
|
+
xml.tag!('wp:BackContent') { xml.text!(options[:back_content] || '') }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
[xml.target!, '1']
|
85
|
+
end
|
86
|
+
|
87
|
+
# Toast options :
|
88
|
+
# - title : string
|
89
|
+
# - content : string
|
90
|
+
# - params : hash
|
91
|
+
def toast_notification_with_options(options = {})
|
92
|
+
xml = Builder::XmlMarkup.new
|
93
|
+
xml.instruct!
|
94
|
+
xml.tag!('wp:Notification', 'xmlns:wp' => 'WPNotification') do
|
95
|
+
xml.tag!('wp:Toast') do
|
96
|
+
xml.tag!('wp:Text1') { xml.text!(options[:title] || '') }
|
97
|
+
xml.tag!('wp:Text2') { xml.text!(options[:content] || '') }
|
98
|
+
xml.tag!('wp:Param') { xml.text!(format_params(options[:params])) }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
[xml.target!, '2']
|
131
102
|
end
|
132
103
|
|
133
104
|
# Raw options :
|
134
105
|
# - raw values send like: <key>value</key>
|
135
|
-
def raw_notification_with_options
|
136
|
-
|
106
|
+
def raw_notification_with_options(options = {})
|
107
|
+
xml = Builder::XmlMarkup.new
|
108
|
+
xml.instruct!
|
109
|
+
xml.root { build_hash(xml, options) }
|
110
|
+
[xml.target!, '3']
|
111
|
+
end
|
137
112
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
notification << '<' << coder.encode(key.to_s) << '>' << coder.encode(value.to_s) << '</' << coder.encode(key.to_s) << '>'
|
113
|
+
def build_hash(xml, options)
|
114
|
+
options.each do |k, v|
|
115
|
+
xml.tag!(k.to_s) { v.is_a?(Hash) ? build_hash(xml, v) : xml.text!(v.to_s) }
|
142
116
|
end
|
143
|
-
notification << '</root>'
|
144
|
-
|
145
|
-
puts notification
|
146
|
-
return notification
|
147
117
|
end
|
148
118
|
|
149
|
-
def format_params
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
params.each do |key,value|
|
154
|
-
p << key.to_s << "=" << value.to_s
|
155
|
-
count += 1
|
156
|
-
if count < length
|
157
|
-
p << "&"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
return p
|
119
|
+
def format_params(params = {})
|
120
|
+
return '' if params.nil?
|
121
|
+
query = params.collect { |k, v| k.to_s + '=' + v.to_s } * '&'
|
122
|
+
'?' + query
|
161
123
|
end
|
162
124
|
|
163
125
|
end
|
data/ruby-mpns.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ruby-mpns"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nicolas VERINAUD"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2013-01-12"
|
13
13
|
s.description = "This gem provides an easy way to send push notifications to Windows Phone devices using Microsoft Push Notification Service."
|
14
14
|
s.email = "n.verinaud@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -43,14 +43,14 @@ Gem::Specification.new do |s|
|
|
43
43
|
s.specification_version = 3
|
44
44
|
|
45
45
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
-
s.add_runtime_dependency(%q<
|
46
|
+
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
47
47
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
48
48
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
49
49
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
50
50
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
51
51
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
52
52
|
else
|
53
|
-
s.add_dependency(%q<
|
53
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
54
54
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
55
55
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
56
56
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
@@ -58,7 +58,7 @@ Gem::Specification.new do |s|
|
|
58
58
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
59
59
|
end
|
60
60
|
else
|
61
|
-
s.add_dependency(%q<
|
61
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
62
62
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
63
63
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
64
64
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
data/test/test_ruby-mpns.rb
CHANGED
@@ -1,7 +1,103 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestRubyMpns < Test::Unit::TestCase
|
4
|
-
should
|
5
|
-
|
4
|
+
should 'safely convert type to symbol' do
|
5
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
6
|
+
assert_equal :raw, mpns.send(:safe_type_to_sym, nil)
|
7
|
+
assert_equal :raw, mpns.send(:safe_type_to_sym, 'beer')
|
8
|
+
assert_equal :raw, mpns.send(:safe_type_to_sym, 'raw')
|
9
|
+
assert_equal :raw, mpns.send(:safe_type_to_sym, :raw)
|
10
|
+
assert_equal :tile, mpns.send(:safe_type_to_sym, 'tile')
|
11
|
+
assert_equal :tile, mpns.send(:safe_type_to_sym, :tile)
|
12
|
+
assert_equal :toast, mpns.send(:safe_type_to_sym, 'toast')
|
13
|
+
assert_equal :toast, mpns.send(:safe_type_to_sym, :toast)
|
14
|
+
end
|
15
|
+
|
16
|
+
should 'get correct notification builder based on type' do
|
17
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
18
|
+
assert_equal :tile_notification_with_options, mpns.send(:notification_builder_for_type, :tile)
|
19
|
+
assert_equal :toast_notification_with_options, mpns.send(:notification_builder_for_type, :toast)
|
20
|
+
assert_equal :raw_notification_with_options, mpns.send(:notification_builder_for_type, :raw)
|
21
|
+
assert_equal :raw_notification_with_options, mpns.send(:notification_builder_for_type, :beer)
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'return correct notification_class' do
|
25
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
26
|
+
_, cls = mpns.send(:build_notification, :tile)
|
27
|
+
assert_equal cls, '1'
|
28
|
+
_, cls = mpns.send(:build_notification, :toast)
|
29
|
+
assert_equal cls, '2'
|
30
|
+
_, cls = mpns.send(:build_notification, :raw)
|
31
|
+
assert_equal cls, '3'
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'format params like a boss' do
|
35
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
36
|
+
q = mpns.send(:format_params, { a: 1, b: 2 })
|
37
|
+
assert_equal q, '?a=1&b=2'
|
38
|
+
q = mpns.send(:format_params, { phone: '+0987 654321', email: 'luke@example.com' })
|
39
|
+
assert_equal q, '?phone=+0987 654321&email=luke@example.com'
|
40
|
+
end
|
41
|
+
|
42
|
+
should 'make tile XML' do
|
43
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
44
|
+
xml, _ = mpns.send(:tile_notification_with_options,
|
45
|
+
{ title: 'title', count: 1337,
|
46
|
+
background_image: 'bg', back_title: 'bktitle',
|
47
|
+
back_background_image: 'bkbg',
|
48
|
+
back_content: 'bkcontent',
|
49
|
+
navigation_uri: 'uri' })
|
50
|
+
assert_equal xml, '<?xml version="1.0" encoding="UTF-8"?>' +
|
51
|
+
'<wp:Notification xmlns:wp="WPNotification">' +
|
52
|
+
'<wp:Tile Id="uri">' +
|
53
|
+
'<wp:BackgroundImage>bg</wp:BackgroundImage>' +
|
54
|
+
'<wp:Count>1337</wp:Count>' +
|
55
|
+
'<wp:Title>title</wp:Title>' +
|
56
|
+
'<wp:BackBackgroundImage>bkbg</wp:BackBackgroundImage>' +
|
57
|
+
'<wp:BackTitle>bktitle</wp:BackTitle>' +
|
58
|
+
'<wp:BackContent>bkcontent</wp:BackContent>' +
|
59
|
+
'</wp:Tile>' +
|
60
|
+
'</wp:Notification>'
|
61
|
+
end
|
62
|
+
|
63
|
+
should 'make toast XML' do
|
64
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
65
|
+
xml, _ = mpns.send(:toast_notification_with_options,
|
66
|
+
{ title: 'title', content: 'content', params: {} })
|
67
|
+
assert_equal xml, '<?xml version="1.0" encoding="UTF-8"?>' +
|
68
|
+
'<wp:Notification xmlns:wp="WPNotification">' +
|
69
|
+
'<wp:Toast>' +
|
70
|
+
'<wp:Text1>title</wp:Text1>' +
|
71
|
+
'<wp:Text2>content</wp:Text2>' +
|
72
|
+
'<wp:Param>?</wp:Param>' +
|
73
|
+
'</wp:Toast>' +
|
74
|
+
'</wp:Notification>'
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'make raw XML' do
|
78
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
79
|
+
xml, _ = mpns.send(:raw_notification_with_options,
|
80
|
+
{ key1: 'val1', key2: 'val2' })
|
81
|
+
assert_equal xml, '<?xml version="1.0" encoding="UTF-8"?>' +
|
82
|
+
'<root>' +
|
83
|
+
'<key1>val1</key1>' +
|
84
|
+
'<key2>val2</key2>' +
|
85
|
+
'</root>'
|
86
|
+
end
|
87
|
+
|
88
|
+
should 'make raw XML with nested tags' do
|
89
|
+
mpns = Object.new.extend MicrosoftPushNotificationService
|
90
|
+
xml, _ = mpns.send(:raw_notification_with_options,
|
91
|
+
{ key1: 'val1', key2: { subkey1: 'subval1', subkey2: { subsubkey1: 'subsubval1' } } })
|
92
|
+
assert_equal xml, '<?xml version="1.0" encoding="UTF-8"?>' +
|
93
|
+
'<root>' +
|
94
|
+
'<key1>val1</key1>' +
|
95
|
+
'<key2>' +
|
96
|
+
'<subkey1>subval1</subkey1>' +
|
97
|
+
'<subkey2>' +
|
98
|
+
'<subsubkey1>subsubval1</subsubkey1>' +
|
99
|
+
'</subkey2>' +
|
100
|
+
'</key2>' +
|
101
|
+
'</root>'
|
6
102
|
end
|
7
103
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mpns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: builder
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|