Home

Awesome

slack-scala-client

Build status GitHub last commit

A Scala library for interacting with the Slack API and real time messaging interface

Installation

SBT

Add SBT dependency:

libraryDependencies += "com.github.slack-scala-client" %% "slack-scala-client" % "1.0.1"

Maven

    <dependency>
        <groupId>com.github.slack-scala-client</groupId>
        <artifactId>slack-scala-client_${scala.version}</artifactId>
        <version>1.0.1</version>
    </dependency>

API Client Usage

There are two different API clients, one exposing an asynchronous interface and the other exposing a synchronous interface. They can be imported from the slack.api package:

import slack.api.SlackApiClient          // Async
import slack.api.BlockingSlackApiClient  // Blocking

Creating an instance of either client simply requires passing in a Slack api token:

val token = "<Your Token Here>"
val client = SlackApiClient(token)

Calling any api functions requires an implicit ActorSystem... one can be created simply:

implicit val system: ActorSystem = ActorSystem("slack")

The async client returns futures as the result of each of its API functions:

val client = SlackApiClient(token)
val res = client.listChannels() // => Future[Seq[Channel]]

res.onComplete {
    case Success(channels) =>  //...
    case Failure(err) => // ...
}

...while the blocking client will block the current thread until the API response has been received:

val client = BlockingSlackApiClient(token)  // Default timeout of 5 seconds
val channels = client.listChannels()  // => Seq[Channel]

The API clients implement the full Slack API. A full list of the available endpoints can be found directly on the classes: SlackApiClient and BlockingSlackApiClient

RTM Client Usage

The real time messaging client is implemented using Pekko and requires having an implicit ActorSystem in scope. Either an ActorSystem or ActorContext will work:

import slack.rtm.SlackRtmClient
import org.apache.pekko.actor.ActorSystem

implicit val system: ActorSystem = ActorSystem("slack")

Creating an instance of the RTM client requires an API token, just like the API clients:

val token = "<Your Token Here>"
val client = SlackRtmClient(token)

Based on the stream of events coming in, the client maintains active state that contains things like channels and users. It can also be used to look up the ID of a user or channel by name:

val state = client.state
val selfId = state.self.id
val chanId = state.getChannelIdForName("general") // => Option[String]

Sending a message is pretty simple:

val generalChanId = state.getChannelIdForName("general").get
client.sendMessage(generalChanId, "Hello!")

Messages can be received very simply as well:

client.onMessage { message =>
    println(s"User: ${message.user}, Message: ${message.text}")
}

Additionally, the client can be used to receive any event sent from Slack:

client.onEvent {
    case e: Message => ...
    case e: UserTyping => ...
    case e: ChannelDeleted => ...
}

A full list of events can be found in Events.scala. One thing to note is the two above functions return an ActorRef which is a handle to the underlying actor running the above handler function. This can be used to terminate the handler by terminating the actor: system.stop(handler), or unregistering it as a listener: client.removeEventListener(handler)

A Pekko actor can be manually registered as an event listener and all events will be sent to that actor:

val actor = system.actorOf(Props[SlackEventHandler])
client.addEventListener(actor)
// Time Passes...
client.removeEventListener(actor)

Finally, an RTM client can easily be terminated and cleaned up by calling close:

client.close()

Simple Bot Example

This is a full implementation of a Slack bot that will listen for anyone mentioning it in a message and will respond to that user.

val token = "..."
implicit val system: ActorSystem = ActorSystem("slack")
implicit val ec: ExecutionContextExecutor = system.dispatcher

val client = SlackRtmClient(token)
val selfId = client.state.self.id

client.onMessage { message =>
  val mentionedIds = SlackUtil.extractMentionedIds(message.text)

  if(mentionedIds.contains(selfId)) {
    client.sendMessage(message.channel, s"<@${message.user}>: Hey!")
  }
}

Caveat Emptor

Changelog

Changelog can be found here