connfu-client 0.1
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/.rspec +3 -0
- data/.rvmrc +2 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +120 -0
- data/LICENSE.txt +661 -0
- data/README.rdoc +398 -0
- data/Rakefile +38 -0
- data/bin/.DS_Store +0 -0
- data/bin/connfu-client +94 -0
- data/connfu-client.gemspec +41 -0
- data/examples/conference/application.rb +68 -0
- data/examples/conference/conference.rb +33 -0
- data/examples/conference/conference_app.rb +25 -0
- data/examples/conference/connfu.log +5 -0
- data/examples/conference/wall.rb +11 -0
- data/examples/provisioning/app/get.rb +29 -0
- data/examples/provisioning/channels/get.rb +34 -0
- data/examples/provisioning/rss/create.rb +28 -0
- data/examples/provisioning/rss/delete.rb +27 -0
- data/examples/provisioning/rss/get.rb +32 -0
- data/examples/provisioning/rss/put.rb +29 -0
- data/examples/provisioning/setup.rb +2 -0
- data/examples/provisioning/twitter/create.rb +31 -0
- data/examples/provisioning/twitter/delete.rb +27 -0
- data/examples/provisioning/twitter/get.rb +32 -0
- data/examples/provisioning/twitter/put.rb +29 -0
- data/examples/provisioning/voice/create.rb +26 -0
- data/examples/provisioning/voice/delete.rb +27 -0
- data/examples/provisioning/voice/get.rb +36 -0
- data/examples/provisioning/voice/phones/create.rb +26 -0
- data/examples/provisioning/voice/phones/delete.rb +28 -0
- data/examples/provisioning/voice/phones/get.rb +38 -0
- data/examples/provisioning/voice/put.rb +38 -0
- data/examples/provisioning/voice/whitelist/create.rb +26 -0
- data/examples/provisioning/voice/whitelist/delete.rb +27 -0
- data/examples/provisioning/voice/whitelist/get.rb +36 -0
- data/examples/provisioning/voice/whitelist/put.rb +27 -0
- data/lib/connfu.rb +134 -0
- data/lib/connfu/cli/generator.rb +71 -0
- data/lib/connfu/connfu_logger.rb +88 -0
- data/lib/connfu/connfu_message_formatter.rb +134 -0
- data/lib/connfu/connfu_stream.rb +182 -0
- data/lib/connfu/dispatcher.rb +164 -0
- data/lib/connfu/dsl.rb +84 -0
- data/lib/connfu/events.rb +32 -0
- data/lib/connfu/listener.rb +85 -0
- data/lib/connfu/listener_channel.rb +100 -0
- data/lib/connfu/message.rb +74 -0
- data/lib/connfu/provisioning.rb +12 -0
- data/lib/connfu/provisioning/application.rb +374 -0
- data/lib/connfu/provisioning/base.rb +95 -0
- data/lib/connfu/provisioning/channel.rb +79 -0
- data/lib/connfu/provisioning/phone.rb +55 -0
- data/lib/connfu/provisioning/rss.rb +21 -0
- data/lib/connfu/provisioning/twitter.rb +28 -0
- data/lib/connfu/provisioning/voice.rb +89 -0
- data/lib/connfu/provisioning/whitelist.rb +62 -0
- data/lib/connfu/version.rb +6 -0
- data/lib/rdoc/generator/template/connfu/_context.rhtml +209 -0
- data/lib/rdoc/generator/template/connfu/_head.rhtml +7 -0
- data/lib/rdoc/generator/template/connfu/class.rhtml +38 -0
- data/lib/rdoc/generator/template/connfu/file.rhtml +36 -0
- data/lib/rdoc/generator/template/connfu/index.rhtml +13 -0
- data/lib/rdoc/generator/template/connfu/resources/apple-touch-icon.png +0 -0
- data/lib/rdoc/generator/template/connfu/resources/css/github.css +129 -0
- data/lib/rdoc/generator/template/connfu/resources/css/main.css +339 -0
- data/lib/rdoc/generator/template/connfu/resources/css/panel.css +389 -0
- data/lib/rdoc/generator/template/connfu/resources/css/reset.css +53 -0
- data/lib/rdoc/generator/template/connfu/resources/favicon.ico +0 -0
- data/lib/rdoc/generator/template/connfu/resources/i/arrows.png +0 -0
- data/lib/rdoc/generator/template/connfu/resources/i/results_bg.png +0 -0
- data/lib/rdoc/generator/template/connfu/resources/i/tree_bg.png +0 -0
- data/lib/rdoc/generator/template/connfu/resources/js/highlight.pack.js +1 -0
- data/lib/rdoc/generator/template/connfu/resources/js/jquery-1.3.2.min.js +19 -0
- data/lib/rdoc/generator/template/connfu/resources/js/jquery-effect.js +593 -0
- data/lib/rdoc/generator/template/connfu/resources/js/main.js +20 -0
- data/lib/rdoc/generator/template/connfu/resources/js/searchdoc.js +628 -0
- data/lib/rdoc/generator/template/connfu/resources/panel/index.html +72 -0
- data/lib/rdoc/generator/template/connfu/se_index.rhtml +8 -0
- data/spec/connfu_message_formatter_spec.rb +88 -0
- data/spec/connfu_spec.rb +51 -0
- data/spec/connfu_stream_spec.rb +84 -0
- data/spec/dispatcher_spec.rb +227 -0
- data/spec/dsl_spec.rb +159 -0
- data/spec/listener_channel_spec.rb +130 -0
- data/spec/listener_spec.rb +67 -0
- data/spec/provisioning/application_spec.rb +47 -0
- data/spec/provisioning/channel_shared_examples.rb +52 -0
- data/spec/provisioning/channel_spec.rb +13 -0
- data/spec/provisioning/phone_spec.rb +88 -0
- data/spec/provisioning/voice_spec.rb +138 -0
- data/spec/provisioning_spec.rb +500 -0
- data/spec/spec_helper.rb +51 -0
- metadata +298 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
require 'connfu/connfu_logger'
|
|
2
|
+
|
|
3
|
+
module Connfu
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Class that dispatches the external events.
|
|
7
|
+
# Currently there is no thread pool, so each event is executed sequentially
|
|
8
|
+
class Dispatcher
|
|
9
|
+
include Connfu::ConnfuLogger
|
|
10
|
+
|
|
11
|
+
attr_reader :continue
|
|
12
|
+
attr_reader :counter
|
|
13
|
+
attr_accessor :max_messages
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Initializer
|
|
17
|
+
#
|
|
18
|
+
# ==== Parameters
|
|
19
|
+
# * +queue+ Connfu::Events instance to wait for incoming Message events
|
|
20
|
+
# * +listener_channels+ Hash of listener_channels.
|
|
21
|
+
# * :key => channel name (valid ListenerChannel::CHANNEL_TYPES)
|
|
22
|
+
# * :value => ListenerChannel instance
|
|
23
|
+
# * +app_channels+ information about application channels to set the channel_name associated to an inbound event
|
|
24
|
+
def initialize(queue, listener_channels, app_channels = [])
|
|
25
|
+
if listener_channels.nil? or !listener_channels.is_a?(Hash) or listener_channels.length == 0
|
|
26
|
+
raise Exception, "Unable to dispatch events if no channel is defined"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@continue = true
|
|
30
|
+
@counter = 0
|
|
31
|
+
@max_messages = 0
|
|
32
|
+
@listener_channels = listener_channels
|
|
33
|
+
@app_channels = app_channels
|
|
34
|
+
logger.debug("Dispatcher initializer")
|
|
35
|
+
@queue = queue
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# start waiting for incoming Message.
|
|
40
|
+
# Should create a new thread and wait to new events to come
|
|
41
|
+
# ==== Parameters
|
|
42
|
+
# * +queue+ optional Connfu::Events instance to wait for incoming Message events. If nil, the value got in the initializer is used
|
|
43
|
+
def start(queue = nil)
|
|
44
|
+
queue.nil? and queue = @queue
|
|
45
|
+
logger.debug("Dispatcher starts")
|
|
46
|
+
@thread = Thread.new {
|
|
47
|
+
while continue
|
|
48
|
+
logger.debug("Dispatcher waiting for a message from the Listener")
|
|
49
|
+
event = queue.get
|
|
50
|
+
@counter = @counter + 1
|
|
51
|
+
logger.debug "---------------------------------"
|
|
52
|
+
logger.debug "#{self.class} => #{event}"
|
|
53
|
+
|
|
54
|
+
if event.is_a?(Array)
|
|
55
|
+
event.each { |ev|
|
|
56
|
+
set_channels!(ev)
|
|
57
|
+
process_message(ev)
|
|
58
|
+
}
|
|
59
|
+
else
|
|
60
|
+
set_channels!(event)
|
|
61
|
+
process_message(event)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# This method should be called for the thread that started the dispatcher
|
|
70
|
+
# in order to wait for dispatching incoming events from the listener
|
|
71
|
+
def join
|
|
72
|
+
@thread.join
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Stop waiting for incoming events
|
|
77
|
+
def stop
|
|
78
|
+
@continue = false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# Helper to validate if dispatcher should wait for new messages
|
|
85
|
+
def continue
|
|
86
|
+
if max_messages > 0
|
|
87
|
+
@continue and @counter < max_messages
|
|
88
|
+
else
|
|
89
|
+
@continue
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Sets the message channel_name attribute.
|
|
95
|
+
# The result is a list of application channels that should be advised about
|
|
96
|
+
# the inbound message
|
|
97
|
+
#
|
|
98
|
+
# * if message["type"].eql?("twitter"): message["channel_type"] is an
|
|
99
|
+
# array of all the application twitter channels that has associated the message twitter account.
|
|
100
|
+
# i.e.
|
|
101
|
+
# Application channels:
|
|
102
|
+
# @app_channels = [
|
|
103
|
+
# {"uid"=>"twitter-channel-1", "type"=>"twitter", "accounts"=>[{"name"=>"juandebravo"}, {"name"=>"connfudev"}]},
|
|
104
|
+
# {"uid"=>"twitter-channel-2", "type"=>"twitter", "accounts"=>[{"name"=>"telefonicaid"}]}]
|
|
105
|
+
# Incoming message:
|
|
106
|
+
# message.channel_type = "twitter"
|
|
107
|
+
# message.from = "juandebravo"
|
|
108
|
+
#
|
|
109
|
+
# set_channels!(message) => message.channel_name = ["twitter-channel-1"]
|
|
110
|
+
#
|
|
111
|
+
# ==== Parameters
|
|
112
|
+
# * +message+ Connfu::Message with no channel_name info
|
|
113
|
+
# ==== Return
|
|
114
|
+
# * Connfu::Message with the channel_name filled with the relevant app channels
|
|
115
|
+
def set_channels!(message) # :doc:
|
|
116
|
+
channel_type = message.channel_type
|
|
117
|
+
|
|
118
|
+
# select channels with the same channel_type as the incoming message
|
|
119
|
+
channels = @app_channels.select { |channel| channel["type"].eql?(channel_type) }
|
|
120
|
+
|
|
121
|
+
# filter channels
|
|
122
|
+
case message.channel_type
|
|
123
|
+
when "twitter" # filter by from or to account
|
|
124
|
+
channels = channels.select { |channel|
|
|
125
|
+
channel["accounts"].select { |item|
|
|
126
|
+
item["name"].eql?(message.from) or item["name"].eql?(message.to)
|
|
127
|
+
}.length > 0
|
|
128
|
+
}
|
|
129
|
+
when "voice" # filter by did
|
|
130
|
+
channels = channels.select { |channel|
|
|
131
|
+
channel["uid"].eql?(message.channel_name)
|
|
132
|
+
#channel["phones"].select{|item|
|
|
133
|
+
# item["phone_number"].eql?(message.to)
|
|
134
|
+
#}.length > 0
|
|
135
|
+
}
|
|
136
|
+
when "sms"
|
|
137
|
+
channels = channels.select { |channel|
|
|
138
|
+
channel["phones"].select{|item|
|
|
139
|
+
item["phone_number"].eql?(message.to)
|
|
140
|
+
}.length > 0
|
|
141
|
+
}
|
|
142
|
+
else
|
|
143
|
+
logger.warn("This code should not be executed because the first select should avoid this")
|
|
144
|
+
logger.info("Unexpected message: #{message.channel_type}")
|
|
145
|
+
channels = []
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# get only the channel unique identifier
|
|
149
|
+
channels = channels.map { |channel| channel["uid"] }
|
|
150
|
+
|
|
151
|
+
logger.debug "Setting channels in the incoming message to #{channels}"
|
|
152
|
+
message.channel_name = channels
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Executes the blocks that are associated to that channel and event type
|
|
156
|
+
# @param *message* incoming message to be processed
|
|
157
|
+
def process_message(message)
|
|
158
|
+
logger.info("Calling event #{message.message_type} in the channel #{message.channel_type}")
|
|
159
|
+
@listener_channels[message.channel_type.to_sym].message(message.message_type.to_sym, message)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
data/lib/connfu/dsl.rb
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'connfu/connfu_logger'
|
|
2
|
+
|
|
3
|
+
module Connfu
|
|
4
|
+
##
|
|
5
|
+
# This class parses a connFu application defined using the DSL
|
|
6
|
+
# i.e.
|
|
7
|
+
#
|
|
8
|
+
# Connfu.application(VALID_TOKEN, ENDPOINT) {
|
|
9
|
+
# listen(:voice) do |conference| {
|
|
10
|
+
# conference.on(:join) do |call|
|
|
11
|
+
# puts "New inbound call from #{call[:from]} on number #{call[:to]}"
|
|
12
|
+
# end
|
|
13
|
+
# }
|
|
14
|
+
# listen(:twitter) do |conference| {
|
|
15
|
+
# twitter.on(:new) do |tweet|
|
|
16
|
+
# puts "#{tweet[:channel_name]} just posted a new tweet: #{tweet.content}"
|
|
17
|
+
# end
|
|
18
|
+
# }
|
|
19
|
+
# }
|
|
20
|
+
#
|
|
21
|
+
module DSL
|
|
22
|
+
include Connfu::ConnfuLogger
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Parses the given block
|
|
28
|
+
# ==== Return
|
|
29
|
+
#
|
|
30
|
+
# Hash of values containing as key the listener channel type and as value the blocks to be executed
|
|
31
|
+
# when an event associated to that channel is received
|
|
32
|
+
def run
|
|
33
|
+
@listener_channels = {}
|
|
34
|
+
if block_given?
|
|
35
|
+
self.instance_exec(&Proc.new)
|
|
36
|
+
@listener_channels
|
|
37
|
+
else
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# This method is called while parsing the application logic and a new channel is defined.
|
|
44
|
+
# It inserts a new ListenerChannels in the listener_channels attribute with the Proc associated to
|
|
45
|
+
# each event type.
|
|
46
|
+
#
|
|
47
|
+
# i.e.
|
|
48
|
+
# listen(:voice) do |conference| {
|
|
49
|
+
# conference.on(:join) do |call|
|
|
50
|
+
# puts "New inbound call from #{call[:from]} on number #{call[:to]}"
|
|
51
|
+
# end
|
|
52
|
+
# }
|
|
53
|
+
#
|
|
54
|
+
# While parsing this snippet of code, a new listener_channel will be stored, indicating that when
|
|
55
|
+
# a new +join+ event associated to a +voice+ channel is received, the line
|
|
56
|
+
#
|
|
57
|
+
# puts "New inbound call from #{call[:from]} on number #{call[:to]}"
|
|
58
|
+
#
|
|
59
|
+
# must be executed.
|
|
60
|
+
#
|
|
61
|
+
# ==== Parameters
|
|
62
|
+
#
|
|
63
|
+
# * +name+ channel name
|
|
64
|
+
# * +args+ actually not in used
|
|
65
|
+
def listen(name, args = {})
|
|
66
|
+
|
|
67
|
+
unless ListenerChannel.valid?(name)
|
|
68
|
+
logger.error "Invalid channel name #{name}"
|
|
69
|
+
return nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Create a new channel listener
|
|
73
|
+
listener_channel = Connfu::ListenerChannel.new(name)
|
|
74
|
+
|
|
75
|
+
# If defined, insert into the channel the desired logic
|
|
76
|
+
block_given? and listener_channel.add_block(&Proc.new)
|
|
77
|
+
|
|
78
|
+
# Add channel to channels array
|
|
79
|
+
@listener_channels.store(name, listener_channel)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Connfu
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# This class is used to send Message instances between transport (listener) and dispatcher layers
|
|
5
|
+
class Events
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Initializer
|
|
9
|
+
def initialize
|
|
10
|
+
@queue = Queue.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# Returns a message from the queue. It waits until there's at least one message in the queue and acts
|
|
15
|
+
# as a FIFO queue.
|
|
16
|
+
#
|
|
17
|
+
# ==== Returns
|
|
18
|
+
# Connfu::Message instance
|
|
19
|
+
def get
|
|
20
|
+
@queue.pop
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Inserts a message in the queue
|
|
25
|
+
#
|
|
26
|
+
# ==== Parameters
|
|
27
|
+
# * +event+ Connfu::Message instance
|
|
28
|
+
def put(event)
|
|
29
|
+
@queue << event
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'connfu/connfu_stream'
|
|
2
|
+
require 'connfu/connfu_logger'
|
|
3
|
+
|
|
4
|
+
module Connfu
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Class that listen to external events.
|
|
8
|
+
# Delegates the behavior in ConnfuStream so any new external resource
|
|
9
|
+
# can be added and no need to change the interface is required
|
|
10
|
+
#
|
|
11
|
+
class Listener
|
|
12
|
+
include Connfu::ConnfuLogger # application logger
|
|
13
|
+
|
|
14
|
+
attr_reader :continue
|
|
15
|
+
attr_reader :counter
|
|
16
|
+
attr_reader :app_stream
|
|
17
|
+
attr_accessor :max_messages # max amount of messages to receive
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Listener initializer.
|
|
21
|
+
#
|
|
22
|
+
# ==== Parameters
|
|
23
|
+
# * +queue+ Connfu::Events instance to forward incoming events to be processed by the Dispatcher class
|
|
24
|
+
# * +app_stream+ valid HTTP stream url to connect and listen events
|
|
25
|
+
# * +token+ valid token to get access to a connFu Stream
|
|
26
|
+
# * +stream_endpoint+ endpoint to open a keepalive HTTP connection
|
|
27
|
+
def initialize(queue, app_stream, token, stream_endpoint)
|
|
28
|
+
@connfu_stream = Connfu::ConnfuStream.new(app_stream, token, stream_endpoint)
|
|
29
|
+
@continue = true
|
|
30
|
+
@counter = 0
|
|
31
|
+
@max_messages = 0
|
|
32
|
+
@queue = queue
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# start listening.
|
|
37
|
+
# Should create a new thread and wait to new events to come
|
|
38
|
+
# ==== Parameters
|
|
39
|
+
# * +queue+ to send incoming events to the Dispatcher class
|
|
40
|
+
def start(queue = nil)
|
|
41
|
+
queue.nil? and queue = @queue
|
|
42
|
+
logger.debug "Listener starts..."
|
|
43
|
+
|
|
44
|
+
@thread = Thread.new {
|
|
45
|
+
# listen to connFu
|
|
46
|
+
@connfu_stream.start_listening
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
while continue do
|
|
50
|
+
logger.debug "Waiting for a message from connFu stream"
|
|
51
|
+
message = @connfu_stream.get
|
|
52
|
+
@counter = @counter + 1
|
|
53
|
+
|
|
54
|
+
logger.debug "#{self.class} got message => #{message}"
|
|
55
|
+
# Write in internal Queue
|
|
56
|
+
queue.put(message)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# Wait to get external events
|
|
63
|
+
def join
|
|
64
|
+
@thread.join
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
##
|
|
68
|
+
# stop waiting for external events
|
|
69
|
+
def stop
|
|
70
|
+
@continue = false
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
##
|
|
74
|
+
# checks if the thread should continue listening or return
|
|
75
|
+
def continue
|
|
76
|
+
if max_messages > 0
|
|
77
|
+
@continue and @counter < max_messages
|
|
78
|
+
else
|
|
79
|
+
@continue
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'connfu/connfu_logger'
|
|
2
|
+
|
|
3
|
+
module Connfu
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# This class models a specific connFu listener channel.
|
|
7
|
+
# A connFu listener channel is the path to fetch events from your resources.
|
|
8
|
+
#
|
|
9
|
+
# ==== Current supported channel types:
|
|
10
|
+
# - +:voice+: inbound calls to a phone number mapped to the application
|
|
11
|
+
# - +:sms+: inbound sms to a phone number mapped to the application
|
|
12
|
+
# - +:twitter+: tweet messages that matches at least one of the rules defined by the application
|
|
13
|
+
# - +:rss+: atom or rss feed
|
|
14
|
+
class ListenerChannel
|
|
15
|
+
include Connfu::ConnfuLogger # application logger
|
|
16
|
+
|
|
17
|
+
# Constant that defines the supported channels
|
|
18
|
+
CHANNEL_TYPES = [:voice, :twitter, :sms, :rss]
|
|
19
|
+
CHANNEL_TYPES.freeze
|
|
20
|
+
CHANNEL_TYPES.each { |channel| channel.freeze }
|
|
21
|
+
|
|
22
|
+
# Constant that defines the supported channel events
|
|
23
|
+
EVENT_TYPES = [:new, :join, :leave, :new_topic]
|
|
24
|
+
EVENT_TYPES.freeze
|
|
25
|
+
EVENT_TYPES.each { |event| event.freeze }
|
|
26
|
+
|
|
27
|
+
# channel name (a CHANNELS item)
|
|
28
|
+
attr_reader :name
|
|
29
|
+
|
|
30
|
+
# blocks associated to the channel. Hash object (key = event_type, value = Proc)
|
|
31
|
+
attr_accessor :blocks
|
|
32
|
+
|
|
33
|
+
# how to filter inbound events from connFu
|
|
34
|
+
attr_reader :_filter
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# Channel initializer
|
|
38
|
+
#
|
|
39
|
+
# ==== Parameters
|
|
40
|
+
# * +name+ channel name (CHANNELS item)
|
|
41
|
+
def initialize(name)
|
|
42
|
+
@name = name
|
|
43
|
+
# initialize an Struct that shall keep the event blocks. There is a specific key per each event type
|
|
44
|
+
@blocks = Struct.new(*EVENT_TYPES).new(*Array.new(EVENT_TYPES.length){Array.new()})
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Method that defines a new event in a channel
|
|
49
|
+
# ==== Parameters
|
|
50
|
+
# * +event+ event type. Must be included in EVENT_TYPES
|
|
51
|
+
#
|
|
52
|
+
def on(event)
|
|
53
|
+
EVENT_TYPES.include?(event) or (self.class.logger.error "Invalid event #{event}" and return)
|
|
54
|
+
block_given? and @blocks[event] << Proc.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
#
|
|
59
|
+
def message(event, arg = nil)
|
|
60
|
+
@blocks[event].each { |block|
|
|
61
|
+
block.call(arg)
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def filter=(value)
|
|
66
|
+
@_filter = value
|
|
67
|
+
# TODO
|
|
68
|
+
# connFu provisioning request
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def filter
|
|
72
|
+
@_filter
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def add_block
|
|
76
|
+
block_given? and self.instance_exec self, &Proc.new
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Avoid using instance_exec: we can directly call the Proc received
|
|
80
|
+
# but we need to change the expectations regarding context "messages"
|
|
81
|
+
# @connfu.listener_channels[:foo].should... => @connfu.should
|
|
82
|
+
#
|
|
83
|
+
#block_given? and Proc.new.call(self)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class << self
|
|
87
|
+
##
|
|
88
|
+
# Checks if a channel name is valid
|
|
89
|
+
# ==== Parameters
|
|
90
|
+
# * +name+ channel name
|
|
91
|
+
# ==== Return
|
|
92
|
+
# true if the channel name if valid, false if not
|
|
93
|
+
def valid?(name)
|
|
94
|
+
CHANNEL_TYPES.include?(name)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|