goshrine_bot 0.1.1 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,143 +0,0 @@
1
- module Faye
2
- class Channel
3
-
4
- include Observable
5
- attr_reader :name
6
-
7
- def initialize(name)
8
- @name = name
9
- end
10
-
11
- def <<(message)
12
- changed(true)
13
- notify_observers(:message, message)
14
- end
15
-
16
- HANDSHAKE = '/meta/handshake'
17
- CONNECT = '/meta/connect'
18
- SUBSCRIBE = '/meta/subscribe'
19
- UNSUBSCRIBE = '/meta/unsubscribe'
20
- DISCONNECT = '/meta/disconnect'
21
-
22
- META = :meta
23
- SERVICE = :service
24
-
25
- class << self
26
- def valid?(name)
27
- Grammar::CHANNEL_NAME =~ name or
28
- Grammar::CHANNEL_PATTERN =~ name
29
- end
30
-
31
- def parse(name)
32
- return nil unless valid?(name)
33
- name.split('/')[1..-1].map { |s| s.to_sym }
34
- end
35
-
36
- def meta?(name)
37
- segments = parse(name)
38
- segments ? (segments.first == META) : nil
39
- end
40
-
41
- def service?(name)
42
- segments = parse(name)
43
- segments ? (segments.first == SERVICE) : nil
44
- end
45
-
46
- def subscribable?(name)
47
- return nil unless valid?(name)
48
- not meta?(name) and not service?(name)
49
- end
50
- end
51
-
52
- class Tree
53
- include Enumerable
54
- attr_accessor :value
55
-
56
- def initialize(value = nil)
57
- @value = value
58
- @children = {}
59
- end
60
-
61
- # Remove channels that have no subscribers
62
- def delete_unobserved_channels
63
- total_observers = 0
64
- if @value
65
- total_observers += @value.count_observers
66
- @value = nil if @value.count_observers == 0
67
- end
68
-
69
- @children.delete_if { |key, subtree|
70
- num_child_observers = subtree.delete_unobserved_channels
71
- total_observers += num_child_observers
72
- num_child_observers == 0
73
- }
74
- total_observers
75
- end
76
-
77
- def each_child
78
- @children.each { |key, subtree| yield(key, subtree) }
79
- end
80
-
81
- def each(prefix = [], &block)
82
- each_child { |path, subtree| subtree.each(prefix + [path], &block) }
83
- yield(prefix, @value) unless @value.nil?
84
- end
85
-
86
- def keys
87
- map { |key, value| '/' + key * '/' }
88
- end
89
-
90
- def [](name)
91
- subtree = traverse(name)
92
- subtree ? subtree.value : nil
93
- end
94
-
95
- def []=(name, value)
96
- subtree = traverse(name, true)
97
- subtree.value = value unless subtree.nil?
98
- end
99
-
100
- def traverse(path, create_if_absent = false)
101
- path = Channel.parse(path) if String === path
102
-
103
- return nil if path.nil?
104
- return self if path.empty?
105
-
106
- subtree = @children[path.first]
107
- return nil if subtree.nil? and not create_if_absent
108
- subtree = @children[path.first] = self.class.new if subtree.nil?
109
-
110
- subtree.traverse(path[1..-1], create_if_absent)
111
- end
112
-
113
- def glob(path = [])
114
- path = Channel.parse(path) if String === path
115
-
116
- return [] if path.nil?
117
- return @value.nil? ? [] : [@value] if path.empty?
118
-
119
- if path == [:*]
120
- return @children.inject([]) do |list, (key, subtree)|
121
- list << subtree.value unless subtree.value.nil?
122
- list
123
- end
124
- end
125
-
126
- if path == [:**]
127
- list = map { |key, value| value }
128
- list.pop unless @value.nil?
129
- return list
130
- end
131
-
132
- list = @children.values_at(path.first, :*).
133
- compact.
134
- map { |t| t.glob(path[1..-1]) }
135
-
136
- list << @children[:**].value if @children[:**]
137
- list.flatten
138
- end
139
- end
140
-
141
- end
142
- end
143
-
@@ -1,283 +0,0 @@
1
- module Faye
2
- class Client
3
- include EventMachine::Deferrable
4
- include Timeouts
5
-
6
- UNCONNECTED = 1
7
- CONNECTING = 2
8
- CONNECTED = 3
9
- DISCONNECTED = 4
10
-
11
- HANDSHAKE = 'handshake'
12
- RETRY = 'retry'
13
- NONE = 'none'
14
-
15
- CONNECTION_TIMEOUT = 60.0
16
-
17
- attr_reader :endpoint, :namespace, :cookie
18
-
19
- def initialize(endpoint = nil, options = {})
20
- @endpoint = endpoint || RackAdapter::DEFAULT_ENDPOINT
21
- @options = options
22
- @timeout = @options[:timeout] || CONNECTION_TIMEOUT
23
- @cookie = @options[:cookie]
24
-
25
- @transport = Transport.get(self)
26
- @state = UNCONNECTED
27
- @namespace = Namespace.new
28
- @outbox = []
29
- @channels = Channel::Tree.new
30
- @current_id = 0
31
-
32
- @advice = {'reconnect' => RETRY, 'interval' => Connection::INTERVAL}
33
- end
34
-
35
- # Request
36
- # MUST include: * channel
37
- # * version
38
- # * supportedConnectionTypes
39
- # MAY include: * minimumVersion
40
- # * ext
41
- # * id
42
- #
43
- # Success Response Failed Response
44
- # MUST include: * channel MUST include: * channel
45
- # * version * successful
46
- # * supportedConnectionTypes * error
47
- # * clientId MAY include: * supportedConnectionTypes
48
- # * successful * advice
49
- # MAY include: * minimumVersion * version
50
- # * advice * minimumVersion
51
- # * ext * ext
52
- # * id * id
53
- # * authSuccessful
54
- def handshake(&block)
55
- return if @advice['reconnect'] == NONE
56
- return if @state != UNCONNECTED
57
-
58
- @state = CONNECTING
59
- @transport.send({
60
- 'channel' => Channel::HANDSHAKE,
61
- 'version' => BAYEUX_VERSION,
62
- 'supportedConnectionTypes' => Transport.supported_connection_types
63
-
64
- }) do |response|
65
- unless response['successful']
66
- EventMachine.add_timer(@advice['interval'] / 1000.0) { handshake(&block) }
67
- return @state = UNCONNECTED
68
- end
69
-
70
- @state = CONNECTED
71
- @client_id = response['clientId']
72
- @transport = Transport.get(self, response['supportedConnectionTypes'])
73
-
74
- block.call if block_given?
75
- end
76
- end
77
-
78
- # Request Response
79
- # MUST include: * channel MUST include: * channel
80
- # * clientId * successful
81
- # * connectionType * clientId
82
- # MAY include: * ext MAY include: * error
83
- # * id * advice
84
- # * ext
85
- # * id
86
- # * timestamp
87
- def connect(&block)
88
-
89
- return if @advice['reconnect'] == NONE or
90
- @state == DISCONNECTED
91
-
92
- if @advice['reconnect'] == HANDSHAKE or @state == UNCONNECTED
93
- begin_reconnect_timeout
94
- return handshake { connect(&block) }
95
- end
96
-
97
- return callback(&block) if @state == CONNECTING
98
- return unless @state == CONNECTED
99
-
100
- set_deferred_status(:succeeded)
101
- set_deferred_status(:deferred)
102
- block.call if block_given?
103
-
104
- return unless @connection_id.nil?
105
-
106
- @connection_id = @namespace.generate
107
- @transport.send({
108
- 'channel' => Channel::CONNECT,
109
- 'clientId' => @client_id,
110
- 'connectionType' => @transport.connection_type,
111
- 'id' => @connection_id
112
-
113
- }, &verify_client_id { |response|
114
- @namespace.release(@connection_id) if @connection_id
115
- @connection_id = nil
116
- remove_timeout(:reconnect)
117
- EventMachine.add_timer(@advice['interval'] / 1000.0) { connect }
118
- })
119
-
120
- begin_reconnect_timeout
121
- end
122
-
123
- # Request Response
124
- # MUST include: * channel MUST include: * channel
125
- # * clientId * successful
126
- # MAY include: * ext * clientId
127
- # * id MAY include: * error
128
- # * ext
129
- # * id
130
- def disconnect
131
- return unless @state == CONNECTED
132
- @state = DISCONNECTED
133
-
134
- @transport.send({
135
- 'channel' => Channel::DISCONNECT,
136
- 'clientId' => @client_id
137
- })
138
-
139
- @channels = Channel::Tree.new
140
- remove_timeout(:reconnect)
141
- end
142
-
143
- # Request Response
144
- # MUST include: * channel MUST include: * channel
145
- # * clientId * successful
146
- # * subscription * clientId
147
- # MAY include: * ext * subscription
148
- # * id MAY include: * error
149
- # * advice
150
- # * ext
151
- # * id
152
- # * timestamp
153
- def subscribe(channels, &block)
154
- connect {
155
- channels = [channels].flatten
156
- validate_channels(channels)
157
-
158
- @transport.send({
159
- 'channel' => Channel::SUBSCRIBE,
160
- 'clientId' => @client_id,
161
- 'subscription' => channels
162
-
163
- }, &verify_client_id { |response|
164
- if response['successful'] and block
165
- channels = [response['subscription']].flatten
166
- channels.each { |channel| @channels[channel] = block }
167
- end
168
- })
169
- }
170
- end
171
-
172
- # Request Response
173
- # MUST include: * channel MUST include: * channel
174
- # * clientId * successful
175
- # * subscription * clientId
176
- # MAY include: * ext * subscription
177
- # * id MAY include: * error
178
- # * advice
179
- # * ext
180
- # * id
181
- # * timestamp
182
- def unsubscribe(channels, &block)
183
- connect {
184
- channels = [channels].flatten
185
- validate_channels(channels)
186
-
187
- @transport.send({
188
- 'channel' => Channel::UNSUBSCRIBE,
189
- 'clientId' => @client_id,
190
- 'subscription' => channels
191
-
192
- }, &verify_client_id { |response|
193
- if response['successful']
194
- channels = [response['subscription']].flatten
195
- channels.each { |channel| @channels[channel] = nil }
196
- end
197
- })
198
- }
199
- end
200
-
201
- # Request Response
202
- # MUST include: * channel MUST include: * channel
203
- # * data * successful
204
- # MAY include: * clientId MAY include: * id
205
- # * id * error
206
- # * ext * ext
207
- def publish(channel, data, id=nil)
208
- connect {
209
- validate_channels([channel])
210
-
211
- enqueue({
212
- 'id' => (id || next_id),
213
- 'channel' => channel,
214
- 'data' => data,
215
- 'clientId' => @client_id
216
- })
217
-
218
- add_timeout(:publish, Connection::MAX_DELAY) { flush! }
219
- }
220
- end
221
-
222
- def handle_error(msg_id, error)
223
- puts "Message #{msg_id} Error #{error}"
224
- end
225
-
226
- def handle_advice(advice)
227
- @advice.update(advice)
228
- @client_id = nil if @advice['reconnect'] == HANDSHAKE
229
- end
230
-
231
- def deliver_messages(messages)
232
- messages.each do |message|
233
- channels = @channels.glob(message['channel'])
234
- channels.each { |callback| callback.call(message['data']) }
235
- end
236
- end
237
-
238
- private
239
-
240
- def begin_reconnect_timeout
241
- add_timeout(:reconnect, @timeout) do
242
- @namespace.release(@connection_id) if @connection_id
243
- @connection_id = nil
244
- @client_id = nil
245
- @state = UNCONNECTED
246
- subscribe(@channels.keys)
247
- end
248
- end
249
-
250
- def enqueue(message)
251
- @outbox << message
252
- end
253
-
254
- def flush!
255
- @transport.send(@outbox)
256
- @outbox = []
257
- end
258
-
259
- def next_id
260
- @current_id += 1
261
- end
262
-
263
- def validate_channels(channels)
264
- channels.each do |channel|
265
- raise "'#{ channel }' is not a valid channel name" unless Channel.valid?(channel)
266
- raise "Clients may not subscribe to channel '#{ channel }'" unless Channel.subscribable?(channel)
267
- end
268
- end
269
-
270
- def verify_client_id(&block)
271
- lambda do |response|
272
- if response['clientId'] != @client_id
273
- false
274
- else
275
- block.call(response)
276
- true
277
- end
278
- end
279
- end
280
-
281
- end
282
- end
283
-
@@ -1,122 +0,0 @@
1
- module Faye
2
- class Connection
3
- include EventMachine::Deferrable
4
- include Observable
5
- include Timeouts
6
-
7
- MAX_DELAY = 0.1
8
- INTERVAL = 0.4
9
- TIMEOUT = 60.0
10
-
11
- attr_reader :id
12
-
13
- def initialize(id, options = {})
14
- @id = id
15
- @options = options
16
- @timeout = @options[:timeout] || TIMEOUT
17
- @channels = Set.new
18
- @inbox = Set.new
19
- @connected = false
20
- @connection_listener = options[:connection_listener]
21
-
22
- # This is for clients that subscribe, but never re-connect to get messages
23
- # (prevents a memory leak)
24
- add_timeout(:deletion, 60 * INTERVAL) do
25
- puts "Deleting orphaned connection: #{@id}"
26
- delete
27
- end
28
-
29
- end
30
-
31
- def update(message, event)
32
- return unless message == :message
33
- @inbox.add(event)
34
- begin_delivery_timeout!
35
- end
36
-
37
- def subscribe(channel)
38
- if @channels.add?(channel)
39
- channel.add_observer(self)
40
- if @options[:subscription_listener]
41
- @options[:subscription_listener].subscribed(self, channel)
42
- end
43
- end
44
- end
45
-
46
- def unsubscribe(channel)
47
- return @channels.each(&method(:unsubscribe)) if channel == :all
48
- return unless @channels.member?(channel)
49
- @channels.delete(channel)
50
- channel.delete_observer(self)
51
- if @options[:subscription_listener]
52
- @options[:subscription_listener].unsubscribed(self, channel)
53
- end
54
- end
55
-
56
- def connect(transport_authentication, &block)
57
- callback(&block)
58
- return if @connected
59
-
60
- @connected = true
61
-
62
- if @connection_listener
63
- @connection_listener.connected(id, transport_authentication)
64
- end
65
-
66
- remove_timeout(:deletion)
67
-
68
- begin_delivery_timeout!
69
- begin_connection_timeout!
70
- end
71
-
72
- def flush!
73
- return unless @connected
74
- release_connection!
75
-
76
- events = @inbox.entries
77
- @inbox = Set.new
78
-
79
- set_deferred_status(:succeeded, events)
80
- set_deferred_status(:deferred)
81
- end
82
-
83
- def disconnect!
84
- unsubscribe(:all)
85
- flush!
86
- end
87
-
88
- private
89
-
90
- def begin_delivery_timeout!
91
- if @delivery_timeout.nil? && @connected && (!@inbox.empty? || @channels.empty?)
92
- add_timeout(:delivery, MAX_DELAY) { flush! }
93
- end
94
- end
95
-
96
- def begin_connection_timeout!
97
- return unless @connection_timeout.nil? and @connected
98
- add_timeout(:connection, @timeout) { flush! }
99
- end
100
-
101
- def delete
102
- unsubscribe(:all)
103
- if @connection_listener
104
- @connection_listener.disconnected(id)
105
- end
106
- changed(true)
107
- notify_observers(:stale_client, self)
108
- end
109
-
110
- def release_connection!
111
- remove_timeout(:connection)
112
- remove_timeout(:delivery)
113
- @connected = false
114
-
115
- add_timeout(:deletion, 10 * INTERVAL) do
116
- delete
117
- end
118
- end
119
-
120
- end
121
- end
122
-
@@ -1,44 +0,0 @@
1
- module Faye
2
- class Error
3
-
4
- def self.parse(string)
5
- return nil unless Grammar::ERROR =~ string
6
- parts = string.split(':')
7
- args = parts[1].split(',')
8
- new(parts[0].to_i, args, parts[2])
9
- end
10
-
11
- def self.method_missing(type, *args)
12
- code = const_get(type.to_s.upcase)
13
- new(code[0], args, code[1]).to_s
14
- end
15
-
16
- attr_reader :code, :args, :message
17
-
18
- def initialize(code, args, message)
19
- @code = code
20
- @args = args
21
- @message = message
22
- end
23
-
24
- def to_s
25
- "#{ @code }:#{ @args * ',' }:#{ @message }"
26
- end
27
-
28
- # http://code.google.com/p/cometd/wiki/BayeuxCodes
29
- VERSION_MISMATCH = [300, 'Version mismatch']
30
- CONNTYPE_MISMATCH = [301, 'Connection types not supported']
31
- EXT_MISMATCH = [302, 'Extension mismatch']
32
- BAD_REQUEST = [400, 'Bad request']
33
- CLIENT_UNKNOWN = [401, 'Unknown client']
34
- PARAMETER_MISSING = [402, 'Missing required parameter']
35
- CHANNEL_FORBIDDEN = [403, 'Forbidden channel']
36
- CHANNEL_UNKNOWN = [404, 'Unknown channel']
37
- CHANNEL_INVALID = [405, 'Invalid channel']
38
- EXT_UNKNOWN = [406, 'Unknown extension']
39
- PUBLISH_FAILED = [407, 'Failed to publish']
40
- SERVER_ERROR = [500, 'Internal server error']
41
-
42
- end
43
- end
44
-
@@ -1,58 +0,0 @@
1
- module Faye
2
- module Grammar
3
-
4
- def self.rule(&block)
5
- source = instance_eval(&block)
6
- %r{^#{string(source)}$}
7
- end
8
-
9
- def self.choice(*list)
10
- '(' + list.map(&method(:string)) * '|' + ')'
11
- end
12
-
13
- def self.repeat(*pattern)
14
- '(' + string(pattern) + ')*'
15
- end
16
-
17
- def self.oneormore(*pattern)
18
- '(' + string(pattern) + ')+'
19
- end
20
-
21
- def self.string(item)
22
- return item.map(&method(:string)) * '' if Array === item
23
- String === item ? item : item.source.gsub(/^\^/, '').gsub(/\$$/, '')
24
- end
25
-
26
- LOWALPHA = rule {[ '[a-z]' ]}
27
- UPALPHA = rule {[ '[A-Z]' ]}
28
- ALPHA = rule {[ choice(LOWALPHA, UPALPHA) ]}
29
- DIGIT = rule {[ '[0-9]' ]}
30
- ALPHANUM = rule {[ choice(ALPHA, DIGIT) ]}
31
- MARK = rule {[ choice(*%w[\\- \\_ \\! \\~ \\( \\) \\$ \\@]) ]}
32
- STRING = rule {[ repeat(choice(ALPHANUM, MARK, ' ', '\\/', '\\*', '\\.')) ]}
33
- TOKEN = rule {[ oneormore(choice(ALPHANUM, MARK)) ]}
34
- INTEGER = rule {[ oneormore(DIGIT) ]}
35
-
36
- CHANNEL_SEGMENT = rule {[ TOKEN ]}
37
- CHANNEL_SEGMENTS = rule {[ CHANNEL_SEGMENT, repeat('\\/', CHANNEL_SEGMENT) ]}
38
- CHANNEL_NAME = rule {[ '\\/', CHANNEL_SEGMENTS ]}
39
-
40
- WILD_CARD = rule {[ '\\*{1,2}' ]}
41
- CHANNEL_PATTERN = rule {[ repeat('\\/', CHANNEL_SEGMENT), '\\/', WILD_CARD ]}
42
-
43
- VERSION_ELEMENT = rule {[ ALPHANUM, repeat(choice(ALPHANUM, '\\-', '\\_')) ]}
44
- VERSION = rule {[ INTEGER, repeat('\\.', VERSION_ELEMENT) ]}
45
-
46
- CLIENT_ID = rule {[ oneormore(ALPHANUM) ]}
47
-
48
- ID = rule {[ oneormore(ALPHANUM) ]}
49
-
50
- ERROR_MESSAGE = rule {[ STRING ]}
51
- ERROR_ARGS = rule {[ STRING, repeat(',', STRING) ]}
52
- ERROR_CODE = rule {[ DIGIT, DIGIT, DIGIT ]}
53
- ERROR = rule {[ choice(string([ERROR_CODE, ':', ERROR_ARGS, ':', ERROR_MESSAGE]),
54
- string([ERROR_CODE, ':', ':', ERROR_MESSAGE])) ]}
55
-
56
- end
57
- end
58
-
@@ -1,20 +0,0 @@
1
- module Faye
2
- class Namespace
3
-
4
- def initialize
5
- @used = {}
6
- end
7
-
8
- def generate
9
- name = Faye.random
10
- name = Faye.random while @used.has_key?(name)
11
- @used[name] = name
12
- end
13
-
14
- def release(name)
15
- @used.delete(name)
16
- end
17
-
18
- end
19
- end
20
-