【君の名は。】 Slack Block Kit を使って社員情報を表示しちゃうスラッシュコマンド


Slack Advent Calendar 2019 の13日目を担当するコーポレートエンジニアの yamashu です。

これはなに

  • Slack のスラッシュコマンドで社員情報を表示してみちゃう試み
    • 人の顔と名前がわからないと仕事でそこそこ困る
    • でも、会社にいる人全員の顔と名前を覚えるのは人類には早すぎる
    • Slack でシュッと表示できたら嬉しみ
  • ソース全体はコチラ
  • 全体の動き
    • スラッシュコマンドで情報を見たい社員を入力
    • こう表示される

やること

  • Slack App セットアップ
  • Block Kit を使ってみる https://api.slack.com/block-kit
    • とてもリッチな UI
    • テンプレートを見ただけでもいろんなことができそうでドキドキする

やらないこと

  • 社員(ユーザ)の情報取得
    • 別の話題のため
    • 弊社だと SmartHR のカスタム社員名簿から取得しています
    • https://smarthr.jp/meibo/
    • 社員の情報をどこに溜めておくかはなかなか業が深い話…
  • Ruby で書いてますが Ruby の使い方とか

Slack App セットアップ

Create New App

Slash Commands

  • 今回はスラッシュコマンドで呼び出すので新しく設定する
  • Request URL にサーバのアドレスを入力する

OAuth & Permissions Scopes

  • 必要な権限をつける

Add Bot User

  • Bot を追加する

Install App to Workspace

  • 作成した App を Workspace にインストールする
  • token が発行されるので後で使います

サーバー側

Block Kit の準備

{
  "type": "section",
  "accessory": {
    "type": "image",
    "image_url": "#{profile_url}",
    "alt_text": "photo"
  },
  "fields": [
    {
      "type": "mrkdwn",
      "text": "*名前*\n#{profile_name}"
    },
    {
      "type": "mrkdwn",
      "text": "*社員番号*\n#{profile_emp_no}"
    },
    {
      "type": "mrkdwn",
      "text": "*グループ*\n#{profile_group}"
    },
    {
      "type": "mrkdwn",
      "text": "*役職*\n#{profile_position}"
    }
    {
      "type": "mrkdwn",
      "text": "*自己紹介*\n#{profile_url}"
    }
  ]
}

Web サーバーをたてる

  • 全体の流れ
    • スラッシュコマンドを受け取る
    • 従業員情報を取得する(今回は省略)
    • Slack に POST する
  • sinatra を使ってサクッと
  • slack-ruby-client を使うと Slack とのやり取りがとても楽
require 'sinatra'
require 'slack-ruby-client'

post '/' do
  begin
    # slack slash commands payload
    # @see https://api.slack.com/slash-commands
    req = URI.decode_www_form(request.body.read)
    request_slack_user_id = req.assoc('user_id').last
    requset_slack_channel_id = req.assoc('channel_id').last
    profile_slack_user_name = req.assoc('text').last

    slack_client = Slack::Web::Client.new(
      token: ENV['SLACK_BOT_TOKEN']
    )
    res = slack_client.users_info(user: profile_slack_user_name)
    profile_slack_user_email = res['user']['profile']['email']

    # Todo: get user profile
    profile_name = ""
    profile_photo_url = "https://a.slack-edge.com/80588/marketing/img/icons/icon_slack_hash_colored.png"  #dummy
    profile_emp_no = ""
    profile_group = ""
    profile_position = ""
    profile_url = ""

    block = [
      type: "section",
      accessory: {
        type: "image",
        image_url: profile_photo_url,
        alt_text: "photo"
      },
      fields: [
                {
          type: "mrkdwn",
          text: "*名前*\n#{profile_name}"
        },
        {
          type: "mrkdwn",
          text: "*社員番号*\n#{profile_emp_no}"
        },
        {
          type: "mrkdwn",
          text: "*グループ*\n#{profile_group}"
        },
        {
          type: "mrkdwn",
          text: "*役職*\n#{profile_position}"
        }
        {
          type: "mrkdwn",
          text: "*自己紹介*\n#{profile_url}"
        }
      ]
    ]

    slack_client.chat_postEphemeral(
      channel: requset_slack_channel_id,
      user: request_slack_user_id,
      blocks: block
    )

    return # slack response
  rescue => error
    'うまく探せなかった、ごめん :bow:'
  end
end

おわりに

こんなタイトルからしてふざけた記事を最後まで読んでいただき超絶感謝です
Slack 使って何かをつくるのはとても楽しいですね