lita-slack 1.5.0 → 1.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c3600cd068e9891e914063b341e384e1e66c117
4
- data.tar.gz: 0dcbfb0f922578b75ec22a835d7d77e7072c22fd
3
+ metadata.gz: 263b8f5a62893a0ca957dbbf02925525e6c4aef0
4
+ data.tar.gz: 8a8d23b254f44196cb4c332c81b445fbac276df0
5
5
  SHA512:
6
- metadata.gz: 7b285b424783c62984f4f31b1dec16937c6ea8807f74b428fd769b83d60dc5ca2793c695ed4ae79efb52c0079c9ddfb813782379aa72c1ebf325a73f3eb17a9b
7
- data.tar.gz: 67da2107713a27eab01d59b19c9256593778341b437c7aeb6f6f832f05eafb359038aa36466fbccd0b5841481712048a4b7590aabd26824b1fc954bb8390e512
6
+ metadata.gz: 09b05e48245ee0966a4a211a6672df6d8042e5a5af27f74c88ea91ad568fe865e0fce44e709e32a5f18afca9198c15826a2c02b3ba60cf423448923e078486ee
7
+ data.tar.gz: 8408c30ff79ef6b025e7e94c29178538b84d01f850ef24e6e41f6ee365b59cf6b3e5d1945605f12efa113b0669422c6e3c67fdef105f6d4a69575ed21c2faf8f
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
4
  - 2.0.0
4
5
  script: bundle exec rake
data/README.md CHANGED
@@ -50,6 +50,14 @@ Lita will join your default channel after initial setup. To have it join additio
50
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
51
  * `: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.
52
52
 
53
+ ## Chat service API
54
+
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::Adapters::ChatService` for details about the provided methods.
56
+
57
+ ## API documentation
58
+
59
+ The API documentation, useful for plugin authors, can be found for the latest gem release on [RubyDoc.info](http://www.rubydoc.info/gems/lita-slack)
60
+
53
61
  ## License
54
62
 
55
63
  [MIT](http://opensource.org/licenses/MIT)
@@ -1,12 +1,20 @@
1
+ require 'lita/adapters/slack/chat_service'
1
2
  require 'lita/adapters/slack/rtm_connection'
2
3
 
3
4
  module Lita
4
5
  module Adapters
6
+ # A Slack adapter for Lita.
7
+ # @api private
5
8
  class Slack < Adapter
6
9
  # Required configuration attributes.
7
10
  config :token, type: String, required: true
8
11
  config :proxy, type: String
9
12
 
13
+ # Provides an object for Slack-specific features.
14
+ def chat_service
15
+ ChatService.new(config)
16
+ end
17
+
10
18
  # Starts the connection.
11
19
  def run
12
20
  return if rtm_connection
@@ -8,6 +8,7 @@ require 'lita/adapters/slack/slack_channel'
8
8
  module Lita
9
9
  module Adapters
10
10
  class Slack < Adapter
11
+ # @api private
11
12
  class API
12
13
  def initialize(config, stubs = nil)
13
14
  @config = config
@@ -20,6 +21,15 @@ module Lita
20
21
  SlackIM.new(response_data["channel"]["id"], user_id)
21
22
  end
22
23
 
24
+ def send_attachments(room_or_user, attachments)
25
+ call_api(
26
+ "chat.postMessage",
27
+ as_user: true,
28
+ channel: room_or_user.id,
29
+ attachments: MultiJson.dump(attachments.map(&:to_hash)),
30
+ )
31
+ end
32
+
23
33
  def set_topic(channel, topic)
24
34
  call_api("channels.setTopic", channel: channel, topic: topic)
25
35
  end
@@ -0,0 +1,36 @@
1
+ module Lita
2
+ module Adapters
3
+ class Slack < Adapter
4
+ # A Slack attachment object.
5
+ # @api public
6
+ # @see https://api.slack.com/docs/attachments
7
+ # @since 1.6.0
8
+ class Attachment
9
+ # @param text [String] The main text of the message.
10
+ # @param options [Hash] Keyword arguments supporting all the option supported by Slack's
11
+ # attachment API. These options will be passed to Slack as provided, with the exception
12
+ # that the +:fallback+ option defaults to the value of +text+ (the first argument to this
13
+ # method) and any value specified for the +:text+ option will be overwritten by the
14
+ # explicit +text+ argument.
15
+ def initialize(text, **options)
16
+ self.text = text
17
+ self.options = options
18
+ end
19
+
20
+ # Converts the attachment into a hash, suitable for being sent to the Slack API.
21
+ # @return [Hash] The converted hash.
22
+ def to_hash
23
+ options.merge({
24
+ fallback: options[:fallback] || text,
25
+ text: text,
26
+ })
27
+ end
28
+
29
+ private
30
+
31
+ attr_accessor :options
32
+ attr_accessor :text
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,29 @@
1
+ require "lita/adapters/slack/attachment"
2
+
3
+ module Lita
4
+ module Adapters
5
+ class Slack < Adapter
6
+ # Slack-specific features made available to +Lita::Robot+.
7
+ # @api public
8
+ # @since 1.6.0
9
+ class ChatService
10
+ attr_accessor :api
11
+
12
+ # @param config [Lita::Configuration] The adapter's configuration data.
13
+ def initialize(config)
14
+ self.api = API.new(config)
15
+ end
16
+
17
+ # @param target [Lita::Room, Lita::User] A room or user object indicating where the
18
+ # attachment should be sent.
19
+ # @param attachments [Attachment, Array<Attachment>] An {Attachment} or array of
20
+ # {Attachment}s to send.
21
+ # @return [void]
22
+ def send_attachments(target, attachments)
23
+ api.send_attachments(target, Array(attachments))
24
+ end
25
+ alias_method :send_attachment, :send_attachments
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,6 +3,7 @@ require 'eventmachine'
3
3
  module Lita
4
4
  module Adapters
5
5
  class Slack < Adapter
6
+ # @api private
6
7
  class EventLoop
7
8
  class << self
8
9
  def defer
@@ -1,6 +1,7 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # @api private
4
5
  class IMMapping
5
6
  def initialize(api, ims)
6
7
  @api = api
@@ -1,6 +1,7 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # @api private
4
5
  class MessageHandler
5
6
  def initialize(robot, robot_id, data)
6
7
  @robot = robot
@@ -70,7 +71,7 @@ module Lita
70
71
  else
71
72
  user = User.find_by_id(link)
72
73
  if user
73
- "@#{user.name}"
74
+ "@#{user.mention_name}"
74
75
  else
75
76
  "@#{link}"
76
77
  end
@@ -1,6 +1,7 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # @api private
4
5
  class RoomCreator
5
6
  class << self
6
7
  def create_room(channel, robot)
@@ -11,6 +11,7 @@ require 'lita/adapters/slack/user_creator'
11
11
  module Lita
12
12
  module Adapters
13
13
  class Slack < Adapter
14
+ # @api private
14
15
  class RTMConnection
15
16
  MAX_MESSAGE_BYTES = 16_000
16
17
 
@@ -1,8 +1,11 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # A struct representing a Slack channel, group, or IM.
5
+ # @api public
4
6
  class SlackChannel
5
7
  class << self
8
+ # @api private
6
9
  def from_data(channel_data)
7
10
  new(
8
11
  channel_data['id'],
@@ -13,15 +16,21 @@ module Lita
13
16
  )
14
17
  end
15
18
 
19
+ # @api private
16
20
  def from_data_array(channels_data)
17
21
  channels_data.map { |channel_data| from_data(channel_data) }
18
22
  end
19
23
  end
20
24
 
25
+ # @return [String] The channel's unique ID.
21
26
  attr_reader :id
27
+ # @return [String] The human-readable name for the channel.
22
28
  attr_reader :name
29
+ # @return [String] A timestamp indicating when the channel was created.
23
30
  attr_reader :created
31
+ # @return [String] The unique ID of the user who created the channel.
24
32
  attr_reader :creator
33
+ # @return [Hash] The raw channel data received from Slack, including many more fields.
25
34
  attr_reader :raw_data
26
35
 
27
36
  def initialize(id, name, created, creator, raw_data)
@@ -34,4 +43,4 @@ module Lita
34
43
  end
35
44
  end
36
45
  end
37
- end
46
+ end
@@ -1,6 +1,7 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # @api private
4
5
  class SlackIM
5
6
  class << self
6
7
  def from_data_array(ims_data)
@@ -1,8 +1,11 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # A struct representing a Slack user.
5
+ # @api public
4
6
  class SlackUser
5
7
  class << self
8
+ # @api private
6
9
  def from_data(user_data)
7
10
  new(
8
11
  user_data['id'],
@@ -12,14 +15,19 @@ module Lita
12
15
  )
13
16
  end
14
17
 
18
+ # @api private
15
19
  def from_data_array(users_data)
16
20
  users_data.map { |user_data| from_data(user_data) }
17
21
  end
18
22
  end
19
23
 
24
+ # @return [String] The user's unique ID.
20
25
  attr_reader :id
26
+ # @return [String] The user's mention name, e.g. @alice.
21
27
  attr_reader :name
28
+ # @return [String] The user's display name, e.g. Alice Bobhart
22
29
  attr_reader :real_name
30
+ # @return [Hash] The raw user data received from Slack, including many more fields.
23
31
  attr_reader :raw_data
24
32
 
25
33
  def initialize(id, name, real_name, raw_data)
@@ -1,5 +1,6 @@
1
1
  module Lita
2
2
  module Adapters
3
+ # @api private
3
4
  class Slack < Adapter
4
5
  TeamData = Struct.new(:ims, :self, :users, :channels, :websocket_url)
5
6
  end
@@ -1,6 +1,7 @@
1
1
  module Lita
2
2
  module Adapters
3
3
  class Slack < Adapter
4
+ # @api private
4
5
  class UserCreator
5
6
  class << self
6
7
  def create_user(slack_user, robot, robot_id)
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-slack"
3
- spec.version = "1.5.0"
3
+ spec.version = "1.6.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,10 +17,11 @@ 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.4.2"
20
+ spec.add_runtime_dependency "lita", ">= 4.6.0"
21
21
  spec.add_runtime_dependency "multi_json"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "pry-byebug"
24
25
  spec.add_development_dependency "rack-test"
25
26
  spec.add_development_dependency "rake"
26
27
  spec.add_development_dependency "rspec", ">= 3.0.0"
@@ -66,6 +66,119 @@ describe Lita::Adapters::Slack::API do
66
66
  end
67
67
  end
68
68
 
69
+ describe "#send_attachments" do
70
+ let(:attachment) do
71
+ Lita::Adapters::Slack::Attachment.new(attachment_text)
72
+ end
73
+ let(:attachment_text) { "attachment text" }
74
+ let(:attachment_hash) do
75
+ {
76
+ fallback: fallback_text,
77
+ text: attachment_text,
78
+ }
79
+ end
80
+ let(:fallback_text) { attachment_text }
81
+ let(:http_response) { MultiJson.dump({ ok: true }) }
82
+ let(:room) { Lita::Room.new("C1234567890") }
83
+ let(:stubs) do
84
+ Faraday::Adapter::Test::Stubs.new do |stub|
85
+ stub.post(
86
+ "https://slack.com/api/chat.postMessage",
87
+ token: token,
88
+ as_user: true,
89
+ channel: room.id,
90
+ attachments: MultiJson.dump([attachment_hash]),
91
+ ) do
92
+ [http_status, {}, http_response]
93
+ end
94
+ end
95
+ end
96
+
97
+ context "with a simple text attachment" do
98
+ it "sends the attachment" do
99
+ response = subject.send_attachments(room, [attachment])
100
+
101
+ expect(response['ok']).to be(true)
102
+ end
103
+ end
104
+
105
+ context "with a different fallback message" do
106
+ let(:attachment) do
107
+ Lita::Adapters::Slack::Attachment.new(attachment_text, fallback: fallback_text)
108
+ end
109
+ let(:fallback_text) { "fallback text" }
110
+
111
+ it "sends the attachment" do
112
+ response = subject.send_attachments(room, [attachment])
113
+
114
+ expect(response['ok']).to be(true)
115
+ end
116
+ end
117
+
118
+ context "with all the valid options" do
119
+ let(:attachment) do
120
+ Lita::Adapters::Slack::Attachment.new(attachment_text, common_hash_data)
121
+ end
122
+ let(:attachment_hash) do
123
+ common_hash_data.merge(fallback: attachment_text, text: attachment_text)
124
+ end
125
+ let(:common_hash_data) do
126
+ {
127
+ author_icon: "http://example.com/author.jpg",
128
+ author_link: "http://example.com/author",
129
+ author_name: "author name",
130
+ color: "#36a64f",
131
+ fields: [{
132
+ title: "priority",
133
+ value: "high",
134
+ short: true,
135
+ }, {
136
+ title: "super long field title",
137
+ value: "super long field value",
138
+ short: false,
139
+ }],
140
+ image_url: "http://example.com/image.jpg",
141
+ pretext: "pretext",
142
+ thumb_url: "http://example.com/thumb.jpg",
143
+ title: "title",
144
+ title_link: "http://example.com/title",
145
+ }
146
+ end
147
+
148
+ it "sends the attachment" do
149
+ response = subject.send_attachments(room, [attachment])
150
+
151
+ expect(response['ok']).to be(true)
152
+ end
153
+ end
154
+
155
+ context "with a Slack error" do
156
+ let(:http_response) do
157
+ MultiJson.dump({
158
+ ok: false,
159
+ error: 'invalid_auth'
160
+ })
161
+ end
162
+
163
+ it "raises a RuntimeError" do
164
+ expect { subject.send_attachments(room, [attachment]) }.to raise_error(
165
+ "Slack API call to chat.postMessage returned an error: invalid_auth."
166
+ )
167
+ end
168
+ end
169
+
170
+ context "with an HTTP error" do
171
+ let(:http_status) { 422 }
172
+ let(:http_response) { '' }
173
+
174
+ it "raises a RuntimeError" do
175
+ expect { subject.send_attachments(room, [attachment]) }.to raise_error(
176
+ "Slack API call to chat.postMessage failed with status code 422."
177
+ )
178
+ end
179
+ end
180
+ end
181
+
69
182
  describe "#set_topic" do
70
183
  let(:channel) { 'C1234567890' }
71
184
  let(:topic) { 'Topic' }
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe Lita::Adapters::Slack::ChatService, lita: true do
4
+ subject { described_class.new(adapter.config) }
5
+
6
+ let(:adapter) { Lita::Adapters::Slack.new(robot) }
7
+ let(:robot) { Lita::Robot.new(registry) }
8
+ let(:room) { Lita::Room.new("C2147483705") }
9
+
10
+ before do
11
+ registry.register_adapter(:slack, Lita::Adapters::Slack)
12
+ end
13
+
14
+ describe "#send_attachments" do
15
+ let(:attachment) { Lita::Adapters::Slack::Attachment.new("attachment text") }
16
+
17
+ it "can send a simple text attachment" do
18
+ expect(subject.api).to receive(:send_attachments).with(room, [attachment])
19
+
20
+ subject.send_attachments(room, attachment)
21
+ end
22
+
23
+ it "is aliased as send_attachment" do
24
+ expect(subject.api).to receive(:send_attachments).with(room, [attachment])
25
+
26
+ subject.send_attachment(room, attachment)
27
+ end
28
+ end
29
+ end
@@ -193,7 +193,7 @@ describe Lita::Adapters::Slack::MessageHandler, lita: true do
193
193
 
194
194
  end
195
195
 
196
- context "changes <@123> links to @name" do
196
+ context "changes <@123> links to @label" do
197
197
  let(:data) do
198
198
  {
199
199
  "type" => "message",
@@ -204,7 +204,7 @@ describe Lita::Adapters::Slack::MessageHandler, lita: true do
204
204
  it "removes formatting" do
205
205
  expect(Lita::Message).to receive(:new).with(
206
206
  robot,
207
- "foo @name bar",
207
+ "foo @label bar",
208
208
  source
209
209
  ).and_return(message)
210
210
 
@@ -21,6 +21,12 @@ describe Lita::Adapters::Slack, lita: true do
21
21
  expect(Lita.adapters[:slack]).to eql(described_class)
22
22
  end
23
23
 
24
+ describe "#chat_service" do
25
+ it "returns an object with Slack-specific methods" do
26
+ expect(subject.chat_service).to be_an_instance_of(described_class::ChatService)
27
+ end
28
+ end
29
+
24
30
  describe "#run" do
25
31
  it "starts the RTM connection" do
26
32
  expect(rtm_connection).to receive(:run)
@@ -9,6 +9,8 @@ SimpleCov.start { add_filter "/spec/" }
9
9
  require "lita-slack"
10
10
  require "lita/rspec"
11
11
 
12
+ require "pry"
13
+
12
14
  Lita.version_3_compatibility_mode = false
13
15
 
14
16
  RSpec.configure do |config|
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.5.0
4
+ version: 1.6.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: 2015-06-12 00:00:00.000000000 Z
12
+ date: 2015-08-29 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.4.2
62
+ version: 4.6.0
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.4.2
69
+ version: 4.6.0
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: multi_json
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -95,6 +95,20 @@ dependencies:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
97
  version: '1.3'
98
+ - !ruby/object:Gem::Dependency
99
+ name: pry-byebug
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
98
112
  - !ruby/object:Gem::Dependency
99
113
  name: rack-test
100
114
  requirement: !ruby/object:Gem::Requirement
@@ -182,6 +196,8 @@ files:
182
196
  - lib/lita-slack.rb
183
197
  - lib/lita/adapters/slack.rb
184
198
  - lib/lita/adapters/slack/api.rb
199
+ - lib/lita/adapters/slack/attachment.rb
200
+ - lib/lita/adapters/slack/chat_service.rb
185
201
  - lib/lita/adapters/slack/event_loop.rb
186
202
  - lib/lita/adapters/slack/im_mapping.rb
187
203
  - lib/lita/adapters/slack/message_handler.rb
@@ -195,6 +211,7 @@ files:
195
211
  - lita-slack.gemspec
196
212
  - locales/en.yml
197
213
  - spec/lita/adapters/slack/api_spec.rb
214
+ - spec/lita/adapters/slack/chat_service_spec.rb
198
215
  - spec/lita/adapters/slack/event_loop_spec.rb
199
216
  - spec/lita/adapters/slack/im_mapping_spec.rb
200
217
  - spec/lita/adapters/slack/message_handler_spec.rb
@@ -227,12 +244,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
244
  version: '0'
228
245
  requirements: []
229
246
  rubyforge_project:
230
- rubygems_version: 2.4.5
247
+ rubygems_version: 2.4.5.1
231
248
  signing_key:
232
249
  specification_version: 4
233
250
  summary: Lita adapter for Slack.
234
251
  test_files:
235
252
  - spec/lita/adapters/slack/api_spec.rb
253
+ - spec/lita/adapters/slack/chat_service_spec.rb
236
254
  - spec/lita/adapters/slack/event_loop_spec.rb
237
255
  - spec/lita/adapters/slack/im_mapping_spec.rb
238
256
  - spec/lita/adapters/slack/message_handler_spec.rb