From 2b3a534e4275e7142176d8cde1ad07efa97990b1 Mon Sep 17 00:00:00 2001 From: Itay Grudev Date: Wed, 1 Dec 2021 13:12:25 +0200 Subject: [PATCH 01/12] Updated local imports to use require_relative --- lib/lita-slack.rb | 2 +- lib/lita/adapters/slack.rb | 4 ++-- lib/lita/adapters/slack/api.rb | 8 ++++---- lib/lita/adapters/slack/chat_service.rb | 2 +- lib/lita/adapters/slack/rtm_connection.rb | 12 ++++++------ 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/lita-slack.rb b/lib/lita-slack.rb index 85426dd..bc6bf15 100644 --- a/lib/lita-slack.rb +++ b/lib/lita-slack.rb @@ -4,4 +4,4 @@ File.join("..", "..", "locales", "*.yml"), __FILE__ )] -require "lita/adapters/slack" +require_relative "lita/adapters/slack" diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 6107cb6..b226900 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -1,5 +1,5 @@ -require 'lita/adapters/slack/chat_service' -require 'lita/adapters/slack/rtm_connection' +require_relative 'slack/chat_service' +require_relative 'slack/rtm_connection' module Lita module Adapters diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index 3bb437c..24eedc1 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -1,9 +1,9 @@ require 'faraday' -require 'lita/adapters/slack/team_data' -require 'lita/adapters/slack/slack_im' -require 'lita/adapters/slack/slack_user' -require 'lita/adapters/slack/slack_channel' +require_relative 'team_data' +require_relative 'slack_im' +require_relative 'slack_user' +require_relative 'slack_channel' module Lita module Adapters diff --git a/lib/lita/adapters/slack/chat_service.rb b/lib/lita/adapters/slack/chat_service.rb index 317997b..48b7475 100644 --- a/lib/lita/adapters/slack/chat_service.rb +++ b/lib/lita/adapters/slack/chat_service.rb @@ -1,4 +1,4 @@ -require "lita/adapters/slack/attachment" +require_relative "attachment" module Lita module Adapters diff --git a/lib/lita/adapters/slack/rtm_connection.rb b/lib/lita/adapters/slack/rtm_connection.rb index 90bae4d..8ecc36a 100644 --- a/lib/lita/adapters/slack/rtm_connection.rb +++ b/lib/lita/adapters/slack/rtm_connection.rb @@ -1,12 +1,12 @@ require 'faye/websocket' require 'multi_json' -require 'lita/adapters/slack/api' -require 'lita/adapters/slack/event_loop' -require 'lita/adapters/slack/im_mapping' -require 'lita/adapters/slack/message_handler' -require 'lita/adapters/slack/room_creator' -require 'lita/adapters/slack/user_creator' +require_relative 'api' +require_relative 'event_loop' +require_relative 'im_mapping' +require_relative 'message_handler' +require_relative 'room_creator' +require_relative 'user_creator' module Lita module Adapters From 1f5084e352c96d214f0fc32d1e2aad3d73974f5b Mon Sep 17 00:00:00 2001 From: Itay Grudev Date: Wed, 1 Dec 2021 18:47:45 +0200 Subject: [PATCH 02/12] Updated connect procedure using rtm.connect instead of rtm.start as the latter is deprecated --- lib/lita/adapters/slack/api.rb | 13 +++++++------ lib/lita/adapters/slack/rtm_connection.rb | 6 +----- lib/lita/adapters/slack/team_data.rb | 2 +- spec/lita/adapters/slack/api_spec.rb | 8 ++++---- spec/lita/adapters/slack/rtm_connection_spec.rb | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index 24eedc1..cef43b3 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -69,15 +69,16 @@ def set_topic(channel, topic) call_api("channels.setTopic", channel: channel, topic: topic) end - def rtm_start - response_data = call_api("rtm.start") + def rtm_connect + response_data = call_api("rtm.connect") + + raise RuntimeError, response_data["error"] if response_data["ok"] != true TeamData.new( - SlackIM.from_data_array(response_data["ims"]), + response_data["team"]["id"], + response_data["team"]["name"], + response_data["team"]["domain"], SlackUser.from_data(response_data["self"]), - SlackUser.from_data_array(response_data["users"]), - SlackChannel.from_data_array(response_data["channels"]) + - SlackChannel.from_data_array(response_data["groups"]), response_data["url"], ) end diff --git a/lib/lita/adapters/slack/rtm_connection.rb b/lib/lita/adapters/slack/rtm_connection.rb index 8ecc36a..a055c86 100644 --- a/lib/lita/adapters/slack/rtm_connection.rb +++ b/lib/lita/adapters/slack/rtm_connection.rb @@ -17,19 +17,15 @@ class RTMConnection class << self def build(robot, config) - new(robot, config, API.new(config).rtm_start) + new(robot, config, API.new(config).rtm_connect) end end def initialize(robot, config, team_data) @robot = robot @config = config - @im_mapping = IMMapping.new(API.new(config), team_data.ims) @websocket_url = team_data.websocket_url @robot_id = team_data.self.id - - UserCreator.create_users(team_data.users, robot, robot_id) - RoomCreator.create_rooms(team_data.channels, robot) end def im_for(user_id) diff --git a/lib/lita/adapters/slack/team_data.rb b/lib/lita/adapters/slack/team_data.rb index e77b3b3..8cdb326 100644 --- a/lib/lita/adapters/slack/team_data.rb +++ b/lib/lita/adapters/slack/team_data.rb @@ -2,7 +2,7 @@ module Lita module Adapters # @api private class Slack < Adapter - TeamData = Struct.new(:ims, :self, :users, :channels, :websocket_url) + TeamData = Struct.new(:id, :name, :domain, :self, :websocket_url) end end end diff --git a/spec/lita/adapters/slack/api_spec.rb b/spec/lita/adapters/slack/api_spec.rb index 771df2e..0f367bd 100644 --- a/spec/lita/adapters/slack/api_spec.rb +++ b/spec/lita/adapters/slack/api_spec.rb @@ -661,25 +661,25 @@ def stubs(postMessage_options = {}) end it "has data on the bot user" do - response = subject.rtm_start + response = subject.rtm_connect expect(response.self.id).to eq('U12345678') end it "has an array of IMs" do - response = subject.rtm_start + response = subject.rtm_connect expect(response.ims[0].id).to eq('D024BFF1M') end it "has an array of users" do - response = subject.rtm_start + response = subject.rtm_connect expect(response.users[0].id).to eq('U023BECGF') end it "has a WebSocket URL" do - response = subject.rtm_start + response = subject.rtm_connect expect(response.websocket_url).to eq('wss://example.com/') end diff --git a/spec/lita/adapters/slack/rtm_connection_spec.rb b/spec/lita/adapters/slack/rtm_connection_spec.rb index 32188f3..e61eae8 100644 --- a/spec/lita/adapters/slack/rtm_connection_spec.rb +++ b/spec/lita/adapters/slack/rtm_connection_spec.rb @@ -39,7 +39,7 @@ def with_websocket(subject, queue) describe ".build" do before do allow(Lita::Adapters::Slack::API).to receive(:new).with(config).and_return(api) - allow(api).to receive(:rtm_start).and_return(rtm_start_response) + allow(api).to receive(:rtm_connect).and_return(rtm_start_response) end it "constructs a new RTMConnection with the results of rtm.start data" do From a05082db59e1b7200ffd3cc11fa69a347c2fe12b Mon Sep 17 00:00:00 2001 From: Itay Grudev Date: Sat, 4 Dec 2021 17:51:39 +0200 Subject: [PATCH 03/12] Fixes specs and removed data dependencies that are no longer provided on rtm.connect --- lib/lita/adapters/slack.rb | 10 +--- lib/lita/adapters/slack/rtm_connection.rb | 4 -- spec/lita/adapters/slack/api_spec.rb | 21 ++------ .../adapters/slack/rtm_connection_spec.rb | 50 ++++--------------- 4 files changed, 13 insertions(+), 72 deletions(-) diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index b226900..4e93361 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -40,7 +40,7 @@ def roster(target) def send_messages(target, strings) api = API.new(config) - api.send_messages(channel_for(target), strings) + api.send_messages(target.room, strings) end def set_topic(target, topic) @@ -60,14 +60,6 @@ def shut_down attr_reader :rtm_connection - def channel_for(target) - if target.private_message? - rtm_connection.im_for(target.user.id) - else - target.room - end - end - def channel_roster(room_id, api) response = api.channels_info room_id response['channel']['members'] diff --git a/lib/lita/adapters/slack/rtm_connection.rb b/lib/lita/adapters/slack/rtm_connection.rb index a055c86..cb9f661 100644 --- a/lib/lita/adapters/slack/rtm_connection.rb +++ b/lib/lita/adapters/slack/rtm_connection.rb @@ -28,10 +28,6 @@ def initialize(robot, config, team_data) @robot_id = team_data.self.id end - def im_for(user_id) - im_mapping.im_for(user_id) - end - def run(queue = nil, options = {}) EventLoop.run do log.debug("Connecting to the Slack Real Time Messaging API.") diff --git a/spec/lita/adapters/slack/api_spec.rb b/spec/lita/adapters/slack/api_spec.rb index 0f367bd..a012369 100644 --- a/spec/lita/adapters/slack/api_spec.rb +++ b/spec/lita/adapters/slack/api_spec.rb @@ -637,11 +637,11 @@ def stubs(postMessage_options = {}) end end - describe "#rtm_start" do + describe "#rtm_connect" do let(:http_status) { 200 } let(:stubs) do Faraday::Adapter::Test::Stubs.new do |stub| - stub.post('https://slack.com/api/rtm.start', token: token) do + stub.post('https://slack.com/api/rtm.connect', token: token) do [http_status, {}, http_response] end end @@ -652,11 +652,8 @@ def stubs(postMessage_options = {}) MultiJson.dump({ ok: true, url: 'wss://example.com/', - users: [{ id: 'U023BECGF' }], - ims: [{ id: 'D024BFF1M' }], self: { id: 'U12345678' }, - channels: [{ id: 'C1234567890' }], - groups: [{ id: 'G0987654321' }], + team: { id: 'T0987654321' }, }) end @@ -666,18 +663,6 @@ def stubs(postMessage_options = {}) expect(response.self.id).to eq('U12345678') end - it "has an array of IMs" do - response = subject.rtm_connect - - expect(response.ims[0].id).to eq('D024BFF1M') - end - - it "has an array of users" do - response = subject.rtm_connect - - expect(response.users[0].id).to eq('U023BECGF') - end - it "has a WebSocket URL" do response = subject.rtm_connect diff --git a/spec/lita/adapters/slack/rtm_connection_spec.rb b/spec/lita/adapters/slack/rtm_connection_spec.rb index e61eae8..6219fd7 100644 --- a/spec/lita/adapters/slack/rtm_connection_spec.rb +++ b/spec/lita/adapters/slack/rtm_connection_spec.rb @@ -9,21 +9,18 @@ def with_websocket(subject, queue) thread.join end - subject { described_class.new(robot, config, rtm_start_response) } + subject { described_class.new(robot, config, rtm_connect_response) } let(:api) { instance_double("Lita::Adapters::Slack::API") } let(:registry) { Lita::Registry.new } let(:robot) { Lita::Robot.new(registry) } - let(:raw_user_data) { Hash.new } - let(:channel) { Lita::Adapters::Slack::SlackChannel.new('C2147483705', 'general', 1360782804, 'U023BECGF', metadata) } - let(:metadata) { Hash.new } - let(:rtm_start_response) do + let(:rtm_connect_response) do Lita::Adapters::Slack::TeamData.new( - [], - Lita::Adapters::Slack::SlackUser.new('U12345678', 'carl', nil, raw_user_data), - [Lita::Adapters::Slack::SlackUser.new('U12345678', 'carl', '', raw_user_data)], - [channel], + 'T2U81E2FP', + 'SlackDemo', + 'slackdemo', + Lita::Adapters::Slack::SlackUser.new('U12345678', 'carl', nil, {}), "wss://example.com/" ) end @@ -39,42 +36,12 @@ def with_websocket(subject, queue) describe ".build" do before do allow(Lita::Adapters::Slack::API).to receive(:new).with(config).and_return(api) - allow(api).to receive(:rtm_connect).and_return(rtm_start_response) + allow(api).to receive(:rtm_connect).and_return(rtm_connect_response) end - it "constructs a new RTMConnection with the results of rtm.start data" do + it "constructs a new RTMConnection with the results of rtm.connect data" do expect(described_class.build(robot, config)).to be_an_instance_of(described_class) end - - it "creates users with the results of rtm.start data" do - expect(Lita::Adapters::Slack::UserCreator).to receive(:create_users) - - described_class.build(robot, config) - end - - it "creates rooms with the results of rtm.start data" do - expect(Lita::Adapters::Slack::RoomCreator).to receive(:create_rooms) - - described_class.build(robot, config) - end - end - - describe "#im_for" do - before do - allow(Lita::Adapters::Slack::API).to receive(:new).with(config).and_return(api) - allow( - Lita::Adapters::Slack::IMMapping - ).to receive(:new).with(api, []).and_return(im_mapping) - allow(im_mapping).to receive(:im_for).with('U12345678').and_return('D024BFF1M') - end - - let(:im_mapping) { instance_double('Lita::Adapters::Slack::IMMapping') } - - it "delegates to the IMMapping" do - with_websocket(subject, queue) do |websocket| - expect(subject.im_for('U12345678')).to eq('D024BFF1M') - end - end end describe "#run" do @@ -118,6 +85,7 @@ def with_websocket(subject, queue) context "when the WebSocket is closed from outside" do it "shuts down the reactor" do with_websocket(subject, queue) do |websocket| + sleep 0.1 # Since this code is run in a thread, we need to wait for it to finish websocket.close expect(EM.stopping?).to be_truthy end From 809d87d0163f93165944d8907f93f636ea01b865 Mon Sep 17 00:00:00 2001 From: Itay Grudev Date: Sun, 5 Dec 2021 18:00:50 +0200 Subject: [PATCH 04/12] Allows Lita-slack to reply in a thread --- lib/lita/adapters/slack.rb | 2 +- lib/lita/adapters/slack/api.rb | 13 +++--- lib/lita/adapters/slack/message_handler.rb | 8 +++- lib/lita/adapters/slack/slack_source.rb | 15 +++++++ lita-slack.gemspec | 2 +- .../adapters/slack/message_handler_spec.rb | 41 ++++++++++++++++--- spec/lita/adapters/slack_spec.rb | 18 ++++++-- spec/spec_helper.rb | 2 +- 8 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 lib/lita/adapters/slack/slack_source.rb diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 4e93361..5cc21d4 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -40,7 +40,7 @@ def roster(target) def send_messages(target, strings) api = API.new(config) - api.send_messages(target.room, strings) + api.send_messages(target.room, strings, thread_ts: target.thread) end def set_topic(target, topic) diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index cef43b3..6433b42 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -55,14 +55,15 @@ def send_attachments(room_or_user, attachments) ) end - def send_messages(channel_id, messages) - call_api( - "chat.postMessage", - **post_message_config, - as_user: true, + def send_messages(channel_id, messages, additional_payload = {}) + data = { channel: channel_id, + as_user: true, text: messages.join("\n"), - ) + }.merge(post_message_config) + .merge(additional_payload) + + call_api( "chat.postMessage", data ) end def set_topic(channel, topic) diff --git a/lib/lita/adapters/slack/message_handler.rb b/lib/lita/adapters/slack/message_handler.rb index b1572b2..9944f5e 100644 --- a/lib/lita/adapters/slack/message_handler.rb +++ b/lib/lita/adapters/slack/message_handler.rb @@ -1,3 +1,5 @@ +require_relative 'slack_source' + module Lita module Adapters class Slack < Adapter @@ -112,9 +114,13 @@ def channel data["channel"] end + def thread + data["thread_ts"] + end + def dispatch_message(user) room = Lita::Room.find_by_id(channel) - source = Source.new(user: user, room: room || channel) + source = SlackSource.new(user: user, room: room || channel, thread: thread) source.private_message! if channel && channel[0] == "D" message = Message.new(robot, body, source) message.command! if source.private_message? diff --git a/lib/lita/adapters/slack/slack_source.rb b/lib/lita/adapters/slack/slack_source.rb new file mode 100644 index 0000000..611bb26 --- /dev/null +++ b/lib/lita/adapters/slack/slack_source.rb @@ -0,0 +1,15 @@ +module Lita + module Adapters + class Slack < Adapter + # @api private + class SlackSource < Lita::Source + attr_reader :thread + + def initialize( user: nil, room: nil, private_message: nil, thread: nil ) + super( user: user, room: room, private_message: private_message ) + @thread = thread + end + end + end + end +end diff --git a/lita-slack.gemspec b/lita-slack.gemspec index 59a929f..0c0aa55 100644 --- a/lita-slack.gemspec +++ b/lita-slack.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency "lita", ">= 4.7.1" spec.add_runtime_dependency "multi_json" - spec.add_development_dependency "bundler", "~> 1.3" + spec.add_development_dependency "bundler" spec.add_development_dependency "pry-byebug" spec.add_development_dependency "rack-test" spec.add_development_dependency "rake" diff --git a/spec/lita/adapters/slack/message_handler_spec.rb b/spec/lita/adapters/slack/message_handler_spec.rb index c449b0c..59ddecf 100644 --- a/spec/lita/adapters/slack/message_handler_spec.rb +++ b/spec/lita/adapters/slack/message_handler_spec.rb @@ -1,10 +1,13 @@ require "spec_helper" +# require_relative '../../../../lib/lita/adapters/slack/slack_source' describe Lita::Adapters::Slack::MessageHandler, lita: true do subject { described_class.new(robot, robot_id, data) } before do allow(robot).to receive(:trigger) + allow(robot).to receive(:alias) + allow(robot).to receive(:receive) Lita::Adapters::Slack::RoomCreator.create_room(channel, robot) end @@ -35,16 +38,17 @@ } end let(:message) { instance_double('Lita::Message', command!: false, extensions: {}) } - let(:source) { instance_double('Lita::Source', private_message?: false) } + let(:source) { instance_double('Lita::Adapters::Slack::SlackSource', private_message?: false) } let(:user) { instance_double('Lita::User', id: 'U023BECGF') } let(:room) { instance_double('Lita::Room', id: "C2147483705", name: "general") } before do allow(Lita::User).to receive(:find_by_id).and_return(user) allow(Lita::Room).to receive(:find_by_id).and_return(room) - allow(Lita::Source).to receive(:new).with( + allow(Lita::Adapters::Slack::SlackSource).to receive(:new).with( user: user, - room: room + room: room, + thread: nil, ).and_return(source) allow(Lita::Message).to receive(:new).with(robot, "Hello", source).and_return(message) allow(robot).to receive(:receive).with(message) @@ -72,9 +76,10 @@ before do allow(Lita::Room).to receive(:find_by_id).and_return(nil) - allow(Lita::Source).to receive(:new).with( + allow(Lita::Adapters::Slack::SlackSource).to receive(:new).with( user: user, - room: "D2147483705" + room: "D2147483705", + thread: nil, ).and_return(source) allow(source).to receive(:private_message!).and_return(true) allow(source).to receive(:private_message?).and_return(true) @@ -156,6 +161,32 @@ end end + context "when the message is in a thread" do + let(:data) do + { + "type" => "message", + "channel" => "C2147483705", + "user" => "U023BECGF", + "text" => "Hello", + "ts" => "1234.5678", + "thread_ts" => "1234.5678", + } + end + let(:source) { instance_double('Lita::Adapters::Slack::SlackSource', private_message?: false, thread: "1234.5678") } + + before do + allow(Lita::Adapters::Slack::SlackSource).to receive(:new).with( + user: user, + room: room, + thread: "1234.5678", + ).and_return(source) + end + + it "sets the source thread option" do + subject.handle + end + end + describe "Removing message formatting" do let(:user) { instance_double('Lita::User', id: 'U123',name: 'name', mention_name: 'label') } diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index fbbbd23..5a082bd 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -73,7 +73,7 @@ end describe "via the Web API, retrieving the roster for a group/mpim channel" do - let(:room_source) { Lita::Source.new(room: 'G024BE91L') } + let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'G024BE91L') } let(:response) do { ok: true, @@ -95,7 +95,7 @@ end describe "via the Web API, retrieving the roster for an im channel" do - let(:room_source) { Lita::Source.new(room: 'D024BFF1M') } + let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'D024BFF1M') } let(:response) do { ok: true, @@ -117,7 +117,7 @@ end describe "#send_messages" do - let(:room_source) { Lita::Source.new(room: 'C024BE91L') } + let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'C024BE91L') } let(:user) { Lita::User.new('U023BECGF') } let(:user_source) { Lita::Source.new(user: user) } let(:private_message_source) do @@ -133,10 +133,20 @@ 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']) + expect(api).to receive(:send_messages).with(room_source.room, ['foo'], { thread_ts: nil }) subject.send_messages(room_source, ['foo']) end + + context "when thread is set" do + let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'C024BE91L', thread: '12345.67890') } + + it "sends the message to the Web API with thread_ts" do + expect(api).to receive(:send_messages).with(room_source.room, ['foo'], { thread_ts: '12345.67890' }) + + subject.send_messages(room_source, ['foo']) + end + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6632cfb..d52bf12 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,7 +6,7 @@ ] SimpleCov.start { add_filter "/spec/" } -require "lita-slack" +require_relative "../lib/lita-slack" require "lita/rspec" require "pry" From 94e0ad4447611ef11b2475f673629d287766d380 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Wed, 8 Dec 2021 17:16:49 +0200 Subject: [PATCH 05/12] Trying optional threads. --- lib/lita/adapters/slack.rb | 2 +- spec/lita/adapters/slack_spec.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 5cc21d4..3628b80 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -40,7 +40,7 @@ def roster(target) def send_messages(target, strings) api = API.new(config) - api.send_messages(target.room, strings, thread_ts: target.thread) + api.send_messages(target.room, strings, thread_ts: (target.thread if target.respond_to?(:thread))) end def set_topic(target, topic) diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index 5a082bd..91948ec 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -147,6 +147,14 @@ subject.send_messages(room_source, ['foo']) end end + + context "with optional thread" do + it "sends the message to the Web API without thread_ts" do + expect(api).to receive(:send_messages).with(private_message_source.room, ['foo'], { thread_ts: nil }) + + subject.send_messages(private_message_source, ['foo']) + end + end end end From 9055f4205c1266e534cea643604ab9b28708117a Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Wed, 8 Dec 2021 17:53:28 +0200 Subject: [PATCH 06/12] Optional thread v2. --- lib/lita/adapters/slack.rb | 6 +++++- spec/lita/adapters/slack_spec.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 3628b80..89910b1 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -40,7 +40,11 @@ def roster(target) def send_messages(target, strings) api = API.new(config) - api.send_messages(target.room, strings, thread_ts: (target.thread if target.respond_to?(:thread))) + if target.respond_to?(:thread) + api.send_messages(target.room, strings, thread_ts: target.thread) + else + api.send_messages(target.room, strings) + end end def set_topic(target, topic) diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index 91948ec..3f5e319 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -150,7 +150,7 @@ context "with optional thread" do it "sends the message to the Web API without thread_ts" do - expect(api).to receive(:send_messages).with(private_message_source.room, ['foo'], { thread_ts: nil }) + expect(api).to receive(:send_messages).with(private_message_source.room, ['foo']) subject.send_messages(private_message_source, ['foo']) end From 8bf876299f440cb2af14776fe370b02a3810e500 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Wed, 8 Dec 2021 18:07:43 +0200 Subject: [PATCH 07/12] Revert "Optional thread v2." This reverts commit 9055f4205c1266e534cea643604ab9b28708117a. --- lib/lita/adapters/slack.rb | 6 +----- spec/lita/adapters/slack_spec.rb | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 89910b1..3628b80 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -40,11 +40,7 @@ def roster(target) def send_messages(target, strings) api = API.new(config) - if target.respond_to?(:thread) - api.send_messages(target.room, strings, thread_ts: target.thread) - else - api.send_messages(target.room, strings) - end + api.send_messages(target.room, strings, thread_ts: (target.thread if target.respond_to?(:thread))) end def set_topic(target, topic) diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index 3f5e319..91948ec 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -150,7 +150,7 @@ context "with optional thread" do it "sends the message to the Web API without thread_ts" do - expect(api).to receive(:send_messages).with(private_message_source.room, ['foo']) + expect(api).to receive(:send_messages).with(private_message_source.room, ['foo'], { thread_ts: nil }) subject.send_messages(private_message_source, ['foo']) end From 6e287e7dd235aa3027980288d58db8e7fec9c9d6 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Wed, 8 Dec 2021 18:10:08 +0200 Subject: [PATCH 08/12] Optional thread v3. --- lib/lita/adapters/slack/api.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index 6433b42..8567a46 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -63,7 +63,7 @@ def send_messages(channel_id, messages, additional_payload = {}) }.merge(post_message_config) .merge(additional_payload) - call_api( "chat.postMessage", data ) + call_api( "chat.postMessage", **data ) end def set_topic(channel, topic) From 60c4ddc0d327ba8bd99413b5928f4a641025e016 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Wed, 8 Dec 2021 18:34:46 +0200 Subject: [PATCH 09/12] Optional thread v4. --- lib/lita/adapters/slack.rb | 6 +++++- lib/lita/adapters/slack/api.rb | 1 + spec/lita/adapters/slack_spec.rb | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 3628b80..89910b1 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -40,7 +40,11 @@ def roster(target) def send_messages(target, strings) api = API.new(config) - api.send_messages(target.room, strings, thread_ts: (target.thread if target.respond_to?(:thread))) + if target.respond_to?(:thread) + api.send_messages(target.room, strings, thread_ts: target.thread) + else + api.send_messages(target.room, strings) + end end def set_topic(target, topic) diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index 8567a46..57135e3 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -62,6 +62,7 @@ def send_messages(channel_id, messages, additional_payload = {}) text: messages.join("\n"), }.merge(post_message_config) .merge(additional_payload) + p data call_api( "chat.postMessage", **data ) end diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index 91948ec..3f5e319 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -150,7 +150,7 @@ context "with optional thread" do it "sends the message to the Web API without thread_ts" do - expect(api).to receive(:send_messages).with(private_message_source.room, ['foo'], { thread_ts: nil }) + expect(api).to receive(:send_messages).with(private_message_source.room, ['foo']) subject.send_messages(private_message_source, ['foo']) end From 1a6facd06c8c69c52cd26fd0b7e49a8af09941f9 Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Wed, 8 Dec 2021 19:17:29 +0200 Subject: [PATCH 10/12] Optional thread v5. --- lib/lita/adapters/slack.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/lita/adapters/slack.rb b/lib/lita/adapters/slack.rb index 89910b1..f98eb36 100644 --- a/lib/lita/adapters/slack.rb +++ b/lib/lita/adapters/slack.rb @@ -41,9 +41,9 @@ def roster(target) def send_messages(target, strings) api = API.new(config) if target.respond_to?(:thread) - api.send_messages(target.room, strings, thread_ts: target.thread) + api.send_messages(target.room || target.user&.id, strings, thread_ts: target.thread) else - api.send_messages(target.room, strings) + api.send_messages(target.room || target.user&.id, strings) end end From ea28007cc80912875f711fd765038a7e8e76b93b Mon Sep 17 00:00:00 2001 From: Nikolay Petrov Date: Thu, 9 Dec 2021 18:25:14 +0200 Subject: [PATCH 11/12] Added spec for user direct messages. --- lib/lita/adapters/slack/api.rb | 1 - spec/lita/adapters/slack_spec.rb | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/lita/adapters/slack/api.rb b/lib/lita/adapters/slack/api.rb index 57135e3..8567a46 100644 --- a/lib/lita/adapters/slack/api.rb +++ b/lib/lita/adapters/slack/api.rb @@ -62,7 +62,6 @@ def send_messages(channel_id, messages, additional_payload = {}) text: messages.join("\n"), }.merge(post_message_config) .merge(additional_payload) - p data call_api( "chat.postMessage", **data ) end diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index 3f5e319..818758e 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -155,6 +155,14 @@ subject.send_messages(private_message_source, ['foo']) end end + + context "with user source" do + it "sends direct message to the Web API" do + expect(api).to receive(:send_messages).with(user_source.user.id, ['foo']) + + subject.send_messages(user_source, ['foo']) + end + end end end From fb60cbfa1696051ebfbf322de376866f7c45dc68 Mon Sep 17 00:00:00 2001 From: Itay Grudev Date: Fri, 24 Dec 2021 12:16:34 +0200 Subject: [PATCH 12/12] Improved thread implementation --- lib/lita-slack.rb | 1 + lib/lita/adapters/slack/message_handler.rb | 4 +-- lib/lita/adapters/slack/slack_source.rb | 15 -------- lib/lita/source.rb | 35 +++++++++++++++++++ .../adapters/slack/message_handler_spec.rb | 12 +++---- spec/lita/adapters/slack_spec.rb | 9 ++--- spec/lita/adapters/source_spec.rb | 10 ++++++ 7 files changed, 58 insertions(+), 28 deletions(-) delete mode 100644 lib/lita/adapters/slack/slack_source.rb create mode 100644 lib/lita/source.rb create mode 100644 spec/lita/adapters/source_spec.rb diff --git a/lib/lita-slack.rb b/lib/lita-slack.rb index bc6bf15..abafffc 100644 --- a/lib/lita-slack.rb +++ b/lib/lita-slack.rb @@ -4,4 +4,5 @@ File.join("..", "..", "locales", "*.yml"), __FILE__ )] +require_relative "lita/source" require_relative "lita/adapters/slack" diff --git a/lib/lita/adapters/slack/message_handler.rb b/lib/lita/adapters/slack/message_handler.rb index 9944f5e..721db71 100644 --- a/lib/lita/adapters/slack/message_handler.rb +++ b/lib/lita/adapters/slack/message_handler.rb @@ -1,5 +1,3 @@ -require_relative 'slack_source' - module Lita module Adapters class Slack < Adapter @@ -120,7 +118,7 @@ def thread def dispatch_message(user) room = Lita::Room.find_by_id(channel) - source = SlackSource.new(user: user, room: room || channel, thread: thread) + source = Source.new(user: user, room: room || channel, thread: thread) source.private_message! if channel && channel[0] == "D" message = Message.new(robot, body, source) message.command! if source.private_message? diff --git a/lib/lita/adapters/slack/slack_source.rb b/lib/lita/adapters/slack/slack_source.rb deleted file mode 100644 index 611bb26..0000000 --- a/lib/lita/adapters/slack/slack_source.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Lita - module Adapters - class Slack < Adapter - # @api private - class SlackSource < Lita::Source - attr_reader :thread - - def initialize( user: nil, room: nil, private_message: nil, thread: nil ) - super( user: user, room: room, private_message: private_message ) - @thread = thread - end - end - end - end -end diff --git a/lib/lita/source.rb b/lib/lita/source.rb new file mode 100644 index 0000000..72c826e --- /dev/null +++ b/lib/lita/source.rb @@ -0,0 +1,35 @@ +module Lita + class Source + + # The room the message came from or should be sent to, as a string. + # @return [String, NilClass] A string uniquely identifying the room. + attr_reader :thread + + # @param user [Lita::User] The user who sent the message or should receive + # the outgoing message. + # @param room [Lita::Room, String] A string or {Lita::Room} uniquely identifying the room + # the user sent the message from, or the room where a reply should go. The format of this + # string (or the ID of the {Lita::Room} object) will differ depending on the chat service. + # @param private_message [Boolean] A flag indicating whether or not the + # message was sent privately. + def initialize(user: nil, room: nil, thread: nil, private_message: false) + @user = user + @thread = thread + + case room + when String + @room = room + @room_object = Room.new(room) + when Room + @room = room.id + @room_object = room + end + + @private_message = private_message + + raise ArgumentError, I18n.t("lita.source.user_or_room_required") if user.nil? && room.nil? + + @private_message = true if room.nil? + end + end +end diff --git a/spec/lita/adapters/slack/message_handler_spec.rb b/spec/lita/adapters/slack/message_handler_spec.rb index 59ddecf..aae8568 100644 --- a/spec/lita/adapters/slack/message_handler_spec.rb +++ b/spec/lita/adapters/slack/message_handler_spec.rb @@ -38,14 +38,14 @@ } end let(:message) { instance_double('Lita::Message', command!: false, extensions: {}) } - let(:source) { instance_double('Lita::Adapters::Slack::SlackSource', private_message?: false) } + let(:source) { instance_double('Lita::Source', private_message?: false) } let(:user) { instance_double('Lita::User', id: 'U023BECGF') } let(:room) { instance_double('Lita::Room', id: "C2147483705", name: "general") } before do allow(Lita::User).to receive(:find_by_id).and_return(user) allow(Lita::Room).to receive(:find_by_id).and_return(room) - allow(Lita::Adapters::Slack::SlackSource).to receive(:new).with( + allow(Lita::Source).to receive(:new).with( user: user, room: room, thread: nil, @@ -76,7 +76,7 @@ before do allow(Lita::Room).to receive(:find_by_id).and_return(nil) - allow(Lita::Adapters::Slack::SlackSource).to receive(:new).with( + allow(Lita::Source).to receive(:new).with( user: user, room: "D2147483705", thread: nil, @@ -172,17 +172,17 @@ "thread_ts" => "1234.5678", } end - let(:source) { instance_double('Lita::Adapters::Slack::SlackSource', private_message?: false, thread: "1234.5678") } + let(:source) { instance_double('Lita::Source', room: room, private_message?: false) } before do - allow(Lita::Adapters::Slack::SlackSource).to receive(:new).with( + allow(Lita::Source).to receive(:new).with( user: user, room: room, thread: "1234.5678", ).and_return(source) end - it "sets the source thread option" do + it "records the room thread" do subject.handle end end diff --git a/spec/lita/adapters/slack_spec.rb b/spec/lita/adapters/slack_spec.rb index 5a082bd..7465ca2 100644 --- a/spec/lita/adapters/slack_spec.rb +++ b/spec/lita/adapters/slack_spec.rb @@ -73,7 +73,7 @@ end describe "via the Web API, retrieving the roster for a group/mpim channel" do - let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'G024BE91L') } + let(:room_source) { Lita::Source.new(room: 'G024BE91L') } let(:response) do { ok: true, @@ -95,7 +95,7 @@ end describe "via the Web API, retrieving the roster for an im channel" do - let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'D024BFF1M') } + let(:room_source) { Lita::Source.new(room: 'D024BFF1M') } let(:response) do { ok: true, @@ -117,7 +117,7 @@ end describe "#send_messages" do - let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'C024BE91L') } + let(:room_source) { Lita::Source.new(room: 'C024BE91L') } let(:user) { Lita::User.new('U023BECGF') } let(:user_source) { Lita::Source.new(user: user) } let(:private_message_source) do @@ -139,7 +139,8 @@ end context "when thread is set" do - let(:room_source) { Lita::Adapters::Slack::SlackSource.new(room: 'C024BE91L', thread: '12345.67890') } + let(:room) { Lita::Room.new('C024BE91L') } + let(:room_source) { Lita::Source.new(room: room, thread: '12345.67890') } it "sends the message to the Web API with thread_ts" do expect(api).to receive(:send_messages).with(room_source.room, ['foo'], { thread_ts: '12345.67890' }) diff --git a/spec/lita/adapters/source_spec.rb b/spec/lita/adapters/source_spec.rb new file mode 100644 index 0000000..170967e --- /dev/null +++ b/spec/lita/adapters/source_spec.rb @@ -0,0 +1,10 @@ +require "spec_helper" + +describe Lita::Source do + subject { described_class.new(room: 'R0000', thread: 'thread') } + + it 'records message source thread' do + expect(subject.thread).to eq('thread') + end + +end