slack-go/slack ćć½ć±ććć¢ć¼ćć«åƾåæ
åŗć使ććć¦ćć Go SDK ć® github.com/slack-go/slack ćć½ć±ććć¢ć¼ć対åæćć¾ćć
@mumoshu ćć㨠@kanata2 ććć®ē“ ę“ćććä»äŗć§ć ![]()
ć½ć±ććć¢ć¼ćć¢ććŖčµ·åć¾ć§ć®ęé
ćć®čØäŗć§ćÆćSlack ć½ć±ććć¢ć¼ćć®ęćē°”åćŖå§ćę¹ć§ä½æć£ććµć³ćć«ć¢ććŖćØåććć®ćććć® Go SDK ć使ć£ć¦åććę¹ę³ć解説ćć¾ćć
ćććøć§ćÆććć¤ćć
ććć§ē“¹ä»ćććµć³ćć«ćÆ v0.8.0 仄äøć§åä½ćć¾ćć
go mod init socket-mode-app
go get github.com/slack-go/slack@v0.8.0
main.go ćēØę
ćØćććć仄äøć®ć½ć¼ć¹ć³ć¼ćććć®ć¾ć¾ć³ćććć¦ćæć¦ćć ććć
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:
// ć¤ćć³ć API ć®ćć³ććŖć³ć°
// 3 ē§ä»„å
ć«ćØćććć ack
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(event.Text, "ććć«ć”ćÆ") {
_, _, err := webApi.PostMessage(
event.Channel,
slack.MsgOptionText(
fmt.Sprintf(":wave: ććć«ć”㯠<@%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:
// ć·ć§ć¼ćć«ććć®ćć³ććŖć³ć°ćØć¢ć¼ćć«čµ·å
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",
"ćæć¹ćÆē»é²",
false,
false,
),
Submit: slack.NewTextBlockObject(
"plain_text",
"éäæ”",
false,
false,
),
Close: slack.NewTextBlockObject(
"plain_text",
"ćć£ć³ć»ć«",
false,
false,
),
Blocks: slack.Blocks{
BlockSet: []slack.Block{
slack.NewInputBlock(
"input-task",
slack.NewTextBlockObject(
"plain_text",
"ćæć¹ćÆ",
false,
false,
),
// multiline is not yet supported
slack.NewPlainTextInputBlockElement(
slack.NewTextBlockObject(
"plain_text",
"ćæć¹ćÆć®č©³ē“°ć»ęéćŖć©ćęøćć¦ćć ćć",
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:
// ć¢ć¼ćć«ććć®éäæ”ććć³ććŖć³ć°
if payload.CallbackID == "modal-id" {
socketMode.Debugf("Submitted Data: %v", payload.View.State.Values)
socketMode.Ack(*envelope.Request)
}
default:
socketMode.Debugf("Skipped: %v", payload)
}
default:
socketMode.Debugf("Skipped: %v", envelope.Type)
}
}
}()
socketMode.Run()
}
čµ·åćć
åć®čØäŗćØåę§ćē°å¢å¤ę°ćčØå®ććäøć§čµ·åćć¦ćæć¾ćććć
export SLACK_APP_TOKEN=xapp-<čŖåć®ćć¼ćÆć³ć®å¤>
export SLACK_BOT_TOKEN=xoxb-<čŖåć®ćć¼ćÆć³ć®å¤>
go run main.go
仄äøć®ćććŖć”ćć»ć¼ćøć蔨示ććć¦ććć°ćę„ē¶ć§ćć¦ćć¾ćļ¼
$ go run main.go
api: 2021/01/19 15:41:48 slack.go:125: Challenging auth...
sm: 2021/01/19 15:41:48 socket_mode_managed_conn.go:241: Starting SocketMode
sm: 2021/01/19 15:41:48 main.go:133: Skipped: connecting
api: 2021/01/19 15:41:48 socket_mode.go:30: Using URL: wss://wss-primary.slack.com/link/?ticket=xxx&app_id=yyy
sm: 2021/01/19 15:41:48 socket_mode_managed_conn.go:249: Dialing to websocket on url wss://wss-primary.slack.com/link/?ticket=xxx&app_id=yyy
sm: 2021/01/19 15:41:49 socket_mode_managed_conn.go:78: WebSocket connection succeeded on try 0
sm: 2021/01/19 15:41:49 socket_mode_managed_conn.go:422: Starting to receive message
sm: 2021/01/19 15:41:49 main.go:133: Skipped: connected
sm: 2021/01/19 15:41:49 socket_mode_managed_conn.go:464: Incoming WebSocket message: {
"type": "hello",
"num_connections": 1,
"debug_info": {
"host": "applink-xxx-yyy",
"build_number": 10,
"approximate_connection_time": 18060
},
"connection_info": {
"app_id": "A111"
}
}
sm: 2021/01/19 15:41:49 socket_mode_managed_conn.go:476: Finished to receive message
sm: 2021/01/19 15:41:49 socket_mode_managed_conn.go:422: Starting to receive message
sm: 2021/01/19 15:41:49 socket_mode_managed_conn.go:319: Received WebSocket message: {"type":"hello","num_connections":1,"debug_info":{"host":"applink-xxx-yyy","build_number":10,"approximate_connection_time":18060},"connection_info":{"app_id":"A111"}}
sm: 2021/01/19 15:41:49 main.go:133: Skipped: hello
sm: 2021/01/19 15:41:51 socket_mode_managed_conn.go:544: WebSocket ping message received: Ping from applink-xxx-yyy
ꬔć®ć¹ććć
ćŖćć£ć·ć£ć«ć®ćµć³ćć«ć³ć¼ććÆä»„äøć®å “ęć«ććć¾ćć®ć§ććć§ććÆćć¦ćæć¦ćć ććć