Techtouch Developers Blog

テックタッチ株式会社の開発チームによるテックブログです

みんなで大喜利ができる SlackBot を作ったよ

この記事はテックタッチアドベントカレンダー7日目の記事です。

こんにちは、フロントエンドエンジニアの tsune です。

みなさんは年末といえば何を連想しますか?僕はお笑いが好きなので、今年の M-1 は誰が優勝するかな〜?とワクワクしています。個人的にはオズワルド推しなので頑張ってもらいたいです!

さて、本日の記事では僕が作った SlackBot について紹介したいと思います。

どんな Bot なの?

冒頭でも書いたとおり僕はお笑いが好きなので、会社の人と大喜利がしたくてしたくてたまりませんでした。その夢を叶えるために社内コミュニケーションツールの一環として作成したのが、今回紹介する Slack 上で大喜利ができるようになる Bot です。

上位の回答のみ回答者が明かされるシステムなので、スベる恐怖に怯えずに参加できるようデザインしています。また、簡単に参加できるように Slack 上でオペレーションが完結するよう心掛けました。

アーキテクチャ

heroku

SlackBot 本体は heroku で常駐する形で稼働しています。Bolt という Slack が提供しているフレームワークを用いて作成しています。

無料アカウントでは、初期状態だと550時間/月までしか利用できず稼働時間のマネージが必要です。クレジットカードを登録することで1000時間/月まで利用できるようになるので、無料アカウントでも常駐 bot の運用が可能になります。(※同一アカウントで他サービスを運用していない前提)

add-on を利用することでスケジューラージョブも利用できるので、定期実行で投稿することも可能です。

firebase

バックエンドには firebase を利用しています。

functions と express でエンドポイントを作成して、bot からのリクエストを受けて firestore 上のデータの取得と更新を行います。

SlackBot にまつわるフレームワーク

Bolt

Bolt とは、Slack が提供しているフレームワークです。Slack API をラップして使いやすくすることで 、Slack アプリケーションの開発を効率的に行えるようにしてくれます。

例として、以下の「お題を設定する際のフォーム」を作成するためのコードを記載します。

/* 入力フォーム */
await client.views
  .open({
    trigger_id: body.trigger_id,
    view: {
      type: 'modal',
      callback_id: CALLBACK_ID,
      title: {
        type: 'plain_text',
        text: 'お題の設定',
      },
      submit: {
        type: 'plain_text',
        text: '送信',
      },
      close: {
        type: 'plain_text',
        text: 'キャンセル',
      },
      blocks: [
        {
          type: 'input',
          block_id: TITLE_BLOCK_ID,
          element: {
            type: 'plain_text_input',
            action_id: TITLE_ACTION_ID,
            placeholder: {
              type: 'plain_text',
              text: '例: こんな結婚式は嫌だ',
            },
          },
          label: {
            type: 'plain_text',
            text: 'お題',
          },
        },
        {
          type: 'input',
          block_id: DUE_DATE_BLOCK_ID,
          element: {
            type: 'datepicker',
            action_id: DUE_DATE_ACTION_ID,
            placeholder: {
              type: 'plain_text',
              text: 'いつまで回答を受け付けますか?',
              emoji: true,
            },
          },
          label: {
            type: 'plain_text',
            text: '回答期限(目安。自動的に回答が締め切られることはあません)',
            emoji: true,
          },
        },
      ],
    },
  })

/* 入力フォームの値を受け取る */
app.view(CALLBACK_ID, async ({ ack, view, client, body, logger }) => {
  const title = view.state.values[TITLE_BLOCK_ID][TITLE_ACTION_ID].value
  const dueDate = view.state.values[DUE_DATE_BLOCK_ID][DUE_DATE_ACTION_ID].selected_date
  // データの加工やAPIへのリクエストなどをよしなにやる

上記のように object で内容を定義するだけで簡単にリッチなフォームを作成できます。

ユーザーの入力値は callback_id block_id action_id をキーとして受け取ることができます。

BlockKit

Slack のメッセージを送るにあたって、BlockKit によってリッチなデザインを構築することができるので簡単に紹介したいと思います。

例として、以下の投票を行う Block のコードを記載します。

[
  {
    type: 'section',
    text: {
      type: 'mrkdwn',
      text: `:speaking_head_in_silhouette: *${kotaeContent}*`,
    },
    accessory: {
      type: 'overflow',
      options: [
        {
          text: {
            type: 'plain_text',
            text: `:first_place_medal: ${convertVoteRankText(1)} - 1票のみ`,
          },
          value: 'first-rank-vote',
        },
        {
          text: {
            type: 'plain_text',
            text: `:second_place_medal: ${convertVoteRankText(2)} - 1票のみ`,
          },
          value: 'second-rank-vote',
        },
        {
          text: {
            type: 'plain_text',
            text: `:third_place_medal: ${convertVoteRankText(3)} - 複数投票可`,
          },
          value: 'third-rank-vote',
        },
      ],
      action_id: ACTION_ID,
    },
  },
]

上記の例では、accessory の overflow という形式を利用して、投票の種類を選択する UI を実現しています。

おわりに

ライブラリを利用することで、想像以上に簡単にインタラクティブな SlackBot を開発することができました。

SlackBot は今回のような社内コミュニケーションから、業務効率化まで、様々な分野で活用できると思うので、みなさんも是非作成してみてください!