colossus 0.6.0 → 0.7.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.
- checksums.yaml +4 -4
- data/lib/colossus.rb +5 -4
- data/lib/colossus/engines/memory/memory.rb +8 -2
- data/lib/colossus/faye/extension.rb +3 -66
- data/lib/colossus/http_writer_client.rb +46 -0
- data/lib/colossus/simple_writer_server.rb +51 -0
- data/lib/colossus/version.rb +1 -1
- metadata +27 -13
- data/lib/colossus/simple_presence_getter.rb +0 -25
- data/lib/colossus/writer_client.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a1798af6e47665a55ac7d9140b00f2317c7cf9f
|
4
|
+
data.tar.gz: 1943594c8954d3cd1255f2b5626b6eee6d08fde1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f08853ae51aa21a4526b33955717b903030ac681df09a3d86eb44a5b6a0c39ac92ca9711195450eced0c8918fc94dce7330e9c767581189542cac1a3558e8bda
|
7
|
+
data.tar.gz: 5e39feee2464f72cdbb66a4f2e8fc2d1bc860fae862d9b2b1600069c7b73b6a4a33796ae97d5182a2a1a6e8433f553323de86ccde79cec54650fb0f3c79321d5
|
data/lib/colossus.rb
CHANGED
@@ -2,14 +2,15 @@ require 'faye'
|
|
2
2
|
require 'json'
|
3
3
|
require 'openssl'
|
4
4
|
require 'faraday'
|
5
|
+
require 'faraday_middleware'
|
5
6
|
require 'observer'
|
6
7
|
require 'em-synchrony'
|
7
8
|
require 'securerandom'
|
8
9
|
|
9
10
|
require 'colossus/configuration'
|
10
11
|
require 'colossus/verifier'
|
11
|
-
require 'colossus/
|
12
|
-
require 'colossus/
|
12
|
+
require 'colossus/http_writer_client'
|
13
|
+
require 'colossus/simple_writer_server'
|
13
14
|
|
14
15
|
require 'colossus/engines/memory/memory'
|
15
16
|
require 'colossus/engines/memory/client_session'
|
@@ -65,7 +66,7 @@ class Colossus
|
|
65
66
|
#
|
66
67
|
# @param user_id [#to_s] The unique identifier of a user
|
67
68
|
#
|
68
|
-
# @return status
|
69
|
+
# @return Hash{String => String} User_id key, status value
|
69
70
|
def get(user_id)
|
70
71
|
engine.get(user_id.to_s)
|
71
72
|
end
|
@@ -76,7 +77,7 @@ class Colossus
|
|
76
77
|
engine.get_multi(user_ids.map(&:to_s))
|
77
78
|
end
|
78
79
|
|
79
|
-
#
|
80
|
+
# (see #get)
|
80
81
|
def get_all
|
81
82
|
engine.get_all
|
82
83
|
end
|
@@ -41,11 +41,17 @@ class Colossus
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def get(user_id)
|
44
|
-
client_sessions
|
44
|
+
if client_sessions.has_key?(user_id)
|
45
|
+
{ user_id => client_sessions[user_id].status }
|
46
|
+
else
|
47
|
+
{ user_id => 'disconnected' }
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
def get_multi(*user_ids)
|
48
|
-
|
52
|
+
statuses = {}
|
53
|
+
user_ids.each { |user_id| statuses[user_id] = get(user_id) }
|
54
|
+
statuses
|
49
55
|
end
|
50
56
|
|
51
57
|
def get_all
|
@@ -3,18 +3,14 @@ class Colossus
|
|
3
3
|
# Faye extension implementing all the presence, authorization,
|
4
4
|
# authentification and push logic.
|
5
5
|
class Extension
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :faye, :colossus
|
7
7
|
|
8
8
|
VALID_STATUSES = %w(disconnected away active).freeze
|
9
9
|
|
10
10
|
def initialize(faye, colossus = Colossus.new)
|
11
|
-
@colossus = colossus
|
12
11
|
@faye = faye
|
12
|
+
@colossus = colossus
|
13
13
|
faye.add_extension(self)
|
14
|
-
@faye_client = faye.get_client
|
15
|
-
colossus_faye_extension = Colossus::WriterClient::FayeExtension.
|
16
|
-
new(colossus.verifier.writer_token)
|
17
|
-
faye_client.add_extension(colossus_faye_extension)
|
18
14
|
end
|
19
15
|
|
20
16
|
def incoming(message, _request, callback)
|
@@ -26,18 +22,13 @@ class Colossus
|
|
26
22
|
handle_user_action(message)
|
27
23
|
message.delete('data')
|
28
24
|
message.delete('ext')
|
29
|
-
elsif message['ext']['writer_token']
|
30
|
-
handle_server_action(message)
|
31
|
-
message.delete('ext')
|
32
25
|
end
|
33
26
|
|
34
27
|
callback.call(message)
|
35
28
|
end
|
36
29
|
|
37
30
|
def acceptable?(message)
|
38
|
-
message['ext'] &&
|
39
|
-
(message['ext']['user_token'] ||
|
40
|
-
message['ext']['writer_token'])
|
31
|
+
message['ext'] && message['ext']['user_token']
|
41
32
|
end
|
42
33
|
|
43
34
|
def handle_user_action(message)
|
@@ -54,60 +45,6 @@ class Colossus
|
|
54
45
|
message
|
55
46
|
end
|
56
47
|
|
57
|
-
def handle_server_action(message)
|
58
|
-
token = message['ext'] && message['ext']['writer_token']
|
59
|
-
|
60
|
-
unless token && colossus.verifier.verify_writer_token(token)
|
61
|
-
message['error'] = 'Invalid Token'
|
62
|
-
message.delete('data')
|
63
|
-
return message
|
64
|
-
end
|
65
|
-
|
66
|
-
if message['channel'].start_with?('/meta/')
|
67
|
-
message.delete('data')
|
68
|
-
message
|
69
|
-
elsif message['channel'].start_with?('/presences/request/')
|
70
|
-
handle_presence_request(message)
|
71
|
-
elsif message['channel'].start_with?('/presences/response/')
|
72
|
-
handle_presence_response(message)
|
73
|
-
elsif message['channel'].start_with?('/users/')
|
74
|
-
handle_publish(message)
|
75
|
-
else
|
76
|
-
message['error'] = 'Unknown Action'
|
77
|
-
message.delete('data')
|
78
|
-
end
|
79
|
-
|
80
|
-
message
|
81
|
-
end
|
82
|
-
|
83
|
-
def handle_presence_request(message)
|
84
|
-
user_ids = message['data'] && message['data']['user_ids']
|
85
|
-
presence_id = message['channel'].partition('/presences/request/').last
|
86
|
-
|
87
|
-
if user_ids && user_ids.is_a?(Array)
|
88
|
-
statuses = colossus.get_multi(user_ids)
|
89
|
-
message['data'].delete('user_ids')
|
90
|
-
faye_client.publish("/presences/response/#{presence_id}", { 'statuses' => Hash[user_ids.zip(statuses)] })
|
91
|
-
message
|
92
|
-
elsif user_ids == nil
|
93
|
-
statuses = colossus.get_all
|
94
|
-
faye_client.publish("/presences/response/#{presence_id}", { 'statuses' => statuses })
|
95
|
-
message
|
96
|
-
else
|
97
|
-
message.delete('data')
|
98
|
-
message['error'] = 'Invalid user_ids data'
|
99
|
-
message
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def handle_presence_response(message)
|
104
|
-
message
|
105
|
-
end
|
106
|
-
|
107
|
-
def handle_publish(message)
|
108
|
-
message
|
109
|
-
end
|
110
|
-
|
111
48
|
def handle_invalid_token(message)
|
112
49
|
message['error'] = 'Invalid Token'
|
113
50
|
message
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Colossus
|
2
|
+
class HTTPWriterClient
|
3
|
+
attr_reader :url, :writer_token, :time_out
|
4
|
+
|
5
|
+
def initialize(url,
|
6
|
+
writer_token = Colossus.config.writer_token,
|
7
|
+
time_out = 2)
|
8
|
+
@url = url
|
9
|
+
@writer_token = writer_token
|
10
|
+
@time_out = time_out
|
11
|
+
end
|
12
|
+
|
13
|
+
def presence(optional_user_ids = nil)
|
14
|
+
user_ids = Array(optional_user_ids) if optional_user_ids
|
15
|
+
connection.post('/presence_request') do |req|
|
16
|
+
req.body = { user_ids: user_ids, writer_token: writer_token }
|
17
|
+
end.body
|
18
|
+
end
|
19
|
+
|
20
|
+
def push(user_ids, message)
|
21
|
+
user_ids = Array(user_ids)
|
22
|
+
connection.post('/message') do |req|
|
23
|
+
req.body = { user_ids: user_ids, message: message, writer_token: writer_token}
|
24
|
+
end.body
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def connection
|
30
|
+
Faraday.new(url, connection_options) do |conf|
|
31
|
+
conf.request :json
|
32
|
+
conf.response :json
|
33
|
+
conf.response :raise_error
|
34
|
+
conf.adapter Faraday.default_adapter
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def connection_options
|
39
|
+
{request: {timeout: 2, open_timeout: 2}}
|
40
|
+
end
|
41
|
+
|
42
|
+
def base_url
|
43
|
+
@base_url ||= URI.parse(url).tap{ |u| u.path=('/') }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Colossus
|
2
|
+
class SimpleWriterServer
|
3
|
+
attr_reader :faye_extension
|
4
|
+
|
5
|
+
def initialize(faye_extension)
|
6
|
+
@faye_extension = faye_extension
|
7
|
+
end
|
8
|
+
|
9
|
+
def presence(writer_token, optional_user_ids = nil)
|
10
|
+
raise 'Invalid token' unless valid?(writer_token)
|
11
|
+
|
12
|
+
case optional_user_ids
|
13
|
+
when Array
|
14
|
+
colossus.get_multi(*optional_user_ids)
|
15
|
+
when String
|
16
|
+
colossus.get(optional_user_ids)
|
17
|
+
when NilClass
|
18
|
+
colossus.get_all
|
19
|
+
else
|
20
|
+
raise 'Invalid user_ids data'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def push(writer_token, user_ids, message)
|
25
|
+
raise 'Invalid token' unless valid?(writer_token)
|
26
|
+
|
27
|
+
case user_ids
|
28
|
+
when Array
|
29
|
+
user_ids.each do |user_id|
|
30
|
+
faye_client.publish("/users/#{user_id}", message)
|
31
|
+
end
|
32
|
+
when String
|
33
|
+
faye_client.publish("/users/#{user_ids}", message)
|
34
|
+
else
|
35
|
+
raise 'Invalid user_ids data'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid?(writer_token)
|
40
|
+
colossus.verifier.verify_writer_token(writer_token)
|
41
|
+
end
|
42
|
+
|
43
|
+
def faye_client
|
44
|
+
faye_extension.faye.get_client
|
45
|
+
end
|
46
|
+
|
47
|
+
def colossus
|
48
|
+
faye_extension.colossus
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/colossus/version.rb
CHANGED
metadata
CHANGED
@@ -1,55 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: colossus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- antoinelyset
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faye
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: em-synchrony
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: faraday
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday_middleware
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
69
|
description: Colossus is a Push and Presence pure Ruby server. It uses Faye internally.
|
@@ -65,10 +79,10 @@ files:
|
|
65
79
|
- lib/colossus/engines/memory/client_session_store.rb
|
66
80
|
- lib/colossus/engines/memory/memory.rb
|
67
81
|
- lib/colossus/faye/extension.rb
|
68
|
-
- lib/colossus/
|
82
|
+
- lib/colossus/http_writer_client.rb
|
83
|
+
- lib/colossus/simple_writer_server.rb
|
69
84
|
- lib/colossus/verifier.rb
|
70
85
|
- lib/colossus/version.rb
|
71
|
-
- lib/colossus/writer_client.rb
|
72
86
|
homepage: https://github.com/antoinelyset/colossus
|
73
87
|
licenses:
|
74
88
|
- MIT
|
@@ -79,17 +93,17 @@ require_paths:
|
|
79
93
|
- lib
|
80
94
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
95
|
requirements:
|
82
|
-
- -
|
96
|
+
- - ">="
|
83
97
|
- !ruby/object:Gem::Version
|
84
98
|
version: '0'
|
85
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
104
|
requirements: []
|
91
105
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.
|
106
|
+
rubygems_version: 2.2.2
|
93
107
|
signing_key:
|
94
108
|
specification_version: 4
|
95
109
|
summary: Colossus, Web Push & Presence made easy.
|
@@ -1,25 +0,0 @@
|
|
1
|
-
class Colossus
|
2
|
-
class SimplePresenceGetter
|
3
|
-
attr_reader :colossus
|
4
|
-
|
5
|
-
def initialize(colossus)
|
6
|
-
@colossus = colossus
|
7
|
-
end
|
8
|
-
|
9
|
-
def get_presences(writer_token, optional_user_ids = nil)
|
10
|
-
raise 'Invalid token' unless valid?(writer_token)
|
11
|
-
user_ids = Array(optional_user_ids) if optional_user_ids
|
12
|
-
if user_ids && user_ids.is_a?(Array)
|
13
|
-
Hash[user_ids.zip(colossus.get_multi(user_ids))]
|
14
|
-
elsif user_ids == nil
|
15
|
-
colossus.get_all
|
16
|
-
else
|
17
|
-
raise 'Invalid user_ids data'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def valid?(writer_token)
|
22
|
-
colossus.verifier.verify_writer_token(writer_token)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
class Colossus
|
2
|
-
class WriterClient
|
3
|
-
attr_reader :url, :writer_token, :time_out
|
4
|
-
|
5
|
-
def initialize(url,
|
6
|
-
writer_token = Colossus.config.writer_token,
|
7
|
-
time_out = 2)
|
8
|
-
@url = url
|
9
|
-
@writer_token = writer_token
|
10
|
-
@time_out = time_out
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_presences(optional_user_ids = nil)
|
14
|
-
user_ids = Array(optional_user_ids) if optional_user_ids
|
15
|
-
unique_token = generate_unique_token
|
16
|
-
EM.synchrony do
|
17
|
-
EM::Synchrony.add_timer(time_out) { raise 'Presence request timed out' }
|
18
|
-
EM::Synchrony.sync(faye_client.subscribe("/presences/response/#{unique_token}") { |message| return message['statuses'] })
|
19
|
-
EM::Synchrony.sync(faye_client.publish("/presences/request/#{unique_token}", user_ids))
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def get_presences_by_http(optional_user_ids = nil)
|
24
|
-
user_ids = Array(optional_user_ids) if optional_user_ids
|
25
|
-
# Custom Content-Type to indicate to the server
|
26
|
-
# this is a simple http request
|
27
|
-
conn = Faraday.new(url, headers: {'Content-Type' => 'application/vnd.http.json'}) do |conf|
|
28
|
-
conf.adapter Faraday.default_adapter
|
29
|
-
conf.response :raise_error
|
30
|
-
end
|
31
|
-
|
32
|
-
body = conn.post do |req|
|
33
|
-
req.body = JSON.dump({ user_ids: user_ids, writer_token: writer_token})
|
34
|
-
end.body
|
35
|
-
|
36
|
-
response = JSON.parse(body)
|
37
|
-
response['statuses']
|
38
|
-
end
|
39
|
-
|
40
|
-
def push_message(user_ids, message)
|
41
|
-
user_ids = Array(user_ids)
|
42
|
-
EM.synchrony do
|
43
|
-
EM::Synchrony.add_timer(time_out) { raise 'Push message timed out' }
|
44
|
-
user_ids.each do |user_id|
|
45
|
-
EM::Synchrony.sync(faye_client.publish("/users/#{user_id}", message))
|
46
|
-
end
|
47
|
-
EM.stop
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def faye_client
|
54
|
-
faye_client = ::Faye::Client.new(url)
|
55
|
-
faye_client.add_extension(FayeExtension.new(writer_token))
|
56
|
-
faye_client
|
57
|
-
end
|
58
|
-
|
59
|
-
def generate_unique_token
|
60
|
-
SecureRandom.hex(8)
|
61
|
-
end
|
62
|
-
|
63
|
-
class FayeExtension
|
64
|
-
attr_reader :token
|
65
|
-
|
66
|
-
def initialize(token)
|
67
|
-
@token = token
|
68
|
-
end
|
69
|
-
|
70
|
-
def incoming(message, callback)
|
71
|
-
callback.call(message)
|
72
|
-
end
|
73
|
-
|
74
|
-
def outgoing(message, callback)
|
75
|
-
message['ext'] ||= {}
|
76
|
-
message['ext']['writer_token'] = token
|
77
|
-
|
78
|
-
callback.call(message)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|