fabriq 0.1.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.
- data/Gemfile +16 -0
- data/Gemfile.lock +42 -0
- data/LICENSE.txt +20 -0
- data/README.md +7 -0
- data/Rakefile +42 -0
- data/TODO.md +1 -0
- data/VERSION +1 -0
- data/bin/fabriq +4 -0
- data/fabriq.gemspec +79 -0
- data/lib/fabriq.rb +43 -0
- data/lib/fabriq/adapter.rb +95 -0
- data/lib/fabriq/adapter/rype_adapter.rb +49 -0
- data/lib/fabriq/cli.rb +37 -0
- data/lib/fabriq/logging.rb +26 -0
- data/lib/fabriq/plugin_port.rb +60 -0
- data/lib/fabriq/skype.rb +36 -0
- data/lib/fabriq/skype/message.rb +27 -0
- data/lib/fabriq/skype/room.rb +30 -0
- data/lib/fabriq/skype_proxy.rb +83 -0
- data/spec/helper.rb +18 -0
- data/spec/lib/fabriq/adapter_spec.rb +153 -0
- data/spec/lib/fabriq/cli_spec.rb +43 -0
- data/spec/lib/fabriq/config_spec.rb +92 -0
- data/spec/lib/fabriq/logging_spec.rb +33 -0
- data/spec/lib/fabriq/plugin_port_spec.rb +106 -0
- data/spec/lib/fabriq/skype/message_spec.rb +49 -0
- data/spec/lib/fabriq/skype/room_spec.rb +67 -0
- data/spec/lib/fabriq/skype_proxy_spec.rb +167 -0
- data/spec/lib/fabriq/skype_spec.rb +71 -0
- data/spec/lib/fabriq_spec.rb +65 -0
- metadata +146 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module Fabriq
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
def config
|
5
|
+
Fabriq::Config
|
6
|
+
end
|
7
|
+
|
8
|
+
def info(msg)
|
9
|
+
send_output :info, msg
|
10
|
+
end
|
11
|
+
|
12
|
+
def error(msg)
|
13
|
+
send_output :error, msg
|
14
|
+
end
|
15
|
+
|
16
|
+
def debug(msg)
|
17
|
+
send_output :debug, msg
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_output(level, msg)
|
21
|
+
return if self.config.runtime_env == "test"
|
22
|
+
puts "#{Time.now.to_s} - #{level.upcase} : #{msg}"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Fabriq
|
2
|
+
module PluginPort
|
3
|
+
extend self
|
4
|
+
extend Fabriq::Logging
|
5
|
+
|
6
|
+
attr_accessor :plugins
|
7
|
+
|
8
|
+
def plugin_load_paths
|
9
|
+
[File.expand_path("~") + "/.fabriq", Dir.pwd].collect do |base_path|
|
10
|
+
Dir.glob("#{base_path}/plugins/*")
|
11
|
+
end.flatten
|
12
|
+
end
|
13
|
+
|
14
|
+
def require_plugins
|
15
|
+
debug "Plugin Load paths: #{plugin_load_paths}"
|
16
|
+
|
17
|
+
plugin_load_paths.each do |plugin_base_dir|
|
18
|
+
next unless File.exist?(plugin_base_dir)
|
19
|
+
require_plugin_from_path plugin_base_dir
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def require_plugin_from_path(plugin_base_dir)
|
24
|
+
plugin_name = plugin_base_dir.split("/").last
|
25
|
+
base_file_path = File.join(plugin_base_dir, "lib", "#{plugin_name}.rb")
|
26
|
+
if File.exist?(base_file_path)
|
27
|
+
require base_file_path
|
28
|
+
else
|
29
|
+
error("Plugin: #{plugin_name} - Base file not found (#{base_file_path}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def register_plugin(klass, &config_block)
|
34
|
+
@plugins ||= []
|
35
|
+
|
36
|
+
plugin = klass.init
|
37
|
+
|
38
|
+
if block_given? && plugin.respond_to?(:configurator)
|
39
|
+
config_block.call(plugin.configurator)
|
40
|
+
end
|
41
|
+
|
42
|
+
invoke_plugin_callback(plugin, :registered)
|
43
|
+
@plugins << plugin
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize_plugins
|
47
|
+
@plugins.each do |plugin|
|
48
|
+
invoke_plugin_callback(plugin, :initialized)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def invoke_plugin_callback(plugin, name, *args)
|
55
|
+
plugin.send(name.to_sym, *args) if plugin.respond_to?(name.to_sym)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
data/lib/fabriq/skype.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative "skype/message"
|
2
|
+
require_relative "skype/room"
|
3
|
+
|
4
|
+
module Fabriq
|
5
|
+
module Skype
|
6
|
+
class << self
|
7
|
+
|
8
|
+
attr_accessor :adapter
|
9
|
+
|
10
|
+
def adapter
|
11
|
+
@adapter || Fabriq::Adapter
|
12
|
+
end
|
13
|
+
|
14
|
+
def rooms
|
15
|
+
adapter.rooms
|
16
|
+
end
|
17
|
+
|
18
|
+
def room_by_id(room_id)
|
19
|
+
rooms.select { |room| room.id == room_id }.first
|
20
|
+
end
|
21
|
+
|
22
|
+
def send_message(message)
|
23
|
+
adapter.enqueue_outgoing_message(message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def listen_for_messages_to_self(&block)
|
27
|
+
adapter.subscribe_to_incoming_messages do |message|
|
28
|
+
if message.private_session? || message.direct?
|
29
|
+
block.call(message)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Fabriq
|
2
|
+
module Skype
|
3
|
+
class Message
|
4
|
+
|
5
|
+
attr_accessor :config, :room, :body, :from_name
|
6
|
+
|
7
|
+
def initialize(room, body, from_name = "")
|
8
|
+
@room = room
|
9
|
+
@body = body
|
10
|
+
@from_name = from_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def config
|
14
|
+
@config || Fabriq::Config
|
15
|
+
end
|
16
|
+
|
17
|
+
def private_session?
|
18
|
+
self.room.private_session?
|
19
|
+
end
|
20
|
+
|
21
|
+
def direct?
|
22
|
+
(self.config.skype_name && self.body.downcase.include?("@#{self.config.skype_name.downcase}")) == true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Fabriq
|
2
|
+
module Skype
|
3
|
+
class Room
|
4
|
+
|
5
|
+
attr_accessor :adapter, :id, :topic, :members, :raw
|
6
|
+
|
7
|
+
def initialize(adapter, id, members, raw)
|
8
|
+
@adapter = adapter
|
9
|
+
@id = id
|
10
|
+
@members = members
|
11
|
+
@raw = raw
|
12
|
+
end
|
13
|
+
|
14
|
+
def private_session?
|
15
|
+
@members.count == 2
|
16
|
+
end
|
17
|
+
|
18
|
+
def send_message(body, opts = {})
|
19
|
+
message = build_message_from_string(body, opts)
|
20
|
+
@adapter.enqueue_outgoing_message(message)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_message_from_string(body, opts = {})
|
24
|
+
body = "@%s: %s" % [opts[:to], body] if opts[:to] && !private_session?
|
25
|
+
Fabriq::Skype::Message.new(self, body)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Fabriq
|
2
|
+
class SkypeProxy
|
3
|
+
|
4
|
+
attr_accessor :adapter, :outgoing_messages
|
5
|
+
|
6
|
+
def initialize(adapter)
|
7
|
+
@adapter = adapter
|
8
|
+
@incoming_mutex = Mutex.new
|
9
|
+
@outgoing_mutex = Mutex.new
|
10
|
+
@incoming_message_callbacks = []
|
11
|
+
@outgoing_messages = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_incoming_message(&callback)
|
15
|
+
@incoming_message_callbacks << callback
|
16
|
+
end
|
17
|
+
|
18
|
+
def subscribe_adapter_message_received
|
19
|
+
@received_messages = []
|
20
|
+
@adapter.message_received do |message|
|
21
|
+
@received_messages << message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def start
|
26
|
+
subscribe_adapter_message_received
|
27
|
+
start_queue_worker_threads
|
28
|
+
end
|
29
|
+
|
30
|
+
def start_queue_worker_threads
|
31
|
+
run_in_thread { start_incoming_queue_worker }
|
32
|
+
run_in_thread { start_outgoing_queue_worker }
|
33
|
+
end
|
34
|
+
|
35
|
+
def start_incoming_queue_worker
|
36
|
+
run_in_throttled_loop do
|
37
|
+
handle_incoming_messages_synchronized
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_outgoing_queue_worker
|
42
|
+
run_in_throttled_loop do
|
43
|
+
handle_outgoing_messages_synchronized
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_incoming_messages_synchronized
|
48
|
+
@incoming_mutex.synchronize do
|
49
|
+
invoke_incoming_message_subscribers(@received_messages.shift)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_outgoing_messages_synchronized
|
54
|
+
@outgoing_mutex.synchronize do
|
55
|
+
if @outgoing_messages.count > 0
|
56
|
+
message = @outgoing_messages.shift
|
57
|
+
@adapter.send_message(message)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def invoke_incoming_message_subscribers(message)
|
63
|
+
@incoming_message_callbacks.each do |callback|
|
64
|
+
run_in_thread { callback.call(message) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def run_in_throttled_loop(&block)
|
72
|
+
while true
|
73
|
+
yield
|
74
|
+
sleep 0.5
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def run_in_thread(&block)
|
79
|
+
Thread.new(&block)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development, :test)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'minitest/spec'
|
13
|
+
require 'minitest/pride'
|
14
|
+
require 'mocha'
|
15
|
+
|
16
|
+
ENV['FABRIQ_ENV'] = "test"
|
17
|
+
|
18
|
+
MiniTest::Unit.autorun
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require_relative "../../helper"
|
2
|
+
require_relative "../../../lib/fabriq/logging"
|
3
|
+
require_relative "../../../lib/fabriq/config"
|
4
|
+
require_relative "../../../lib/fabriq/adapter"
|
5
|
+
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
describe Fabriq::Adapter do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@skype_adapter = mock('Skype Adapter')
|
12
|
+
@subject = Fabriq::Adapter
|
13
|
+
@subject.adapter = @skype_adapter
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#load' do
|
17
|
+
it "assigns the configured skype-adapter" do
|
18
|
+
Fabriq::Config.adapter = skype_adapter_class = Class.new
|
19
|
+
@subject.load
|
20
|
+
@subject.adapter.must_be_kind_of(skype_adapter_class )
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#run' do
|
25
|
+
before do
|
26
|
+
@subject.stubs(:init_skype_proxy)
|
27
|
+
@subject.stubs(:find_available_rooms)
|
28
|
+
@skype_adapter.stubs(:attach)
|
29
|
+
@skype_adapter.stubs(:wait)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "inits the skype proxy" do
|
33
|
+
@subject.expects(:init_skype_proxy)
|
34
|
+
@subject.run
|
35
|
+
end
|
36
|
+
|
37
|
+
it "attaches the internal adapter" do
|
38
|
+
@skype_adapter.expects(:attach)
|
39
|
+
@subject.run
|
40
|
+
end
|
41
|
+
|
42
|
+
it "loads all available rooms from skype" do
|
43
|
+
room = mock('Room')
|
44
|
+
@subject.expects(:find_available_rooms).yields([room])
|
45
|
+
@subject.run
|
46
|
+
@subject.rooms.must_include(room)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "calls the passed callback after loading rooms" do
|
50
|
+
@subject.stubs(:find_available_rooms).yields()
|
51
|
+
proc = -> {}
|
52
|
+
proc.expects(:call)
|
53
|
+
@subject.run(&proc)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "asks the internal adapter to enable wait mode" do
|
57
|
+
@skype_adapter.expects(:wait)
|
58
|
+
@subject.run
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#init_skype_proxy' do
|
63
|
+
before do
|
64
|
+
@proxy_class = mock('ProxyClass')
|
65
|
+
@proxy_instance = mock('ProxyInstance')
|
66
|
+
@proxy_class.stubs(:new).returns(@proxy_instance)
|
67
|
+
@proxy_instance.stubs(:start)
|
68
|
+
@subject.skype_proxy_class = @proxy_class
|
69
|
+
end
|
70
|
+
|
71
|
+
it "creates and assigns a new proxy object" do
|
72
|
+
@subject.init_skype_proxy
|
73
|
+
@subject.proxy.must_equal(@proxy_instance)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "passes itself as adapter to the proxy instance" do
|
77
|
+
@proxy_class.expects(:new).with(@subject).returns(@proxy_instance)
|
78
|
+
@subject.init_skype_proxy
|
79
|
+
end
|
80
|
+
|
81
|
+
it "calls #start on the proxy instance" do
|
82
|
+
@proxy_instance.expects(:start)
|
83
|
+
@subject.init_skype_proxy
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#find_skype_room_by_id' do
|
88
|
+
it "returns the matching room by id" do
|
89
|
+
room = mock('Room', :id => "ab99")
|
90
|
+
@subject.rooms = [room]
|
91
|
+
@subject.find_skype_room_by_id("ab99").must_equal(room)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns nil on no match" do
|
95
|
+
@subject.rooms = []
|
96
|
+
@subject.find_skype_room_by_id("ab99").must_be_nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#enqueue_outgoing_message' do
|
101
|
+
it "attaches the passed message to the proxy's outgoing message collection" do
|
102
|
+
message = mock('Message')
|
103
|
+
@subject.proxy = OpenStruct.new(outgoing_messages: [])
|
104
|
+
@subject.proxy.outgoing_messages.expects(:<<).with(message)
|
105
|
+
@subject.enqueue_outgoing_message(message)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#subscribe_to_incoming_messages' do
|
110
|
+
it "adds the passed callback to the proxy's incoming-message-callbacks collection" do
|
111
|
+
proc = -> {}
|
112
|
+
@subject.proxy = mock('Proxy')
|
113
|
+
@subject.proxy.expects(:on_incoming_message).with() { |callback| callback.must_equal(&proc) }
|
114
|
+
@subject.subscribe_to_incoming_messages(&proc)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#message_received' do
|
119
|
+
before do
|
120
|
+
@raw_message = { room_id: "abx12" }
|
121
|
+
@skype_adapter.stubs(:message_received).yields(@raw_message)
|
122
|
+
@subject.stubs(:build_skype_message)
|
123
|
+
@subject.stubs(:find_skype_room_by_id)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "hooks into the adapters #message_received event" do
|
127
|
+
@skype_adapter.expects(:message_received)
|
128
|
+
@subject.message_received
|
129
|
+
end
|
130
|
+
|
131
|
+
it "finds the Skype::Room for a received message" do
|
132
|
+
@subject.expects(:find_skype_room_by_id).with("abx12")
|
133
|
+
@subject.message_received
|
134
|
+
end
|
135
|
+
|
136
|
+
it "builds a Skype::Message and yields it" do
|
137
|
+
proc = -> {}
|
138
|
+
skype_message = mock('Message')
|
139
|
+
@subject.stubs(:build_skype_message).returns(skype_message)
|
140
|
+
proc.expects(:call).with(skype_message)
|
141
|
+
@subject.message_received(&proc)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '#send_message' do
|
146
|
+
it "invokes #send_message on the skype adapter" do
|
147
|
+
message = OpenStruct.new(room: OpenStruct.new( raw: "raw_room" ), body: "text")
|
148
|
+
@skype_adapter.expects(:send_message).with("raw_room", "text")
|
149
|
+
@subject.send_message(message)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative "../../helper"
|
2
|
+
require_relative "../../../lib/fabriq/cli"
|
3
|
+
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
describe Fabriq::CLI do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@cli = Fabriq::CLI
|
10
|
+
@cli.stubs(:exit)
|
11
|
+
@cli.skype = @skype = mock('Skype')
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#run' do
|
15
|
+
it "lists available rooms if 'rooms' is passed as first argument" do
|
16
|
+
@cli.expects(:list_available_rooms)
|
17
|
+
@cli.run(['rooms'])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "exists the process with success(0)" do
|
21
|
+
@cli.expects(:exit).with(0)
|
22
|
+
@cli.run([])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#list_available_rooms' do
|
27
|
+
before do
|
28
|
+
@cli.stubs(:cli_out)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "collects all Skype Rooms" do
|
32
|
+
@skype.expects(:rooms).returns([])
|
33
|
+
@cli.list_available_rooms
|
34
|
+
end
|
35
|
+
|
36
|
+
it "prints information about each collected room" do
|
37
|
+
room = OpenStruct.new({ topic: "Test", id: 99 })
|
38
|
+
@skype.stubs(:rooms).returns([room])
|
39
|
+
@cli.expects(:cli_out).with() { |out| out =~ /99(.*)Test/ }
|
40
|
+
@cli.list_available_rooms
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|