lita-slack 1.7.2 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/README.md +15 -3
- data/lib/lita/adapters/slack.rb +56 -3
- data/lib/lita/adapters/slack/api.rb +37 -1
- data/lib/lita/adapters/slack/message_handler.rb +23 -7
- data/lita-slack.gemspec +3 -3
- data/spec/lita/adapters/slack/api_spec.rb +403 -3
- data/spec/lita/adapters/slack/message_handler_spec.rb +70 -9
- data/spec/lita/adapters/slack_spec.rb +84 -23
- data/spec/spec_helper.rb +1 -1
- metadata +7 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca96105086115398590afb975e36f44633faf31d
|
4
|
+
data.tar.gz: 21f62a27417aa3fa13fbfc4f4c4091319ee84265
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c93fb3be8f2403c50766c7d6cb0127e528efd05e3da10f21aeda34364bef857f0b01ff7b7dcee1b9666f8bc2cd44306a87bd9540a613c241aea8691c1e793aab
|
7
|
+
data.tar.gz: 5dd83d261ce894a9992ac06a1d7af3830cb98cebf8e70bb045f0ae67151628bb81a84b4baca1248d9e37c0454f4f84857d2a83aecb61f0223b73b750a143a7f8
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# lita-slack
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/lita-slack.png)](http://badge.fury.io/rb/lita-slack)
|
4
|
-
[![Build Status](https://travis-ci.org/
|
4
|
+
[![Build Status](https://travis-ci.org/litaio/lita-slack.png?branch=master)](https://travis-ci.org/litaio/lita-slack)
|
5
5
|
|
6
6
|
**lita-slack** is an adapter for [Lita](https://www.lita.io/) that allows you to use the robot with [Slack](https://slack.com/). The current adapter is not compatible with pre-1.0.0 versions, as it now uses Slack's [Real Time Messaging API](https://api.slack.com/rtm).
|
7
7
|
|
@@ -21,7 +21,11 @@ gem "lita-slack"
|
|
21
21
|
|
22
22
|
### Optional attributes
|
23
23
|
|
24
|
+
* `link_names` (Boolean) – Set to `true` to turn all Slack usernames in messages sent by Lita into links.
|
25
|
+
* `parse` (String) – Specify the parsing mode. See https://api.slack.com/docs/formatting#parsing_modes.
|
24
26
|
* `proxy` (String) – Specify a HTTP proxy URL. (e.g. "http://squid.example.com:3128")
|
27
|
+
* `unfurl_links` (Boolean) – Set to `true` to automatically add previews for all links in messages sent by Lita.
|
28
|
+
* `unfurl_media` (Boolean) – Set to `false` to prevent automatic previews for media files in messages sent by Lita.
|
25
29
|
|
26
30
|
**Note**: When using lita-slack, the adapter will overwrite the bot's name and mention name with the values set on the server, so `config.robot.name` and `config.robot.mention_name` will have no effect.
|
27
31
|
|
@@ -35,7 +39,13 @@ Each Slack user has a unique ID that never changes even if their real name or us
|
|
35
39
|
Lita.configure do |config|
|
36
40
|
config.robot.adapter = :slack
|
37
41
|
config.robot.admins = ["U012A3BCD"]
|
42
|
+
|
38
43
|
config.adapters.slack.token = "abcd-1234567890-hWYd21AmMH2UHAkx29vb5c1Y"
|
44
|
+
|
45
|
+
config.adapters.slack.link_names = true
|
46
|
+
config.adapters.slack.parse = "full"
|
47
|
+
config.adapters.slack.unfurl_links = false
|
48
|
+
config.adapters.slack.unfurl_media = false
|
39
49
|
end
|
40
50
|
```
|
41
51
|
|
@@ -47,12 +57,14 @@ Lita will join your default channel after initial setup. To have it join additio
|
|
47
57
|
|
48
58
|
* `:connected` - When the robot has connected to Slack. No payload.
|
49
59
|
* `:disconnected` - When the robot has disconnected from Slack. No payload.
|
50
|
-
* `:slack_user_created` - When the robot creates/updates a user's info - name, mention name, etc., as directed by Slack. The payload has a single object, a `Lita::Slack::Adapters::SlackUser` object, under the `:slack_user` key.
|
51
60
|
* `:slack_channel_created` - When the robot creates/updates a channel's or group's info, as directed by Slack. The payload has a single object, a `Lita::Slack::Adapters::SlackChannel` object, under the `:slack_channel` key.
|
61
|
+
* `:slack_reaction_added` - When a reaction has been added to a previous message. The payload includes `:user` (a `Lita::User` for the sender of the message in question), `:name` (the string name of the reaction added), `:item` (a hash of raw data from Slack about the message), and `:event_ts` (a string timestamp used to identify the message).
|
62
|
+
* `:slack_reaction_removed` - When a reaction has been removed from a previous message. The payload is the same as the `:slack_reaction_added` message.
|
63
|
+
* `:slack_user_created` - When the robot creates/updates a user's info - name, mention name, etc., as directed by Slack. The payload has a single object, a `Lita::Slack::Adapters::SlackUser` object, under the `:slack_user` key.
|
52
64
|
|
53
65
|
## Chat service API
|
54
66
|
|
55
|
-
lita-slack supports Lita 4.6's chat service API for Slack-specific functionality. You can access this API object by calling the `Lita::Robot#chat_service`. See the API docs for `Lita::Slack::
|
67
|
+
lita-slack supports Lita 4.6's chat service API for Slack-specific functionality. You can access this API object by calling the `Lita::Robot#chat_service`. See the API docs for `Lita::Adapters::Slack::ChatService` for details about the provided methods.
|
56
68
|
|
57
69
|
## API documentation
|
58
70
|
|
data/lib/lita/adapters/slack.rb
CHANGED
@@ -9,12 +9,20 @@ module Lita
|
|
9
9
|
# Required configuration attributes.
|
10
10
|
config :token, type: String, required: true
|
11
11
|
config :proxy, type: String
|
12
|
+
config :parse, type: [String]
|
13
|
+
config :link_names, type: [true, false]
|
14
|
+
config :unfurl_links, type: [true, false]
|
15
|
+
config :unfurl_media, type: [true, false]
|
12
16
|
|
13
17
|
# Provides an object for Slack-specific features.
|
14
18
|
def chat_service
|
15
19
|
ChatService.new(config)
|
16
20
|
end
|
17
21
|
|
22
|
+
def mention_format(name)
|
23
|
+
"@#{name}"
|
24
|
+
end
|
25
|
+
|
18
26
|
# Starts the connection.
|
19
27
|
def run
|
20
28
|
return if rtm_connection
|
@@ -23,10 +31,16 @@ module Lita
|
|
23
31
|
rtm_connection.run
|
24
32
|
end
|
25
33
|
|
26
|
-
|
27
|
-
|
34
|
+
# Returns UID(s) in an Array or String for:
|
35
|
+
# Channels, MPIMs, IMs
|
36
|
+
def roster(target)
|
37
|
+
api = API.new(config)
|
38
|
+
room_roster target.id, api
|
39
|
+
end
|
28
40
|
|
29
|
-
|
41
|
+
def send_messages(target, strings)
|
42
|
+
api = API.new(config)
|
43
|
+
api.send_messages(channel_for(target), strings)
|
30
44
|
end
|
31
45
|
|
32
46
|
def set_topic(target, topic)
|
@@ -53,6 +67,45 @@ module Lita
|
|
53
67
|
target.room
|
54
68
|
end
|
55
69
|
end
|
70
|
+
|
71
|
+
def channel_roster(room_id, api)
|
72
|
+
response = api.channels_info room_id
|
73
|
+
response['channel']['members']
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the members of a group, but only can do so if it's a member
|
77
|
+
def group_roster(room_id, api)
|
78
|
+
response = api.groups_list
|
79
|
+
group = response['groups'].select { |hash| hash['id'].eql? room_id }.first
|
80
|
+
group.nil? ? [] : group['members']
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the members of a mpim, but only can do so if it's a member
|
84
|
+
def mpim_roster(room_id, api)
|
85
|
+
response = api.mpim_list
|
86
|
+
mpim = response['groups'].select { |hash| hash['id'].eql? room_id }.first
|
87
|
+
mpim.nil? ? [] : mpim['members']
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the user of an im
|
91
|
+
def im_roster(room_id, api)
|
92
|
+
response = api.mpim_list
|
93
|
+
im = response['ims'].select { |hash| hash['id'].eql? room_id }.first
|
94
|
+
im.nil? ? '' : im['user']
|
95
|
+
end
|
96
|
+
|
97
|
+
def room_roster(room_id, api)
|
98
|
+
case room_id
|
99
|
+
when /^C/
|
100
|
+
channel_roster room_id, api
|
101
|
+
when /^G/
|
102
|
+
# Groups & MPIMs have the same room ID pattern, check both if needed
|
103
|
+
roster = group_roster room_id, api
|
104
|
+
roster.empty? ? mpim_roster(room_id, api) : roster
|
105
|
+
when /^D/
|
106
|
+
im_roster room_id, api
|
107
|
+
end
|
108
|
+
end
|
56
109
|
end
|
57
110
|
|
58
111
|
# Register Slack adapter to Lita
|
@@ -13,6 +13,11 @@ module Lita
|
|
13
13
|
def initialize(config, stubs = nil)
|
14
14
|
@config = config
|
15
15
|
@stubs = stubs
|
16
|
+
@post_message_config = {}
|
17
|
+
@post_message_config[:parse] = config.parse unless config.parse.nil?
|
18
|
+
@post_message_config[:link_names] = config.link_names ? 1 : 0 unless config.link_names.nil?
|
19
|
+
@post_message_config[:unfurl_links] = config.unfurl_links unless config.unfurl_links.nil?
|
20
|
+
@post_message_config[:unfurl_media] = config.unfurl_media unless config.unfurl_media.nil?
|
16
21
|
end
|
17
22
|
|
18
23
|
def im_open(user_id)
|
@@ -21,6 +26,26 @@ module Lita
|
|
21
26
|
SlackIM.new(response_data["channel"]["id"], user_id)
|
22
27
|
end
|
23
28
|
|
29
|
+
def channels_info(channel_id)
|
30
|
+
call_api("channels.info", channel: channel_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def channels_list
|
34
|
+
call_api("channels.list")
|
35
|
+
end
|
36
|
+
|
37
|
+
def groups_list
|
38
|
+
call_api("groups.list")
|
39
|
+
end
|
40
|
+
|
41
|
+
def mpim_list
|
42
|
+
call_api("mpim.list")
|
43
|
+
end
|
44
|
+
|
45
|
+
def im_list
|
46
|
+
call_api("im.list")
|
47
|
+
end
|
48
|
+
|
24
49
|
def send_attachments(room_or_user, attachments)
|
25
50
|
call_api(
|
26
51
|
"chat.postMessage",
|
@@ -30,6 +55,16 @@ module Lita
|
|
30
55
|
)
|
31
56
|
end
|
32
57
|
|
58
|
+
def send_messages(channel_id, messages)
|
59
|
+
call_api(
|
60
|
+
"chat.postMessage",
|
61
|
+
**post_message_config,
|
62
|
+
as_user: true,
|
63
|
+
channel: channel_id,
|
64
|
+
text: messages.join("\n"),
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
33
68
|
def set_topic(channel, topic)
|
34
69
|
call_api("channels.setTopic", channel: channel, topic: topic)
|
35
70
|
end
|
@@ -51,6 +86,7 @@ module Lita
|
|
51
86
|
|
52
87
|
attr_reader :stubs
|
53
88
|
attr_reader :config
|
89
|
+
attr_reader :post_message_config
|
54
90
|
|
55
91
|
def call_api(method, post_data = {})
|
56
92
|
response = connection.post(
|
@@ -79,7 +115,7 @@ module Lita
|
|
79
115
|
|
80
116
|
def parse_response(response, method)
|
81
117
|
unless response.success?
|
82
|
-
raise "Slack API call to #{method} failed with status code #{response.status}."
|
118
|
+
raise "Slack API call to #{method} failed with status code #{response.status}: '#{response.body}'. Headers: #{response.headers}"
|
83
119
|
end
|
84
120
|
|
85
121
|
MultiJson.load(response.body)
|
@@ -16,6 +16,8 @@ module Lita
|
|
16
16
|
handle_hello
|
17
17
|
when "message"
|
18
18
|
handle_message
|
19
|
+
when "reaction_added", "reaction_removed"
|
20
|
+
handle_reaction
|
19
21
|
when "user_change", "team_join"
|
20
22
|
handle_user_change
|
21
23
|
when "bot_added", "bot_changed"
|
@@ -44,7 +46,7 @@ module Lita
|
|
44
46
|
normalized_message = remove_formatting(normalized_message) unless normalized_message.nil?
|
45
47
|
|
46
48
|
attachment_text = Array(data["attachments"]).map do |attachment|
|
47
|
-
attachment["text"]
|
49
|
+
attachment["text"] || attachment["fallback"]
|
48
50
|
end
|
49
51
|
|
50
52
|
([normalized_message] + attachment_text).compact.join("\n")
|
@@ -115,16 +117,13 @@ module Lita
|
|
115
117
|
source.private_message! if channel && channel[0] == "D"
|
116
118
|
message = Message.new(robot, body, source)
|
117
119
|
message.command! if source.private_message?
|
120
|
+
message.extensions[:slack] = { timestamp: data["ts"] }
|
118
121
|
log.debug("Dispatching message to Lita from #{user.id}.")
|
119
122
|
robot.receive(message)
|
120
123
|
end
|
121
124
|
|
122
125
|
def from_self?(user)
|
123
|
-
|
124
|
-
robot_user = User.find_by_name(robot.name)
|
125
|
-
|
126
|
-
robot_user && robot_user.id == user.id
|
127
|
-
end
|
126
|
+
user.id == robot_id
|
128
127
|
end
|
129
128
|
|
130
129
|
def handle_bot_change
|
@@ -151,6 +150,7 @@ module Lita
|
|
151
150
|
|
152
151
|
def handle_message
|
153
152
|
return unless supported_subtype?
|
153
|
+
return if data["user"] == 'USLACKBOT'
|
154
154
|
|
155
155
|
user = User.find_by_id(data["user"]) || User.create(data["user"])
|
156
156
|
|
@@ -159,6 +159,22 @@ module Lita
|
|
159
159
|
dispatch_message(user)
|
160
160
|
end
|
161
161
|
|
162
|
+
def handle_reaction
|
163
|
+
log.debug "#{type} event received from Slack"
|
164
|
+
|
165
|
+
# find or create user
|
166
|
+
user = User.find_by_id(data["user"]) || User.create(data["user"])
|
167
|
+
|
168
|
+
# avoid processing reactions added/removed by self
|
169
|
+
return if from_self?(user)
|
170
|
+
|
171
|
+
# build a payload following slack convention for reactions
|
172
|
+
payload = { user: user, name: data["reaction"], item: data["item"], event_ts: data["event_ts"] }
|
173
|
+
|
174
|
+
# trigger the appropriate slack reaction event
|
175
|
+
robot.trigger("slack_#{type}".to_sym, payload)
|
176
|
+
end
|
177
|
+
|
162
178
|
def handle_unknown
|
163
179
|
unless data["reply_to"]
|
164
180
|
log.debug("#{type} event received from Slack and will be ignored.")
|
@@ -176,7 +192,7 @@ module Lita
|
|
176
192
|
|
177
193
|
# Types of messages Lita should dispatch to handlers.
|
178
194
|
def supported_message_subtypes
|
179
|
-
%w(
|
195
|
+
%w(me_message)
|
180
196
|
end
|
181
197
|
|
182
198
|
def supported_subtype?
|
data/lita-slack.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "lita-slack"
|
3
|
-
spec.version = "1.
|
3
|
+
spec.version = "1.8.0"
|
4
4
|
spec.authors = ["Ken J.", "Jimmy Cuadra"]
|
5
5
|
spec.email = ["kenjij@gmail.com", "jimmy@jimmycuadra.com"]
|
6
6
|
spec.description = %q{Lita adapter for Slack.}
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.add_runtime_dependency "eventmachine"
|
18
18
|
spec.add_runtime_dependency "faraday"
|
19
19
|
spec.add_runtime_dependency "faye-websocket", ">= 0.8.0"
|
20
|
-
spec.add_runtime_dependency "lita", ">= 4.
|
20
|
+
spec.add_runtime_dependency "lita", ">= 4.7.1"
|
21
21
|
spec.add_runtime_dependency "multi_json"
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.3"
|
@@ -25,6 +25,6 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "rack-test"
|
26
26
|
spec.add_development_dependency "rake"
|
27
27
|
spec.add_development_dependency "rspec", ">= 3.0.0"
|
28
|
-
spec.add_development_dependency "simplecov"
|
28
|
+
spec.add_development_dependency "simplecov", ">= 0.9.2"
|
29
29
|
spec.add_development_dependency "coveralls"
|
30
30
|
end
|
@@ -60,7 +60,277 @@ describe Lita::Adapters::Slack::API do
|
|
60
60
|
|
61
61
|
it "raises a RuntimeError" do
|
62
62
|
expect { subject.im_open(user_id) }.to raise_error(
|
63
|
-
"Slack API call to im.open failed with status code 422."
|
63
|
+
"Slack API call to im.open failed with status code 422: ''. Headers: {}"
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#channels_info" do
|
70
|
+
let(:channel_id) { 'C024BE91L' }
|
71
|
+
let(:stubs) do
|
72
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
73
|
+
stub.post('https://slack.com/api/channels.info', token: token, channel: channel_id) do
|
74
|
+
[http_status, {}, http_response]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "with a successful response" do
|
80
|
+
let(:http_response) do
|
81
|
+
MultiJson.dump({
|
82
|
+
ok: true,
|
83
|
+
channel: {
|
84
|
+
id: 'C024BE91L'
|
85
|
+
}
|
86
|
+
})
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns a response with the Channel's ID" do
|
90
|
+
response = subject.channels_info(channel_id)
|
91
|
+
|
92
|
+
expect(response['channel']['id']).to eq(channel_id)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "with a Slack error" do
|
97
|
+
let(:http_response) do
|
98
|
+
MultiJson.dump({
|
99
|
+
ok: false,
|
100
|
+
error: 'channel_not_found'
|
101
|
+
})
|
102
|
+
end
|
103
|
+
|
104
|
+
it "raises a RuntimeError" do
|
105
|
+
expect { subject.channels_info(channel_id) }.to raise_error(
|
106
|
+
"Slack API call to channels.info returned an error: channel_not_found."
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "with an HTTP error" do
|
112
|
+
let(:http_status) { 422 }
|
113
|
+
let(:http_response) { '' }
|
114
|
+
|
115
|
+
it "raises a RuntimeError" do
|
116
|
+
expect { subject.channels_info(channel_id) }.to raise_error(
|
117
|
+
"Slack API call to channels.info failed with status code 422: ''. Headers: {}"
|
118
|
+
)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#channels_list" do
|
124
|
+
let(:channel_id) { 'C024BE91L' }
|
125
|
+
let(:stubs) do
|
126
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
127
|
+
stub.post('https://slack.com/api/channels.list', token: token) do
|
128
|
+
[http_status, {}, http_response]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "with a successful response" do
|
134
|
+
let(:http_response) do
|
135
|
+
MultiJson.dump({
|
136
|
+
ok: true,
|
137
|
+
channel: [{
|
138
|
+
id: 'C024BE91L'
|
139
|
+
}]
|
140
|
+
})
|
141
|
+
end
|
142
|
+
|
143
|
+
it "returns a response with the Channel's ID" do
|
144
|
+
response = subject.channels_list
|
145
|
+
|
146
|
+
expect(response['channel'].first['id']).to eq(channel_id)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "with a Slack error" do
|
151
|
+
let(:http_response) do
|
152
|
+
MultiJson.dump({
|
153
|
+
ok: false,
|
154
|
+
error: 'invalid_auth'
|
155
|
+
})
|
156
|
+
end
|
157
|
+
|
158
|
+
it "raises a RuntimeError" do
|
159
|
+
expect { subject.channels_list }.to raise_error(
|
160
|
+
"Slack API call to channels.list returned an error: invalid_auth."
|
161
|
+
)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "with an HTTP error" do
|
166
|
+
let(:http_status) { 422 }
|
167
|
+
let(:http_response) { '' }
|
168
|
+
|
169
|
+
it "raises a RuntimeError" do
|
170
|
+
expect { subject.channels_list }.to raise_error(
|
171
|
+
"Slack API call to channels.list failed with status code 422: ''. Headers: {}"
|
172
|
+
)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#groups_list" do
|
178
|
+
let(:channel_id) { 'G024BE91L' }
|
179
|
+
let(:stubs) do
|
180
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
181
|
+
stub.post('https://slack.com/api/groups.list', token: token) do
|
182
|
+
[http_status, {}, http_response]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "with a successful response" do
|
188
|
+
let(:http_response) do
|
189
|
+
MultiJson.dump({
|
190
|
+
ok: true,
|
191
|
+
groups: [{
|
192
|
+
id: 'G024BE91L'
|
193
|
+
}]
|
194
|
+
})
|
195
|
+
end
|
196
|
+
|
197
|
+
it "returns a response with groupss Channel ID's" do
|
198
|
+
response = subject.groups_list
|
199
|
+
|
200
|
+
expect(response['groups'].first['id']).to eq(channel_id)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "with a Slack error" do
|
205
|
+
let(:http_response) do
|
206
|
+
MultiJson.dump({
|
207
|
+
ok: false,
|
208
|
+
error: 'invalid_auth'
|
209
|
+
})
|
210
|
+
end
|
211
|
+
|
212
|
+
it "raises a RuntimeError" do
|
213
|
+
expect { subject.groups_list }.to raise_error(
|
214
|
+
"Slack API call to groups.list returned an error: invalid_auth."
|
215
|
+
)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe "with an HTTP error" do
|
220
|
+
let(:http_status) { 422 }
|
221
|
+
let(:http_response) { '' }
|
222
|
+
|
223
|
+
it "raises a RuntimeError" do
|
224
|
+
expect { subject.groups_list }.to raise_error(
|
225
|
+
"Slack API call to groups.list failed with status code 422: ''. Headers: {}"
|
226
|
+
)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "#mpim_list" do
|
232
|
+
let(:channel_id) { 'G024BE91L' }
|
233
|
+
let(:stubs) do
|
234
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
235
|
+
stub.post('https://slack.com/api/mpim.list', token: token) do
|
236
|
+
[http_status, {}, http_response]
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "with a successful response" do
|
242
|
+
let(:http_response) do
|
243
|
+
MultiJson.dump({
|
244
|
+
ok: true,
|
245
|
+
groups: [{
|
246
|
+
id: 'G024BE91L'
|
247
|
+
}]
|
248
|
+
})
|
249
|
+
end
|
250
|
+
|
251
|
+
it "returns a response with MPIMs Channel ID's" do
|
252
|
+
response = subject.mpim_list
|
253
|
+
|
254
|
+
expect(response['groups'].first['id']).to eq(channel_id)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "with a Slack error" do
|
259
|
+
let(:http_response) do
|
260
|
+
MultiJson.dump({
|
261
|
+
ok: false,
|
262
|
+
error: 'invalid_auth'
|
263
|
+
})
|
264
|
+
end
|
265
|
+
|
266
|
+
it "raises a RuntimeError" do
|
267
|
+
expect { subject.mpim_list }.to raise_error(
|
268
|
+
"Slack API call to mpim.list returned an error: invalid_auth."
|
269
|
+
)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "with an HTTP error" do
|
274
|
+
let(:http_status) { 422 }
|
275
|
+
let(:http_response) { '' }
|
276
|
+
|
277
|
+
it "raises a RuntimeError" do
|
278
|
+
expect { subject.mpim_list }.to raise_error(
|
279
|
+
"Slack API call to mpim.list failed with status code 422: ''. Headers: {}"
|
280
|
+
)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
describe "#im_list" do
|
286
|
+
let(:channel_id) { 'D024BFF1M' }
|
287
|
+
let(:stubs) do
|
288
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
289
|
+
stub.post('https://slack.com/api/im.list', token: token) do
|
290
|
+
[http_status, {}, http_response]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
describe "with a successful response" do
|
296
|
+
let(:http_response) do
|
297
|
+
MultiJson.dump({
|
298
|
+
ok: true,
|
299
|
+
ims: [{
|
300
|
+
id: 'D024BFF1M'
|
301
|
+
}]
|
302
|
+
})
|
303
|
+
end
|
304
|
+
|
305
|
+
it "returns a response with IMs Channel ID's" do
|
306
|
+
response = subject.im_list
|
307
|
+
|
308
|
+
expect(response['ims'].first['id']).to eq(channel_id)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
describe "with a Slack error" do
|
313
|
+
let(:http_response) do
|
314
|
+
MultiJson.dump({
|
315
|
+
ok: false,
|
316
|
+
error: 'invalid_auth'
|
317
|
+
})
|
318
|
+
end
|
319
|
+
|
320
|
+
it "raises a RuntimeError" do
|
321
|
+
expect { subject.im_list }.to raise_error(
|
322
|
+
"Slack API call to im.list returned an error: invalid_auth."
|
323
|
+
)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
describe "with an HTTP error" do
|
328
|
+
let(:http_status) { 422 }
|
329
|
+
let(:http_response) { '' }
|
330
|
+
|
331
|
+
it "raises a RuntimeError" do
|
332
|
+
expect { subject.im_list }.to raise_error(
|
333
|
+
"Slack API call to im.list failed with status code 422: ''. Headers: {}"
|
64
334
|
)
|
65
335
|
end
|
66
336
|
end
|
@@ -173,7 +443,137 @@ describe Lita::Adapters::Slack::API do
|
|
173
443
|
|
174
444
|
it "raises a RuntimeError" do
|
175
445
|
expect { subject.send_attachments(room, [attachment]) }.to raise_error(
|
176
|
-
"Slack API call to chat.postMessage failed with status code 422."
|
446
|
+
"Slack API call to chat.postMessage failed with status code 422: ''. Headers: {}"
|
447
|
+
)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
describe "#send_messages" do
|
453
|
+
let(:messages) { ["attachment text"] }
|
454
|
+
let(:http_response) { MultiJson.dump({ ok: true }) }
|
455
|
+
let(:room) { "C1234567890" }
|
456
|
+
let(:stubs) do
|
457
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
458
|
+
stub.post(
|
459
|
+
"https://slack.com/api/chat.postMessage",
|
460
|
+
token: token,
|
461
|
+
as_user: true,
|
462
|
+
channel: room,
|
463
|
+
text: messages.join("\n"),
|
464
|
+
) do
|
465
|
+
[http_status, {}, http_response]
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
context "with a simple text attachment" do
|
471
|
+
it "sends the attachment" do
|
472
|
+
response = subject.send_messages(room, messages)
|
473
|
+
|
474
|
+
expect(response['ok']).to be(true)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context "with configuration" do
|
479
|
+
before do
|
480
|
+
allow(config).to receive(:link_names).and_return(true)
|
481
|
+
end
|
482
|
+
|
483
|
+
def stubs(postMessage_options = {})
|
484
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
485
|
+
stub.post(
|
486
|
+
"https://slack.com/api/chat.postMessage",
|
487
|
+
token: token,
|
488
|
+
link_names: 1,
|
489
|
+
as_user: true,
|
490
|
+
channel: room,
|
491
|
+
text: messages.join("\n"),
|
492
|
+
) do
|
493
|
+
[http_status, {}, http_response]
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
it "sends the message with configuration" do
|
499
|
+
response = subject.send_messages(room, messages)
|
500
|
+
|
501
|
+
expect(response['ok']).to be(true)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
context "with a different fallback message" do
|
506
|
+
let(:attachment) do
|
507
|
+
Lita::Adapters::Slack::Attachment.new(attachment_text, fallback: fallback_text)
|
508
|
+
end
|
509
|
+
let(:fallback_text) { "fallback text" }
|
510
|
+
|
511
|
+
it "sends the attachment" do
|
512
|
+
response = subject.send_messages(room, messages)
|
513
|
+
|
514
|
+
expect(response['ok']).to be(true)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
context "with all the valid options" do
|
519
|
+
let(:attachment) do
|
520
|
+
Lita::Adapters::Slack::Attachment.new(attachment_text, common_hash_data)
|
521
|
+
end
|
522
|
+
let(:attachment_hash) do
|
523
|
+
common_hash_data.merge(fallback: attachment_text, text: attachment_text)
|
524
|
+
end
|
525
|
+
let(:common_hash_data) do
|
526
|
+
{
|
527
|
+
author_icon: "http://example.com/author.jpg",
|
528
|
+
author_link: "http://example.com/author",
|
529
|
+
author_name: "author name",
|
530
|
+
color: "#36a64f",
|
531
|
+
fields: [{
|
532
|
+
title: "priority",
|
533
|
+
value: "high",
|
534
|
+
short: true,
|
535
|
+
}, {
|
536
|
+
title: "super long field title",
|
537
|
+
value: "super long field value",
|
538
|
+
short: false,
|
539
|
+
}],
|
540
|
+
image_url: "http://example.com/image.jpg",
|
541
|
+
pretext: "pretext",
|
542
|
+
thumb_url: "http://example.com/thumb.jpg",
|
543
|
+
title: "title",
|
544
|
+
title_link: "http://example.com/title",
|
545
|
+
}
|
546
|
+
end
|
547
|
+
|
548
|
+
it "sends the attachment" do
|
549
|
+
response = subject.send_messages(room, messages)
|
550
|
+
|
551
|
+
expect(response['ok']).to be(true)
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
context "with a Slack error" do
|
556
|
+
let(:http_response) do
|
557
|
+
MultiJson.dump({
|
558
|
+
ok: false,
|
559
|
+
error: 'invalid_auth'
|
560
|
+
})
|
561
|
+
end
|
562
|
+
|
563
|
+
it "raises a RuntimeError" do
|
564
|
+
expect { subject.send_messages(room, messages) }.to raise_error(
|
565
|
+
"Slack API call to chat.postMessage returned an error: invalid_auth."
|
566
|
+
)
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
context "with an HTTP error" do
|
571
|
+
let(:http_status) { 422 }
|
572
|
+
let(:http_response) { '' }
|
573
|
+
|
574
|
+
it "raises a RuntimeError" do
|
575
|
+
expect { subject.send_messages(room, messages) }.to raise_error(
|
576
|
+
"Slack API call to chat.postMessage failed with status code 422: ''. Headers: {}"
|
177
577
|
)
|
178
578
|
end
|
179
579
|
end
|
@@ -231,7 +631,7 @@ describe Lita::Adapters::Slack::API do
|
|
231
631
|
|
232
632
|
it "raises a RuntimeError" do
|
233
633
|
expect { subject.set_topic(channel, topic) }.to raise_error(
|
234
|
-
"Slack API call to channels.setTopic failed with status code 422."
|
634
|
+
"Slack API call to channels.setTopic failed with status code 422: ''. Headers: {}"
|
235
635
|
)
|
236
636
|
end
|
237
637
|
end
|
@@ -30,10 +30,11 @@ describe Lita::Adapters::Slack::MessageHandler, lita: true do
|
|
30
30
|
"type" => "message",
|
31
31
|
"channel" => "C2147483705",
|
32
32
|
"user" => "U023BECGF",
|
33
|
-
"text" => "Hello"
|
33
|
+
"text" => "Hello",
|
34
|
+
"ts" => "1234.5678"
|
34
35
|
}
|
35
36
|
end
|
36
|
-
let(:message) { instance_double('Lita::Message', command!: false) }
|
37
|
+
let(:message) { instance_double('Lita::Message', command!: false, extensions: {}) }
|
37
38
|
let(:source) { instance_double('Lita::Source', private_message?: false) }
|
38
39
|
let(:user) { instance_double('Lita::User', id: 'U023BECGF') }
|
39
40
|
|
@@ -49,8 +50,12 @@ describe Lita::Adapters::Slack::MessageHandler, lita: true do
|
|
49
50
|
|
50
51
|
it "dispatches the message to Lita" do
|
51
52
|
expect(robot).to receive(:receive).with(message)
|
53
|
+
subject.handle
|
54
|
+
end
|
52
55
|
|
56
|
+
it "saves the timestamp in extensions" do
|
53
57
|
subject.handle
|
58
|
+
expect(message.extensions[:slack][:timestamp]).to eq("1234.5678")
|
54
59
|
end
|
55
60
|
|
56
61
|
context "when the message is a direct message" do
|
@@ -468,19 +473,27 @@ describe Lita::Adapters::Slack::MessageHandler, lita: true do
|
|
468
473
|
end
|
469
474
|
end
|
470
475
|
|
471
|
-
context "with a message from
|
476
|
+
context "with a message from slackbot" do
|
472
477
|
let(:data) do
|
473
478
|
{
|
474
479
|
"type" => "message",
|
475
|
-
"
|
480
|
+
"user" => "USLACKBOT"
|
476
481
|
}
|
477
482
|
end
|
478
|
-
let(:user) { instance_double('Lita::User', id: 12345) }
|
479
483
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
+
it "does not dispatch the message to Lita" do
|
485
|
+
expect(robot).not_to receive(:receive)
|
486
|
+
|
487
|
+
subject.handle
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
context "with a message from the robot itself" do
|
492
|
+
let(:data) do
|
493
|
+
{
|
494
|
+
"type" => "message",
|
495
|
+
"user" => robot_id
|
496
|
+
}
|
484
497
|
end
|
485
498
|
|
486
499
|
it "does not dispatch the message to Lita" do
|
@@ -578,6 +591,54 @@ describe Lita::Adapters::Slack::MessageHandler, lita: true do
|
|
578
591
|
end
|
579
592
|
end
|
580
593
|
|
594
|
+
context "with a reaction_added message" do
|
595
|
+
let(:data) do
|
596
|
+
{
|
597
|
+
"type" => "reaction_added",
|
598
|
+
"user" => "U023BECGF",
|
599
|
+
"item"=>{"type"=>"message", "channel"=>"C2147483705", "ts"=>"1234567.000008"},
|
600
|
+
"reaction"=>"+1",
|
601
|
+
"event_ts"=>"1234.5678"
|
602
|
+
}
|
603
|
+
end
|
604
|
+
let(:user) { instance_double('Lita::User', id: 'U023BECGF') }
|
605
|
+
let(:payload) { {user: user, name: data["reaction"], item: data["item"], event_ts: data["event_ts"]} }
|
606
|
+
|
607
|
+
before do
|
608
|
+
allow(Lita::User).to receive(:find_by_id).and_return(user)
|
609
|
+
allow(robot).to receive(:trigger).with(:slack_reaction_added, payload)
|
610
|
+
end
|
611
|
+
|
612
|
+
it "triggers the slack_reaction_added event with the correct payload" do
|
613
|
+
expect(robot).to receive(:trigger).with(:slack_reaction_added, payload)
|
614
|
+
subject.handle
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
context "with a reaction_removed message" do
|
619
|
+
let(:data) do
|
620
|
+
{
|
621
|
+
"type" => "reaction_removed",
|
622
|
+
"user" => "U023BECGF",
|
623
|
+
"item"=>{"type"=>"message", "channel"=>"C2147483705", "ts"=>"1234567.000008"},
|
624
|
+
"reaction"=>"+1",
|
625
|
+
"event_ts"=>"1234.5678"
|
626
|
+
}
|
627
|
+
end
|
628
|
+
let(:user) { instance_double('Lita::User', id: 'U023BECGF') }
|
629
|
+
let(:payload) { {user: user, name: data["reaction"], item: data["item"], event_ts: data["event_ts"]} }
|
630
|
+
|
631
|
+
before do
|
632
|
+
allow(Lita::User).to receive(:find_by_id).and_return(user)
|
633
|
+
allow(robot).to receive(:trigger).with(:slack_reaction_removed, payload)
|
634
|
+
end
|
635
|
+
|
636
|
+
it "triggers the slack_reaction_removed event with the correct payload" do
|
637
|
+
expect(robot).to receive(:trigger).with(:slack_reaction_removed, payload)
|
638
|
+
subject.handle
|
639
|
+
end
|
640
|
+
end
|
641
|
+
|
581
642
|
context "with an unknown message" do
|
582
643
|
let(:data) { { "type" => "???" } }
|
583
644
|
|
@@ -27,6 +27,12 @@ describe Lita::Adapters::Slack, lita: true do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
describe "#mention_format" do
|
31
|
+
it "returns the name prefixed with an @" do
|
32
|
+
expect(subject.mention_format("carl")).to eq("@carl")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
30
36
|
describe "#run" do
|
31
37
|
it "starts the RTM connection" do
|
32
38
|
expect(rtm_connection).to receive(:run)
|
@@ -42,6 +48,74 @@ describe Lita::Adapters::Slack, lita: true do
|
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
51
|
+
describe "#roster" do
|
52
|
+
describe "via the Web API, retrieving the roster for a channel" do
|
53
|
+
let(:room_source) { Lita::Source.new(room: 'C024BE91L') }
|
54
|
+
let(:response) do
|
55
|
+
{
|
56
|
+
ok: true,
|
57
|
+
channel: {
|
58
|
+
members: ['C024BE91L']
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
let(:api) { instance_double('Lita::Adapters::Slack::API') }
|
63
|
+
|
64
|
+
before do
|
65
|
+
allow(Lita::Adapters::Slack::API).to receive(:new).with(subject.config).and_return(api)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns UID(s)" do
|
69
|
+
expect(subject).to receive(:channel_roster).with(room_source.room_object.id, api)
|
70
|
+
|
71
|
+
subject.roster(room_source.room_object)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "via the Web API, retrieving the roster for a group/mpim channel" do
|
76
|
+
let(:room_source) { Lita::Source.new(room: 'G024BE91L') }
|
77
|
+
let(:response) do
|
78
|
+
{
|
79
|
+
ok: true,
|
80
|
+
groups: [{ id: 'G024BE91L' }]
|
81
|
+
}
|
82
|
+
end
|
83
|
+
let(:api) { instance_double('Lita::Adapters::Slack::API') }
|
84
|
+
|
85
|
+
before do
|
86
|
+
allow(Lita::Adapters::Slack::API).to receive(:new).with(subject.config).and_return(api)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns UID(s)" do
|
90
|
+
expect(subject).to receive(:group_roster).with(room_source.room_object.id, api).and_return(%q{})
|
91
|
+
expect(subject).to receive(:mpim_roster).with(room_source.room_object.id, api).and_return(%q{G024BE91L})
|
92
|
+
|
93
|
+
subject.roster(room_source.room_object)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "via the Web API, retrieving the roster for an im channel" do
|
98
|
+
let(:room_source) { Lita::Source.new(room: 'D024BFF1M') }
|
99
|
+
let(:response) do
|
100
|
+
{
|
101
|
+
ok: true,
|
102
|
+
ims: [{ id: 'D024BFF1M' }]
|
103
|
+
}
|
104
|
+
end
|
105
|
+
let(:api) { instance_double('Lita::Adapters::Slack::API') }
|
106
|
+
|
107
|
+
before do
|
108
|
+
allow(Lita::Adapters::Slack::API).to receive(:new).with(subject.config).and_return(api)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "returns UID" do
|
112
|
+
expect(subject).to receive(:im_roster).with(room_source.room_object.id, api)
|
113
|
+
|
114
|
+
subject.roster(room_source.room_object)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
45
119
|
describe "#send_messages" do
|
46
120
|
let(:room_source) { Lita::Source.new(room: 'C024BE91L') }
|
47
121
|
let(:user) { Lita::User.new('U023BECGF') }
|
@@ -50,32 +124,19 @@ describe Lita::Adapters::Slack, lita: true do
|
|
50
124
|
Lita::Source.new(room: 'C024BE91L', user: user, private_message: true)
|
51
125
|
end
|
52
126
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
subject.run
|
57
|
-
|
58
|
-
subject.send_messages(room_source, ['foo'])
|
59
|
-
end
|
60
|
-
|
61
|
-
it "sends messages to users" do
|
62
|
-
allow(rtm_connection).to receive(:im_for).with(user.id).and_return('D024BFF1M')
|
63
|
-
|
64
|
-
expect(rtm_connection).to receive(:send_messages).with('D024BFF1M', ['foo'])
|
127
|
+
describe "via the Web API" do
|
128
|
+
let(:api) { instance_double('Lita::Adapters::Slack::API') }
|
65
129
|
|
66
|
-
|
130
|
+
before do
|
131
|
+
allow(Lita::Adapters::Slack::API).to receive(:new).with(subject.config).and_return(api)
|
132
|
+
end
|
67
133
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
it "sends messages to users when the source is marked as a private message" do
|
72
|
-
allow(rtm_connection).to receive(:im_for).with(user.id).and_return('D024BFF1M')
|
73
|
-
|
74
|
-
expect(rtm_connection).to receive(:send_messages).with('D024BFF1M', ['foo'])
|
75
|
-
|
76
|
-
subject.run
|
134
|
+
it "does not send via the RTM api" do
|
135
|
+
expect(rtm_connection).to_not receive(:send_messages)
|
136
|
+
expect(api).to receive(:send_messages).with(room_source.room, ['foo'])
|
77
137
|
|
78
|
-
|
138
|
+
subject.send_messages(room_source, ['foo'])
|
139
|
+
end
|
79
140
|
end
|
80
141
|
end
|
81
142
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lita-slack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken J.
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -59,14 +59,14 @@ dependencies:
|
|
59
59
|
requirements:
|
60
60
|
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 4.
|
62
|
+
version: 4.7.1
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 4.
|
69
|
+
version: 4.7.1
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: multi_json
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,14 +157,14 @@ dependencies:
|
|
157
157
|
requirements:
|
158
158
|
- - ">="
|
159
159
|
- !ruby/object:Gem::Version
|
160
|
-
version:
|
160
|
+
version: 0.9.2
|
161
161
|
type: :development
|
162
162
|
prerelease: false
|
163
163
|
version_requirements: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
165
|
- - ">="
|
166
166
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
167
|
+
version: 0.9.2
|
168
168
|
- !ruby/object:Gem::Dependency
|
169
169
|
name: coveralls
|
170
170
|
requirement: !ruby/object:Gem::Requirement
|
@@ -244,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
244
244
|
version: '0'
|
245
245
|
requirements: []
|
246
246
|
rubyforge_project:
|
247
|
-
rubygems_version: 2.
|
247
|
+
rubygems_version: 2.5.1
|
248
248
|
signing_key:
|
249
249
|
specification_version: 4
|
250
250
|
summary: Lita adapter for Slack.
|
@@ -262,4 +262,3 @@ test_files:
|
|
262
262
|
- spec/lita/adapters/slack/user_creator_spec.rb
|
263
263
|
- spec/lita/adapters/slack_spec.rb
|
264
264
|
- spec/spec_helper.rb
|
265
|
-
has_rdoc:
|