slanger 0.4.1 → 0.4.2
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.
Potentially problematic release.
This version of slanger might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +44 -1
- data/lib/slanger/api.rb +5 -0
- data/lib/slanger/api/event.rb +15 -0
- data/lib/slanger/api/event_publisher.rb +24 -0
- data/lib/slanger/api/request_validation.rb +103 -0
- data/lib/slanger/api/server.rb +56 -0
- data/lib/slanger/channel.rb +19 -7
- data/lib/slanger/connection.rb +2 -1
- data/lib/slanger/handler.rb +3 -3
- data/lib/slanger/presence_channel.rb +1 -2
- data/lib/slanger/service.rb +1 -1
- data/lib/slanger/version.rb +1 -1
- data/slanger.rb +4 -0
- data/spec/have_attributes.rb +64 -0
- data/spec/integration/channel_spec.rb +114 -0
- data/spec/integration/integration_spec.rb +68 -0
- data/spec/integration/presence_channel_spec.rb +158 -0
- data/spec/integration/private_channel_spec.rb +79 -0
- data/spec/integration/replaced_handler_spec.rb +23 -0
- data/spec/integration/ssl_spec.rb +18 -0
- data/spec/server.crt +12 -0
- data/spec/server.key +15 -0
- data/spec/slanger_helper_methods.rb +109 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/unit/channel_spec.rb +69 -0
- data/spec/unit/request_validation_spec.rb +64 -0
- data/spec/unit/webhook_spec.rb +43 -0
- metadata +88 -38
- data/lib/slanger/api_server.rb +0 -64
data/spec/server.crt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIBvzCCASgCCQCsMkmDVYNDETANBgkqhkiG9w0BAQUFADAkMQswCQYDVQQGEwJE
|
3
|
+
RTEVMBMGA1UEAwwMc2xhbmdlci50ZXN0MB4XDTEyMDQxMTE2NDMwNloXDTE5MDIx
|
4
|
+
NDE2NDMwNlowJDELMAkGA1UEBhMCREUxFTATBgNVBAMMDHNsYW5nZXIudGVzdDCB
|
5
|
+
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmlTxrcqXw+hbdjnpNENgx4p6T+x7
|
6
|
+
SgN/5ti3+gr5ZJElebEdJdGymM/KK817GFhLuYSEv72oEVitC1ISCfo/iOu4S71Y
|
7
|
+
sGsrdyPVl3cDswSkvmo27J3rtAbY1fNDs68YFAQGH8wlQtPSPvd9KBKg0klafsDU
|
8
|
+
VvDYjQ+XZ2+ZKZECAwEAATANBgkqhkiG9w0BAQUFAAOBgQCHGqUddcsTfvV0Nk3F
|
9
|
+
zZ5kGvAiZ02MUourZ4GVs5uBYtkIrQ7HAlQbHAbC8d7e0UVgcTwUKgwpw/RfNR/O
|
10
|
+
Ho/zn7lPciLQ7VMnOZ2+MfbJ2HIFgZL6qH1gTcQpBW4s3gKR5hFpaGJ+8l/cmEWj
|
11
|
+
AvywaOcSLex+q0OwZaiusiDorg==
|
12
|
+
-----END CERTIFICATE-----
|
data/spec/server.key
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXQIBAAKBgQCaVPGtypfD6Ft2Oek0Q2DHinpP7HtKA3/m2Lf6CvlkkSV5sR0l
|
3
|
+
0bKYz8orzXsYWEu5hIS/vagRWK0LUhIJ+j+I67hLvViwayt3I9WXdwOzBKS+ajbs
|
4
|
+
neu0BtjV80OzrxgUBAYfzCVC09I+930oEqDSSVp+wNRW8NiND5dnb5kpkQIDAQAB
|
5
|
+
AoGABGzBDSGM3mIQFUCtzgDMiowO27HFCyc0iJLYG4QrCFYdA/MvCcGMZFM40a6v
|
6
|
+
g9AsQ6JoB/NRGUY4l+V/fOe+4Iuycf8+vN1mrSVR1lTjy/mOwj900pc4ff6cDv6S
|
7
|
+
bI/hm4BNiuj8OD11R+ZK07Lo1iCzBkAy53RkTFcBk74MYgECQQDMyAMT0DhlRBqD
|
8
|
+
4vrPF+GZ+rMYpeTjuNDOZphIwzxpv70uyh2RNg+7F6U91Qxz6vpbIkz8Zf4TgdwM
|
9
|
+
u/rroktxAkEAwO6wyzidm2yrPMPtnwxDIYnH/ETdNraa3JyHsjXsQwGAIG80+hCv
|
10
|
+
QfCA/LmvNOm/Mpe1EyiAeI1/YJp4a2xwIQJBAKysFpQ1ZehVtbnxwaSwMWXiE/Q7
|
11
|
+
pjYyl7cCoXPxVFai+8WhXa8dE8Shmo75v2dbAsGnuZy177jJLiB6vYjFL7ECQQCI
|
12
|
+
Zri7lLVo8zVFasgO0F6N0ZmAMzeqvQNTwZ72UcVNwjvRso3j1fPyTJUFGEpUwIWa
|
13
|
+
wUMV3mal1HQf2lYUrL/BAkBBtXqOLFHINHUmffdRSV/2HECYXHazb6lAnL8nnQX0
|
14
|
+
vin2ujCli9mcYWnrY7zwlXdAxgQv5Q2ByQT9Fd8S7FjA
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module SlangerHelperMethods
|
2
|
+
def start_slanger_with_options options={}
|
3
|
+
# Fork service. Our integration tests MUST block the main thread because we want to wait for i/o to finish.
|
4
|
+
@server_pid = EM.fork_reactor do
|
5
|
+
Thin::Logging.silent = true
|
6
|
+
|
7
|
+
opts = { host: '0.0.0.0',
|
8
|
+
api_port: '4567',
|
9
|
+
websocket_port: '8080',
|
10
|
+
app_key: '765ec374ae0a69f4ce44',
|
11
|
+
secret: 'your-pusher-secret',
|
12
|
+
activity_timeout: 100
|
13
|
+
}
|
14
|
+
|
15
|
+
Slanger::Config.load opts.merge(options)
|
16
|
+
|
17
|
+
Slanger::Service.run
|
18
|
+
end
|
19
|
+
wait_for_slanger
|
20
|
+
end
|
21
|
+
|
22
|
+
alias start_slanger start_slanger_with_options
|
23
|
+
|
24
|
+
def stop_slanger
|
25
|
+
# Ensure Slanger is properly stopped. No orphaned processes allowed!
|
26
|
+
Process.kill 'SIGKILL', @server_pid
|
27
|
+
Process.wait @server_pid
|
28
|
+
end
|
29
|
+
|
30
|
+
def wait_for_slanger opts = {}
|
31
|
+
opts = { port: 8080 }.update opts
|
32
|
+
begin
|
33
|
+
TCPSocket.new('0.0.0.0', opts[:port]).close
|
34
|
+
rescue
|
35
|
+
sleep 0.005
|
36
|
+
retry
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def new_websocket opts = {}
|
41
|
+
opts = { key: Pusher.key, protocol: 7 }.update opts
|
42
|
+
uri = "ws://0.0.0.0:8080/app/#{opts[:key]}?client=js&version=1.8.5&protocol=#{opts[:protocol]}"
|
43
|
+
|
44
|
+
EM::HttpRequest.new(uri).get.tap { |ws| ws.errback &errback }
|
45
|
+
end
|
46
|
+
|
47
|
+
def em_stream opts = {}
|
48
|
+
messages = []
|
49
|
+
|
50
|
+
em_thread do
|
51
|
+
websocket = new_websocket opts
|
52
|
+
|
53
|
+
stream(websocket, messages) do |message|
|
54
|
+
yield websocket, messages
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
return messages
|
59
|
+
end
|
60
|
+
|
61
|
+
def em_thread
|
62
|
+
Thread.new do
|
63
|
+
EM.run do
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
end.join
|
67
|
+
end
|
68
|
+
|
69
|
+
def stream websocket, messages
|
70
|
+
websocket.stream do |message|
|
71
|
+
messages << JSON.parse(message)
|
72
|
+
|
73
|
+
yield message
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def send_subscribe options
|
78
|
+
info = { user_id: options[:user_id], user_info: { name: options[:name] } }
|
79
|
+
socket_id = JSON.parse(options[:message]['data'])['socket_id']
|
80
|
+
to_sign = [socket_id, 'presence-channel', info.to_json].join ':'
|
81
|
+
|
82
|
+
digest = OpenSSL::Digest::SHA256.new
|
83
|
+
|
84
|
+
options[:user].send({
|
85
|
+
event: 'pusher:subscribe',
|
86
|
+
data: {
|
87
|
+
auth: [Pusher.key, OpenSSL::HMAC.hexdigest(digest, Pusher.secret, to_sign)].join(':'),
|
88
|
+
channel_data: info.to_json,
|
89
|
+
channel: 'presence-channel'
|
90
|
+
}
|
91
|
+
}.to_json)
|
92
|
+
end
|
93
|
+
|
94
|
+
def private_channel websocket, message
|
95
|
+
socket_id = JSON.parse(message['data'])['socket_id']
|
96
|
+
to_sign = [socket_id, 'private-channel'].join ':'
|
97
|
+
|
98
|
+
digest = OpenSSL::Digest::SHA256.new
|
99
|
+
|
100
|
+
websocket.send({
|
101
|
+
event: 'pusher:subscribe',
|
102
|
+
data: {
|
103
|
+
auth: [Pusher.key, OpenSSL::HMAC.hexdigest(digest, Pusher.secret, to_sign)].join(':'),
|
104
|
+
channel: 'private-channel'
|
105
|
+
}
|
106
|
+
}.to_json)
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
|
3
|
+
require 'active_support/json'
|
4
|
+
require 'active_support/core_ext/hash'
|
5
|
+
require 'eventmachine'
|
6
|
+
require 'em-http-request'
|
7
|
+
require 'pusher'
|
8
|
+
require 'thin'
|
9
|
+
require 'slanger_helper_methods'
|
10
|
+
require 'have_attributes'
|
11
|
+
require 'openssl'
|
12
|
+
require 'socket'
|
13
|
+
require 'timecop'
|
14
|
+
require 'pry'
|
15
|
+
require 'webmock/rspec'
|
16
|
+
require 'slanger'
|
17
|
+
|
18
|
+
WebMock.disable!
|
19
|
+
|
20
|
+
module Slanger; end
|
21
|
+
|
22
|
+
def errback
|
23
|
+
@errback ||= Proc.new { |e| fail 'cannot connect to slanger. your box might be too slow. try increasing sleep value in the before block' }
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec.configure do |config|
|
27
|
+
config.formatter = 'documentation'
|
28
|
+
config.color = true
|
29
|
+
config.mock_framework = :mocha
|
30
|
+
config.order = 'random'
|
31
|
+
config.include SlangerHelperMethods
|
32
|
+
config.fail_fast = true
|
33
|
+
config.after(:each) { stop_slanger if @server_pid }
|
34
|
+
config.before :all do
|
35
|
+
Pusher.tap do |p|
|
36
|
+
p.host = '0.0.0.0'
|
37
|
+
p.port = 4567
|
38
|
+
p.app_id = 'your-pusher-app-id'
|
39
|
+
p.secret = 'your-pusher-secret'
|
40
|
+
p.key = '765ec374ae0a69f4ce44'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'slanger'
|
3
|
+
|
4
|
+
def clear_redis_connections
|
5
|
+
Slanger::Redis.instance_variables.each do |ivar|
|
6
|
+
Slanger::Redis.send :remove_instance_variable, ivar
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'Slanger::Channel' do
|
11
|
+
let(:channel) { Slanger::Channel.create channel_id: 'test' }
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
EM::Hiredis.stubs(:connect).returns stub_everything('redis', :pubsub => stub_everything('redis'))
|
15
|
+
clear_redis_connections
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:each) do
|
19
|
+
clear_redis_connections
|
20
|
+
EM::Hiredis.unstub(:connect)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#unsubscribe' do
|
24
|
+
it 'decrements channel subscribers on Redis' do
|
25
|
+
Slanger::Redis.expects(:hincrby).
|
26
|
+
with('channel_subscriber_count', channel.channel_id, -1).
|
27
|
+
once.returns mock { expects(:callback).once.yields(2) }
|
28
|
+
|
29
|
+
channel.unsubscribe 1
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'activates a webhook when the last subscriber of a channel unsubscribes' do
|
33
|
+
Slanger::Webhook.expects(:post).
|
34
|
+
with(name: 'channel_vacated', channel: channel.channel_id).
|
35
|
+
once
|
36
|
+
|
37
|
+
Slanger::Redis.expects(:hincrby).
|
38
|
+
with('channel_subscriber_count', channel.channel_id, -1).
|
39
|
+
times(3).returns mock {
|
40
|
+
expects(:callback).times(3).yields(2).then.yields(1).then.yields(0)
|
41
|
+
}
|
42
|
+
|
43
|
+
3.times { |i| channel.unsubscribe i + 1 }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#subscribe' do
|
48
|
+
it 'increments channel subscribers on Redis' do
|
49
|
+
Slanger::Redis.expects(:hincrby).
|
50
|
+
with('channel_subscriber_count', channel.channel_id, 1).
|
51
|
+
once.returns mock { expects(:callback).once.yields(2) }
|
52
|
+
channel.subscribe { |m| nil }
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'activates a webhook when the first subscriber of a channel joins' do
|
56
|
+
Slanger::Webhook.expects(:post).
|
57
|
+
with(name: 'channel_occupied', channel: channel.channel_id).
|
58
|
+
once
|
59
|
+
|
60
|
+
Slanger::Redis.expects(:hincrby).
|
61
|
+
with('channel_subscriber_count', channel.channel_id, 1).
|
62
|
+
times(3).returns mock {
|
63
|
+
expects(:callback).times(3).yields(1).then.yields(2).then.yields(3)
|
64
|
+
}
|
65
|
+
|
66
|
+
3.times { channel.subscribe { |m| nil } }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Slanger::Api::RequestValidation do
|
5
|
+
describe '#socket_id' do
|
6
|
+
it 'validation' do
|
7
|
+
socket_id = "POST\n/apps/99759/events\nauth_key=840543d97de9803651b1&auth_timestamp=123&auth_version=1.0&body_md5=some_md5&dummy="
|
8
|
+
|
9
|
+
expect {validate(nil) }.not_to raise_error Slanger::Api::InvalidRequest
|
10
|
+
expect {validate("1234.123455") }.not_to raise_error Slanger::Api::InvalidRequest
|
11
|
+
|
12
|
+
expect {validate(socket_id) }.to raise_error Slanger::Api::InvalidRequest
|
13
|
+
expect {validate("something 123")}.to raise_error Slanger::Api::InvalidRequest
|
14
|
+
|
15
|
+
expect {validate("1234.12345 ") }.to raise_error Slanger::Api::InvalidRequest
|
16
|
+
expect {validate(" 1234.12345") }.to raise_error Slanger::Api::InvalidRequest
|
17
|
+
expect {validate("hello\n1234.123456\nhomakov") }.to raise_error Slanger::Api::InvalidRequest
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
before do
|
22
|
+
request = mock("request")
|
23
|
+
request.expects(:authenticate).times(0..2)
|
24
|
+
Signature::Request.expects(:new).times(0..2).returns request
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#channels" do
|
28
|
+
let(:body) { {socket_id: "1234.5678", channels: channels}.to_json }
|
29
|
+
|
30
|
+
context "with valid channels" do
|
31
|
+
let(:channels) { ["MY_CHANNEL", "presence-abcd"] }
|
32
|
+
|
33
|
+
it "returns an array of valid channel_id values" do
|
34
|
+
rv = Slanger::Api::RequestValidation.new(body, {}, "")
|
35
|
+
|
36
|
+
expect(rv.channels).to eq ["MY_CHANNEL", "presence-abcd"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with invalid channels" do
|
41
|
+
let(:channels) { ["MY_CHANNEL:presence-abcd", "presence-abcd"] }
|
42
|
+
|
43
|
+
it "rejects invalid channels" do
|
44
|
+
expect{ Slanger::Api::RequestValidation.new(body, {}, "")}.to raise_error Slanger::Api::InvalidRequest
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#socket_id" do
|
50
|
+
it do
|
51
|
+
rv = Slanger::Api::RequestValidation.new(body("1234.5678"), {}, "")
|
52
|
+
expect(rv.socket_id).to eq "1234.5678"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate(socket_id)
|
57
|
+
Slanger::Api::RequestValidation.new(body(socket_id), {}, "").socket_id
|
58
|
+
end
|
59
|
+
|
60
|
+
def body(socket_id)
|
61
|
+
{socket_id: socket_id}.to_json
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lib/slanger/webhook'
|
3
|
+
|
4
|
+
describe 'Slanger::Webhook' do
|
5
|
+
|
6
|
+
around do |example|
|
7
|
+
Slanger::Config.load webhook_url: 'https://example.com/pusher',
|
8
|
+
app_key: 'PUSHER_APP_KEY', secret: 'secret'
|
9
|
+
WebMock.enable!
|
10
|
+
Timecop.freeze(Time.now) { example.run }
|
11
|
+
WebMock.disable!
|
12
|
+
Slanger::Config.load webhook_url: nil
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.post' do
|
16
|
+
it 'make a POST request to the endpoint' do
|
17
|
+
payload = {
|
18
|
+
time_ms: Time.now.strftime('%s%L'),
|
19
|
+
events: [{ name: 'channel_occupied', channel: 'test channel' }]
|
20
|
+
}.to_json
|
21
|
+
|
22
|
+
digest = OpenSSL::Digest::SHA256.new
|
23
|
+
hmac = OpenSSL::HMAC.hexdigest(digest, Slanger::Config.secret, payload)
|
24
|
+
|
25
|
+
stub_request(:post, Slanger::Config.webhook_url).
|
26
|
+
with(body: payload, headers: {
|
27
|
+
"X-Pusher-Key" => Slanger::Config.app_key,
|
28
|
+
"X-Pusher-Signature" => hmac,
|
29
|
+
"Content-Type" => 'application/json'
|
30
|
+
}).
|
31
|
+
to_return(:status => 200, :body => {}.to_json, :headers => {})
|
32
|
+
|
33
|
+
Slanger::Webhook.post name: 'channel_occupied', channel: 'test channel'
|
34
|
+
|
35
|
+
WebMock.should have_requested(:post, Slanger::Config.webhook_url).
|
36
|
+
with(body: payload, headers: {
|
37
|
+
"X-Pusher-Key" => Slanger::Config.app_key,
|
38
|
+
"X-Pusher-Signature" => hmac,
|
39
|
+
"Content-Type" => 'application/json'
|
40
|
+
})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slanger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stevie Graham
|
8
|
+
- Mark Burns
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-
|
12
|
+
date: 2015-05-16 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: eventmachine
|
@@ -100,28 +101,14 @@ dependencies:
|
|
100
101
|
requirements:
|
101
102
|
- - "~>"
|
102
103
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
104
|
+
version: 4.2.1
|
104
105
|
type: :runtime
|
105
106
|
prerelease: false
|
106
107
|
version_requirements: !ruby/object:Gem::Requirement
|
107
108
|
requirements:
|
108
109
|
- - "~>"
|
109
110
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: glamazon
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.3.1
|
118
|
-
type: :runtime
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 0.3.1
|
111
|
+
version: 4.2.1
|
125
112
|
- !ruby/object:Gem::Dependency
|
126
113
|
name: sinatra
|
127
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,20 +193,6 @@ dependencies:
|
|
206
193
|
- - "~>"
|
207
194
|
- !ruby/object:Gem::Version
|
208
195
|
version: 3.1.2
|
209
|
-
- !ruby/object:Gem::Dependency
|
210
|
-
name: rake
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
212
|
-
requirements:
|
213
|
-
- - ">="
|
214
|
-
- !ruby/object:Gem::Version
|
215
|
-
version: '0'
|
216
|
-
type: :development
|
217
|
-
prerelease: false
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
219
|
-
requirements:
|
220
|
-
- - ">="
|
221
|
-
- !ruby/object:Gem::Version
|
222
|
-
version: '0'
|
223
196
|
- !ruby/object:Gem::Dependency
|
224
197
|
name: timecop
|
225
198
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,8 +249,52 @@ dependencies:
|
|
276
249
|
- - "~>"
|
277
250
|
- !ruby/object:Gem::Version
|
278
251
|
version: 0.10.1
|
252
|
+
- !ruby/object:Gem::Dependency
|
253
|
+
name: pry-byebug
|
254
|
+
requirement: !ruby/object:Gem::Requirement
|
255
|
+
requirements:
|
256
|
+
- - "~>"
|
257
|
+
- !ruby/object:Gem::Version
|
258
|
+
version: 2.0.0
|
259
|
+
type: :development
|
260
|
+
prerelease: false
|
261
|
+
version_requirements: !ruby/object:Gem::Requirement
|
262
|
+
requirements:
|
263
|
+
- - "~>"
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: 2.0.0
|
266
|
+
- !ruby/object:Gem::Dependency
|
267
|
+
name: bundler
|
268
|
+
requirement: !ruby/object:Gem::Requirement
|
269
|
+
requirements:
|
270
|
+
- - "~>"
|
271
|
+
- !ruby/object:Gem::Version
|
272
|
+
version: '1.5'
|
273
|
+
type: :development
|
274
|
+
prerelease: false
|
275
|
+
version_requirements: !ruby/object:Gem::Requirement
|
276
|
+
requirements:
|
277
|
+
- - "~>"
|
278
|
+
- !ruby/object:Gem::Version
|
279
|
+
version: '1.5'
|
280
|
+
- !ruby/object:Gem::Dependency
|
281
|
+
name: rake
|
282
|
+
requirement: !ruby/object:Gem::Requirement
|
283
|
+
requirements:
|
284
|
+
- - "~>"
|
285
|
+
- !ruby/object:Gem::Version
|
286
|
+
version: 10.4.2
|
287
|
+
type: :development
|
288
|
+
prerelease: false
|
289
|
+
version_requirements: !ruby/object:Gem::Requirement
|
290
|
+
requirements:
|
291
|
+
- - "~>"
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: 10.4.2
|
279
294
|
description: A websocket service compatible with Pusher libraries
|
280
|
-
email:
|
295
|
+
email:
|
296
|
+
- sjtgraham@mac.com
|
297
|
+
- markthedeveloper@gmail.com
|
281
298
|
executables:
|
282
299
|
- slanger
|
283
300
|
extensions: []
|
@@ -285,7 +302,11 @@ extra_rdoc_files: []
|
|
285
302
|
files:
|
286
303
|
- README.md
|
287
304
|
- bin/slanger
|
288
|
-
- lib/slanger/
|
305
|
+
- lib/slanger/api.rb
|
306
|
+
- lib/slanger/api/event.rb
|
307
|
+
- lib/slanger/api/event_publisher.rb
|
308
|
+
- lib/slanger/api/request_validation.rb
|
309
|
+
- lib/slanger/api/server.rb
|
289
310
|
- lib/slanger/channel.rb
|
290
311
|
- lib/slanger/config.rb
|
291
312
|
- lib/slanger/connection.rb
|
@@ -301,8 +322,23 @@ files:
|
|
301
322
|
- lib/slanger/web_socket_server.rb
|
302
323
|
- lib/slanger/webhook.rb
|
303
324
|
- slanger.rb
|
304
|
-
|
305
|
-
|
325
|
+
- spec/have_attributes.rb
|
326
|
+
- spec/integration/channel_spec.rb
|
327
|
+
- spec/integration/integration_spec.rb
|
328
|
+
- spec/integration/presence_channel_spec.rb
|
329
|
+
- spec/integration/private_channel_spec.rb
|
330
|
+
- spec/integration/replaced_handler_spec.rb
|
331
|
+
- spec/integration/ssl_spec.rb
|
332
|
+
- spec/server.crt
|
333
|
+
- spec/server.key
|
334
|
+
- spec/slanger_helper_methods.rb
|
335
|
+
- spec/spec_helper.rb
|
336
|
+
- spec/unit/channel_spec.rb
|
337
|
+
- spec/unit/request_validation_spec.rb
|
338
|
+
- spec/unit/webhook_spec.rb
|
339
|
+
homepage: https://github.com/stevegraham/slanger
|
340
|
+
licenses:
|
341
|
+
- MIT
|
306
342
|
metadata: {}
|
307
343
|
post_install_message:
|
308
344
|
rdoc_options: []
|
@@ -320,8 +356,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
320
356
|
version: '0'
|
321
357
|
requirements: []
|
322
358
|
rubyforge_project:
|
323
|
-
rubygems_version: 2.
|
359
|
+
rubygems_version: 2.4.5
|
324
360
|
signing_key:
|
325
361
|
specification_version: 4
|
326
362
|
summary: A websocket service compatible with Pusher libraries
|
327
|
-
test_files:
|
363
|
+
test_files:
|
364
|
+
- spec/have_attributes.rb
|
365
|
+
- spec/integration/channel_spec.rb
|
366
|
+
- spec/integration/integration_spec.rb
|
367
|
+
- spec/integration/presence_channel_spec.rb
|
368
|
+
- spec/integration/private_channel_spec.rb
|
369
|
+
- spec/integration/replaced_handler_spec.rb
|
370
|
+
- spec/integration/ssl_spec.rb
|
371
|
+
- spec/server.crt
|
372
|
+
- spec/server.key
|
373
|
+
- spec/slanger_helper_methods.rb
|
374
|
+
- spec/spec_helper.rb
|
375
|
+
- spec/unit/channel_spec.rb
|
376
|
+
- spec/unit/request_validation_spec.rb
|
377
|
+
- spec/unit/webhook_spec.rb
|