alexandre-normand/slackscot

Is There A Way To Access The slack.Client Object?

pmcintyresfdc opened this issue · 17 comments

Goal: Create channels and possibly other direct slack commands

What's the best way to go about this? I can't find any way to directly access the slack.Client object. Did I miss something?

Thanks!

Thanks for the question, @pmcintyresfdc!

You're correct that there's no way at the moment but it's something I had imagined as a desirable feature. The reason a slack.Client isn't directly injected in plugins is that it makes it a little harder to mock and test.

What I had imagined is that we'd add more injected "services" here as small interfaces that could be easily mocked out in plugin tests as the need for them came in. You can see some examples already.

And yes, there's overhead to add support for slack.Client features. The main reason to inject small interfaces instead is to nudge plugin writers to write good tests for their plugins and give them the ability to do so more easily.

I think adding support for some channel APIs would be a great addition. I'd love to see a PR if you're interested in giving it a shot. Otherwise, I could potentially do this soon but I might ask that you provide a list of the APIs you're interested in. Sounds like one was CreateChannel?

Oh and if you have other ideas of how to approach the problem, I'd be interested in hearing about them.

Just remembered there was the addition of slacktest since last time I was thinking about testability and it seems like one could potentially use a slack.Client and still have a path to testing a plugin.

I think that to enable that testing path, I'd have to expose an option that would set OptionAPIURL which is probably a good idea regardless.

That said, tests might still be easier to write with the injected services so maybe both can co-exist.

@pmcintyresfdc: I ended up going with the addition of injection of the slack.Client in Plugin instances. The slacktest server does help with testing when using the slack client directly.

If you'd like, you can pull the branch #134 and see if that meets your needs. If you're using go modules, that should be easy but otherwise, I think I'll wrap up the work in the coming days to add plugin testing support that receives a slacktest.Server so plugin writers can set up their test server and then have the test driver run through the messages.

@alexandre-normand A quick review looks like it'd meet our needs perfectly. Although I think I'll still try to submit a PR for including the channel actions directly - I'm mostly interested in create, archive, and unarchive. At least I can once I get through the usual internal approvals to contribute to a project ;)

I'll give it a test and let you know how it looks.

PS - You're super responsive! Rock on!

@alexandre-normand A quick review looks like it'd meet our needs perfectly. Although I think I'll still try to submit a PR for including the channel actions directly - I'm mostly interested in create, archive, and unarchive. At least I can once I get through the usual internal approvals to contribute to a project ;)

Sounds great! I think small service interfaces can still be nicer when writing plugins so I think both can complement different usages. I can imagine the added slack.Client to be used for prototyping with new slack APIs with a subsequent phase to create a service interface and allow easier testing of all the functionality of a plugin without having to deal with the slack API internals too much.

I'll probably add to my PR with the addition of the slack.Client with support in assertplugin for a slacktest.Server tonight but you don't have to review that part unless you're really curious.

And feel free to post questions here if you need help or guidance with the addition of a plugin service for the channel operations.

Also, thanks for spending time to contribute back to the project. Much appreciated 🙇

FYI: I merged my PR adding the *slack.Client to Plugin and tagged a v1.37.0 version.

I ended up finding a path to testability without having to write a lot of code. It would still be harder to write concise tests than a more mock-oriented approach but it does offer more flexibility in the usage of the slack API so it's reasonable.

I still think it makes sense to have additional small scoped slack services with proper support in assertplugin. Let me know if you have thoughts and questions as you try to add something for channel creation/archiving.

My channel test was half successful. The Slack API gets called but fails due to perms on a custom integration token (aka bot token). Thus far attempts to use a proper app haven't been working due to missing_scope errors during the RTM connect.

One interesting thing is that response.Info.URL is empty...

slack: 2019/12/12 09:23:42 websocket_managed_conn.go:177: Connecting to RTM
slack: 2019/12/12 09:23:42 rtm.go:71: Using URL: 
slack: 2019/12/12 09:23:42 websocket_managed_conn.go:181: Failed to start or connect to RTM: missing_scope
slack: 2019/12/12 09:23:42 websocket_managed_conn.go:147: reconnection 1 failed: missing_scope reconnecting in 100ms

I was anticipating you might have issues with slack oauth scopes but I'm surprised this would be on the RTM connect. I'm not exactly sure what the situation is but here are a few things to check (sorry if some of them sound stupid):

  • Make sure you're using the Bot User OAuth Access Token (the xoxb token).
  • Check your requested scopes
  • Make sure you've "reinstalled the app" after changing scopes

I know that the channels.create API requires the channels:manage oauth scope which is only part of the new oauth scopes so that's one you'll have to pay attention to. If you're using the bot token, I'm surprised that you'd get missing_scope on the RTM connect but I'm not super familiar with how that aligns with the granular scopes.

Do you mind taking a screenshot (or just a copy paste) of your OAuth & Permissions page? Just make sure to omit the tokens so as to not make them accidentally public 😬.

Looks like it was because I was using a beta app rather than an older kind. Got the RTM connect working but now I'm getting an not_allowed_token_type error. Working with slack support now ;)

Looks like it was because I was using a beta app rather than an older kind. Got the RTM connect working but now I'm getting an not_allowed_token_type error. Working with slack support now ;)

Do you mean that you were using the new beta oauth scopes? Because I think that you'd have to use those in order to use the channels:manage. I haven't tried this myself beyond ad-hoc API tests using their web UI but channels.create seems to only be available for apps using the new beta oauth scopes. I was expecting that there would be a way to get the correct oauth scopes to still be able to do RTM though (but I don't know what the required granular scopes would be for not having played with that yet).

Yup. They're saying what you just said. Guess they'll help me figure out how to use the new one to do it. I'll let you know soon :)

lol, they'll get back to me. Guess this is getting interesting.

The tl;dr is that the RTM API can't be used with beta apps. They recommended using a second app for the channel creation and other problematic calls.

The tl;dr is that the RTM API can't be used with beta apps. They recommended using a second app for the channel creation and other problematic calls.

That's disappointing. Do you know if that's going to be the intended behavior as they get out of beta or is that acknowledged as a limitation that should be worked on?

They sounded like they didn't know if it was going to be "fixed" or not. Hopefully so.

🤞 . This was still a good addition to slackscot for access to other APIs. Thanks for the request!