diff --git a/lib/discourse_chat/provider/slack/slack_command_controller.rb b/lib/discourse_chat/provider/slack/slack_command_controller.rb index 8d636db..32d5e2a 100644 --- a/lib/discourse_chat/provider/slack/slack_command_controller.rb +++ b/lib/discourse_chat/provider/slack/slack_command_controller.rb @@ -66,12 +66,17 @@ module DiscourseChat::Provider::SlackProvider end end - transcript = SlackTranscript.load_transcript(slack_channel_id: slack_channel_id, - channel_name: channel_name, - requested_messages: requested_messages, - first_message_ts: first_message_ts) + error_message = { text: I18n.t("chat_integration.provider.slack.transcript.error") } - return { text: I18n.t("chat_integration.provider.slack.transcript.error") } unless transcript + return error_message unless transcript = SlackTranscript.new(channel_name: channel_name) + return error_message unless transcript.load_user_data + return error_message unless transcript.load_chat_history(slack_channel_id: slack_channel_id) + + if first_message_ts + return error_message unless transcript.set_first_message_by_ts(first_message_ts) + else + return error_message unless transcript.set_first_message_by_index(-requested_messages) + end return transcript.build_slack_ui @@ -92,16 +97,16 @@ module DiscourseChat::Provider::SlackProvider first_message = (action_name == 'first_message') ? changed_val : constant_val last_message = (action_name == 'first_message') ? constant_val : changed_val - transcript = SlackTranscript.load_transcript(slack_channel_id: json[:channel][:id], - channel_name: "##{json[:channel][:name]}", - first_message_ts: first_message, - last_message_ts: last_message) + error_message = { text: I18n.t("chat_integration.provider.slack.transcript.error") } - return { text: I18n.t("chat_integration.provider.slack.transcript.error") } unless transcript + return error_message unless transcript = SlackTranscript.new(channel_name: "##{json[:channel][:name]}") + return error_message unless transcript.load_user_data + return error_message unless transcript.load_chat_history(slack_channel_id: json[:channel][:id]) - message = transcript.build_slack_ui + return error_message unless transcript.set_first_message_by_ts(first_message) + return error_message unless transcript.set_last_message_by_ts(last_message) - return message + return transcript.build_slack_ui end def slack_token_valid? diff --git a/lib/discourse_chat/provider/slack/slack_transcript_helper.rb b/lib/discourse_chat/provider/slack/slack_transcript_helper.rb index 77074b8..584c682 100644 --- a/lib/discourse_chat/provider/slack/slack_transcript_helper.rb +++ b/lib/discourse_chat/provider/slack/slack_transcript_helper.rb @@ -84,37 +84,50 @@ module DiscourseChat::Provider::SlackProvider class SlackTranscript attr_reader :users, :channel_id - def initialize(raw_history:, raw_users:, channel_id:, channel_name:, requested_messages: nil, first_message_ts: nil, last_message_ts: nil) - - requested_messages ||= 10 - - raw_messages = raw_history['messages'].reverse - # Build some message objects - @messages = [] - raw_messages.each_with_index do |message, index| - next unless message["type"] == "message" - this_message = SlackMessage.new(message, self) - @messages << this_message - - # Auto set first and last based on requested_messages - @first_message = this_message if index == raw_messages.length - requested_messages - @last_message = this_message if index == raw_messages.length - 1 - end - - @first_message = @messages.find { |m| m.ts == first_message_ts } || @first_message if first_message_ts - @last_message = @messages.find { |m| m.ts == last_message_ts } || @last_message if last_message_ts - - @first_message_index = @messages.index(@first_message) - @last_message_index = @messages.index(@last_message) - - @users = raw_users['members'] - @channel_id = channel_id + def initialize(channel_name:) @channel_name = channel_name + + @first_message_index = 0 + @last_message_index = -1 # We can use negative array indicies to select the last message - fancy! + end + + def set_first_message_by_ts(ts) + message_index = @messages.find_index { |m| m.ts == ts } + @first_message_index = message_index if message_index + end + + def set_last_message_by_ts(ts) + message_index = @messages.find_index { |m| m.ts == ts } + @last_message_index = message_index if message_index + end + + def set_first_message_by_index(val) + @first_message_index = val if @messages[val] + end + + def set_last_message_by_index(val) + @last_message_index = val if @messages[val] + end + + def first_message + return @messages[@first_message_index] + end + + def last_message + return @messages[@last_message_index] + end + + # These two methods convert potentially negative array indices into positive ones + def first_message_number + return @first_message_index < 0 ? @messages.length + @first_message_index : @first_message_index + end + def last_message_number + return @last_message_index < 0 ? @messages.length + @last_message_index : @last_message_index end def build_transcript post_content = "[quote]\n" - post_content << "[**#{I18n.t('chat_integration.provider.slack.transcript.view_on_slack', name: @channel_name)}**](#{@first_message.url})\n" + post_content << "[**#{I18n.t('chat_integration.provider.slack.transcript.view_on_slack', name: @channel_name)}**](#{first_message.url})\n" all_avatars = {} @@ -162,41 +175,41 @@ module DiscourseChat::Provider::SlackProvider return { text: "<#{link}|#{I18n.t("chat_integration.provider.slack.transcript.post_to_discourse")}>", attachments: [ { - pretext: I18n.t("chat_integration.provider.slack.transcript.first_message_pretext", n: @messages.length - @first_message_index), - fallback: "#{@first_message.username} - #{@first_message.raw_text}", + pretext: I18n.t("chat_integration.provider.slack.transcript.first_message_pretext", n: @messages.length - first_message_number), + fallback: "#{first_message.username} - #{first_message.raw_text}", color: "#007AB8", - author_name: @first_message.username, - author_icon: @first_message.avatar, - text: @first_message.raw_text, + author_name: first_message.username, + author_icon: first_message.avatar, + text: first_message.raw_text, footer: I18n.t("chat_integration.provider.slack.transcript.posted_in", name: @channel_name), - ts: @first_message.ts, - callback_id: @last_message.ts, + ts: first_message.ts, + callback_id: last_message.ts, actions: [ { name: "first_message", text: I18n.t("chat_integration.provider.slack.transcript.change_first_message"), type: "select", - options: first_message_options = @messages[ [(@first_message_index - 20), 0].max .. @last_message_index] + options: first_message_options = @messages[ [(first_message_number - 20), 0].max .. last_message_number] .map { |m| { text: "#{m.username}: #{m.text}", value: m.ts } } } ], }, { - pretext: I18n.t("chat_integration.provider.slack.transcript.last_message_pretext", n: @messages.length - @last_message_index), - fallback: "#{@last_message.username} - #{@last_message.raw_text}", + pretext: I18n.t("chat_integration.provider.slack.transcript.last_message_pretext", n: @messages.length - last_message_number), + fallback: "#{last_message.username} - #{last_message.raw_text}", color: "#007AB8", - author_name: @last_message.username, - author_icon: @last_message.avatar, - text: @last_message.raw_text, + author_name: last_message.username, + author_icon: last_message.avatar, + text: last_message.raw_text, footer: I18n.t("chat_integration.provider.slack.transcript.posted_in", name: @channel_name), - ts: @last_message.ts, - callback_id: @first_message.ts, + ts: last_message.ts, + callback_id: first_message.ts, actions: [ { name: "last_message", text: I18n.t("chat_integration.provider.slack.transcript.change_last_message"), type: "select", - options: @messages[@first_message_index..(@last_message_index + 20)] + options: @messages[first_message_number..(last_message_number + 20)] .map { |m| { text: "#{m.username}: #{m.text}", value: m.ts } } } ], @@ -206,7 +219,7 @@ module DiscourseChat::Provider::SlackProvider } end - def self.load_user_data + def load_user_data http = Net::HTTP.new("slack.com", 443) http.use_ssl = true @@ -216,10 +229,12 @@ module DiscourseChat::Provider::SlackProvider return false unless response.kind_of? Net::HTTPSuccess json = JSON.parse(response.body) return false unless json['ok'] - return json + + @users = json['members'] + end - def self.load_chat_history(slack_channel_id:, count: 500) + def load_chat_history(slack_channel_id:, count: 500) http = Net::HTTP.new("slack.com", 443) http.use_ssl = true @@ -236,21 +251,17 @@ module DiscourseChat::Provider::SlackProvider return false unless response.kind_of? Net::HTTPSuccess json = JSON.parse(response.body) return false unless json['ok'] - return json - end - def self.load_transcript(slack_channel_id:, channel_name:, requested_messages: nil, first_message_ts: nil, last_message_ts: nil) - return false unless raw_users = self.load_user_data + raw_messages = json['messages'].reverse - return false unless raw_history = self.load_chat_history(slack_channel_id: slack_channel_id) + # Build some message objects + @messages = [] + raw_messages.each_with_index do |message, index| + next unless message["type"] == "message" + this_message = SlackMessage.new(message, self) + @messages << this_message + end - self.new(raw_history: raw_history, - raw_users: raw_users, - channel_id: slack_channel_id, - channel_name: channel_name, - requested_messages: requested_messages, - first_message_ts: first_message_ts, - last_message_ts: last_message_ts) end end