Add transcript posting support to slack

This commit is contained in:
David Taylor 2017-07-24 16:43:37 +01:00
parent 2d7f25d7e6
commit 8ca4797797
4 changed files with 138 additions and 0 deletions

View File

@ -73,7 +73,13 @@ en:
*List rules:* `/discourse status` *List rules:* `/discourse status`
*Post transcript:* `/discourse post [n]`
Create a draft topic on discourse containing the last `n` posts in this channel
*Help:* `/discourse help` *Help:* `/discourse help`
transcript_error: "Something went wrong when building the transcript, sorry!"
post_to_discourse: "Click here to post on Discourse"
api_required: "Sorry, this integration isn't setup to support posting transcripts."
####################################### #######################################
########## TELEGRAM STRINGS ########### ########## TELEGRAM STRINGS ###########

View File

@ -38,10 +38,90 @@ module DiscourseChat::Provider::SlackProvider
# Create channel if doesn't exist # Create channel if doesn't exist
channel ||= DiscourseChat::Channel.create!(provider:provider, data:{identifier: channel_id}) channel ||= DiscourseChat::Channel.create!(provider:provider, data:{identifier: channel_id})
if tokens[0] == 'post'
return process_post_request(channel, tokens, params[:channel_id])
end
return ::DiscourseChat::Helper.process_command(channel, tokens) return ::DiscourseChat::Helper.process_command(channel, tokens)
end end
def process_post_request(channel, tokens, slack_channel_id)
if SiteSetting.chat_integration_slack_access_token.empty?
return I18n.t("chat_integration.provider.slack.api_required")
end
http = Net::HTTP.new("slack.com", 443)
http.use_ssl = true
messages_to_load = 10
if tokens.size > 1
begin
messages_to_load = Integer(tokens[1], 10)
rescue ArgumentError
return I18n.t("chat_integration.provider.slack.parse_error")
end
end
error_text = I18n.t("chat_integration.provider.slack.transcript_error")
# Load the user data (we need this to change user IDs into usernames)
req = Net::HTTP::Post.new(URI('https://slack.com/api/users.list'))
req.set_form_data({token: SiteSetting.chat_integration_slack_access_token})
response = http.request(req)
return error_text unless response.kind_of? Net::HTTPSuccess
json = JSON.parse(response.body)
return error_text unless json['ok']
users = json["members"]
# Now load the chat message history
req = Net::HTTP::Post.new(URI('https://slack.com/api/channels.history'))
data = {
token: SiteSetting.chat_integration_slack_access_token,
channel: slack_channel_id,
count: messages_to_load
}
req.set_form_data(data)
response = http.request(req)
return error_text unless response.kind_of? Net::HTTPSuccess
json = JSON.parse(response.body)
return error_text unless json['ok']
post_content = ""
json["messages"].reverse.each do |message|
next unless message["type"] == "message"
username = ""
if message["user"]
username = users.find{|u| u["id"] == message["user"]}["name"]
elsif message.key?("username")
username = message["username"]
end
post_content << "[quote='@#{username}']\n"
post_content << message["text"]
if message.key?("attachments")
message["attachments"].each do |attachment|
next unless attachment.key?("fallback")
post_content << "\n[quote]\n#{attachment["fallback"]}\n[/quote]"
end
end
post_content << "\n[/quote]\n\n"
end
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")}>"
end
def slack_token_valid? def slack_token_valid?
params.require(:token) params.require(:token)

View File

@ -304,6 +304,8 @@ RSpec.describe DiscourseChat::Manager do
describe '.save_transcript' do describe '.save_transcript' do
it 'saves a transcript to redis' do it 'saves a transcript to redis' do
freeze_time
key = DiscourseChat::Helper.save_transcript("Some content here") key = DiscourseChat::Helper.save_transcript("Some content here")
expect($redis.get("chat_integration:transcript:#{key}")).to eq("Some content here") expect($redis.get("chat_integration:transcript:#{key}")).to eq("Some content here")

View File

@ -109,6 +109,56 @@ describe 'Slack Command Controller', type: :request do
end end
end end
end end
describe 'post transcript' do
before do
SiteSetting.chat_integration_slack_access_token = 'abcde'
end
it 'generates a transcript properly' do
stub1 = stub_request(:post, "https://slack.com/api/users.list").to_return(body: '{"ok":true,"members":[{"id":"U5Z773QLS","name":"david"}]}')
stub2 = stub_request(:post, "https://slack.com/api/channels.history").to_return(body: '{"ok":true,"messages":[{"type":"message","user":"U5Z773QLS","text":"And this is a slack message with an attachment: <https:\/\/meta.discourse.org>","attachments":[{"title":"Discourse Meta","title_link":"https:\/\/meta.discourse.org","text":"Discussion about the next-generation open source Discourse forum software","fallback":"Discourse Meta","thumb_url":"https:\/\/discourse-meta.s3-us-west-1.amazonaws.com\/original\/3X\/c\/b\/cb4bec8901221d4a646e45e1fa03db3a65e17f59.png","from_url":"https:\/\/meta.discourse.org","thumb_width":350,"thumb_height":349,"service_icon":"https:\/\/discourse-meta.s3-us-west-1.amazonaws.com\/original\/3X\/c\/b\/cb4bec8901221d4a646e45e1fa03db3a65e17f59.png","service_name":"meta.discourse.org","id":1}],"ts":"1500910064.045243"},{"type":"message","user":"U5Z773QLS","text":"Hello world, this is a slack message","ts":"1500910051.036792"}],"has_more":true}')
post "/chat-integration/slack/command.json",
text: "post 2",
channel_name: 'general',
channel_id:'C6029G78F',
token: token
json = JSON.parse(response.body)
expect(json["text"]).to include(I18n.t("chat_integration.provider.slack.post_to_discourse"))
end
it 'deals with failed API calls correctly' do
stub1 = stub_request(:post, "https://slack.com/api/users.list").to_return(status: 403)
post "/chat-integration/slack/command.json",
text: "post 2",
channel_name: 'general',
channel_id:'C6029G78F',
token: token
json = JSON.parse(response.body)
expect(json["text"]).to include(I18n.t("chat_integration.provider.slack.transcript_error"))
end
it 'errors correctly if there is no api key' do
SiteSetting.chat_integration_slack_access_token = ''
post "/chat-integration/slack/command.json",
text: "post 2",
channel_name: 'general',
channel_id:'C6029G78F',
token: token
json = JSON.parse(response.body)
expect(json["text"]).to include(I18n.t("chat_integration.provider.slack.api_required"))
end
end
end end
end end
end end