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.
@@ -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
-
@@ -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
-