mike-neckのブログ

Java or Groovy or Swift or Golang

Slack の Bolt フレームワークを Spring Boot + Kotlin で試してみた

Slack の Bolt フレームワークJava でもリリースされたということなので、早速試してみた

slack.dev


まずは gradle スクリプトを準備する。なお、普通に curl https://start.spring.io/build.gradle -d dependencies=configuration-processor,web -d language=kotlin -d javaVersion=11 して出てきた結果に手を少し加えただけである。

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
  id("org.springframework.boot") version "2.2.5.RELEASE"
  id("io.spring.dependency-management") version "1.0.9.RELEASE"
  kotlin("jvm") version "1.3.61"
  kotlin("plugin.spring") version "1.3.61"
  kotlin("kapt") version "1.3.61"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

configurations {
  compileOnly {
    extendsFrom(configurations.kapt.get())
  }
}

repositories {
  mavenCentral()
}

dependencies {
  implementation("org.springframework.boot:spring-boot-starter-actuator")
  implementation("org.springframework.boot:spring-boot-starter-web")

  kapt("org.springframework.boot:spring-boot-configuration-processor")

  implementation("org.jetbrains.kotlin:kotlin-reflect")
  implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
  implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

  // bolt を追加した
  implementation("com.slack.api:bolt:1.0.1")
  implementation("com.slack.api:bolt-servlet:1.0.1")

  testImplementation("org.springframework.boot:spring-boot-starter-test") {
    exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
  }
}

tasks.withType<Test> {
  useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
  kotlinOptions {
    freeCompilerArgs = listOf("-Xjsr305=strict")
    jvmTarget = "11"
  }
}

bolt が slack に投稿できるようにするために、 bot ユーザーのトークンとシークレットが必要になる。それを application.properties に記載できるようにする。また、それら 2 つの値は bolt の AppConfig というオブジェクトを通じて App クラスに渡すので、このクラスで生成できるようにしておく。

@ConstructorBinding
@ConfigurationProperties("bolt")
data class BoltConfig(
    val token: String,
    val secret: String
) {
  fun appConfig(): AppConfig =
      AppConfig.builder().singleTeamBotToken(token).signingSecret(secret).build()
}

次に、bolt アプリケーションの本体を表象する Appインスタンスと、 bolt のコントローラーを提供する SlackAppServlet を bean 登録する。

@EnableConfigurationProperties(BoltConfig::class)
@SpringBootApplication
class BoltExampleAppApplication {
  @Bean
  fun app(
      boltConfig: BoltConfig): App =
    App(boltConfig.appConfig())
      .command("/hello") { req, context -> context.ack("hello :groovy:") }

  @Bean
  fun slackAppServlet(app: App): ServletRegistrationBean<SlackAppServlet> =
      ServletRegistrationBean(SlackAppServlet(app), "/slack/events")
}

あとは main メソッドを用意するだけでよい

fun main(args: Array<String>) {
  runApplication<BoltExampleAppApplication>(*args)
}

サーブレットアプリケーションなので、それを動かすサーバーを建てる必要があるのだが、 ngrok が紹介されていたので、それを使うことにした。

ngrok は以下の手順で使えるようになった

  • github アカウントでログイン
  • ngrok のバイナリをダウンロード
  • パスを通す
  • トークンの設定を行うコマンド(ngrok のページに表示されている)を実行する

特に指定してなければ、ローカルで 8080 ポートで実行されているので、

ngrok http 8080

でインターネットからリクエストが送れるようになる


接続

api.slack.com

こちらのページから、アプリケーションを作るか、選ぶかする

次に、 Features / Slash Commands の画面を左のメニューから選択する

f:id:mike_neck:20200320145226p:plain

Create New Command ボタンを押して、コマンド、URL 、 説明等を入力する。 URL は ngrok を起動した時に表示されている URL に パスを追加したものを入れる(個々での例だと、 ngrok が https://aabbcc.ngrok.io なら https://aabbcc.ngrok.io/slack/events)

次に 左のメニューから Features / OAuth & Permissions を選択して、 Install App to Workspace を選ぶ。すると Bot User OAuth Access Token を取得する。

次に Settings / Basic Information を選び、 App Credentials の中から Signing Secret を取得する。

この2つの値が BoltConfig に渡せるように、 application.properties を記述する。

bolt.token=Bot User OAuth Access Token の値
bolt.secret=Signing Secret の値

これで、 Spring Boot アプリケーションを起動する。

Slack から /hello と入力すると、次のように表示される

f:id:mike_neck:20200320150212p:plain