Last active
August 14, 2023 16:16
-
-
Save seratch/f10a868249c5503ac734d7fab6e63960 to your computer and use it in GitHub Desktop.
Slack Socket Mode in Go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module socket-mode-app | |
go 1.15 | |
require github.com/slack-go/slack v0.8.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
go mod init socket-mode-app | |
go get github.com/slack-go/slack@v0.8.0 | |
vi main.go | |
export SLACK_APP_TOKEN=xapp-{your own value} | |
export SLACK_BOT_TOKEN=xoxb-{your own value} | |
go run main.go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"github.com/slack-go/slack/socketmode" | |
"log" | |
"os" | |
"strings" | |
"github.com/slack-go/slack" | |
"github.com/slack-go/slack/slackevents" | |
) | |
func main() { | |
webApi := slack.New( | |
os.Getenv("SLACK_BOT_TOKEN"), | |
slack.OptionAppLevelToken(os.Getenv("SLACK_APP_TOKEN")), | |
slack.OptionDebug(true), | |
slack.OptionLog(log.New(os.Stdout, "api: ", log.Lshortfile|log.LstdFlags)), | |
) | |
socketMode := socketmode.New( | |
webApi, | |
socketmode.OptionDebug(true), | |
socketmode.OptionLog(log.New(os.Stdout, "sm: ", log.Lshortfile|log.LstdFlags)), | |
) | |
authTest, authTestErr := webApi.AuthTest() | |
if authTestErr != nil { | |
fmt.Fprintf(os.Stderr, "SLACK_BOT_TOKEN is invalid: %v\n", authTestErr) | |
os.Exit(1) | |
} | |
selfUserId := authTest.UserID | |
go func() { | |
for envelope := range socketMode.Events { | |
switch envelope.Type { | |
case socketmode.EventTypeEventsAPI: | |
// Events API: | |
// Acknowledge the eventPayload first | |
socketMode.Ack(*envelope.Request) | |
eventPayload, _ := envelope.Data.(slackevents.EventsAPIEvent) | |
switch eventPayload.Type { | |
case slackevents.CallbackEvent: | |
switch event := eventPayload.InnerEvent.Data.(type) { | |
case *slackevents.MessageEvent: | |
if event.User != selfUserId && | |
strings.Contains(strings.ToLower(event.Text), "hello") { | |
_, _, err := webApi.PostMessage( | |
event.Channel, | |
slack.MsgOptionText( | |
fmt.Sprintf(":wave: Hi there, <@%v>!", event.User), | |
false, | |
), | |
) | |
if err != nil { | |
log.Printf("Failed to reply: %v", err) | |
} | |
} | |
default: | |
socketMode.Debugf("Skipped: %v", event) | |
} | |
default: | |
socketMode.Debugf("unsupported Events API eventPayload received") | |
} | |
case socketmode.EventTypeInteractive: | |
// Shortcuts: | |
payload, _ := envelope.Data.(slack.InteractionCallback) | |
switch payload.Type { | |
case slack.InteractionTypeShortcut: | |
if payload.CallbackID == "socket-mode-shortcut" { | |
socketMode.Ack(*envelope.Request) | |
modalView := slack.ModalViewRequest{ | |
Type: "modal", | |
CallbackID: "modal-id", | |
Title: slack.NewTextBlockObject( | |
"plain_text", | |
"New Task", | |
false, | |
false, | |
), | |
Submit: slack.NewTextBlockObject( | |
"plain_text", | |
"Submit", | |
false, | |
false, | |
), | |
Close: slack.NewTextBlockObject( | |
"plain_text", | |
"Cancel", | |
false, | |
false, | |
), | |
Blocks: slack.Blocks{ | |
BlockSet: []slack.Block{ | |
slack.NewInputBlock( | |
"input-task", | |
slack.NewTextBlockObject( | |
"plain_text", | |
"Task Description", | |
false, | |
false, | |
), | |
// multiline is not yet supported | |
slack.NewPlainTextInputBlockElement( | |
slack.NewTextBlockObject( | |
"plain_text", | |
"Describe the task in detail with its timeline", | |
false, | |
false, | |
), | |
"input", | |
), | |
), | |
}, | |
}, | |
} | |
resp, err := webApi.OpenView(payload.TriggerID, modalView) | |
if err != nil { | |
log.Printf("Failed to opemn a modal: %v", err) | |
} | |
socketMode.Debugf("views.open response: %v", resp) | |
} | |
case slack.InteractionTypeViewSubmission: | |
// View Submission: | |
if payload.CallbackID == "modal-id" { | |
socketMode.Debugf("Submitted Data: %v", payload.View.State.Values) | |
socketMode.Ack(*envelope.Request) | |
} | |
default: | |
// Others | |
socketMode.Debugf("Skipped: %v", payload) | |
} | |
default: | |
socketMode.Debugf("Skipped: %v", envelope.Type) | |
} | |
} | |
}() | |
socketMode.Run() | |
} |
Hey @Shadrocks, checking the examples in their repository should be helpful. https://github.com/slack-go/slack/tree/master/examples
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is outstanding framework, can you provide any additional examples of how to use it? I have it running, but I don't know what to do with it after that?