Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jacob-ian/slap
Easily build Slack Apps with Go
https://github.com/jacob-ian/slap
go golang slack slack-bot
Last synced: 2 days ago
JSON representation
Easily build Slack Apps with Go
- Host: GitHub
- URL: https://github.com/jacob-ian/slap
- Owner: jacob-ian
- License: bsd-3-clause
- Created: 2024-02-29T05:38:40.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2024-03-18T05:06:59.000Z (8 months ago)
- Last Synced: 2024-06-21T14:08:11.302Z (5 months ago)
- Topics: go, golang, slack, slack-bot
- Language: Go
- Homepage: https://pkg.go.dev/github.com/jacob-ian/slap
- Size: 41 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Slap: Easily build Slack Apps with Go
A Slack application framework inspired by [Slack's Bolt Framework](https://api.slack.com/bolt) and the `net/http` library.
## Examples
### Slash Commands
```go
app.RegisterCommand("/hi", func(req *slap.CommandRequest) error {
// Respond with 200 and an ephemeral message immediately
req.AckWithAction(slap.CommandResponseAction{
ResponseType: slap.RespondEphemeral,
Text: "Hi, how are you?"
})// Send another message!
channel, ts, err := req.Client.PostEphemeral(req.Payload.ChannelID, req.Payload.UserID, slack.MsgOptionText("You said: " + req.Payload.Text))
if err != nil {
return err
}// Open a modal!
res, err := req.Client.OpenView(req.Payload.TriggerID, slack.ModalViewRequest{
Type: "modal",
CallbackID: "form-modal",
Title: &slack.TextBlockObject{
Type: "plain_text",
Text: "Form"
}
...
})return nil
})
```
### View Submissions
```go
app.RegisterViewSubmission("form-modal", func(req *slap.ViewSubmissionRequest) error {
// Get a value from the view submission
text := req.Payload.View.State.Values["text-input"]["text-input"]
if !isTextValid(text) {
// Respond with 200 and an error visible to the user
req.AckWithAction(slap.ViewResponseAction{
ResponseAction: slap.ViewResponseErrors,
Errors: map[string]string{
"text-input": "Please input a valid sentence"
}
})
return nil
}// Close the modal stack using the "clear" response action
req.AckWithAction(slap.ViewResponseAction{
ResponseAction: slap.ViewResponseClear
})// Do something with the text value - save it to a store with the user's ID
if err := store.save(req.Payload.User.ID, text); err != nil {
return err
}return nil
})```
### Block Actions
```go
app.RegisterBlockAction("start-button", func(req *slap.BlockActionRequest) error {
// Respond to Slack with 200
req.Ack()// Open a modal!
res, err := req.Client.OpenView(req.Payload.TriggerID, slack.ModalViewRequest{
Type: "modal",
CallbackID: "form-modal",
Title: &slack.TextBlockObject{
Type: "plain_text",
Text: "Form"
}
...
})return nil
})
```### Events API
```go
app.RegisterEventHandler("message", func(req *slap.EventRequest) error {
// Parse the inner Events API event
var message slack.MessageEvent
if err := json.Unmarshal(req.Payload.Event, &message); err != nil {
return err
}// Respond to Slack with 200
req.Ack()// Ignore messages that your bot has sent or you will get stuck in recursive message hell
if message.BotId != "" {
return nil
}// Do something with the message
slog.Info("Received message", "message", message.Text)
_, _, err := req.Client.PostMessage(message.Channel, slack.MsgOptionText("You wrote: " + message.Text, false))
if err != nil {
return err
}return nil
})
```## Quick Start
1. Create a Slack App at [api.slack.com/apps](https://api.slack.com/apps) and install it to your workspace (_Settings -> Install App_)
1. Set the following environment variables from your Slack App Settings
```
export BOT_TOKEN={Settings -> Install App -> Bot User OAuth Token}
```
```
export SIGNING_SECRET={Settings -> Basic Information -> Signing Secret}
```
1. Add the following to your `main.go`
```go
package mainimport (
"net/http"
"os""github.com/jacob-ian/slap"
)func main() {
router := http.NewServeMux()app := slap.New(slap.Config{
Router: router,
BotToken: func(teamID string) (string, error) {
return os.Getenv("BOT_TOKEN"), nil
},
SigningSecret: os.Getenv("SIGNING_SECRET"),
})app.RegisterCommand("/start", func(req *slap.CommandRequest) error {
req.AckWithAction(slap.CommandResponseAction{
ResponseType: slap.RespondInChannel,
Text: "Hello world!",
})
return nil
})server := &http.Server{
Addr: ":4000",
Handler: router,
}
panic(server.ListenAndServe())
}
```
1. Run `go run main.go`
1. Use [ngrok](https://ngrok.com) to get a public URL for your local environment
1. Update your Slack App Settings:
1. Slash Commands -> Create New Command
- Command: `/start`
- Request URL: `https://{YOUR NGROK URL}/commands`
1. Use the `/start` command in your Slack Client## Usage Guide
### Slack API Settings
To use Slap, you will need to update your Slack App's settings at [api.slack.com/apps](https://api.slack.com/apps).
#### Slash Commands
For all Slash Commands:
- Request URL: `https://{YOUR PUBLIC URL}/commands`
#### Interactivity & Shortcuts
- Turn on Interactivity
- Request URL: `https://{YOUR PUBLIC URL}/interactions`
#### Event Subscriptions
- Enable Events
- Request URL: `https://{YOUR PUBLIC URL}/events`
- Slap will automatically complete URL verification
### Multiple Workspace Distribution
Slap supports app distribution to multiple workspaces with the `BotTokenGetter` in `slap.Config`:
```go
app := slap.New(slap.Config{
...,
BotToken: func(teamID string) (string, error) {
token, err := db.GetBotTokenByTeamID(teamID)
if err != nil {
return "", err
}
return token, nil
}
})
```
This allows for the fetching of a workspace's bot token from your store by the workspace's Team ID, which is then used by the Slack API client.## To Do
- [ ] Add shortcut support
- [ ] Add `view_closed` support
- [ ] Add `block_suggestion` support
- [ ] Add support for Gorilla Mux
- [ ] Add support for Echo## Special Thanks
Thank you to the contributors at [github.com/go-slack/slack](https://github.com/go-slack/slack) for creating and maintaining the Slack API client and types
which are needed to make Slap work.