slack-ruby / slack-ruby-client

A Ruby and command-line client for the Slack Web, Real Time Messaging and Event APIs.
MIT License
1.19k stars 214 forks source link

RealTime Client not working - getting not_allowed_token_type error #466

Closed Roko131 closed 1 year ago

Roko131 commented 1 year ago

Calling client.start! causes not_allowed_token_type error when trying to start a realtime client

To reproduce just follow the readme example

ruby -v # ruby 3.1.2p20
gem install slack-ruby-client -v '2.1.0'
gem install async-websocket -v '~> 0.8.0'

Trying to start client but getting error:

require 'slack-ruby-client'
client = Slack::RealTime::Client.new(token: ENV['SLACK_BOT_TOKEN']) # xoxb-...

client.start!
# Slack::Web::Api::Errors::NotAllowedTokenType: not_allowed_token_type

If it helps I can use token to post messages using curl:

curl -X POST -F channel=C1234 -F text="Reminder: we've got a softball game tonight!" https://slack.com/api/chat.postMessage -H "Authorization: Bearer xoxb-1234..."

Am I missing something?

Roko131 commented 1 year ago

Another thing I tried was following this Intro to Socket Mode

I switched socket mode on at my app and created an app-level-token with connections:write scope permission

But still getting Slack::Web::Api::Errors::NotAllowedTokenType: not_allowed_token_type error

Socket mode on image

dblock commented 1 year ago

I believe you need a RTM token for RTM clients and there's no way to obtain it for new apps without OAuth v1 and a classic app. Per https://api.slack.com/rtm:

Screenshot 2023-04-14 at 11 38 55 AM

~To build a new non-RTM app you would start with something like https://github.com/slack-ruby/slack-ruby-bot-server-events.~

Socket mode feature request is https://github.com/slack-ruby/slack-ruby-client/issues/414.

~Probably nothing we can do about it here, so I propose closing this issue.~ Or is there something we can clarify in the documentation? Maybe add what I said above to it?

Roko131 commented 1 year ago

Thanks,

I suggest to clarify in documentation. It was unclear to me. Indeed adding what you said would help or:

I would add two things to clarify:

  1. In the RealTime Client I would add something like "Notice this is not the new Socket app implantation. this is not available to new apps, only to legacy class app see here...
  2. I would also add a "socket mode client" section- like RealTime Client - which only says it's Slack's new preferred way for for Realtime Event and it's not yet supported

What was confusing to me there was no mention at all for the legacy/now socket mode. Specially as someone who is unfamiliar with Slack.

For me, after reading RealTime Client](https://github.com/slack-ruby/slack-ruby-client#realtime-client) it was a straight procedure which just didn't work. I thought I was doing something wrong.

More so I wasn't aware there is a distinction between old legacy mode to new socket mode- I suggest make that clear in the slack-ruby-client Gem where relevant, like RealTime Client.

Thanks

Oh and if it helps other people, that's what I ended up doing:

require 'em-websocket'
require 'faye/websocket'

require 'http' # can use any rest client gem

# Notice!! this is an APP-LEVEL-TOKEN with only connections:write permission (see https://api.slack.com/authentication/token-types#app)
slack_app_level_token = 'xapp-1-abcd-123456.....'

# get web-socket link:
get_ws_link_api_url = 'https://slack.com/api/apps.connections.open'
ws_socket_link = HTTP.headers('Authorization': "Bearer #{slack_app_level_token}").post(get_ws_link_api_url, form: {}).dig('url')

EM.run do
  ws = Faye::WebSocket::Client.new(ws_socket_link)

  ws.on :open do |event|
    p [:open]
    ws.send('Hello, world!')
  end

  ws.on :message do |event|
    p [:message, event.data]
  end

  ws.on :error do |error|
    puts "error: #{error}"
    # puts "error: #{error} onerror: #{error}, #{error.inspect}, #{error.backtrace}"
  end

  ws.on :close do |event|
    p [:close, event.code, event.reason]
    ws = nil
  end

  EM::Timer.new(5*60) do # set a timer for 5 minutes (300 seconds)
    puts "WebSocket timed out"
    ws.close(1000, "WebSocket timed out") # close the WebSocket connection
    EM.stop
  end

end
dblock commented 1 year ago

Thanks. I'll close this. Care to PR the suggested doc changes?

PS: The immediate problem you'll run into EventMachine is that it does not maintain your websocket alive. We struggled with this in https://github.com/slack-ruby/slack-ruby-client/issues/257 and related issues. So I wouldn't put the code above in production.