23
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Slack ć‚½ć‚±ćƒƒćƒˆćƒ¢ćƒ¼ćƒ‰ć®ęœ€ć‚‚ē°”å˜ćŖå§‹ć‚ę–¹ (Go ē·Ø)

23
Last updated at Posted at 2021-01-19

slack-go/slack ćŒć‚½ć‚±ćƒƒćƒˆćƒ¢ćƒ¼ćƒ‰ć«åÆ¾åæœ :tada:

åŗƒćä½æć‚ć‚Œć¦ć„ć‚‹ Go SDK 恮 github.com/slack-go/slack ćŒć‚½ć‚±ćƒƒćƒˆćƒ¢ćƒ¼ćƒ‰åÆ¾åæœć—ć¾ć—ćŸ :tada: @mumoshu さんと @kanata2 さんの瓠晓らしい仕事です :clap:

ć‚½ć‚±ćƒƒćƒˆćƒ¢ćƒ¼ćƒ‰ć‚¢ćƒ—ćƒŖčµ·å‹•ć¾ć§ć®ę‰‹é †

ć“ć®čØ˜äŗ‹ć§ćÆć€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

ę¬”ć®ć‚¹ćƒ†ćƒƒćƒ—

ć‚Ŗćƒ•ć‚£ć‚·ćƒ£ćƒ«ć®ć‚µćƒ³ćƒ—ćƒ«ć‚³ćƒ¼ćƒ‰ćÆä»„äø‹ć®å “ę‰€ć«ć‚ć‚Šć¾ć™ć®ć§ć€ćƒć‚§ćƒƒć‚Æć—ć¦ćæć¦ćć ć•ć„ć€‚

23
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?