diff --git a/README.md b/README.md index 3cc6ed2..cdebfcb 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Lita.configure do |config| config.robot.adapter = :slack config.robot.admins = ["U012A3BCD"] config.adapters.slack.token = "abcd-1234567890-hWYd21AmMH2UHAkx29vb5c1Y" + config.adapters.slack.parse = "full" # See https://api.slack.com/docs/formatting#parsing_modes end ``` diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 56eb82b..fb227be 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -9,6 +9,7 @@ class Slack < Adapter # Required configuration attributes. config :token, type: String, required: true config :proxy, type: String + config :parse, type: String # Provides an object for Slack-specific features. def chat_service @@ -28,9 +29,8 @@ def run end def send_messages(target, strings) - return unless rtm_connection - - rtm_connection.send_messages(channel_for(target), strings) + api = API.new(config) + api.send_messages(channel_for(target), strings) end def set_topic(target, topic) diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index 6fd829a..3e90fa0 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -30,6 +30,16 @@ def send_attachments(room_or_user, attachments) ) end + def send_messages(channel_id, messages) + call_api( + "chat.postMessage", + as_user: true, + channel: channel_id, + text: messages.join("\n"), + parse: config.parse, + ) + end + def set_topic(channel, topic) call_api("channels.setTopic", channel: channel, topic: topic) end diff --git a/spec/lita/adapters/slack/api_spec.rb b/spec/lita/adapters/slack/api_spec.rb index c7c8ae8..cfac3f0 100644 --- a/spec/lita/adapters/slack/api_spec.rb +++ b/spec/lita/adapters/slack/api_spec.rb @@ -179,6 +179,110 @@ end end + describe "#send_messages" do + let(:messages) { ["attachment text"] } + let(:http_response) { MultiJson.dump({ ok: true }) } + let(:room) { "C1234567890" } + let(:stubs) do + Faraday::Adapter::Test::Stubs.new do |stub| + stub.post( + "https://slack.com/api/chat.postMessage", + token: token, + as_user: true, + channel: room, + text: messages.join("\n"), + parse: nil, + ) do + [http_status, {}, http_response] + end + end + end + + context "with a simple text attachment" do + it "sends the attachment" do + response = subject.send_messages(room, messages) + + expect(response['ok']).to be(true) + end + end + + context "with a different fallback message" do + let(:attachment) do + Lita::Adapters::Slack::Attachment.new(attachment_text, fallback: fallback_text) + end + let(:fallback_text) { "fallback text" } + + it "sends the attachment" do + response = subject.send_messages(room, messages) + + expect(response['ok']).to be(true) + end + end + + context "with all the valid options" do + let(:attachment) do + Lita::Adapters::Slack::Attachment.new(attachment_text, common_hash_data) + end + let(:attachment_hash) do + common_hash_data.merge(fallback: attachment_text, text: attachment_text) + end + let(:common_hash_data) do + { + author_icon: "http://example.com/author.jpg", + author_link: "http://example.com/author", + author_name: "author name", + color: "#36a64f", + fields: [{ + title: "priority", + value: "high", + short: true, + }, { + title: "super long field title", + value: "super long field value", + short: false, + }], + image_url: "http://example.com/image.jpg", + pretext: "pretext", + thumb_url: "http://example.com/thumb.jpg", + title: "title", + title_link: "http://example.com/title", + } + end + + it "sends the attachment" do + response = subject.send_messages(room, messages) + + expect(response['ok']).to be(true) + end + end + + context "with a Slack error" do + let(:http_response) do + MultiJson.dump({ + ok: false, + error: 'invalid_auth' + }) + end + + it "raises a RuntimeError" do + expect { subject.send_messages(room, messages) }.to raise_error( + "Slack API call to chat.postMessage returned an error: invalid_auth." + ) + end + end + + context "with an HTTP error" do + let(:http_status) { 422 } + let(:http_response) { '' } + + it "raises a RuntimeError" do + expect { subject.send_messages(room, messages) }.to raise_error( + "Slack API call to chat.postMessage failed with status code 422." + ) + end + end + end + describe "#set_topic" do let(:channel) { 'C1234567890' } let(:topic) { 'Topic' } diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index d051633..f4e256c 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -1,5 +1,5 @@ -require "spec_helper" +require "spec_helper" describe Lita::Adapters::Slack, lita: true do subject { described_class.new(robot) } @@ -56,32 +56,19 @@ Lita::Source.new(room: 'C024BE91L', user: user, private_message: true) end - it "sends messages to rooms" do - expect(rtm_connection).to receive(:send_messages).with(room_source.room, ['foo']) - - subject.run - - subject.send_messages(room_source, ['foo']) - end - - it "sends messages to users" do - allow(rtm_connection).to receive(:im_for).with(user.id).and_return('D024BFF1M') + describe "via the Web API" do + let(:api) { instance_double('Lita::Adapters::Slack::API') } - expect(rtm_connection).to receive(:send_messages).with('D024BFF1M', ['foo']) + before do + allow(Lita::Adapters::Slack::API).to receive(:new).with(subject.config).and_return(api) + end - subject.run - - subject.send_messages(user_source, ['foo']) - end - - it "sends messages to users when the source is marked as a private message" do - allow(rtm_connection).to receive(:im_for).with(user.id).and_return('D024BFF1M') - - expect(rtm_connection).to receive(:send_messages).with('D024BFF1M', ['foo']) - - subject.run + it "does not send via the RTM api" do + expect(rtm_connection).to_not receive(:send_messages) + expect(api).to receive(:send_messages).with(room_source.room, ['foo']) - subject.send_messages(private_message_source, ['foo']) + subject.send_messages(room_source, ['foo']) + end end end