pushr-wns 1.0.0.pre
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/MIT-LICENSE +20 -0
- data/README.md +35 -0
- data/lib/pushr-wns/version.rb +3 -0
- data/lib/pushr/configuration_wns.rb +15 -0
- data/lib/pushr/daemon/wns.rb +26 -0
- data/lib/pushr/daemon/wns_support/access_token.rb +57 -0
- data/lib/pushr/daemon/wns_support/connection_manager.rb +34 -0
- data/lib/pushr/daemon/wns_support/connection_wns.rb +110 -0
- data/lib/pushr/feedback_wns.rb +10 -0
- data/lib/pushr/message_wns.rb +36 -0
- data/lib/pushr/message_wns_toast.rb +9 -0
- data/lib/pushr/wns.rb +15 -0
- data/spec/lib/pushr/configuration_wns_spec.rb +35 -0
- data/spec/lib/pushr/daemon/wns_spec.rb +13 -0
- data/spec/lib/pushr/daemon/wns_support/access_token_spec.rb +27 -0
- data/spec/lib/pushr/daemon/wns_support/connection_manager_spec.rb +56 -0
- data/spec/lib/pushr/daemon/wns_support/connection_wns_spec.rb +38 -0
- data/spec/lib/pushr/feedback_wns_spec.rb +27 -0
- data/spec/lib/pushr/message_wns_spec.rb +49 -0
- data/spec/lib/pushr/message_wns_toast_spec.rb +38 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/vcr.rb +4 -0
- data/spec/vcr/pushr/daemon/wns_support/access_token/does_not_receive_token_unsuccesful.yml +46 -0
- data/spec/vcr/pushr/daemon/wns_support/access_token/receives_token_succesful.yml +46 -0
- data/spec/vcr/pushr/daemon/wns_support/connection_manager/creates_first_connection_succesful.yml +47 -0
- data/spec/vcr/pushr/daemon/wns_support/connection_manager/creates_multiple_connections_succesful.yml +99 -0
- data/spec/vcr/pushr/daemon/wns_support/connection_wns/sends_a_message_succesful.yml +51 -0
- metadata +268 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: db74413af288d7801a8b7bfa71fce8339c75feafb6b9452fd248247fed978113
|
4
|
+
data.tar.gz: 0a7d25172fae765322497e8d2725f650b778e3caf99e582d85b614d5720853cb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 118acb36e76025bd83ccd244862972aa5a37bc3dddcf16727ac4a983edfeed0886c9af63755d2a297e6e5a288e88059f27b81e46d3107a3aafe460d34f5b902d
|
7
|
+
data.tar.gz: b673fb65bc2617c2079fec5a99a79b7575b928435201fa7cf89120dbb80f7b4379f787792bb9e0880e81468d700391a58e6268221654215bed0056908429bfbc
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
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.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# PushrWns
|
2
|
+
|
3
|
+
[](https://travis-ci.org/9to5/pushr-wns)
|
4
|
+
[](https://codeclimate.com/github/9to5/pushr-wns)
|
5
|
+
[](https://coveralls.io/r/9to5/pushr-wns)
|
6
|
+
|
7
|
+
Please see [pushr-core](https://github.com/9to5/pushr-core) for more information.
|
8
|
+
|
9
|
+
## Configuration
|
10
|
+
|
11
|
+
Redis:
|
12
|
+
```ruby
|
13
|
+
Pushr::ConfigurationWns.create(app: 'app_name', connections: 2, enabled: true, client_id: '<client_id>', client_secret: '<client_secret>)
|
14
|
+
```
|
15
|
+
|
16
|
+
YAML:
|
17
|
+
```yaml
|
18
|
+
- type: Pushr::ConfigurationWns
|
19
|
+
app: wns-app
|
20
|
+
enabled: true
|
21
|
+
connections: 1
|
22
|
+
client_id: client_id_here
|
23
|
+
client_secret: client_secret_here
|
24
|
+
```
|
25
|
+
|
26
|
+
## Sending notifications
|
27
|
+
|
28
|
+
WNS:
|
29
|
+
```ruby
|
30
|
+
Pushr::MessageWns.create(
|
31
|
+
app: 'test', channel_uri: 'https://db3.notify.windows.com/?token=token',
|
32
|
+
data: '<toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image id="1" '\
|
33
|
+
'src="World" /><text id="1">Hello</text></binding></visual></toast>',
|
34
|
+
content_type: 'text/xml', x_wns_type: 'wns/toast')
|
35
|
+
```
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pushr
|
2
|
+
class ConfigurationWns < Pushr::Configuration
|
3
|
+
attr_accessor :client_id, :client_secret
|
4
|
+
validates :client_id, :client_secret, presence: true
|
5
|
+
|
6
|
+
def name
|
7
|
+
:wns
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_hash
|
11
|
+
{ type: self.class.to_s, app: app, enabled: enabled, connections: connections, client_id: client_id,
|
12
|
+
client_secret: client_secret }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Pushr
|
2
|
+
module Daemon
|
3
|
+
class Wns
|
4
|
+
attr_accessor :configuration, :handlers
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@configuration = options
|
8
|
+
@handlers = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def start
|
12
|
+
access_token = Pushr::Daemon::WnsSupport::AccessToken.new(configuration)
|
13
|
+
configuration.connections.times do |i|
|
14
|
+
connection = WnsSupport::ConnectionManager.new(configuration.name, access_token, i + 1)
|
15
|
+
handler = MessageHandler.new("pushr:#{configuration.key}", connection, configuration.app, i + 1)
|
16
|
+
handler.start
|
17
|
+
@handlers << handler
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop
|
22
|
+
@handlers.map(&:stop)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# In the authentication with WNS, the cloud service submits an HTTP request over Secure Sockets Layer (SSL). The
|
2
|
+
# parameters are supplied in the "application/x-www-for-urlencoded" format. Supply your Package SID in the "client_id"
|
3
|
+
# field and your secret key in the "client_secret" field. For syntax details, see the access token request reference.
|
4
|
+
|
5
|
+
module Pushr
|
6
|
+
module Daemon
|
7
|
+
module WnsSupport
|
8
|
+
class AuthenticationError < StandardError; end
|
9
|
+
|
10
|
+
class AccessToken
|
11
|
+
def initialize(configuration)
|
12
|
+
@configuration = configuration
|
13
|
+
@expires_in = Time.now
|
14
|
+
@semaphore = Mutex.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def get
|
18
|
+
@semaphore.synchronize { request_token if expired? || @access_token.nil? }
|
19
|
+
@access_token
|
20
|
+
end
|
21
|
+
|
22
|
+
def expired?
|
23
|
+
Time.now > @expires_in
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_token
|
27
|
+
uri = URI('https://login.live.com/accesstoken.srf')
|
28
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
29
|
+
request.set_form_data(params)
|
30
|
+
response = http(uri).request(request)
|
31
|
+
response_hsh = MultiJson.load(response.body)
|
32
|
+
if response.code.to_i != 200
|
33
|
+
fail AuthenticationError, response_hsh['error_description']
|
34
|
+
else
|
35
|
+
process_response(response_hsh)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def http(uri)
|
40
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
41
|
+
http.use_ssl = true
|
42
|
+
http
|
43
|
+
end
|
44
|
+
|
45
|
+
def process_response(params)
|
46
|
+
@expires_in = Time.now + params['expires_in']
|
47
|
+
@access_token = params['access_token']
|
48
|
+
end
|
49
|
+
|
50
|
+
def params
|
51
|
+
{ grant_type: 'client_credentials', scope: 'notify.windows.com', client_id: @configuration.client_id,
|
52
|
+
client_secret: @configuration.client_secret }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Pushr
|
2
|
+
module Daemon
|
3
|
+
module WnsSupport
|
4
|
+
class ConnectionManager
|
5
|
+
attr_accessor :name
|
6
|
+
def initialize(app_name, access_token, i)
|
7
|
+
@pool = {}
|
8
|
+
@app_name = app_name
|
9
|
+
@access_token = access_token
|
10
|
+
@i = i
|
11
|
+
@name = "#{app_name}: ConnectionWns #{i}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(uri)
|
15
|
+
key = "#{uri.scheme}://#{uri.host}"
|
16
|
+
unless @pool.key? key
|
17
|
+
@pool[key] = ConnectionWns.new(@app_name, @access_token, @i)
|
18
|
+
end
|
19
|
+
@pool[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(message)
|
23
|
+
uri = URI.parse(message.channel_uri)
|
24
|
+
connection = get(uri)
|
25
|
+
connection.write(message)
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
@pool.size
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Pushr
|
2
|
+
module Daemon
|
3
|
+
module WnsSupport
|
4
|
+
class ConnectionError < StandardError; end
|
5
|
+
|
6
|
+
class ConnectionWns
|
7
|
+
attr_reader :response, :name
|
8
|
+
IDLE_PERIOD = 5 * 60
|
9
|
+
|
10
|
+
def initialize(app_name, access_token, i)
|
11
|
+
@app_name = app_name
|
12
|
+
@access_token = access_token
|
13
|
+
@name = "#{app_name}: ConnectionWns #{i}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(message)
|
17
|
+
retry_count = 0
|
18
|
+
begin
|
19
|
+
response = notification_request(message)
|
20
|
+
handle_error_response(response, message) unless response.code.eql? '200'
|
21
|
+
rescue => e
|
22
|
+
retry_count += 1
|
23
|
+
retry if retry_count < 10
|
24
|
+
raise e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# http://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx
|
31
|
+
def handle_error_response(response, message)
|
32
|
+
case response.code.to_i
|
33
|
+
when 403
|
34
|
+
# TODO: retry with new credentials
|
35
|
+
when 404, 410
|
36
|
+
Pushr::FeedbackWns.create(app: @app_name, device: message.channel_uri, follow_up: 'delete',
|
37
|
+
failed_at: Time.now)
|
38
|
+
when 406
|
39
|
+
# TODO: Throttle
|
40
|
+
end
|
41
|
+
|
42
|
+
Pushr::Daemon.logger.error("[#{@name}] #{response.code} #{response.message}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def notification_request(message)
|
46
|
+
uri = URI.parse(message.channel_uri)
|
47
|
+
connect(uri) unless @last_use
|
48
|
+
post(uri, message.data, headers(message))
|
49
|
+
end
|
50
|
+
|
51
|
+
def post(uri, data, headers, retry_count = 0)
|
52
|
+
reconnect_idle if idle_period_exceeded?
|
53
|
+
|
54
|
+
begin
|
55
|
+
response = @connection.post("#{uri.path}?#{uri.query}", data, headers)
|
56
|
+
@last_use = Time.now
|
57
|
+
rescue EOFError, Errno::ECONNRESET, Timeout::Error => e
|
58
|
+
retry_count += 1
|
59
|
+
Pushr::Daemon.logger.error("[#{@name}] Lost connection to #{PUSH_URL} (#{e.class.name}), reconnecting ##{retry_count}...")
|
60
|
+
if retry_count <= 3
|
61
|
+
reconnect
|
62
|
+
sleep 1
|
63
|
+
retry
|
64
|
+
end
|
65
|
+
raise ConnectionError, "#{@name} tried #{retry_count - 1} times to reconnect but failed (#{e.class.name})."
|
66
|
+
end
|
67
|
+
|
68
|
+
response
|
69
|
+
end
|
70
|
+
|
71
|
+
def open_http(host, port)
|
72
|
+
http = Net::HTTP.new(host, port)
|
73
|
+
http.use_ssl = true
|
74
|
+
http
|
75
|
+
end
|
76
|
+
|
77
|
+
def headers(message)
|
78
|
+
{ 'Authorization' => "Bearer #{@access_token.get}",
|
79
|
+
'Content-type' => message.content_type,
|
80
|
+
'Content-length' => "#{message.data.bytes.count}",
|
81
|
+
'X-WNS-RequestForStatus' => 'true',
|
82
|
+
'X-WNS-Type' => message.x_wns_type }
|
83
|
+
end
|
84
|
+
|
85
|
+
def connect(uri)
|
86
|
+
@last_use = Time.now
|
87
|
+
@connection = open_http(uri.host, uri.port)
|
88
|
+
@connection.start
|
89
|
+
Pushr::Daemon.logger.info("[#{@name}] Connected to #{uri.scheme}://#{uri.host}")
|
90
|
+
end
|
91
|
+
|
92
|
+
def idle_period_exceeded?
|
93
|
+
# Timeout on the http connection is 5 minutes, reconnect after 5 minutes
|
94
|
+
@last_use + IDLE_PERIOD < Time.now
|
95
|
+
end
|
96
|
+
|
97
|
+
def reconnect_idle
|
98
|
+
Pushr::Daemon.logger.info("[#{@name}] Idle period exceeded, reconnecting...")
|
99
|
+
reconnect
|
100
|
+
end
|
101
|
+
|
102
|
+
def reconnect
|
103
|
+
@connection.finish
|
104
|
+
@last_use = Time.now
|
105
|
+
@connection.start
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Pushr
|
2
|
+
class FeedbackWns < Pushr::Feedback
|
3
|
+
attr_accessor :device, :follow_up, :failed_at
|
4
|
+
validates :follow_up, inclusion: { in: %w(delete), message: '%{value} is not a valid follow-up' }
|
5
|
+
|
6
|
+
def to_hash
|
7
|
+
{ type: 'Pushr::FeedbackWns', app: app, device: device, follow_up: follow_up, failed_at: failed_at }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Pushr
|
2
|
+
class MessageWns < Pushr::Message
|
3
|
+
POSTFIX = 'wns'
|
4
|
+
|
5
|
+
attr_accessor :channel_uri, :data, :content_type, :x_wns_type
|
6
|
+
validates :channel_uri, :data, :content_type, :x_wns_type, presence: true
|
7
|
+
validates :content_type, inclusion: { in: ['text/xml', 'application/octet-stream'] }
|
8
|
+
validates :x_wns_type, inclusion: { in: ['wns/toast', 'wns/badge', 'wns/tile', 'wns/raw'] }
|
9
|
+
validate :channel_uri_domain
|
10
|
+
validate :data_size
|
11
|
+
|
12
|
+
def channel_uri_domain
|
13
|
+
return if channel_uri && URI.parse(channel_uri).host.end_with?('notify.windows.com')
|
14
|
+
errors.add(:channel_uri, 'channel_uri domain should end with \'notify.windows.com\'')
|
15
|
+
end
|
16
|
+
|
17
|
+
def data_size
|
18
|
+
errors.add(:data, 'is more thank 5000 bytes') if data && data.bytes.count > 5000
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_message
|
22
|
+
hsh = {}
|
23
|
+
%w(channel_uri data).each do |variable|
|
24
|
+
hsh[variable] = send(variable) if send(variable)
|
25
|
+
end
|
26
|
+
MultiJson.dump(hsh)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_hash
|
30
|
+
hsh = { type: self.class.to_s, app: app, channel_uri: channel_uri, data: data, content_type: content_type,
|
31
|
+
x_wns_type: x_wns_type }
|
32
|
+
hsh[Pushr::Core.external_id_tag] = external_id if external_id
|
33
|
+
hsh
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/pushr/wns.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'active_model'
|
4
|
+
require 'pushr-wns/version'
|
5
|
+
require 'pushr/configuration'
|
6
|
+
require 'pushr/configuration_wns'
|
7
|
+
require 'pushr/message'
|
8
|
+
require 'pushr/message_wns'
|
9
|
+
require 'pushr/message_wns_toast'
|
10
|
+
require 'pushr/feedback'
|
11
|
+
require 'pushr/feedback_wns'
|
12
|
+
require 'pushr/daemon/wns'
|
13
|
+
require 'pushr/daemon/wns_support/connection_manager'
|
14
|
+
require 'pushr/daemon/wns_support/connection_wns'
|
15
|
+
require 'pushr/daemon/wns_support/access_token'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/configuration_wns'
|
3
|
+
|
4
|
+
describe Pushr::ConfigurationWns do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
Pushr::Core.configure do |config|
|
8
|
+
config.redis = ConnectionPool.new(size: 1, timeout: 1) { MockRedis.new }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'all' do
|
13
|
+
it 'returns all configurations' do
|
14
|
+
expect(Pushr::Configuration.all).to eql([])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'create' do
|
19
|
+
it 'should create a configuration' do
|
20
|
+
config = Pushr::ConfigurationWns.new(app: 'app_name', connections: 2, enabled: true)
|
21
|
+
expect(config.key).to eql('app_name:wns')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'save' do
|
26
|
+
let(:config) do
|
27
|
+
Pushr::ConfigurationWns.new(app: 'app_name', connections: 2, enabled: true, client_id: 'id', client_secret: 'sec')
|
28
|
+
end
|
29
|
+
it 'should save a configuration' do
|
30
|
+
config.save
|
31
|
+
expect(Pushr::Configuration.all.count).to eql(1)
|
32
|
+
expect(Pushr::Configuration.all[0].class).to eql(Pushr::ConfigurationWns)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/daemon/wns'
|
3
|
+
require 'pushr/daemon/wns_support/connection_wns'
|
4
|
+
|
5
|
+
describe Pushr::Daemon::Wns do
|
6
|
+
let(:wns) { Pushr::Daemon::Wns.new(test: 'test') }
|
7
|
+
|
8
|
+
describe 'responds to' do
|
9
|
+
it 'configuration' do
|
10
|
+
expect(wns.configuration).to eql(test: 'test')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/configuration_wns'
|
3
|
+
require 'pushr/daemon/wns_support/access_token'
|
4
|
+
|
5
|
+
describe Pushr::Daemon::WnsSupport::AccessToken do
|
6
|
+
subject { Pushr::Daemon::WnsSupport::AccessToken.new(config) }
|
7
|
+
|
8
|
+
let(:config) do
|
9
|
+
Pushr::ConfigurationWns.new(app: 'app_name', connections: 2, enabled: true, client_id: client_id,
|
10
|
+
client_secret: client_secret)
|
11
|
+
end
|
12
|
+
describe 'receives token' do
|
13
|
+
let(:client_id) { 'test' }
|
14
|
+
let(:client_secret) { 'secret' }
|
15
|
+
it 'succesful', :vcr do
|
16
|
+
expect(subject.get).to eql('access_token')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'does not receive token' do
|
21
|
+
let(:client_id) { 'invalid_test' }
|
22
|
+
let(:client_secret) { 'invalid_secret' }
|
23
|
+
it 'unsuccesful', :vcr do
|
24
|
+
expect { subject.get }.to raise_error(Pushr::Daemon::WnsSupport::AuthenticationError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/daemon'
|
3
|
+
require 'pushr/daemon/logger'
|
4
|
+
require 'pushr/configuration_wns'
|
5
|
+
require 'pushr/message_wns'
|
6
|
+
require 'pushr/daemon/wns_support/access_token'
|
7
|
+
require 'pushr/daemon/wns_support/connection_wns'
|
8
|
+
require 'pushr/daemon/wns_support/connection_manager'
|
9
|
+
|
10
|
+
describe Pushr::Daemon::WnsSupport::ConnectionManager do
|
11
|
+
before(:each) do
|
12
|
+
Pushr::Core.configure do |config|
|
13
|
+
config.redis = ConnectionPool.new(size: 1, timeout: 1) { MockRedis.new }
|
14
|
+
end
|
15
|
+
|
16
|
+
logger = double('logger')
|
17
|
+
allow(logger).to receive(:info)
|
18
|
+
allow(logger).to receive(:error)
|
19
|
+
allow(logger).to receive(:warn)
|
20
|
+
Pushr::Daemon.logger = logger
|
21
|
+
end
|
22
|
+
|
23
|
+
subject { Pushr::Daemon::WnsSupport::ConnectionManager.new('app_name', access_token, 1) }
|
24
|
+
let(:access_token) { double('Pushr::Daemon::WnsSupport::AccessToken', get: 'access_token') }
|
25
|
+
|
26
|
+
let(:message) do
|
27
|
+
hsh = { app: 'app_name', channel_uri: 'https://db3.notify.windows.com/?token=token',
|
28
|
+
data: '<toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image id="1" '\
|
29
|
+
'src="World" /><text id="1">Hello</text></binding></visual></toast>',
|
30
|
+
content_type: 'text/xml', x_wns_type: 'wns/toast' }
|
31
|
+
Pushr::MessageWns.new(hsh)
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:message2) do
|
35
|
+
hsh = { app: 'app_name', channel_uri: 'https://db4.notify.windows.com/?token=token',
|
36
|
+
data: '<toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image id="1" '\
|
37
|
+
'src="World" /><text id="1">Hello</text></binding></visual></toast>',
|
38
|
+
content_type: 'text/xml', x_wns_type: 'wns/toast' }
|
39
|
+
Pushr::MessageWns.new(hsh)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'creates first connection' do
|
43
|
+
it 'succesful', :vcr do
|
44
|
+
subject.write(message)
|
45
|
+
expect(subject.size).to eql(1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'creates multiple connections' do
|
50
|
+
it 'succesful', :vcr do
|
51
|
+
subject.write(message)
|
52
|
+
subject.write(message2)
|
53
|
+
expect(subject.size).to eql(2)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/daemon'
|
3
|
+
require 'pushr/wns'
|
4
|
+
require 'pushr/daemon/logger'
|
5
|
+
require 'pushr/message_wns'
|
6
|
+
require 'pushr/configuration_wns'
|
7
|
+
require 'pushr/daemon/delivery_error'
|
8
|
+
|
9
|
+
describe Pushr::Daemon::WnsSupport::ConnectionWns do
|
10
|
+
before(:each) do
|
11
|
+
Pushr::Core.configure do |config|
|
12
|
+
config.redis = ConnectionPool.new(size: 1, timeout: 1) { MockRedis.new }
|
13
|
+
end
|
14
|
+
|
15
|
+
logger = double('logger')
|
16
|
+
allow(logger).to receive(:info)
|
17
|
+
allow(logger).to receive(:error)
|
18
|
+
allow(logger).to receive(:warn)
|
19
|
+
Pushr::Daemon.logger = logger
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:access_token) { double('Pushr::Daemon::WnsSupport::AccessToken', get: 'access_token') }
|
23
|
+
let(:message) do
|
24
|
+
hsh = { app: 'app_name', channel_uri: 'https://db3.notify.windows.com/?token=token',
|
25
|
+
data: '<toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image id="1" '\
|
26
|
+
'src="World" /><text id="1">Hello</text></binding></visual></toast>' }
|
27
|
+
Pushr::MessageWnsToast.new(hsh)
|
28
|
+
end
|
29
|
+
let(:connection) { Pushr::Daemon::WnsSupport::ConnectionWns.new('app_name', access_token, 1) }
|
30
|
+
|
31
|
+
describe 'sends a message' do
|
32
|
+
|
33
|
+
it 'succesful', :vcr do
|
34
|
+
connection.write(message)
|
35
|
+
# TODO: expect(connection.write(message).code).to eql '200'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/feedback_wns'
|
3
|
+
|
4
|
+
describe Pushr::FeedbackWns do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
Pushr::Core.configure do |config|
|
8
|
+
config.redis = ConnectionPool.new(size: 1, timeout: 1) { MockRedis.new }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'create' do
|
13
|
+
it 'should create a feedback' do
|
14
|
+
feedback = Pushr::FeedbackWns.new(app: 'app_name', device: 'ab' * 20, follow_up: 'delete', failed_at: Time.now)
|
15
|
+
expect(feedback.app).to eql('app_name')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'save' do
|
20
|
+
let!(:feedback) do
|
21
|
+
Pushr::FeedbackWns.create(app: 'app_name', device: 'ab' * 20, follow_up: 'delete', failed_at: Time.now)
|
22
|
+
end
|
23
|
+
it 'should save a feedback' do
|
24
|
+
expect(Pushr::Feedback.next.class).to eql(Pushr::FeedbackWns)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/message_wns'
|
3
|
+
|
4
|
+
describe Pushr::MessageWns do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
Pushr::Core.configure do |config|
|
8
|
+
config.redis = ConnectionPool.new(size: 1, timeout: 1) { MockRedis.new }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'next' do
|
13
|
+
it 'returns next message' do
|
14
|
+
expect(Pushr::Message.next('pushr:app_name:wns')).to eql(nil)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:message) do
|
19
|
+
hsh = { app: 'app_name', channel_uri: channel_uri,
|
20
|
+
data: '<toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image id="1" '\
|
21
|
+
'src="World" /><text id="1">Hello</text></binding></visual></toast>',
|
22
|
+
content_type: 'text/xml', x_wns_type: 'wns/toast' }
|
23
|
+
Pushr::MessageWns.new(hsh)
|
24
|
+
end
|
25
|
+
describe 'save' do
|
26
|
+
let(:channel_uri) { 'https://db3.notify.windows.com/?token=token' }
|
27
|
+
|
28
|
+
it 'should return true' do
|
29
|
+
expect(message.save).to eql true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should save a message' do
|
33
|
+
message.save
|
34
|
+
expect(Pushr::Message.next('pushr:app_name:wns')).to be_kind_of(Pushr::MessageWns)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should respond to to_message' do
|
38
|
+
expect(message.to_message).to be_kind_of(String)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'validate channel_uri' do
|
43
|
+
let(:channel_uri) { 'https://db3.invalid.domain/?token=token' }
|
44
|
+
it 'should respond to to_message' do
|
45
|
+
expect(message.valid?).to be_falsy
|
46
|
+
expect(message.errors[:channel_uri]).to eql(['channel_uri domain should end with \'notify.windows.com\''])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pushr/message_wns'
|
3
|
+
require 'pushr/message_wns_toast'
|
4
|
+
|
5
|
+
describe Pushr::MessageWnsToast do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Pushr::Core.configure do |config|
|
9
|
+
config.redis = ConnectionPool.new(size: 1, timeout: 1) { MockRedis.new }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'next' do
|
14
|
+
it 'returns next message' do
|
15
|
+
expect(Pushr::Message.next('pushr:app_name:wns')).to eql(nil)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'save' do
|
20
|
+
let(:message) do
|
21
|
+
hsh = { app: 'app_name', channel_uri: 'https://db3.notify.windows.com/?token=token-here', data: 'data' }
|
22
|
+
Pushr::MessageWnsToast.new(hsh)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return true' do
|
26
|
+
expect(message.save).to eql true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should save a message' do
|
30
|
+
message.save
|
31
|
+
expect(Pushr::Message.next('pushr:app_name:wns')).to be_kind_of(Pushr::MessageWnsToast)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should respond to to_message' do
|
35
|
+
expect(message.to_message).to be_kind_of(String)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
|
6
|
+
require 'simplecov'
|
7
|
+
require 'coveralls'
|
8
|
+
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
10
|
+
SimpleCov::Formatter::HTMLFormatter,
|
11
|
+
Coveralls::SimpleCov::Formatter
|
12
|
+
])
|
13
|
+
SimpleCov.start
|
14
|
+
|
15
|
+
require 'vcr'
|
16
|
+
require 'pushr/core'
|
17
|
+
require 'mock_redis'
|
18
|
+
|
19
|
+
Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.raise_errors_for_deprecations!
|
23
|
+
config.run_all_when_everything_filtered = true
|
24
|
+
# config.filter_run :focus
|
25
|
+
|
26
|
+
# Run specs in random order to surface order dependencies. If you find an
|
27
|
+
# order dependency and want to debug it, you can fix the order by providing
|
28
|
+
# the seed, which is printed after each run.
|
29
|
+
# --seed 1234
|
30
|
+
config.order = 'random'
|
31
|
+
|
32
|
+
config.around(:each, :vcr) do |example|
|
33
|
+
name = example.metadata[:full_description].split(/\s+/, 2).join('/').underscore.gsub(/[^\w\/]+/, '_')
|
34
|
+
options = example.metadata.slice(:record, :match_requests_on).except(:example_group)
|
35
|
+
VCR.use_cassette(name, options) { example.call }
|
36
|
+
end
|
37
|
+
end
|
data/spec/support/vcr.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://login.live.com/accesstoken.srf
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: grant_type=client_credentials&scope=notify.windows.com&client_id=invalid_test&client_secret=invalid_secret
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Content-Type:
|
17
|
+
- application/x-www-form-urlencoded
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 400
|
21
|
+
message: Bad Request
|
22
|
+
headers:
|
23
|
+
Cache-Control:
|
24
|
+
- no-store
|
25
|
+
Pragma:
|
26
|
+
- no-cache
|
27
|
+
Content-Length:
|
28
|
+
- '66'
|
29
|
+
Content-Type:
|
30
|
+
- application/json
|
31
|
+
Server:
|
32
|
+
- Microsoft-IIS/7.5
|
33
|
+
X-Wlid-Error:
|
34
|
+
- '0x80049D59'
|
35
|
+
Ppserver:
|
36
|
+
- 'PPV: 30 H: BAYIDSLGN2E025 V: 0'
|
37
|
+
Date:
|
38
|
+
- Tue, 28 Oct 2014 13:26:38 GMT
|
39
|
+
Connection:
|
40
|
+
- close
|
41
|
+
body:
|
42
|
+
encoding: UTF-8
|
43
|
+
string: '{"error":"invalid_client","error_description":"Invalid client id"}'
|
44
|
+
http_version:
|
45
|
+
recorded_at: Tue, 28 Oct 2014 13:26:38 GMT
|
46
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,46 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://login.live.com/accesstoken.srf
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: grant_type=client_credentials&scope=notify.windows.com&client_id=test&client_secret=secret
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Host:
|
17
|
+
- login.live.com
|
18
|
+
Content-Type:
|
19
|
+
- application/x-www-form-urlencoded
|
20
|
+
response:
|
21
|
+
status:
|
22
|
+
code: 200
|
23
|
+
message: OK
|
24
|
+
headers:
|
25
|
+
Cache-Control:
|
26
|
+
- no-store
|
27
|
+
Pragma:
|
28
|
+
- no-cache
|
29
|
+
Content-Length:
|
30
|
+
- '444'
|
31
|
+
Content-Type:
|
32
|
+
- application/json
|
33
|
+
Server:
|
34
|
+
- Microsoft-IIS/7.5
|
35
|
+
Ppserver:
|
36
|
+
- 'PPV: 30 H: BAYIDSLGN1A015 V: 0'
|
37
|
+
Date:
|
38
|
+
- Mon, 27 Oct 2014 16:48:34 GMT
|
39
|
+
Connection:
|
40
|
+
- close
|
41
|
+
body:
|
42
|
+
encoding: UTF-8
|
43
|
+
string: '{"token_type":"bearer","access_token":"access_token","expires_in":86400}'
|
44
|
+
http_version:
|
45
|
+
recorded_at: Mon, 27 Oct 2014 16:48:34 GMT
|
46
|
+
recorded_with: VCR 2.9.3
|
data/spec/vcr/pushr/daemon/wns_support/connection_manager/creates_first_connection_succesful.yml
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://db3.notify.windows.com/?token=token
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: <toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image
|
9
|
+
id="1" src="World" /><text id="1">Hello</text></binding></visual></toast>
|
10
|
+
headers:
|
11
|
+
Authorization:
|
12
|
+
- Bearer access_token
|
13
|
+
Content-Type:
|
14
|
+
- text/xml
|
15
|
+
Content-Length:
|
16
|
+
- '158'
|
17
|
+
X-Wns-Requestforstatus:
|
18
|
+
- 'true'
|
19
|
+
X-Wns-Type:
|
20
|
+
- wns/toast
|
21
|
+
Accept-Encoding:
|
22
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
23
|
+
Accept:
|
24
|
+
- "*/*"
|
25
|
+
User-Agent:
|
26
|
+
- Ruby
|
27
|
+
response:
|
28
|
+
status:
|
29
|
+
code: 401
|
30
|
+
message: Unauthorized
|
31
|
+
headers:
|
32
|
+
Content-Length:
|
33
|
+
- '0'
|
34
|
+
X-Wns-Msg-Id:
|
35
|
+
- 79647B0871EAD6E2
|
36
|
+
X-Wns-Debug-Trace:
|
37
|
+
- DB3WNS2011334
|
38
|
+
Www-Authenticate:
|
39
|
+
- Bearer error="invalid_request",error_description="Invalid token"
|
40
|
+
Date:
|
41
|
+
- Mon, 10 Nov 2014 10:21:43 GMT
|
42
|
+
body:
|
43
|
+
encoding: UTF-8
|
44
|
+
string: ''
|
45
|
+
http_version:
|
46
|
+
recorded_at: Mon, 10 Nov 2014 10:21:43 GMT
|
47
|
+
recorded_with: VCR 2.9.3
|
data/spec/vcr/pushr/daemon/wns_support/connection_manager/creates_multiple_connections_succesful.yml
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://db3.notify.windows.com/?token=token
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: <toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image
|
9
|
+
id="1" src="World" /><text id="1">Hello</text></binding></visual></toast>
|
10
|
+
headers:
|
11
|
+
Authorization:
|
12
|
+
- Bearer access_token
|
13
|
+
Content-Type:
|
14
|
+
- text/xml
|
15
|
+
Content-Length:
|
16
|
+
- '158'
|
17
|
+
X-Wns-Requestforstatus:
|
18
|
+
- 'true'
|
19
|
+
X-Wns-Type:
|
20
|
+
- wns/toast
|
21
|
+
Accept-Encoding:
|
22
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
23
|
+
Accept:
|
24
|
+
- "*/*"
|
25
|
+
User-Agent:
|
26
|
+
- Ruby
|
27
|
+
response:
|
28
|
+
status:
|
29
|
+
code: 200
|
30
|
+
message: OK
|
31
|
+
headers:
|
32
|
+
Content-Length:
|
33
|
+
- '0'
|
34
|
+
X-Wns-Deviceconnectionstatus:
|
35
|
+
- connected
|
36
|
+
X-Wns-Notificationstatus:
|
37
|
+
- received
|
38
|
+
X-Wns-Status:
|
39
|
+
- received
|
40
|
+
X-Wns-Msg-Id:
|
41
|
+
- 402E73F068974F89
|
42
|
+
X-Wns-Debug-Trace:
|
43
|
+
- DB3WNS4011733
|
44
|
+
Date:
|
45
|
+
- Mon, 27 Oct 2014 16:48:34 GMT
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: ''
|
49
|
+
http_version:
|
50
|
+
recorded_at: Mon, 27 Oct 2014 16:48:35 GMT
|
51
|
+
- request:
|
52
|
+
method: post
|
53
|
+
uri: https://db4.notify.windows.com/?token=token
|
54
|
+
body:
|
55
|
+
encoding: UTF-8
|
56
|
+
string: <toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image
|
57
|
+
id="1" src="World" /><text id="1">Hello</text></binding></visual></toast>
|
58
|
+
headers:
|
59
|
+
Authorization:
|
60
|
+
- Bearer access_token
|
61
|
+
Content-Type:
|
62
|
+
- text/xml
|
63
|
+
Content-Length:
|
64
|
+
- '158'
|
65
|
+
X-Wns-Requestforstatus:
|
66
|
+
- 'true'
|
67
|
+
X-Wns-Type:
|
68
|
+
- wns/toast
|
69
|
+
Accept-Encoding:
|
70
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
71
|
+
Accept:
|
72
|
+
- "*/*"
|
73
|
+
User-Agent:
|
74
|
+
- Ruby
|
75
|
+
response:
|
76
|
+
status:
|
77
|
+
code: 200
|
78
|
+
message: OK
|
79
|
+
headers:
|
80
|
+
Content-Length:
|
81
|
+
- '0'
|
82
|
+
X-Wns-Deviceconnectionstatus:
|
83
|
+
- connected
|
84
|
+
X-Wns-Notificationstatus:
|
85
|
+
- received
|
86
|
+
X-Wns-Status:
|
87
|
+
- received
|
88
|
+
X-Wns-Msg-Id:
|
89
|
+
- 402E73F068974F89
|
90
|
+
X-Wns-Debug-Trace:
|
91
|
+
- DB3WNS4011733
|
92
|
+
Date:
|
93
|
+
- Mon, 27 Oct 2014 16:48:34 GMT
|
94
|
+
body:
|
95
|
+
encoding: UTF-8
|
96
|
+
string: ''
|
97
|
+
http_version:
|
98
|
+
recorded_at: Mon, 27 Oct 2014 16:48:35 GMT
|
99
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,51 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://db3.notify.windows.com/?token=token
|
6
|
+
body:
|
7
|
+
encoding: UTF-8
|
8
|
+
string: <toast launch=""><visual lang="en-US"><binding template="ToastImageAndText01"><image
|
9
|
+
id="1" src="World" /><text id="1">Hello</text></binding></visual></toast>
|
10
|
+
headers:
|
11
|
+
Authorization:
|
12
|
+
- Bearer access_token
|
13
|
+
Content-Type:
|
14
|
+
- text/xml
|
15
|
+
Content-Length:
|
16
|
+
- '158'
|
17
|
+
X-Wns-Requestforstatus:
|
18
|
+
- 'true'
|
19
|
+
X-Wns-Type:
|
20
|
+
- wns/toast
|
21
|
+
Accept-Encoding:
|
22
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
23
|
+
Accept:
|
24
|
+
- "*/*"
|
25
|
+
User-Agent:
|
26
|
+
- Ruby
|
27
|
+
response:
|
28
|
+
status:
|
29
|
+
code: 200
|
30
|
+
message: OK
|
31
|
+
headers:
|
32
|
+
Content-Length:
|
33
|
+
- '0'
|
34
|
+
X-Wns-Deviceconnectionstatus:
|
35
|
+
- connected
|
36
|
+
X-Wns-Notificationstatus:
|
37
|
+
- received
|
38
|
+
X-Wns-Status:
|
39
|
+
- received
|
40
|
+
X-Wns-Msg-Id:
|
41
|
+
- 402E73F068974F89
|
42
|
+
X-Wns-Debug-Trace:
|
43
|
+
- DB3WNS4011733
|
44
|
+
Date:
|
45
|
+
- Mon, 27 Oct 2014 16:48:34 GMT
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: ''
|
49
|
+
http_version:
|
50
|
+
recorded_at: Mon, 27 Oct 2014 16:48:35 GMT
|
51
|
+
recorded_with: VCR 2.9.3
|
metadata
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pushr-wns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tom Pesman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: multi_json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pushr-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activemodel
|
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
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mock_redis
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: vcr
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rake
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: coveralls
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rubocop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: WNS support for the modular push daemon.
|
196
|
+
email:
|
197
|
+
- tom@tnux.net
|
198
|
+
executables: []
|
199
|
+
extensions: []
|
200
|
+
extra_rdoc_files: []
|
201
|
+
files:
|
202
|
+
- MIT-LICENSE
|
203
|
+
- README.md
|
204
|
+
- lib/pushr-wns/version.rb
|
205
|
+
- lib/pushr/configuration_wns.rb
|
206
|
+
- lib/pushr/daemon/wns.rb
|
207
|
+
- lib/pushr/daemon/wns_support/access_token.rb
|
208
|
+
- lib/pushr/daemon/wns_support/connection_manager.rb
|
209
|
+
- lib/pushr/daemon/wns_support/connection_wns.rb
|
210
|
+
- lib/pushr/feedback_wns.rb
|
211
|
+
- lib/pushr/message_wns.rb
|
212
|
+
- lib/pushr/message_wns_toast.rb
|
213
|
+
- lib/pushr/wns.rb
|
214
|
+
- spec/lib/pushr/configuration_wns_spec.rb
|
215
|
+
- spec/lib/pushr/daemon/wns_spec.rb
|
216
|
+
- spec/lib/pushr/daemon/wns_support/access_token_spec.rb
|
217
|
+
- spec/lib/pushr/daemon/wns_support/connection_manager_spec.rb
|
218
|
+
- spec/lib/pushr/daemon/wns_support/connection_wns_spec.rb
|
219
|
+
- spec/lib/pushr/feedback_wns_spec.rb
|
220
|
+
- spec/lib/pushr/message_wns_spec.rb
|
221
|
+
- spec/lib/pushr/message_wns_toast_spec.rb
|
222
|
+
- spec/spec_helper.rb
|
223
|
+
- spec/support/vcr.rb
|
224
|
+
- spec/vcr/pushr/daemon/wns_support/access_token/does_not_receive_token_unsuccesful.yml
|
225
|
+
- spec/vcr/pushr/daemon/wns_support/access_token/receives_token_succesful.yml
|
226
|
+
- spec/vcr/pushr/daemon/wns_support/connection_manager/creates_first_connection_succesful.yml
|
227
|
+
- spec/vcr/pushr/daemon/wns_support/connection_manager/creates_multiple_connections_succesful.yml
|
228
|
+
- spec/vcr/pushr/daemon/wns_support/connection_wns/sends_a_message_succesful.yml
|
229
|
+
homepage: https://github.com/9to5/pushr-wns
|
230
|
+
licenses:
|
231
|
+
- MIT
|
232
|
+
metadata: {}
|
233
|
+
post_install_message:
|
234
|
+
rdoc_options: []
|
235
|
+
require_paths:
|
236
|
+
- lib
|
237
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
238
|
+
requirements:
|
239
|
+
- - ">="
|
240
|
+
- !ruby/object:Gem::Version
|
241
|
+
version: 2.2.0
|
242
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
243
|
+
requirements:
|
244
|
+
- - ">"
|
245
|
+
- !ruby/object:Gem::Version
|
246
|
+
version: 1.3.1
|
247
|
+
requirements: []
|
248
|
+
rubyforge_project:
|
249
|
+
rubygems_version: 2.7.6
|
250
|
+
signing_key:
|
251
|
+
specification_version: 4
|
252
|
+
summary: WNS (Windows Phone) part of the modular push daemon.
|
253
|
+
test_files:
|
254
|
+
- spec/lib/pushr/configuration_wns_spec.rb
|
255
|
+
- spec/lib/pushr/daemon/wns_spec.rb
|
256
|
+
- spec/lib/pushr/daemon/wns_support/access_token_spec.rb
|
257
|
+
- spec/lib/pushr/daemon/wns_support/connection_manager_spec.rb
|
258
|
+
- spec/lib/pushr/daemon/wns_support/connection_wns_spec.rb
|
259
|
+
- spec/lib/pushr/feedback_wns_spec.rb
|
260
|
+
- spec/lib/pushr/message_wns_spec.rb
|
261
|
+
- spec/lib/pushr/message_wns_toast_spec.rb
|
262
|
+
- spec/spec_helper.rb
|
263
|
+
- spec/support/vcr.rb
|
264
|
+
- spec/vcr/pushr/daemon/wns_support/access_token/does_not_receive_token_unsuccesful.yml
|
265
|
+
- spec/vcr/pushr/daemon/wns_support/access_token/receives_token_succesful.yml
|
266
|
+
- spec/vcr/pushr/daemon/wns_support/connection_manager/creates_first_connection_succesful.yml
|
267
|
+
- spec/vcr/pushr/daemon/wns_support/connection_manager/creates_multiple_connections_succesful.yml
|
268
|
+
- spec/vcr/pushr/daemon/wns_support/connection_wns/sends_a_message_succesful.yml
|