0

I have making a post request in Ruby to a slack endpoint and its failing, here is my request, not sure what I'm missing:

#!/usr/bin/env ruby
#Notification Script Test

def send_slack_message
    slack_rooms = [ '#test_channel_notify' ]
    slack_token_file = (File.join(ENV['HOME'], '.slack_api_token'))
    slack_api_token = (File.open(@slack_token_file).readlines)[0].chomp
    msg = 'This is a test message send'
    slack_url = "https://slack.com/api/chat.postMessage"
    %x{curl -k -X POST -d"token=#{slack_api_token}\&channel=#{slack_rooms}\&text=#{msg}" '#{slack_url}'} 
end

send_slack_message

I am getting the following error, not sure what I'm missing:

./cap2.rb:7:in `initialize': no implicit conversion of nil into String (TypeError)
from ./cap2.rb:7:in `open'
from ./cap2.rb:7:in `send_slack_message'
from ./cap2.rb:13:in `<main>'

I am a ruby novice so I may be missing everything would love some help!

user2019182
  • 295
  • 5
  • 19
  • 3
    `slack_token_file` not `@slack_token_file` – Kris Apr 28 '17 at 13:38
  • I saw it immediately after I posted this..LOL. Im curious if you see anything wrong with my actual post request, as the curl is returning properly but nothing is getting posted to the channel I created. – user2019182 Apr 28 '17 at 13:39

3 Answers3

2

The error says that you can't give nil to File.open. Make sure @slack_token_file exists and is not nil.

yoones
  • 2,394
  • 1
  • 16
  • 20
  • Yup I saw that as you posted this response. I removed the @ since its not a global variable and I'm not getting that error anymore! – user2019182 Apr 28 '17 at 13:37
  • Im curious if you see anything wrong with my actual post request, as the curl is returning properly but nothing is getting posted to the channel I created. – user2019182 Apr 28 '17 at 13:38
  • @user2019182 That's another question ;) – yoones Apr 28 '17 at 13:39
1

The slack API wants to receive the payload in this format: 'payload={"json": "data"}' Using Net::HTTP you can make a POST request like this:

require 'net/http'
require 'uri'

def payload(message, channel)
  { channel: channel, username: 'your-username', text: message, icon_emoji: ':robot_face:' }
end

msg = 'This is a test message send'
body = payload(msg, '#test_channel_notify').to_json

url = URI("https://slack.com/api/chat.postMessage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request.body = "payload=#{body}"
http.request(request)
Shiyason
  • 759
  • 7
  • 16
0

While your original problem has been solved, I will provide an alternative solution which follows the more common practice of storing secret credentials as environment variables, not as files (which can, for example, more easily exfiltrated by accident, committed to source control, pasted to a presentation, etc).

Set SLACK_TOKEN in your environment, and then use:

#!/usr/bin/env ruby
#Notification Script Test

def send_slack_message
    slack_rooms = [ '#test_channel_notify' ]
    slack_api_token = ENV['SLACK_TOKEN']
    msg = 'This is a test message send'
    slack_url = "https://slack.com/api/chat.postMessage"
    %x{curl -k -X POST -d"token=#{slack_api_token}\&channel=#{slack_rooms}\&text=#{msg}" '#{slack_url}'} 
end

send_slack_message
Community
  • 1
  • 1
msanford
  • 11,803
  • 11
  • 66
  • 93