こんにちは。楽楽勤怠バックエンドチームの mako _makokです。 皆様はSlack アプリを開発されるときはどうやって開発されていますか? Hubotでしょうか?それともHttp Clientから直で叩いていますか? 今回はSlack API を簡単に使え、爆速でSlack アプリを開発するための フレームワーク Bolt のご紹介をさせていただきます。 Boltとは JavaScript Java Python スラッシュコマンドについて スラッシュコマンドの概要 スラッシュコマンドを登録する Boltを使う Slack API を叩いてみる スラッシュコマンドを作る レシーバーの作成 スラッシュコマンドのアクションを作成する 余談: Block Kit まとめ おまけ 参考 Boltとは Slack API チーム謹製のSlack API Client + スラッシュコマンド用のレシーバを兼ね備えた、Slack アプリ開発 用の フレームワーク です。 現時点では JavaScript (TypeScript), Java , Python の SDK が配布されています。 オープンソース で開発されていおり、 リポジトリ はそれぞれ以下です。 JavaScript 主にTypeScriptで開発されています。 型フレンドリーにSlack API を使用することができます。 github.com Java kotlin用のextensionやSpring BootやKtorなど Java , KotlinのWeb Frameworkへのextensionやサンプルなども豊富にあります。 github.com Python type hintフレンドリーな開発ができます。 一部独自のアプローチでSlack アプリが抱える問題を解決したりしています。 github.com どの言語でも細かな差はありますが、基本的なインターフェースは同じなので自身の好きな言語を選択してください。 今回は bolt-js を使用して解説していこうと思います。 スラッシュコマンドについて Boltの説明に入る前に、スラッシュコマンドについて説明します。 スラッシュコマンドは、Slack上で /foo のようにし、それをトリガーとして様々なアクションを行うことができます。 もし既にSlackをインストールしてあるのであれば、 / と入力してみてください。 デフォルトで登録されているいくつかのスラッシュコマンドが一覧表示されます。 続けて /remind と入力してみると、リマインダー登録用のモーダルが表示されると思います。 スラッシュコマンドの概要 スラッシュコマンドを簡略化すると、以下のように動いています。 スラッシュコマンドを入力すると、指定したエンドポイントにSlackからHttp Requestが送られてきます。 スラッシュコマンドを登録する スラッシュコマンドは https://api.slack.com/apps/{app_id}/slash-commands にアクセスし、 Create New Command を押すと以下の画面が出てきます。 Commandに登録したいスラッシュコマンド、Request URLにSlackからのリク エス トを受け取るエンドポイントを設定します。 Boltを使う Slack API を使うために、Boltの初期化をしていきます。 今回は bolt-js を利用するので、npmでインストールします。 プロジェクトを作成し、 npm install @slack/bolt とするだけでインストールが完了します。 TypeScriptはお好みで入れてください。 最初にAppを インスタンス 化します。 import { App } from '@slack/bolt' const app = new App ( { token: process .env.SLACK_BOT_TOKEN , signingSecret: process .env.SLACK_SIGNING_SECRET , } ) (async () => { // Start your app await app.start ( process .env.PORT || 3000 ); console .log ( '⚡️ Bolt app is running!' ); } )(); tokenとsingleSecretは以下から取得することができます。 singleSecret https://api.slack.com/apps/{app_id} token https://api.slack.com/apps/{app_id} Slack API を叩いてみる Boltの初期化は完了したので、実際にSlack API を叩いていきます。 以下は chat.postMessage を叩いて、チームメンバーが参加したらメッセージを送信するサンプルです。 app.event ( 'team_join' , async ( { event , client } ) => { try { await client.chat.postMessage ( { channel: 'foo' , text: `いらっしゃい、<@ ${ event.user.id } >! 🎉` , } ) } catch ( error ) { console .error ( error ) } } ) 第一引数にイベント名、第二引数にリスナーを設定します。 リスナーのclientは認証済みのものが渡されるので、すぐにSlack API を叩くことができます。 また、リスナーを介さずSlack API を叩くことも可能です。 App自体が WebClient を持っているので、tokenを都度渡して実行します。 await app.client.chat.postMessage ( { token: process .env.SLACK_BOT_TOKEN , channel: 'foo' , text: `いらっしゃい、<@ ${ event.user.id } >! 🎉` , } ) さらに、BoltにはSlack API を更に簡単に扱うためのユーティリティが用意されています。 例えば、更に簡単に chat.postMessage を実行できる say() 関数などがあります。 以下は「おはよう」というメッセージに反応して、「今日もいい天気!」と返す スクリプト です。 app.message ( 'おはよう' , async ( { message , say } ) => { await say ( `今日もいい天気!` ); } ); say() 関数はチャンネルが特定できるイベントであれば、使用することができます。 スラッシュコマンドを作る Boltでは簡単にスラッシュコマンドを作ることができます。 レシーバーの作成 Slackからのリク エス トを受け取ってレスポンスを返すレシーバー、以下のように設定します。 import { App , ExpressReceiver } from '@slack/bolt' export const expressReceiver = new ExpressReceiver ( { signingSecret: process .env.SLACK_SIGNING_SECRET , endpoints: '/events' } ) export const app = new App ( { receiver: expressReceiver , token: process .env.SLACK_BOT_TOKEN } ) ExpressReceiver を App に渡すだけで、簡単にレシーバーの設定をすることができます。 エンドポイントは /events と記載してありますが、実際のルーティングは /slack/events となるので注意してください。 このエンドポイントを「スラッシュコマンドについて」で紹介した、Request URLに設定して準備完了です。 スラッシュコマンドのアクションを作成する スラッシュコマンドを入力されたときのアクションを書いていきます。 今回は /register-word というスラッシュコマンドが入力されると、モーダルが開き、情報を入力してsubmitすると入力された内容が送信され、それを受けとるサンプルです。 const close: PlainTextElement = { type : 'plain_text' , text: 'キャンセル' } const submit: PlainTextElement = { type : 'plain_text' , text: '登録' } function buildBlocks () : KnownBlock [] { const keywordInput: InputBlock = { type : 'input' , block_id: 'keyword' , label: { type : 'plain_text' , text: '検索ワード' , } , element: { type : 'plain_text_input' , action_id: 'keyword_input' , } , } // ... return [ keywordInput ] } const VIEW_ID = 'dialog_1' export const register = ( app: App ) => { app.command ( '/register-word' , async ( { ack , body , context , command } ) => { await ack () try { await app.client.views.open ( { token: context.botToken , trigger_id: body.trigger_id , view: { type : 'modal' , callback_id: VIEW_ID , title: { type : 'plain_text' , text: '検索ワードの登録' , } , blocks: buildBlocks (), private_metadata: command.channel_id , close , submit } , } ) } catch ( err ) { console .error ( err ) } } ) app.view ( VIEW_ID , async ( { ack , view , context , body } ) => { await ack () const values = view.state.values const keyword = values.keyword.keyword_input.value // ... } ) } まず app.command でスラッシュコマンドを待機します。 app.command ( '/register-word' , async ( { ack , body , context , command } ) => { } 最初に ack() 関数を実行します。 この関数はSlackに対して即座にレスポンスを返すことができます。 スラッシュコマンドは3秒以内にレスポンスを返さないといけないというルールがあるので、まずはレスポンスを返します。 後続の処理は非同期で実行されます。 await ack () スラッシュコマンドを受け取ったら views.open を叩きます。 この API では Block Kit で作成されたViewを表示することができます。 submitに登録されているオブジェクトがクリックされると実際にsubmitされます。 submitされたフォームのデータは app.view で受け取ることができます。 app.view ( VIEW_ID , async ( { ack , view , context , body } ) => { await ack () const values = view.state.values const keyword = values.keyword.keyword_input.value // ... } ) views.open で設定された callback_id を検知して発火します。 フォームの中身は view.state.values の中にあります。 values以下のオブジェクト構造は views.open で使用しているBlock Kit内で決めることができます。 const keywordInput: InputBlock = { type : 'input' , block_id: 'keyword' , label: { type : 'plain_text' , text: '検索ワード' , } , element: { type : 'plain_text_input' , // action_idがvalues以下のプロパティとなる action_id: 'keyword_input' , } , } 余談: Block Kit Block Kitを利用することで、複雑なUIを表現する事ができます。 Block Kitについては公式のドキュメントがわかりやすいです。 api.slack.com また、 Block Kit Builder というツールもあり、プレビューしながらUIを構築することが可能です。 まとめ 今回はBoltについて紹介させていただきました。 今回紹介しきれなかった機能もたくさんあるので、みなさんもぜひ触ってみてSlackアプリを作ってみてください。 改めて、Boltのメリットをまとめます。 Slack API チームがメンテナンスしているので、信頼性が高い 型安全にSlack API を扱うことができる Slack API を簡単に使うための便利なユーティリティ スラッシュコマンド用のレシーバーを簡単に生成できる おまけ Bolt + Firestore + Cloud Functions 成果物として、スラッシュコマンドからワード登録モーダルを開き、毎朝バッチで勉強会情報を通知してくれるサンプルを作ってみました。 よろしければ参考にしてみてください。 github.com 参考 Bolt入門ガイド( https://slack.dev/bolt-js/ja-jp/tutorial/getting-started ) Slack API ( https://api.slack.com/apis ) Bolt for JavaScript を使った Slack アプリ開発 で知っておくと捗る 7 つのこと( https://qiita.com/seratch/items/dcedc7476eac5f681d30 ) ※冒頭画像のSlackロゴは、 公式サイト で配布されているものを使用しております。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com