lita-flowdock 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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +10 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.md +43 -0
- data/Rakefile +13 -0
- data/lib/lita-flowdock.rb +7 -0
- data/lib/lita/adapters/flowdock.rb +56 -0
- data/lib/lita/adapters/flowdock/connector.rb +83 -0
- data/lib/lita/adapters/flowdock/message_handler.rb +83 -0
- data/lib/lita/adapters/flowdock/users_creator.rb +27 -0
- data/lita-flowdock.gemspec +29 -0
- data/locales/en.yml +4 -0
- data/spec/lita/adapters/flowdock/connector_spec.rb +48 -0
- data/spec/lita/adapters/flowdock/message_handler_spec.rb +257 -0
- data/spec/lita/adapters/flowdock/users_creator_spec.rb +51 -0
- data/spec/lita/adapters/flowdock_spec.rb +77 -0
- data/spec/spec_helper.rb +19 -0
- metadata +222 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd90cf335f976ea77188bfc0c4a2d24ced729245
|
4
|
+
data.tar.gz: 553087cdca235214d0d402a3f2a8f0d153d94a2a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 34370d1303bb6c60f3e865b21b9658560eee8b9bda64e59c330ae3963b83e533943724b5444a4cc3724691c959f1b4b1f1e3b2582c982b9f117b30b8d0e72091
|
7
|
+
data.tar.gz: e16d9e9248541766d5e08461dbfd1c57852b7c1db4f8f92415c967b8177dbded3451d90f8d43db8631e9f5a5cb84e66a44551da25d9b469bca21fabc5a580ba3
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2015 Ben House
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# lita-flowdock
|
2
|
+
|
3
|
+
[](https://travis-ci.org/bhouse/lita-flowdock)
|
4
|
+
[](https://coveralls.io/r/bhouse/lita-flowdock?branch=master)
|
5
|
+
|
6
|
+
## Testing
|
7
|
+
```shell
|
8
|
+
git clone https://github.com/litaio/development-environment ~/lita-dev
|
9
|
+
git clone git@github.com:bhouse/lita-flowdock.git ~/lita-dev/lita-flowdock
|
10
|
+
cd ~/lita-dev
|
11
|
+
vagrant up
|
12
|
+
vagrant ssh
|
13
|
+
```
|
14
|
+
|
15
|
+
On the vagrant vm:
|
16
|
+
|
17
|
+
```shell
|
18
|
+
export $ORG=<flowdock organization name>
|
19
|
+
export $FLOW_NAME=<flowdock flow name>
|
20
|
+
export $FLOW_API_TOKEN=<flowdock flow api token>
|
21
|
+
```
|
22
|
+
|
23
|
+
```shell
|
24
|
+
cd /vagrant
|
25
|
+
lita new .
|
26
|
+
echo 'gem "lita-whois"' >> Gemfile
|
27
|
+
echo 'gem "lita-flowdock", git: "git@github.com:bhouse/lita-flowdock.git", branch: "master"' >> Gemfile
|
28
|
+
bundle config local.lita-flowdock /vagrant/lita-flowdock
|
29
|
+
cat << EOF > lita_config.rb
|
30
|
+
Lita.configure do |config|
|
31
|
+
config.robot.name = "Lita"
|
32
|
+
config.robot.log_level = :info
|
33
|
+
config.robot.adapter = :flowdock
|
34
|
+
config.adapters.flowdock.api_key = "$FLOW_API_TOKEN"
|
35
|
+
config.adapters.flowdock.organization = "$ORG"
|
36
|
+
config.adapters.flowdock.flows = ["$FLOW_NAME"]
|
37
|
+
end
|
38
|
+
EOF
|
39
|
+
apt-get update && apt-get install build-essential -y
|
40
|
+
bundle install --path vendor/bundle
|
41
|
+
bundle update
|
42
|
+
bundle exec lita
|
43
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rubocop/rake_task'
|
4
|
+
require 'bump/tasks'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
RuboCop::RakeTask.new do |task|
|
9
|
+
task.options = [ '--lint' ]
|
10
|
+
task.fail_on_error = true
|
11
|
+
end
|
12
|
+
|
13
|
+
task default: [:rubocop, :spec]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'flowdock'
|
2
|
+
require 'lita/adapters/flowdock/connector'
|
3
|
+
|
4
|
+
module Lita
|
5
|
+
module Adapters
|
6
|
+
class Flowdock < Adapter
|
7
|
+
namespace 'flowdock'
|
8
|
+
|
9
|
+
config :api_token, type: String, required: true
|
10
|
+
config :bot_name, type: String, required: true
|
11
|
+
config :organization, type: String, required: true
|
12
|
+
config :flows, type: [Symbol, Array], required: true
|
13
|
+
|
14
|
+
|
15
|
+
def mention_format(name)
|
16
|
+
"@#{name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
return if connector
|
21
|
+
@connector = Connector.new(
|
22
|
+
robot,
|
23
|
+
config.api_token,
|
24
|
+
config.organization,
|
25
|
+
config.flows
|
26
|
+
)
|
27
|
+
|
28
|
+
connector.run
|
29
|
+
rescue Interrupt
|
30
|
+
shut_down
|
31
|
+
end
|
32
|
+
|
33
|
+
def shut_down
|
34
|
+
return unless connector
|
35
|
+
connector.shut_down
|
36
|
+
rescue RuntimeError
|
37
|
+
robot.trigger(:disconnected)
|
38
|
+
log.info('Disconnected')
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_messages(target, messages)
|
42
|
+
connector.send_messages(target.room, messages)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_reader :connector
|
48
|
+
|
49
|
+
def bot_name
|
50
|
+
config.bot_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Lita.register_adapter(:flowdock, Flowdock)
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'em-eventsource'
|
3
|
+
require 'flowdock'
|
4
|
+
require 'lita/adapters/flowdock/message_handler'
|
5
|
+
require 'lita/adapters/flowdock/users_creator'
|
6
|
+
|
7
|
+
module Lita
|
8
|
+
module Adapters
|
9
|
+
class Flowdock < Adapter
|
10
|
+
class Connector
|
11
|
+
|
12
|
+
def initialize(robot, api_token, organization, flows, flowdock_client=nil)
|
13
|
+
@robot = robot
|
14
|
+
@api_token = api_token
|
15
|
+
@organization = organization
|
16
|
+
@flows = flows
|
17
|
+
@client =
|
18
|
+
flowdock_client || Flowdock::Client.new(api_token: api_token)
|
19
|
+
|
20
|
+
UsersCreator.create_users(client.get('/users'))
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
EM.run do
|
25
|
+
@source = EventMachine::EventSource.new(
|
26
|
+
"https://#{api_token}@stream.flowdock.com/flows?filter=#{request_flows}",
|
27
|
+
{query: 'text/event-stream'},
|
28
|
+
{'Accept' => 'text/event-stream'}
|
29
|
+
)
|
30
|
+
|
31
|
+
source.open do
|
32
|
+
log.info('Connected to flowdock streaming API')
|
33
|
+
robot.trigger(:connected)
|
34
|
+
end
|
35
|
+
|
36
|
+
source.message do |message|
|
37
|
+
event = MultiJson.load(message)
|
38
|
+
receive_message(event)
|
39
|
+
end
|
40
|
+
|
41
|
+
source.error do |error|
|
42
|
+
log.error(error.inspect)
|
43
|
+
EM.stop
|
44
|
+
end
|
45
|
+
|
46
|
+
source.start
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def send_messages(target, messages)
|
51
|
+
messages.each do |message|
|
52
|
+
client.chat_message(flow: target, content: message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def shut_down
|
57
|
+
source.close
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
attr_reader :robot, :api_token, :organization, :flows, :source,
|
62
|
+
:client
|
63
|
+
|
64
|
+
def log
|
65
|
+
Lita.logger
|
66
|
+
end
|
67
|
+
|
68
|
+
def receive_message(event)
|
69
|
+
log.debug("Event received: #{event.inspect}")
|
70
|
+
MessageHandler.new(robot, robot_id, event, client).handle
|
71
|
+
end
|
72
|
+
|
73
|
+
def request_flows
|
74
|
+
flows.map {|f| "#{organization}/#{f}" }.join(',')
|
75
|
+
end
|
76
|
+
|
77
|
+
def robot_id
|
78
|
+
@robot_id ||= client.get('/user')['id']
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'lita/adapters/flowdock/users_creator'
|
2
|
+
|
3
|
+
module Lita
|
4
|
+
module Adapters
|
5
|
+
class Flowdock < Adapter
|
6
|
+
class MessageHandler
|
7
|
+
def initialize(robot, robot_id, data, flowdock_client)
|
8
|
+
@robot = robot
|
9
|
+
@robot_id = robot_id
|
10
|
+
@data = data
|
11
|
+
@flowdock_client = flowdock_client
|
12
|
+
@type = data['event']
|
13
|
+
end
|
14
|
+
|
15
|
+
def handle
|
16
|
+
case type
|
17
|
+
when "message"
|
18
|
+
handle_message
|
19
|
+
when "activity.user"
|
20
|
+
handle_user_activity
|
21
|
+
when "action"
|
22
|
+
handle_action
|
23
|
+
else
|
24
|
+
handle_unknown
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
attr_reader :robot, :robot_id, :data, :type, :flowdock_client
|
30
|
+
|
31
|
+
def body
|
32
|
+
data['content'] || ""
|
33
|
+
end
|
34
|
+
|
35
|
+
def dispatch_message(user)
|
36
|
+
source = Source.new(user: user, room: flow)
|
37
|
+
message = Message.new(robot, body, source)
|
38
|
+
robot.receive(message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def flow
|
42
|
+
data['flow']
|
43
|
+
end
|
44
|
+
|
45
|
+
def from_self?(user)
|
46
|
+
user.id.to_i == robot_id
|
47
|
+
end
|
48
|
+
|
49
|
+
def log
|
50
|
+
Lita.logger
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_message
|
54
|
+
log.debug("Handling message: #{data.inspect}")
|
55
|
+
user = User.find_by_id(data['user']) || create_user(data['user'])
|
56
|
+
log.debug("User found: #{user.inspect}")
|
57
|
+
return if from_self?(user)
|
58
|
+
dispatch_message(user)
|
59
|
+
end
|
60
|
+
|
61
|
+
def handle_user_activity
|
62
|
+
log.debug("Handling user activity: #{data.inspect}")
|
63
|
+
end
|
64
|
+
|
65
|
+
def handle_action
|
66
|
+
log.debug("Handling action: #{data.inspect}")
|
67
|
+
if %w{add_people join}.include?(data['content']['type'])
|
68
|
+
UsersCreator.create_users(flowdock_client.get('/users'))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def handle_unknown
|
73
|
+
log.debug("Unknown message type: #{data.inspect}")
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_user(id)
|
77
|
+
user = flowdock_client.get("/user/#{id}")
|
78
|
+
UsersCreator.create_user(user)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Lita
|
2
|
+
module Adapters
|
3
|
+
class Flowdock < Adapter
|
4
|
+
class UsersCreator
|
5
|
+
class << self
|
6
|
+
def create_user(flowdock_user)
|
7
|
+
Lita.logger.debug("Creating user: #{flowdock_user['nick']}")
|
8
|
+
User.create(
|
9
|
+
flowdock_user['id'],
|
10
|
+
{
|
11
|
+
'name' => flowdock_user['name'],
|
12
|
+
'mention_name' => flowdock_user['nick']
|
13
|
+
}
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_users(flowdock_users)
|
18
|
+
flowdock_users.each do |flowdock_user|
|
19
|
+
create_user(flowdock_user)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "lita-flowdock"
|
3
|
+
spec.version = "0.1.0"
|
4
|
+
spec.authors = ["Ben House"]
|
5
|
+
spec.email = ["ben@benhouse.io"]
|
6
|
+
spec.description = %q{flowdock adapter for lita.io}
|
7
|
+
spec.summary = %q{connects lita.io to flowdock chat service}
|
8
|
+
spec.homepage = "https://github.com/bhouse/lita-flowdock"
|
9
|
+
spec.license = "MIT"
|
10
|
+
spec.metadata = { "lita_plugin_type" => "adapter" }
|
11
|
+
|
12
|
+
spec.files = `git ls-files`.split($/)
|
13
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
14
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
15
|
+
spec.require_paths = ["lib"]
|
16
|
+
|
17
|
+
spec.add_runtime_dependency "lita", "~> 4.2.0"
|
18
|
+
spec.add_runtime_dependency "em-eventsource"
|
19
|
+
spec.add_runtime_dependency "flowdock"
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rack-test"
|
24
|
+
spec.add_development_dependency "rspec", ">= 3.0.0"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
spec.add_development_dependency "coveralls"
|
27
|
+
spec.add_development_dependency "rubocop"
|
28
|
+
spec.add_development_dependency "bump"
|
29
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lita::Adapters::Flowdock::Connector, lita: true do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
let(:registry) { Lita::Registry.new }
|
7
|
+
let(:robot) { Lita::Robot.new(registry) }
|
8
|
+
let(:api_token) { 'a8f828cfe7efc65b53b3de06761e83e9' }
|
9
|
+
let(:organization) { 'lita-test' }
|
10
|
+
let(:flows) { ['testing'] }
|
11
|
+
let(:fd_client) { instance_double('Flowdock::Client') }
|
12
|
+
let(:users) {
|
13
|
+
[
|
14
|
+
{'id' => 1, 'name' => 'Test User1', 'nick' => 'user1'},
|
15
|
+
{'id' => 2, 'name' => 'Test User2', 'nick' => 'user2'}
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
describe "#new" do
|
20
|
+
it "creates users" do
|
21
|
+
expect(fd_client).to receive(:get).with('/users').and_return(users)
|
22
|
+
expect(Lita::Adapters::Flowdock::UsersCreator).to receive(
|
23
|
+
:create_users
|
24
|
+
).with(users)
|
25
|
+
subject.new(robot, api_token, organization, flows, fd_client)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#run" do
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#send_messages" do
|
33
|
+
let(:target) { 'testing:lita-test' }
|
34
|
+
let(:message) { 'foo' }
|
35
|
+
subject {
|
36
|
+
described_class.new(robot, api_token, organization, flows, fd_client)
|
37
|
+
}
|
38
|
+
|
39
|
+
before do
|
40
|
+
allow(fd_client).to receive(:get).with('/users').and_return(users)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "sends messages" do
|
44
|
+
expect(fd_client).to receive(:chat_message).with(flow: target, content: message)
|
45
|
+
subject.send_messages(target, [message])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lita::Adapters::Flowdock::MessageHandler, lita: true do
|
4
|
+
subject { described_class.new(robot, robot_id, data, fd_client) }
|
5
|
+
|
6
|
+
let(:fd_client) { instance_double('Flowdock::Client') }
|
7
|
+
let(:robot) {
|
8
|
+
instance_double('Lita::Robot', name: 'Lita', mention_name: 'lita')
|
9
|
+
}
|
10
|
+
let(:robot_id) { 123456 }
|
11
|
+
let(:robot_fd_user) {
|
12
|
+
{ 'id' => robot_id, 'name' => 'Lita', 'nick' => 'lita' }
|
13
|
+
}
|
14
|
+
let(:test_user_id) { 3 }
|
15
|
+
let(:test_fd_user) {
|
16
|
+
{ 'id' => test_user_id, 'name' => 'Test User3', 'nick' => 'user3' }
|
17
|
+
}
|
18
|
+
let(:test_flow) { 'testing:lita-test' }
|
19
|
+
|
20
|
+
before do
|
21
|
+
allow(fd_client).to receive(:get).with(
|
22
|
+
"/user/#{robot_id}").and_return(robot_fd_user)
|
23
|
+
allow(fd_client).to receive(:get).with(
|
24
|
+
"/user/#{test_user_id}").and_return(test_fd_user)
|
25
|
+
allow(robot).to receive(:alias)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#handle" do
|
29
|
+
context "a normal message" do
|
30
|
+
let(:data) do
|
31
|
+
{
|
32
|
+
'content' => 'Hello World!',
|
33
|
+
'event' => 'message',
|
34
|
+
'flow' => test_flow,
|
35
|
+
'user' => test_user_id
|
36
|
+
}
|
37
|
+
end
|
38
|
+
let(:message) { instance_double('Lita::Message', command!: false) }
|
39
|
+
let(:source) { instance_double('Lita::Source', private_message?: false) }
|
40
|
+
let(:user) { instance_double('Lita::User', id: test_user_id) }
|
41
|
+
|
42
|
+
before do
|
43
|
+
allow(Lita::User).to receive(:find_by_id).and_return(user)
|
44
|
+
allow(Lita::Source).to receive(:new).with(
|
45
|
+
user: user,
|
46
|
+
room: test_flow
|
47
|
+
).and_return(source)
|
48
|
+
allow(Lita::Message).to receive(:new).with(
|
49
|
+
robot, 'Hello World!', source).and_return(message)
|
50
|
+
allow(robot).to receive(:receive).with(message)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "dispatches the message to lita" do
|
54
|
+
expect(robot).to receive(:receive).with(message)
|
55
|
+
|
56
|
+
subject.handle
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when the message is nil" do
|
60
|
+
let(:data) do
|
61
|
+
{
|
62
|
+
'event' => 'message',
|
63
|
+
'flow' => test_flow,
|
64
|
+
'user' => test_user_id,
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
it "dispatches an empty message to Lita" do
|
69
|
+
expect(Lita::Message).to receive(:new).with(
|
70
|
+
robot,
|
71
|
+
"",
|
72
|
+
source
|
73
|
+
).and_return(message)
|
74
|
+
|
75
|
+
subject.handle
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "a message with an unsupported type" do
|
81
|
+
let(:data) do
|
82
|
+
{
|
83
|
+
'content' => 'this type is not supported',
|
84
|
+
'event' => 'unsupported',
|
85
|
+
'flow' => test_flow,
|
86
|
+
'user' => test_user_id
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
it "does not dispatch the message to Lita" do
|
91
|
+
expect(robot).not_to receive(:receive)
|
92
|
+
|
93
|
+
subject.handle
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "a message from the robot itself" do
|
98
|
+
let(:data) do
|
99
|
+
{
|
100
|
+
'content' => 'reply from lita',
|
101
|
+
'event' => 'message',
|
102
|
+
'flow' => test_flow,
|
103
|
+
'user' => robot_id
|
104
|
+
}
|
105
|
+
end
|
106
|
+
let(:robot_user) { instance_double('Lita::User', id: robot_id) }
|
107
|
+
|
108
|
+
before do
|
109
|
+
allow(Lita::User).to receive(:find_by_id).and_return(robot_user)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "does not dispatch the message to Lita" do
|
113
|
+
expect(robot).not_to receive(:receive)
|
114
|
+
|
115
|
+
subject.handle
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "a message from an unknown user" do
|
120
|
+
let(:new_user_id) { 4 }
|
121
|
+
let(:new_fd_user) {
|
122
|
+
{ 'id' => new_user_id, 'name' => 'Test User4', 'nick' => 'user4' }
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
let(:data) do
|
127
|
+
{
|
128
|
+
'content' => "hi i'm new here",
|
129
|
+
'event' => 'message',
|
130
|
+
'flow' => test_flow,
|
131
|
+
'user' => new_user_id
|
132
|
+
}
|
133
|
+
end
|
134
|
+
let(:user4) { instance_double(
|
135
|
+
'Lita::User', id: 4, name: 'Test User4', mention_name: 'user4'
|
136
|
+
)}
|
137
|
+
|
138
|
+
before do
|
139
|
+
allow(Lita::User).to receive(:find_by_id).with(
|
140
|
+
new_user_id).and_return(nil)
|
141
|
+
allow(fd_client).to receive(:get).with(
|
142
|
+
"/user/#{new_user_id}").and_return(new_fd_user)
|
143
|
+
allow(robot).to receive(:receive)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "creates the new user" do
|
147
|
+
expect(Lita::User).to receive(:create).with(
|
148
|
+
new_user_id,
|
149
|
+
{
|
150
|
+
"name" => 'Test User4',
|
151
|
+
"mention_name" => 'user4'
|
152
|
+
}
|
153
|
+
).and_return(user4)
|
154
|
+
|
155
|
+
subject.handle
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "receives a user activity message" do
|
160
|
+
let(:data) do
|
161
|
+
{
|
162
|
+
'content' => { 'last_activity' => 1317715364447 },
|
163
|
+
'event' => 'activity.user',
|
164
|
+
'flow' => test_flow,
|
165
|
+
'user' => test_user_id
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
it "doesn't dispatch a message to Lita" do
|
170
|
+
expect(robot).not_to receive(:receive)
|
171
|
+
|
172
|
+
subject.handle
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "receives an action message" do
|
177
|
+
context "for adding a user to the flow" do
|
178
|
+
let(:data) do
|
179
|
+
{
|
180
|
+
'content' => {'type' => 'add_people', 'description' => 'user5'},
|
181
|
+
'event' => 'action',
|
182
|
+
'flow' => test_flow,
|
183
|
+
'user' => test_user_id
|
184
|
+
}
|
185
|
+
end
|
186
|
+
let(:added_user_id) { 5 }
|
187
|
+
let(:added_user_fd) do
|
188
|
+
{ 'id' => 5, 'name' => 'Test User5', 'nick' => 'user5' }
|
189
|
+
end
|
190
|
+
|
191
|
+
before do
|
192
|
+
allow(Lita::User).to receive(:find_by_id).with(5).and_return(nil)
|
193
|
+
allow(fd_client).to receive(:get).with(
|
194
|
+
"/user/#{added_user_id}").and_return(added_user_fd)
|
195
|
+
allow(robot).to receive(:receive)
|
196
|
+
allow(fd_client).to receive(:get).with(
|
197
|
+
'/users').and_return([added_user_fd])
|
198
|
+
end
|
199
|
+
|
200
|
+
it "creates the new user" do
|
201
|
+
expect(Lita::User).to receive(:create).with(
|
202
|
+
5, { 'name' => 'Test User5', 'mention_name' => 'user5' })
|
203
|
+
subject.handle
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "for a user joining the flow" do
|
208
|
+
let(:joining_user_id) { 6 }
|
209
|
+
let(:joining_user_fd) do
|
210
|
+
{ 'id' => 6, 'name' => 'Test User6', 'nick' => 'user6' }
|
211
|
+
end
|
212
|
+
let(:data) do
|
213
|
+
{
|
214
|
+
'content' => {'type' => 'join', 'description' => 'tbd'},
|
215
|
+
'event' => 'action',
|
216
|
+
'flow' => test_flow,
|
217
|
+
'user' => joining_user_id
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
before do
|
222
|
+
allow(Lita::User).to receive(:find_by_id).with(6).and_return(nil)
|
223
|
+
allow(fd_client).to receive(:get).with(
|
224
|
+
"/user/#{joining_user_id}").and_return(joining_user_fd)
|
225
|
+
allow(robot).to receive(:receive)
|
226
|
+
allow(fd_client).to receive(:get).with(
|
227
|
+
'/users').and_return([joining_user_fd])
|
228
|
+
end
|
229
|
+
|
230
|
+
it "creates the new user" do
|
231
|
+
expect(Lita::User).to receive(:create).with(
|
232
|
+
6, { 'name' => 'Test User6', 'mention_name' => 'user6' })
|
233
|
+
subject.handle
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "for an unsupported action message type" do
|
238
|
+
let(:data) do
|
239
|
+
{
|
240
|
+
'content' => {
|
241
|
+
'type' => 'add_rss_feed',
|
242
|
+
'description' => 'http://example.com/rss'
|
243
|
+
},
|
244
|
+
'event' => 'action',
|
245
|
+
'flow' => test_flow,
|
246
|
+
'user' => test_user_id
|
247
|
+
}
|
248
|
+
end
|
249
|
+
|
250
|
+
it "doesn't dispatch the message to Lita" do
|
251
|
+
expect(robot).not_to receive(:receive)
|
252
|
+
subject.handle
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lita::Adapters::Flowdock::UsersCreator do
|
4
|
+
subject { described_class }
|
5
|
+
|
6
|
+
def stubbed_user(id)
|
7
|
+
instance_double(
|
8
|
+
'Lita::User', id: id, name: "Test User#{id}", mention_name: "user#{id}"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#create_user" do
|
13
|
+
let(:user) do
|
14
|
+
{
|
15
|
+
'id' => 1,
|
16
|
+
'name' => 'Test User1',
|
17
|
+
'nick' => 'user1'
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
it "creates a single Lita user" do
|
22
|
+
expect(Lita::User).to receive(:create).with(
|
23
|
+
1,
|
24
|
+
{ 'name' => 'Test User1', 'mention_name' => 'user1' }
|
25
|
+
).and_return(stubbed_user(1))
|
26
|
+
|
27
|
+
subject.create_user(user)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#create_users" do
|
32
|
+
let(:users) do
|
33
|
+
[
|
34
|
+
{'id' => 1, 'name' => 'Test User1', 'nick' => 'user1'},
|
35
|
+
{'id' => 2, 'name' => 'Test User2', 'nick' => 'user2'},
|
36
|
+
{'id' => 3, 'name' => 'Test User3', 'nick' => 'user3'}
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "creates multiple Lita users" do
|
41
|
+
(1..3).each do |id|
|
42
|
+
expect(Lita::User).to receive(:create).with(
|
43
|
+
id,
|
44
|
+
{ 'name' => "Test User#{id}", 'mention_name' => "user#{id}" }
|
45
|
+
).and_return(stubbed_user(id))
|
46
|
+
end
|
47
|
+
|
48
|
+
subject.create_users(users)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Lita::Adapters::Flowdock, lita: true do
|
4
|
+
subject { described_class.new(robot) }
|
5
|
+
|
6
|
+
let(:robot) { Lita::Robot.new(registry) }
|
7
|
+
let(:connector) { instance_double('Lita::Adapters::Flowdock::Connector') }
|
8
|
+
let(:api_token) { '46d96d3c91623d4cb6235bb94ac771fb' }
|
9
|
+
let(:organization) { 'lita-test' }
|
10
|
+
let(:flows) { ['test-flow'] }
|
11
|
+
|
12
|
+
before do
|
13
|
+
registry.register_adapter(:flowdock, described_class)
|
14
|
+
registry.config.adapters.flowdock.api_token = api_token
|
15
|
+
registry.config.adapters.flowdock.organization = organization
|
16
|
+
registry.config.adapters.flowdock.flows = flows
|
17
|
+
|
18
|
+
allow(
|
19
|
+
described_class::Connector
|
20
|
+
).to receive(:new).with(
|
21
|
+
robot,
|
22
|
+
api_token,
|
23
|
+
organization,
|
24
|
+
flows
|
25
|
+
).and_return(connector)
|
26
|
+
allow(connector).to receive(:run)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "registers with Lita" do
|
30
|
+
expect(Lita.adapters[:flowdock]).to eql(described_class)
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#run" do
|
34
|
+
it "starts the streaming connection" do
|
35
|
+
expect(connector).to receive(:run)
|
36
|
+
subject.run
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does nothing if the streaming connection is already created" do
|
40
|
+
expect(connector).to receive(:run).once
|
41
|
+
|
42
|
+
subject.run
|
43
|
+
subject.run
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#send_messages" do
|
48
|
+
let(:room_source) { Lita::Source.new(room: '1234abcd') }
|
49
|
+
let(:user) { Lita::User.new('987654') }
|
50
|
+
let(:user_source) { Lita::Source.new(user: user) }
|
51
|
+
|
52
|
+
it "sends messages to flows" do
|
53
|
+
expect(connector).to receive(:send_messages).with(room_source.room, ['foo'])
|
54
|
+
|
55
|
+
subject.run
|
56
|
+
|
57
|
+
subject.send_messages(room_source, ['foo'])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#shut_down" do
|
62
|
+
before { allow(connector).to receive(:shut_down) }
|
63
|
+
|
64
|
+
it "shuts down the streaming connection" do
|
65
|
+
expect(connector).to receive(:shut_down)
|
66
|
+
|
67
|
+
subject.run
|
68
|
+
subject.shut_down
|
69
|
+
end
|
70
|
+
|
71
|
+
it "does nothing if the streaming connection hasn't been created yet" do
|
72
|
+
expect(connector).not_to receive(:shut_down)
|
73
|
+
|
74
|
+
subject.shut_down
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "simplecov"
|
2
|
+
require "coveralls"
|
3
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
4
|
+
SimpleCov::Formatter::HTMLFormatter,
|
5
|
+
Coveralls::SimpleCov::Formatter
|
6
|
+
]
|
7
|
+
SimpleCov.start { add_filter "/spec/" }
|
8
|
+
|
9
|
+
require "lita-flowdock"
|
10
|
+
require "lita/rspec"
|
11
|
+
|
12
|
+
# A compatibility mode is provided for older plugins upgrading from Lita 3. Since this plugin
|
13
|
+
# was generated with Lita 4, the compatibility mode should be left disabled.
|
14
|
+
Lita.version_3_compatibility_mode = false
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.color = true
|
18
|
+
config.formatter = :documentation
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lita-flowdock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben House
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lita
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: em-eventsource
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: flowdock
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack-test
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.0.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.0.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: coveralls
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: bump
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description: flowdock adapter for lita.io
|
168
|
+
email:
|
169
|
+
- ben@benhouse.io
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- ".gitignore"
|
175
|
+
- ".travis.yml"
|
176
|
+
- Gemfile
|
177
|
+
- LICENSE
|
178
|
+
- README.md
|
179
|
+
- Rakefile
|
180
|
+
- lib/lita-flowdock.rb
|
181
|
+
- lib/lita/adapters/flowdock.rb
|
182
|
+
- lib/lita/adapters/flowdock/connector.rb
|
183
|
+
- lib/lita/adapters/flowdock/message_handler.rb
|
184
|
+
- lib/lita/adapters/flowdock/users_creator.rb
|
185
|
+
- lita-flowdock.gemspec
|
186
|
+
- locales/en.yml
|
187
|
+
- spec/lita/adapters/flowdock/connector_spec.rb
|
188
|
+
- spec/lita/adapters/flowdock/message_handler_spec.rb
|
189
|
+
- spec/lita/adapters/flowdock/users_creator_spec.rb
|
190
|
+
- spec/lita/adapters/flowdock_spec.rb
|
191
|
+
- spec/spec_helper.rb
|
192
|
+
homepage: https://github.com/bhouse/lita-flowdock
|
193
|
+
licenses:
|
194
|
+
- MIT
|
195
|
+
metadata:
|
196
|
+
lita_plugin_type: adapter
|
197
|
+
post_install_message:
|
198
|
+
rdoc_options: []
|
199
|
+
require_paths:
|
200
|
+
- lib
|
201
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - ">="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
|
+
requirements:
|
208
|
+
- - ">="
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '0'
|
211
|
+
requirements: []
|
212
|
+
rubyforge_project:
|
213
|
+
rubygems_version: 2.2.2
|
214
|
+
signing_key:
|
215
|
+
specification_version: 4
|
216
|
+
summary: connects lita.io to flowdock chat service
|
217
|
+
test_files:
|
218
|
+
- spec/lita/adapters/flowdock/connector_spec.rb
|
219
|
+
- spec/lita/adapters/flowdock/message_handler_spec.rb
|
220
|
+
- spec/lita/adapters/flowdock/users_creator_spec.rb
|
221
|
+
- spec/lita/adapters/flowdock_spec.rb
|
222
|
+
- spec/spec_helper.rb
|