From 4d811ed83e2d1b448e481f5688cece9b1e014ce6 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Thu, 3 Aug 2017 15:48:33 +0100 Subject: [PATCH] Make transcript generation object-oriented --- .../slack/slack_command_controller.rb | 78 ++--------- .../provider/slack/slack_provider.rb | 1 + .../provider/slack/slack_transcript_helper.rb | 127 ++++++++++++++++++ 3 files changed, 137 insertions(+), 69 deletions(-) create mode 100644 lib/discourse_chat/provider/slack/slack_transcript_helper.rb diff --git a/lib/discourse_chat/provider/slack/slack_command_controller.rb b/lib/discourse_chat/provider/slack/slack_command_controller.rb index 480b6f5..2b60478 100644 --- a/lib/discourse_chat/provider/slack/slack_command_controller.rb +++ b/lib/discourse_chat/provider/slack/slack_command_controller.rb @@ -11,9 +11,9 @@ module DiscourseChat::Provider::SlackProvider only: :command def command - text = process_command(params) + message = process_command(params) - render json: { text: text } + render json: message end def process_command(params) @@ -42,7 +42,7 @@ module DiscourseChat::Provider::SlackProvider return process_post_request(channel, tokens, params[:channel_id]) end - return ::DiscourseChat::Helper.process_command(channel, tokens) + return { text: ::DiscourseChat::Helper.process_command(channel, tokens)} end @@ -73,7 +73,7 @@ module DiscourseChat::Provider::SlackProvider return error_text unless response.kind_of? Net::HTTPSuccess json = JSON.parse(response.body) return error_text unless json['ok'] - users = json["members"] + raw_users = json # Now load the chat message history req = Net::HTTP::Post.new(URI('https://slack.com/api/channels.history')) @@ -89,78 +89,18 @@ module DiscourseChat::Provider::SlackProvider return error_text unless response.kind_of? Net::HTTPSuccess json = JSON.parse(response.body) return error_text unless json['ok'] + raw_history = json - first_post_link = "https://slack.com/archives/#{slack_channel_id}/p" - first_post_link += json["messages"].reverse.first["ts"].gsub('.', '') + transcript = SlackTranscript.new(raw_history, raw_users, slack_channel_id) - post_content = "" - - post_content << "[quote]\n" - - post_content << "[**#{I18n.t('chat_integration.provider.slack.view_on_slack')}**](#{first_post_link})\n" - - users_in_transcript = [] - last_user = '' - json["messages"].reverse.each do |message| - next unless message["type"] == "message" - - username = "" - if user_id = message["user"] - user = users.find { |u| u["id"] == user_id } - users_in_transcript << user - username = user["name"] - elsif message.key?("username") - username = message["username"] - end - - same_user = last_user == username - last_user = username - - if not same_user - post_content << "\n" - post_content << "![#{username}] " if message["user"] - post_content << "**@#{username}:** " - end - - text = message["text"] - - # Format links (don't worry about special cases @ # !) - text.gsub!(/<(.*?)>/) do |match| - group = $1 - parts = group.split('|') - link = parts[0].start_with?('@', '#', '!') ? '' : parts[0] - text = parts.length > 1 ? parts[1] : parts[0] - "[#{text}](#{link})" - end - - # Add an extra * to each side for bold - text.gsub!(/\*(.*?)\*/) do |match| - "*#{match}*" - end - - post_content << message["text"] - - if message.key?("attachments") - message["attachments"].each do |attachment| - next unless attachment.key?("fallback") - post_content << "\n> #{attachment["fallback"]}\n" - end - end - - post_content << "\n" - end - - post_content << "[/quote]\n\n" - - users_in_transcript.uniq.each do |user| - post_content << "[#{user["name"]}]: #{user["profile"]["image_24"]}\n" if user - end + post_content = transcript.build_transcript secret = DiscourseChat::Helper.save_transcript(post_content) link = "#{Discourse.base_url}/chat-transcript/#{secret}" - return "<#{link}|#{I18n.t("chat_integration.provider.slack.post_to_discourse")}>" + return { text: "<#{link}|#{I18n.t("chat_integration.provider.slack.post_to_discourse")}>", + } end diff --git a/lib/discourse_chat/provider/slack/slack_provider.rb b/lib/discourse_chat/provider/slack/slack_provider.rb index 0079100..1e1496c 100644 --- a/lib/discourse_chat/provider/slack/slack_provider.rb +++ b/lib/discourse_chat/provider/slack/slack_provider.rb @@ -151,4 +151,5 @@ module DiscourseChat::Provider::SlackProvider end require_relative "slack_message_formatter.rb" +require_relative "slack_transcript_helper.rb" require_relative "slack_command_controller.rb" diff --git a/lib/discourse_chat/provider/slack/slack_transcript_helper.rb b/lib/discourse_chat/provider/slack/slack_transcript_helper.rb new file mode 100644 index 0000000..9cc1b59 --- /dev/null +++ b/lib/discourse_chat/provider/slack/slack_transcript_helper.rb @@ -0,0 +1,127 @@ +module DiscourseChat::Provider::SlackProvider + class SlackMessage + def initialize(raw_message, transcript) + @raw = raw_message + @transcript = transcript + end + + def username + if user + return user['name'] + elsif @raw.key?("username") + return @raw["username"] + end + end + + def avatar + return nil unless user + return user["profile"]["image_24"] + end + + def url + channel_id = @transcript.channel_id + ts = @raw['ts'].gsub('.', '') + + return "https://slack.com/archives/#{channel_id}/p#{ts}" + end + + def text + text = @raw["text"] + + # Format links (don't worry about special cases @ # !) + text.gsub!(/<(.*?)>/) do |match| + group = $1 + parts = group.split('|') + link = parts[0].start_with?('@', '#', '!') ? '' : parts[0] + text = parts.length > 1 ? parts[1] : parts[0] + "[#{text}](#{link})" + end + + # Add an extra * to each side for bold + text.gsub!(/\*(.*?)\*/) do |match| + "*#{match}*" + end + + return text + end + + def attachments + attachments = [] + + return attachments unless @raw.key?('attachments') + + @raw["attachments"].each do |attachment| + next unless attachment.key?("fallback") + attachments << attachment["fallback"] + end + + return attachments + end + + private + def user + return nil unless user_id = @raw["user"] + users = @transcript.users + user = users.find { |u| u["id"] == user_id } + end + + end + + class SlackTranscript + attr_reader :users, :channel_id + + def initialize(raw_history, raw_users, channel_id) + # Build some message objects + @messages = [] + raw_history['messages'].reverse.each do |message| + next unless message["type"] == "message" + @messages << SlackMessage.new(message, self) + end + + @users = raw_users['members'] + @channel_id = channel_id + end + + def build_transcript + post_content = "[quote]\n" + post_content << "[**#{I18n.t('chat_integration.provider.slack.view_on_slack')}**](#{@messages.first.url})\n" + + all_avatars = {} + + last_username = '' + + @messages.each do |m| + same_user = m.username == last_username + last_username = m.username + + unless same_user + if avatar = m.avatar + all_avatars[m.username] ||= avatar + end + + post_content << "\n" + post_content << "![#{m.username}] " if m.avatar + post_content << "**@#{m.username}:** " + end + + post_content << m.text + + m.attachments.each do |attachment| + post_content << "\n> #{attachment}\n" + end + + post_content << "\n" + end + + post_content << "[/quote]\n\n" + + all_avatars.each do |username, url| + post_content << "[#{username}]: #{url}\n" + end + + return post_content + end + + end + +end