goshrine_bot 0.1.1 → 0.1.5
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/.rvmrc +1 -0
- data/README.rdoc +5 -6
- data/TODO.txt +2 -1
- data/goshrine_bot.gemspec +3 -1
- data/goshrine_bot.yml +21 -3
- data/lib/goshrine_bot/client.rb +41 -54
- data/lib/goshrine_bot/cookies.rb +45 -0
- data/lib/goshrine_bot/faye_auth_ext.rb +17 -0
- data/lib/goshrine_bot/faye_transport_patch.rb +43 -0
- data/lib/goshrine_bot/game.rb +3 -3
- data/lib/goshrine_bot/runner.rb +1 -1
- data/lib/goshrine_bot.rb +11 -5
- metadata +35 -41
- data/lib/goshrine_bot/faye/channel.rb +0 -143
- data/lib/goshrine_bot/faye/client.rb +0 -283
- data/lib/goshrine_bot/faye/connection.rb +0 -122
- data/lib/goshrine_bot/faye/error.rb +0 -44
- data/lib/goshrine_bot/faye/grammar.rb +0 -58
- data/lib/goshrine_bot/faye/namespace.rb +0 -20
- data/lib/goshrine_bot/faye/rack_adapter.rb +0 -115
- data/lib/goshrine_bot/faye/server.rb +0 -266
- data/lib/goshrine_bot/faye/timeouts.rb +0 -21
- data/lib/goshrine_bot/faye/transport.rb +0 -123
- data/lib/goshrine_bot/faye.rb +0 -36
- data/lib/goshrine_bot/httpclient.rb +0 -288
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rack'
|
3
|
-
require 'thin'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
module Faye
|
7
|
-
class AlwaysEmptyHash
|
8
|
-
def initialize
|
9
|
-
@h = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def method_missing(m, *args)
|
13
|
-
@h.send(m, *args)
|
14
|
-
end
|
15
|
-
|
16
|
-
def []=(key,value)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class RackAdapter
|
21
|
-
|
22
|
-
# Only supported under Thin
|
23
|
-
ASYNC_RESPONSE = [-1, AlwaysEmptyHash.new, []].freeze
|
24
|
-
|
25
|
-
DEFAULT_ENDPOINT = '/bayeux'
|
26
|
-
SCRIPT_PATH = File.join(ROOT, 'faye-client-min.js')
|
27
|
-
|
28
|
-
TYPE_JSON = {'Content-Type' => 'application/json'}
|
29
|
-
TYPE_SCRIPT = {'Content-Type' => 'text/javascript'}
|
30
|
-
TYPE_TEXT = {'Content-Type' => 'text/plain'}
|
31
|
-
|
32
|
-
def initialize(app = nil, options = nil)
|
33
|
-
@app = app if app.respond_to?(:call)
|
34
|
-
@options = [app, options].grep(Hash).first || {}
|
35
|
-
|
36
|
-
@endpoint = @options[:mount] || DEFAULT_ENDPOINT
|
37
|
-
@endpoint_re = Regexp.new('^' + @endpoint + '(/[^/]+)*(\\.js)?$')
|
38
|
-
@server = Server.new(@options)
|
39
|
-
end
|
40
|
-
|
41
|
-
def get_client
|
42
|
-
@client ||= Client.new(@server)
|
43
|
-
end
|
44
|
-
|
45
|
-
def run(port)
|
46
|
-
handler = Rack::Handler.get('thin')
|
47
|
-
handler.run(self, :Port => port)
|
48
|
-
end
|
49
|
-
|
50
|
-
def call(env)
|
51
|
-
ensure_reactor_running!
|
52
|
-
request = Rack::Request.new(env)
|
53
|
-
|
54
|
-
unless request.path_info =~ @endpoint_re
|
55
|
-
env['faye.client'] = get_client
|
56
|
-
return @app ? @app.call(env) :
|
57
|
-
[404, TYPE_TEXT, ["Sure you're not looking for #{@endpoint} ?"]]
|
58
|
-
end
|
59
|
-
|
60
|
-
if request.path_info =~ /\.js$/
|
61
|
-
return [200, TYPE_SCRIPT, File.new(SCRIPT_PATH)]
|
62
|
-
end
|
63
|
-
|
64
|
-
begin
|
65
|
-
json_msg = request.post? ? request.body.read : request.params['message']
|
66
|
-
message = JSON.parse(json_msg)
|
67
|
-
jsonp = request.params['jsonp'] || JSONP_CALLBACK
|
68
|
-
|
69
|
-
@server.flush_connection(message) if request.get?
|
70
|
-
|
71
|
-
on_response(env, message) do |replies|
|
72
|
-
response = JSON.unparse(replies)
|
73
|
-
response = "#{ jsonp }(#{ response });" if request.get?
|
74
|
-
response
|
75
|
-
end
|
76
|
-
rescue Exception => e
|
77
|
-
puts "Caught #{e.message}: " + e.backtrace.join("\n")
|
78
|
-
[400, TYPE_TEXT, 'Bad request']
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
def on_response(env, message, &block)
|
85
|
-
request = Rack::Request.new(env)
|
86
|
-
type = request.get? ? TYPE_SCRIPT : TYPE_JSON
|
87
|
-
callback = env['async.callback']
|
88
|
-
transport_authentication = env['faye.transport_authentication']
|
89
|
-
|
90
|
-
if callback
|
91
|
-
body = DeferredBody.new
|
92
|
-
callback.call [200, type, body]
|
93
|
-
@server.process(message, transport_authentication, false) { |r| body.succeed block.call(r) }
|
94
|
-
return ASYNC_RESPONSE
|
95
|
-
end
|
96
|
-
|
97
|
-
response = nil
|
98
|
-
@server.process(message, transport_authentication, false) { |r| response = block.call(r) }
|
99
|
-
sleep(0.1) while response.nil?
|
100
|
-
[200, type, [response]]
|
101
|
-
end
|
102
|
-
|
103
|
-
def ensure_reactor_running!
|
104
|
-
Thread.new { EM.run } unless EM.reactor_running?
|
105
|
-
while not EM.reactor_running?; end
|
106
|
-
end
|
107
|
-
|
108
|
-
class DeferredBody
|
109
|
-
include EventMachine::Deferrable
|
110
|
-
alias :each :callback
|
111
|
-
end
|
112
|
-
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
@@ -1,266 +0,0 @@
|
|
1
|
-
module Faye
|
2
|
-
class Server
|
3
|
-
def initialize(options = {})
|
4
|
-
@options = options
|
5
|
-
@channels = Channel::Tree.new
|
6
|
-
@clients = {}
|
7
|
-
@namespace = Namespace.new
|
8
|
-
@security_policy = options[:security_policy]
|
9
|
-
end
|
10
|
-
|
11
|
-
# Notifies the server of stale connections that should be deleted
|
12
|
-
def update(message, client)
|
13
|
-
return unless message == :stale_client
|
14
|
-
destroy_client(client)
|
15
|
-
end
|
16
|
-
|
17
|
-
def client_ids
|
18
|
-
@clients.keys
|
19
|
-
end
|
20
|
-
|
21
|
-
def process(messages, transport_authentication = nil, local = false, &callback)
|
22
|
-
messages = [messages].flatten
|
23
|
-
processed, responses = 0, []
|
24
|
-
|
25
|
-
messages.each do |message|
|
26
|
-
handle(message, transport_authentication, local) do |reply|
|
27
|
-
reply = [reply].flatten
|
28
|
-
responses.concat(reply)
|
29
|
-
processed += 1
|
30
|
-
callback[responses] if processed == messages.size
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def flush_connection(messages)
|
36
|
-
[messages].flatten.each do |message|
|
37
|
-
client = @clients[message['clientId']]
|
38
|
-
client.flush! if client
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def connection(id)
|
45
|
-
return @clients[id] if @clients.has_key?(id)
|
46
|
-
client = Connection.new(id, @options)
|
47
|
-
client.add_observer(self)
|
48
|
-
@clients[id] = client
|
49
|
-
end
|
50
|
-
|
51
|
-
def destroy_client(client)
|
52
|
-
client.disconnect!
|
53
|
-
client.delete_observer(self)
|
54
|
-
@namespace.release(client.id)
|
55
|
-
@clients.delete(client.id)
|
56
|
-
end
|
57
|
-
|
58
|
-
def handle(message, transport_authentication = nil, local = false, &callback)
|
59
|
-
client_id = message['clientId']
|
60
|
-
channel = message['channel']
|
61
|
-
|
62
|
-
allowed_to_publish = local || @security_policy.nil? || Channel.meta?(channel) || @security_policy.can_publish(transport_authentication, channel, message)
|
63
|
-
|
64
|
-
if !allowed_to_publish
|
65
|
-
response = { 'channel' => channel,
|
66
|
-
'version' => BAYEUX_VERSION,
|
67
|
-
'id' => message['id'],
|
68
|
-
'error' => Error.channel_forbidden(channel),
|
69
|
-
'successful' => false }
|
70
|
-
return callback[response]
|
71
|
-
end
|
72
|
-
|
73
|
-
@channels.glob(channel).each do |c|
|
74
|
-
c << message
|
75
|
-
end
|
76
|
-
|
77
|
-
if Channel.meta?(channel)
|
78
|
-
response = __send__(Channel.parse(channel)[1], message, transport_authentication, local)
|
79
|
-
|
80
|
-
client_id = response['clientId']
|
81
|
-
response['advice'] ||= {}
|
82
|
-
response['advice']['reconnect'] ||= @clients.has_key?(client_id) ? 'retry' : 'handshake'
|
83
|
-
response['advice']['interval'] ||= (Connection::INTERVAL * 1000).floor
|
84
|
-
|
85
|
-
return callback[response] unless response['channel'] == Channel::CONNECT and
|
86
|
-
response['successful'] == true
|
87
|
-
|
88
|
-
return connection(response['clientId']).connect(transport_authentication) do |events|
|
89
|
-
callback[[response] + events]
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
return callback[[]] if message['clientId'].nil? or Channel.service?(channel)
|
94
|
-
|
95
|
-
response = make_response(message)
|
96
|
-
response['successful'] = true
|
97
|
-
callback[response]
|
98
|
-
end
|
99
|
-
|
100
|
-
def make_response(message)
|
101
|
-
response = {}
|
102
|
-
%w[id clientId channel].each do |field|
|
103
|
-
if message[field]
|
104
|
-
response[field] = message[field]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
response
|
108
|
-
end
|
109
|
-
|
110
|
-
# MUST contain * version
|
111
|
-
# * supportedConnectionTypes
|
112
|
-
# MAY contain * minimumVersion
|
113
|
-
# * ext
|
114
|
-
# * id
|
115
|
-
def handshake(message, transport_authentication, local = false)
|
116
|
-
response = make_response(message)
|
117
|
-
response['version'] = BAYEUX_VERSION
|
118
|
-
|
119
|
-
response['error'] = Error.parameter_missing('version') if message['version'].nil?
|
120
|
-
|
121
|
-
unless local
|
122
|
-
response['supportedConnectionTypes'] = CONNECTION_TYPES
|
123
|
-
|
124
|
-
client_conns = message['supportedConnectionTypes']
|
125
|
-
|
126
|
-
# This is a fix for the (non-spec following) cometd.js client
|
127
|
-
client_conns = client_conns.values if client_conns.is_a?(Hash)
|
128
|
-
|
129
|
-
if client_conns
|
130
|
-
common_conns = client_conns.select { |c| CONNECTION_TYPES.include?(c) }
|
131
|
-
response['error'] = Error.conntype_mismatch(*client_conns) if common_conns.empty?
|
132
|
-
else
|
133
|
-
response['error'] = Error.parameter_missing('supportedConnectionTypes')
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
response['successful'] = response['error'].nil?
|
138
|
-
return response unless response['successful']
|
139
|
-
|
140
|
-
client_id = @namespace.generate
|
141
|
-
response['clientId'] = connection(client_id).id
|
142
|
-
connection_listener = @options[:connection_listener]
|
143
|
-
if connection_listener
|
144
|
-
connection_listener.connected(client_id, transport_authentication)
|
145
|
-
end
|
146
|
-
response
|
147
|
-
end
|
148
|
-
|
149
|
-
# MUST contain * clientId
|
150
|
-
# * connectionType
|
151
|
-
# MAY contain * ext
|
152
|
-
# * id
|
153
|
-
def connect(message, transport_authentication, local = false)
|
154
|
-
response = make_response(message)
|
155
|
-
|
156
|
-
client_id = message['clientId']
|
157
|
-
client = client_id ? @clients[client_id] : nil
|
158
|
-
|
159
|
-
response['error'] = Error.client_unknown(client_id) if client.nil?
|
160
|
-
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
161
|
-
response['error'] = Error.parameter_missing('connectionType') if message['connectionType'].nil?
|
162
|
-
|
163
|
-
response['successful'] = response['error'].nil?
|
164
|
-
response.delete('clientId') unless response['successful']
|
165
|
-
return response unless response['successful']
|
166
|
-
|
167
|
-
response['clientId'] = client.id
|
168
|
-
response
|
169
|
-
end
|
170
|
-
|
171
|
-
# MUST contain * clientId
|
172
|
-
# MAY contain * ext
|
173
|
-
# * id
|
174
|
-
def disconnect(message, transport_authentication, local = false)
|
175
|
-
response = make_response(message)
|
176
|
-
|
177
|
-
client_id = message['clientId']
|
178
|
-
client = client_id ? @clients[client_id] : nil
|
179
|
-
|
180
|
-
response['error'] = Error.client_unknown(client_id) if client.nil?
|
181
|
-
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
182
|
-
|
183
|
-
response['successful'] = response['error'].nil?
|
184
|
-
response.delete('clientId') unless response['successful']
|
185
|
-
return response unless response['successful']
|
186
|
-
|
187
|
-
destroy_client(client)
|
188
|
-
|
189
|
-
response['clientId'] = client_id
|
190
|
-
response
|
191
|
-
end
|
192
|
-
|
193
|
-
# MUST contain * clientId
|
194
|
-
# * subscription
|
195
|
-
# MAY contain * ext
|
196
|
-
# * id
|
197
|
-
def subscribe(message, transport_authentication, local = false)
|
198
|
-
response = make_response(message)
|
199
|
-
|
200
|
-
client_id = message['clientId']
|
201
|
-
client = client_id ? @clients[client_id] : nil
|
202
|
-
|
203
|
-
subscription = message['subscription']
|
204
|
-
subscription = [subscription].flatten
|
205
|
-
|
206
|
-
response['error'] = Error.client_unknown(client_id) if client.nil?
|
207
|
-
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
208
|
-
response['error'] = Error.parameter_missing('subscription') if message['subscription'].nil?
|
209
|
-
|
210
|
-
response['subscription'] = subscription.compact
|
211
|
-
|
212
|
-
subscription.each do |channel|
|
213
|
-
next if response['error']
|
214
|
-
response['error'] = Error.channel_forbidden(channel) unless local or Channel.subscribable?(channel)
|
215
|
-
response['error'] = Error.channel_invalid(channel) unless Channel.valid?(channel)
|
216
|
-
if @security_policy
|
217
|
-
response['error'] = Error.channel_forbidden(channel) unless @security_policy.can_subscribe(transport_authentication, channel, message)
|
218
|
-
end
|
219
|
-
|
220
|
-
next if response['error']
|
221
|
-
channel = @channels[channel] ||= Channel.new(channel)
|
222
|
-
client.subscribe(channel)
|
223
|
-
end
|
224
|
-
|
225
|
-
response['successful'] = response['error'].nil?
|
226
|
-
response
|
227
|
-
end
|
228
|
-
|
229
|
-
# MUST contain * clientId
|
230
|
-
# * subscription
|
231
|
-
# MAY contain * ext
|
232
|
-
# * id
|
233
|
-
def unsubscribe(message, transport_authentication, local = false)
|
234
|
-
response = make_response(message)
|
235
|
-
|
236
|
-
client_id = message['clientId']
|
237
|
-
client = client_id ? @clients[client_id] : nil
|
238
|
-
|
239
|
-
subscription = message['subscription']
|
240
|
-
subscription = [subscription].flatten
|
241
|
-
|
242
|
-
response['error'] = Error.client_unknown(client_id) if client.nil?
|
243
|
-
response['error'] = Error.parameter_missing('clientId') if client_id.nil?
|
244
|
-
response['error'] = Error.parameter_missing('subscription') if message['subscription'].nil?
|
245
|
-
|
246
|
-
response['subscription'] = subscription.compact
|
247
|
-
|
248
|
-
subscription.each do |channel|
|
249
|
-
next if response['error']
|
250
|
-
|
251
|
-
if not Channel.valid?(channel)
|
252
|
-
response['error'] = Error.channel_invalid(channel)
|
253
|
-
next
|
254
|
-
end
|
255
|
-
|
256
|
-
channel = @channels[channel]
|
257
|
-
client.unsubscribe(channel) if channel
|
258
|
-
end
|
259
|
-
|
260
|
-
response['successful'] = response['error'].nil?
|
261
|
-
response
|
262
|
-
end
|
263
|
-
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Faye
|
2
|
-
module Timeouts
|
3
|
-
def add_timeout(name, delay, &block)
|
4
|
-
@timeouts ||= {}
|
5
|
-
return if @timeouts.has_key?(name)
|
6
|
-
@timeouts[name] = EventMachine.add_timer(delay) do
|
7
|
-
@timeouts.delete(name)
|
8
|
-
block.call
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def remove_timeout(name)
|
13
|
-
@timeouts ||= {}
|
14
|
-
timeout = @timeouts[name]
|
15
|
-
return if timeout.nil?
|
16
|
-
EventMachine.cancel_timer(timeout)
|
17
|
-
@timeouts.delete(name)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
@@ -1,123 +0,0 @@
|
|
1
|
-
#require 'em-http'
|
2
|
-
require 'json'
|
3
|
-
require 'uri'
|
4
|
-
|
5
|
-
module Faye
|
6
|
-
|
7
|
-
class Transport
|
8
|
-
def initialize(client, endpoint, cookie = nil)
|
9
|
-
@client = client
|
10
|
-
@endpoint = endpoint
|
11
|
-
@cookie = cookie
|
12
|
-
end
|
13
|
-
|
14
|
-
def connection_type
|
15
|
-
self.class.connection_type
|
16
|
-
end
|
17
|
-
|
18
|
-
def send(message, &block)
|
19
|
-
if message.is_a?(Hash) and not message.has_key?('id')
|
20
|
-
message['id'] = @client.namespace.generate
|
21
|
-
end
|
22
|
-
|
23
|
-
request(message) { |responses|
|
24
|
-
if block_given?
|
25
|
-
messages, deliverable = [], true
|
26
|
-
[responses].flatten.each do |response|
|
27
|
-
|
28
|
-
if message.is_a?(Hash) and response['id'] == message['id']
|
29
|
-
deliverable = false if block.call(response) == false
|
30
|
-
end
|
31
|
-
|
32
|
-
if response['advice']
|
33
|
-
@client.handle_advice(response['advice'])
|
34
|
-
end
|
35
|
-
|
36
|
-
if response['data'] and response['channel']
|
37
|
-
messages << response
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
@client.deliver_messages(messages) if deliverable
|
43
|
-
end
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
@transports = {}
|
48
|
-
|
49
|
-
class << self
|
50
|
-
attr_accessor :connection_type
|
51
|
-
|
52
|
-
def get(client, connection_types = nil)
|
53
|
-
endpoint = client.endpoint
|
54
|
-
connection_types ||= supported_connection_types
|
55
|
-
|
56
|
-
candidate_class = @transports.find do |type, klass|
|
57
|
-
connection_types.include?(type) and
|
58
|
-
klass.usable?(endpoint)
|
59
|
-
end
|
60
|
-
|
61
|
-
unless candidate_class
|
62
|
-
raise "Could not find a usable connection type for #{ endpoint }"
|
63
|
-
end
|
64
|
-
|
65
|
-
candidate_class.last.new(client, endpoint, client.cookie)
|
66
|
-
end
|
67
|
-
|
68
|
-
def register(type, klass)
|
69
|
-
@transports[type] = klass
|
70
|
-
klass.connection_type = type
|
71
|
-
end
|
72
|
-
|
73
|
-
def supported_connection_types
|
74
|
-
@transports.keys
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
class HttpTransport < Transport
|
80
|
-
def self.usable?(endpoint)
|
81
|
-
endpoint.is_a?(String)
|
82
|
-
end
|
83
|
-
|
84
|
-
def request(message, &block)
|
85
|
-
content = JSON.unparse(message)
|
86
|
-
|
87
|
-
url = URI.parse(@endpoint)
|
88
|
-
headers = {'Accept' => 'application/json', :host => url.host, :cookie => @cookie}
|
89
|
-
request = GoshrineBot::HttpClient.request(
|
90
|
-
:host => url.host,
|
91
|
-
:port => url.port,
|
92
|
-
:contenttype => 'application/json',
|
93
|
-
:request => url.path,
|
94
|
-
:verb => 'POST',
|
95
|
-
:content => content,
|
96
|
-
:custom_headers => headers)
|
97
|
-
|
98
|
-
request.callback do |response|
|
99
|
-
begin
|
100
|
-
block.call(JSON.parse(response[:content]))
|
101
|
-
rescue JSON::ParserError => e
|
102
|
-
puts "Bad JSON: #{response[:content].inspect}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
Transport.register 'long-polling', HttpTransport
|
108
|
-
|
109
|
-
class LocalTransport < Transport
|
110
|
-
def self.usable?(endpoint)
|
111
|
-
endpoint.is_a?(Server)
|
112
|
-
end
|
113
|
-
|
114
|
-
def request(message, &block)
|
115
|
-
@endpoint.process(message, nil, true) do |response|
|
116
|
-
block.call(response)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
Transport.register 'in-process', LocalTransport
|
121
|
-
|
122
|
-
end
|
123
|
-
|
data/lib/goshrine_bot/faye.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# This is a hacked up (and old) version of jcoglan's excellent Faye library.
|
2
|
-
# Hacks include adding cookie support (so we can use the cookies from a rails login),
|
3
|
-
# and avoiding use of em-http-request
|
4
|
-
|
5
|
-
require 'forwardable'
|
6
|
-
require 'observer'
|
7
|
-
require 'set'
|
8
|
-
require 'rubygems'
|
9
|
-
require 'eventmachine'
|
10
|
-
|
11
|
-
module Faye
|
12
|
-
VERSION = '0.3.2'
|
13
|
-
|
14
|
-
ROOT = File.expand_path(File.dirname(__FILE__))
|
15
|
-
|
16
|
-
BAYEUX_VERSION = '1.0'
|
17
|
-
ID_LENGTH = 128
|
18
|
-
JSONP_CALLBACK = 'jsonpcallback'
|
19
|
-
CONNECTION_TYPES = %w[long-polling callback-polling]
|
20
|
-
|
21
|
-
%w[ timeouts grammar namespace
|
22
|
-
server channel connection
|
23
|
-
error client transport
|
24
|
-
].each do |lib|
|
25
|
-
require File.join(ROOT, 'faye', lib)
|
26
|
-
end
|
27
|
-
|
28
|
-
autoload :RackAdapter, File.join(ROOT, 'faye', 'rack_adapter')
|
29
|
-
|
30
|
-
def self.random(bitlength = ID_LENGTH)
|
31
|
-
field = 2 ** bitlength
|
32
|
-
strlen = bitlength / 4
|
33
|
-
("%0#{strlen}s" % rand(field).to_s(16)).gsub(' ', '0')
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|