A pure functional library for easily building slack bots, built on cats 3.x, http4s and the Slack Java SDK.
Right now, slash commands are supported (contributions welcome!). This library takes care of
- Interacting with Slack's API
- Encoding/decoding payloads
- Verifying signature validity
- Handling background callbacks for longer running commands
Simply provide your business logic and you've got a deployable app!
- See SpaceNewsExample for a working example of a slash command handler.
- See docs/tutorial.md for a walk-through of configuring and running SpaceNewsExample.
Add the following dependency:
libraryDependencies += "io.laserdisc" %% "slack4s" % latestVersion
In this example, our slash command handler will take the form of a persistent HTTP service.
With your signing secret in hand, getting a skeleton handler up and running is as simple as:
import cats.effect.{IO, IOApp}
import io.laserdisc.slack4s.slashcmd.*
object MySlackBot extends IOApp.Simple {
val secret: SigningSecret = SigningSecret.unsafeFrom("your-signing-secret") // demo purposes - please don't hardcode secrets
override def run: IO[Unit] = SlashCommandBotBuilder[IO](secret).serve
}
Set your slash command's Request URL to
https://{your-base-url}/slack/slashCmd
Issue your slash command, e.g. /slack4s foo
and you should get the default response:
The builder has some more useful functions if you need to customize your deployment further:
SlashCommandBotBuilder[IO](secret)
.withCommandMapper(testCommandMapper) // your mapper impl, see next section
.withBindOptions(port = 9999, address = "192.168.0.1") // by default, binds to 0.0.0.0:8080
.withHttp4sBuilder{
// offer the chance to customize http4s' BlazeServerBuilder used under the hood
// USE WITH CAUTION; it overrides any settings set by slack4s
_.withIdleTimeout(10.seconds)
.withMaxConnections(512)
}
.serve
If your container runtime (e.g. k8s, AWS ECS) needs a health check endpoint, use:
https://{your-base-url}/healthCheck
Create an implementation of CommandMapper[F]
and pass it to the builder as follows e.g.:
val myMapper: CommandMapper[F] = .. // see the next section
SlashCommandBotBuilder[IO](secret)
.withCommandMapper(myMapper)
.serve
CommandMapper[F]
is a type alias for:
SlashCommandPayload => F[Command[F]]
Your implementation of this effect defines your business logic. The input is the slash command request from Slack. The output defines how to respond to that request.
Slack4s will only evaluate this effect if the incoming request's slack signature has been validated against your signing secret.
- This Java class provided by Slack's Java SDK (a dependency of this library) models the incoming request.
- Of primary interest is the
text
field, containing the arguments to you/command
as provided by the user. - Other fields provide contextual information about the call, such as
userId
,channelName
, etc.
text
value, as it comes verbatim from the user.
Not only should you sanitize this input appropriately, you'll also have to handle/strip any formatting it contains. Slack users tend to copy and paste slack text into commands - don't be surprised to get formatted input, e.g. *homer simpson*
instead of homer simpson
.
This is the description of how - and when - to handle the user's request. The scaladoc on Command[F] should have all the information you need, but at a high level, It defines the following fields:
- handler:
F[ChatPostMessageRequest]
- The effect to evaluate in response to the input.
- ChatPostMessageRequest is the Slack API Java model representing the response message.
- Importing
io.laserdisc.slack4s.slack._
gives you a bunch of convenience functions to build this reponse object (e.g.slackMessage(...)
,markdownWithImgSection(...)
, etc.) - You can explore with the possible response structures by playing with the excellent Slack Block Kit Builder.
- Importing
- responseType:
ResponseType
- Whether to respond immediately, or process the information in a background queue and post to a callback URL.
- See the scaladoc for ResponseType for all the options here.
- logId:
LogToken
"NA"
by default, this token used in slack4s's logs when processing this particular command (useful for log filtering)