/slack

Slack client for go

Primary LanguageGoMIT LicenseMIT

slack

Build Status

GoDoc

Status

  • Many APIs are still unimplemented (please file an issue!)
  • RTM events are not covered entirely yet (please file an issue!)

Missing parts are missing only because the author does not have immediate need for them. With proper prodding, I will gladly take on implementing them.

Please see #4 for a list of currently known unimplemented methods.

Features

Auto-generated API

All of the APIs in this library is generated by a tool, reducing human errors.

Supports Google App Engine

Google App Engine does not allow the use of raw net/http clients. Instead you need to use the urlfetch package. This library allows you to pass the HTTP client that it should use:

ctx := appengine.NewContext(r)
httpCl := urlfetch.Client(ctx)
slackCl := slack.New(token, slack.WithClient(httpCl))

Google API style library

All of the APIs in this library resemble that of google.golang.org/api, and is very predictable across all APIs.

Full support for context.Context

The API is designed from the ground up to integrate well with context.Context.

Mock Server

A server that mocks the Slack API calls is available, which should help you integrate your applications with Slack while you are still in development.

Note: many mock methods are still NOT properly implemented. Please see server/mockserver/mockserver.go and server/mockserver/response.go. PRs welcome!

Slack Proxy

Sometimes you want a tool that talks to the Slack API, but don't want to really send messages. We have a simple server that can intercept methods that have side effects, while sending everything else to the real Slack API server, called slaproxy (you can compile it from cmd/slaproxy/slaproxy.go)

We even have Docker container for it

docker run -e SLACK_TOKEN=xxx -e SLACK_LISTEN=:9999 lestrrat/slaproxy

Synopsis

Simple REST Client:

package slack_test

import (
  "context"
  "fmt"
  "os"

  "github.com/lestrrat-go/slack"
)

func ExampleClient() {
  ctx, cancel := context.WithCancel(context.Background())
  defer cancel()

  token := os.Getenv("SLACK_TOKEN")
  cl := slack.New(token)

  // check if we are connected
  authres, err := cl.Auth().Test().Do(ctx)
  if err != nil {
    fmt.Printf("failed to test authentication: %s\n", err)
    return
  }
  fmt.Printf("%#v\n", authres)

  // simplest possible message
  chatres, err := cl.Chat().PostMessage("@username").
    Text("Hello, World!").
    Do(ctx)
  if err != nil {
    fmt.Printf("failed to post messsage: %s\n", err)
    return
  }
  fmt.Printf("%#v\n", chatres)
}

A mock server

package slack_test

import (
  "context"
  "net/http"
  "time"

  "github.com/lestrrat-go/slack"
  "github.com/lestrrat-go/slack/server"
  "github.com/lestrrat-go/slack/server/mockserver"
)

func ExampleMockServer() {
  token := "..."
  h := mockserver.New(mockserver.WithToken(token))
  s := server.New()

  h.InstallHandlers(s)

  srv := http.Server{Handler: s, Addr: ":8080"}
  go srv.ListenAndServe()
  ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  defer cancel()
  cl := slack.New(token, slack.WithAPIEndpoint("http://localhost:8080"))
  if _, err := cl.Auth().Test().Do(ctx); err != nil {
    log.Printf("failed to call auth.test: %s", err)
    return
  }

  srv.Shutdown(ctx)
}

RTM

See the README in the rtm/ directory.

Calling Conventions

The API is constructed along the same lines of Google API Go libraries (https://google.golang.org/api), so if you are familiar with that style you should have no problem. But if you have not used their API, I'm sure you're confused - I know I was when I first saw their API.

This section will walk you through how the APIs in this REST client generally work. The basic idea is that you have a central client, which you can create via New:

  client := slack.New(token)

The client is nothing but a placeholder for other "services". For example, to use the slack APIs for chat.* endpoints, lookup the ChatService object which can be obtained by calling the Chat() method:

  service := client.Chat()

The ChatService object can construct an intermediate object, which are called the Call objects. These objects exist to accumulate parameters that you want to ultimately call the API endpoint with.

In the initial call to construct the objects, you will have to enter the mandatory parameters. For example, to start a PostMessage call (which is supposed to access chat.postMessage endpoint), you do:

  call := service.PostMessage(channel)

The channel parameter is required, so you must pass that to the PostMessage method (you would think that text is always required, but you could either provide text, or an attachment with text, so it's not always the case)

Once you have the call object, you can specify additional parameters which are optional. The following would specify a text attribute for this call.

  call.Text(yourMessage)

Finally, when you are done tweaking your call object, you should call Do, which will fire the actual request.

  res, err := call.Do(ctx)

And you are done. Don't for get to pass a context.Context to all Do calls.

Also, for your convenience these call object methods can all be chained. So the above example could look like the following:

  res, err := client.Chat().PostMessage(channel).Text(yourMessage).Do(ctx)

Hacking

To add REST endpoints, edit endpoints.json, and then run

make generate

New code will be generated, and you can run your tests, or compile your program with it.

If you want to dump what go-slack is sending/receiving you can compile your program using the "debug0" tag. Just be aware that it will be very noisy:

go build -tags debug0 -o your-program your-code.go 

Acknowledgements

Based on github.com/nlopes/slack.