Block Kit を使ってより情報的なレストラン検索コマンドを作ろう

By Tomomi Imura

Published: 2019-03-28
Updated: 2022-01-31

OAuth 権限設定についての変更がありましたので、チュートリアルのその設定部分の編集しました。

こんにちは、みなさんいかがお過ごしですか。さて最近、Slack の新しいメッセージ UI フレームワーク Block Kit がリリースされました。これを使えば皆さんの Slack アプリから送信できるメッセージがさらにリッチになり、例えばタスクのリストや投票結果などが一つのメッセージでより情報的になります。

Block Kit は、ビジュアルツール Block Kit Builder を使うとさらに簡単にプロトタイプでき、さらにこのツールで生成された JSON ストリングをコードにそのまま組み込むことができます。

このチュートリアルでは、検索結果を閲覧するユーザー体験を Block Kit を使ってメッセージを組み立てることでよりよくするための手順を紹介していきたいと思います。

はじめるのに必要なもの

このチュートリアルでは Node.js を使って Slash Command アプリを作成していきます。JavaScript または他のプログラミング言語の経験が必要です。

コードは、ブラウザ上でコードを実行できデプロイの必要もない、ウェブ IDE である Glitch を使用します。

まずは下のリンクから “remix” して始めましょう。リミックスとは GitHub でいう Fork のようなものだと思ってください。

🎏🥫 ソースコード: https://glitch.com/edit/#!/slash-blockkit

🎏🍴 Remix のリンク: https://glitch.com/edit/#!/remix/slash-blockkit

それから、ここではこのアプリをもっとおもしろくするために Yelp API を使用していますので、このサイトから Yelp Client ID と API key を取得してください。詳しくは Yelp ディベロッパー・サイトから。

では始めましょう。このアプリ上でのユーザーの手順は次の通りです。

  1. まずユーザが、/find-food [食のジャンル], [場所] (例 /find-food burrito, San Francisco) とコマンドを入力
  2. アプリが検索結果のレストランを表示

Slash Command に応答

まずは /find-food コマンドに応答してごくシンプルなテキストを返す、という Slash command から作っていきましょう。

アプリのセットアップ

まずは Slack App マネージメント でアプリの作成をします。

新規アプリを作成

次に slash command を加え、そのコマンド情報を入力します。ここでは /find-food としてみましょう。使われるパラメータは、食べ物と場所をコンマで区切った短い文になります。例えば /find-food pancake, shibuya のようになります。

コマンドを有効にすることによって commands という bot 権限スコープが自動的に追加されます。

Request URL は https://your-server/route となりますので Glitch から “remix” した際は Glitch がランダムな単語ふたつからなるプロジェクトネームを生成しますので、Request URL は https://sassy-shrimp.glitch.me/command のような感じになります。

Config

次に Settings > Basic information で Signing Secret key を取得します。

このキー情報と、Yelp API の認証情報は、🗝 .env ファイルに保管します。

SLACK_SIGNING_SECRET=fca39e3de...

YELP_CLIENT_ID=sIskJpLm5f...
YELP_API_KEY=ySz84qKNl...

(Glitch 上のサンプルコードには .env.sample というファイルを用意してあるので、それを .envにコピーし、認証情報を入力してください。)

下の Node.js コードでは依存するモジュールをインポートし、 Express サーバを動かしています。それからここでは、リクエスト署名(Signing Secret)を検証するために、リクエスト・ペイロードをそのまま受け取っています。(詳しくはこの日本語記事と、チュートリアルから。)

const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const signature = require('./verifySignature');

const app = express();

const rawBodyBuffer = (req, res, buf, encoding) => {
  if (buf && buf.length)  req.rawBody = buf.toString(encoding || 'utf8');
};

app.use(bodyParser.urlencoded({verify: rawBodyBuffer, extended: true }));
app.use(bodyParser.json({ verify: rawBodyBuffer }));

const server = app.listen(process.env.PORT || 5000);

シンプルなメッセージの送信

次に HTTP POST メソッドルートを使って Slash command のリクエスト・ペイロードを受け取るためのエンドポイントを作ります。受け取りの時にそのリクエストが正規に Slack からきているものかを確認します。検証結果が問題なかった場合にのみ、ユーザからのパラメータを受け取って、パースします。この場合、食べ物のジャンルと場所のクエリを受け取ります。

そのクエリを Yelp API に投げ、その結果を受け取ります。

app.post('/command', async (req, res) => {
  
  if(!signature.isVerified(req)) {
    res.sendStatus(404);     
    return;
    
  } else {
    const query = req.body.text ? req.body.text : 'lunch, San Francisco';
    const queries = query.split(',');
    const term = queries.shift(); // "Pizza" 
    const location = queries; // "San Francisco, CA"
    const places = await getPlaces(query, location);
  }
  
  const message = { // will generate it }
  res.json(message);
}

このコードでは getPlaces() 関数で Yelp API から結果をうけとる仕組みにしています。 (詳しくはソースコードを見てください。)

Yelp REST API から返された結果の JSON 配列は次のような感じになります。(チュートリアルをわかりやすくするために、 JSON の内容を簡略化しています)

[{ 
 name: 'Zero Zero',
 image_url:
  'https://s3-media2.fl.yelpcdn.com/bphoto/JB5XNOgdQHocE4nI9DHWkA/o.jpg',
 url:'https://www.yelp.com/biz/zero-zero-san-francisco',
 review_count: 3128,
 rating: 4,
 price: '$$',
 location:
  {
    display_address: [ '826 Folsom St', 'San Francisco, CA 94107' ] },
    phone: '+14153488800'
 }...
]

まず、この情報の一部を使って、コマンドを送信したユーザーにごく簡単なメッセージを返してみましょう。サーバには HTTP 200 のレスポンスをすれば良いのですが、この場合は JSON を返しましょう。Slack チャンネル上に全ユーザーに見えるようにメッセージする場合は下のような JSON を送信します。

const message = {
  response_type: 'in_channel',
  text: places[0].name,
}; 
res.json(message);

このレスポンスは Slack 上ではこう表示されます。

Message

Block Kit でメッセージにもっと情報を

さて、次は Block Kit エレメントで、このメッセージを、もっと情報の入った読みやすいメッセージにしましょう。

Block Kit は、組み立て可能のレイアウトやエレメントといったブロックで構成されています。

今からこれを使って、メッセージレイアウトを構成する JSON に書き換え、リッチなメッセージでレストラン情報を表示させましょう。

Block Kit message anatomy GIF

ビジュアル・サンドボックスである Block Kit Builder を使ってブラウザ上でデザインをプロトタイプしていきましょう。

左側にあるメニューからレイアウトもしくはエレメントを選んでいくと、真ん中にはプレビューが、右には生成された JSON 配列が表示されます。

Block Kit Builder GIF

生成されたコードをコピーして、前のコードの message オブジェクトの text: places[0].name 部分を下のように block として書き換えます。


const message = {
      response_type: 'in_channel',   
      blocks: [
        // Result 1
        {
          type: 'section',
          text: {
            type: 'mrkdwn',
            text: `*<${places[0].url}|${places[0].name}>* \n${places[0].location.display_address.join(' ')} \n\nRating: ${places[0].rating} \nPrice: ${places[0].price}`
          },
          accessory: {
            type: 'image',
            image_url: `${places[0].image_url}`,
            alt_text: 'venue image'
          }
        },       
        {
          'type': 'context',
          'elements': [
            {
              'type': 'plain_text',
              'text': `${places[0].review_count} Yelp reviews`,
              'emoji': true
            }
          ]
        },
        {
          'type': 'divider'
        },
     }
  ]
};

エレメントで text type 部分を mrkdwn とすることによってテキストに太字やリンクなどのマークダウンをしようすることもできます。詳しくは An overview of message composition(英語)から。

では、できあがった Slash command をクライアント上で試してみましょう!こんな感じに表示されましたか?🙆

more contexual message with Block Kit

いぇ〜い! でもなんだか、お腹すいてきたわ。

他にはどうやってリッチ・メッセージが送信できる?

さて、今回は Slash command の結果をリッチ・メッセージで送信してみましたが、他にもいろいろな機能を一緒に使えます。例えば incoming webhooks、Web API の chat.postMessagechat.postEphemeral メソッドで送信できます。アクションなどのインタラクティブ機能にも使うことができます。

ベスト・プラクティス

Block Kit Builder 上でメッセージレイアウトやエレメントをいろいろ試してみてクリエイティブなメッセージ UI を試してみてください。プロトタイプで遊んでみるのは大いに推奨しますが、ここで気をつけてもらいたいのは、実際のプロダクトとなる UI を構築するにはまず何よりもユーザーを第一に考えてください。メッセージは読みやすいものでなくてはなりません。可能だからと言って何もかも詰め込むのはよくありません。内容が多くなってしまう場合には、たとえば “Read more…” など、さらなるユーザーアクションを促すボタン機能などを追加するのもいいかもしれません。 いろいろプロトタイプを作ってテストしてみましょう。モバイルでのテストも忘れないでください。

このチュートリアルによって、なにか新しいアイデアが浮かんだり、前に作ったアプリの改良などをしてみたい、と思ってくれていたら幸いです!

ご質問やコメントがありましたら、開発者サポート (@SlackAPI または support@slack.com) までご連絡ください。


おすすめの関連記事 🦄