Skip to content

Commit

Permalink
fix: adds documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ajpauwels committed Oct 9, 2023
1 parent 7828c75 commit 8fb2c1e
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 6 deletions.
112 changes: 111 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,113 @@
# slack-bot

Docs will be included here
This is a simple Slack bot that allows for any number of plugins
("handlers") to be added to it dynamically, allowing it to do any
number of totally custom actions by simply adding a bit of code that
conforms to a handler interface.

A handler can also be sourced from an external package for extra fun!

## Writing a new handler

New handlers can be added to the `pkg/handlers` module, they simply
need to conform to the `SlackSlashCommandHandler` interface defined in
the `pkg/slack/bot.go` file.

A description of each function of the interface is provided below.

```
Handle(arguments []string, request SlackSlashCommandBody) (*SlackResponse, error)
```

This is the primary meat of the interface, and is what the internal
Slack bot logic will call when a slash command is received from
Slack. A slash command looks a bit like this: `/bot-name [command]
[args...]`

The Slack bot code will call `Handle(...)` with the `[args...]`
provided in the `arguments` parameter. The `request` parameter
contains the raw request as sent by Slack in case any of that data is
necessary for handling. The `SlackSlashCommandBody` struct is also
defined in the `pkg/slack/bot.go` file.

Once the requested action has been handled, this function must return
either an error or a pointer to a `SlackResponse` struct, also defined
in `pkg/slack/bot.go`.

The `SlackResponse` type is simply the object expected by the Slack
API as a response to an interaction with the bot. It contains a
`ResponseType` field which should be set to either `ephemeral` if the
response should only be seen by the requester, or `in_channel` if it
should be seen by everyone in the channel. The `Text` field should be
the contents of that response.

Currently, this interface and workflow is simple and optimized for
receiving commands and providing a reponse in the channel. In the
future, it may be modified to support more complex workflows involving
modals or other more advanced Slack features.

```
CommandName() string
```

This should return a single word which is the expected command that a
user will pass in the Slack slash command to invoke this handler. As
an example, for the `EchoHandler` defined in `pkg/handlers/echo.go`,
the `CommandName()` function returns `echo`, which means it will be
called when a user types in `/bot-name echo ...`.

```
CommandArguments() string
```

This should return the list of arguments this command expects to
receive. It is used exclusively for when the bot generates the help
text available at `/bot-name help`.

```
CommandDescription() string
```

This should return a short text description of this handler, what it
does, and how to use it. It is used exclusively for when the bot
generates the help text available at `/bot-name help`.

## Adding a new handler to the bot

Once you've written a new handler, it needs to be added to the
initialization of the Slack bot. This is very simple, just go to
`cmd/slack-bot/main.go` and find the `CreateHandlers()` function. You
can call the constructors of your various handlers and add them to the
array returned here.

## Help text and other conveniences

Once the handler is written and added to `CreateHandlers()`, no
further action is required. Simply build and push your bot, the
internal bot logic will automatically handle the new command word and
will add a help text for your command to the `/bot-name help` command.

## Creating a Slack bot and connecting it to this code

1. Create a new Slack bot by logging in to your workpace on the Slack
website and then going to the New App page or clicking
[here](https://api.slack.com/apps?new_app=1).

2. Go to the OAuth & Permissions section and assign the `commands`
OAuth scope to your app.

3. Go to the Slash Commands section and create a new command using
whatever you want as the command text (typically the app name is a
good idea), so that the general flow is `/bot-name [handler name]
[args...]`. Set the URL to the URL that you've set up this Slack
bot to listen under.

4. Wherever this Slack bot runs, it needs its secret Slack signing key
in order to properly verify HTTP requests coming from Slack. Fetch
this signing key by going to the Basic Information section and
copying the Signing Secret to put it inside the `slack.signingkey`
value in the bot's config.

5. Install the app to your workspace by going to Basic Information >
Install your app. The slash command should now be available across
all channels in your workspace.
11 changes: 6 additions & 5 deletions cmd/slack-bot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,8 @@ func main() {

logger.Info("config", zap.Uint16("port", config.Port), zap.String("slack.signingkey", string(config.Slack.SigningKey)))

// Create the list of supported handlers
echoHandler := handlers.NewEchoHandler()
handlers := []slack.SlackSlashCommandHandler{echoHandler}

// Create slack bot server
slackBot := slack.NewSlackBot(config.Port, config.Slack.SigningKey, handlers)
slackBot := slack.NewSlackBot(config.Port, config.Slack.SigningKey, CreateHandlers())
logger.Info("starting server", zap.Uint16("port", config.Port))
err := slackBot.ListenAndServe(logger)

Expand All @@ -80,3 +76,8 @@ func main() {
}
}
}

func CreateHandlers() []slack.SlackSlashCommandHandler {
echoHandler := handlers.NewEchoHandler()
return []slack.SlackSlashCommandHandler{echoHandler}
}

0 comments on commit 8fb2c1e

Please sign in to comment.