Published: 2019-11-24
Updated: 2020-02-11
OAuth 権限設定についての変更がありましたので、チュートリアルのその設定部分を編集しました。
先日おこなわれた TinySpec Osaka & Tokyo でお約束した通り、日本語の App Home チュートリアルを書きました。
今回新しくリリースされた機能、App Home は、ユーザと Slack を1対1で繋ぐことができるスペースで、さらにユーザに直感的にアプリを使ってもらうために加えられた機能なのです。App Home には3つのタブがあり、アプリについての情報をみるための About、チャット対話式ボット機能がある場合にそのボットとダイレクトメッセージで会話できる Messages、そして今回新しく Home タブが加わりました。
この Home タブは、アプリと各ユーザの間を繋ぐプライベート・スペースで、動的で継続的なコンテンツを提供できるビジュアル・インターフェイスなのです。
App Home って前からあったよね?
もしかしてすでに、ユーザがアプリを開いた時に発生するイベント、 app_home_opened
をご存知かもしれません。以前に紹介した Bolt JavaScript framework チュートリアルの Hello world, Bolt⚡️ Bolt フレームワークを使って Slack Bot を作ろう でも触れられています。今回はさらにそれがバージョンアップして、 Home タブとともに、メッセージだけではなく Block Kit を使って動的なコンテンツを表示するとこが可能になりました。
App Home タブ活用例
Google カレンダーの App Home タブ活用例を見てみましょう。
ユーザは Home タブから毎日のカレンダーを見ることができるだけではなく、予定への返答を変更したり、Zoom などのカンファレンス・コールへのジョインなどもここから行うことができるのです。
他、ミーティングなどの予定のある1分前に通知をする機能もついているのです。グーグル、グッドジョブ👍
🔨 App Home を実装してみよう
さて、この App Home をどうやって使うことができるのか、一緒にアプリを制作しながら試してみましょう。ここでは、ユーザがちょっとしたメモをとることができる Stickies(付箋)アプリを作ってみます。
ユーザー・フロー
ここでのユーザー・フローは下の通りになります。
- ユーザが Slackクライアントの左メニューからアプリ名をクリック
- アプリの Home タブが開く
- ユーザが Home ビュー上にある Add a stickie (メモの追加)ボタンをクリック
- モーダルが表示されるので、ユーザがメモ内容を入力し Create(作成)をクリック
- Home が自動的に更新され、入力内容が ビューに反映される
アプリケーション・フロー
ここでのアプリ側のフローは次の通りになります。
- ユーザが App Home をオープンすることにより
app_home_opened
イベントが発生し、アプリのサーバに情報が送信される - アプリは、そのイベント・ペイロードから user ID を抽出し
views.publish
メソッドによって、ボタン UI のある初期画面を表示 - ユーザがその “Add a Stickie” ボタンをクリックすることにより、そのインタラクションがトリガーされる
- アプリは
views.open
メソッドで入力フォーム UI のあるモーダルを表示 - ユーザがそのフォーム内容を送信することによって、
view_submission
のついたもうひとつのインタラクションがトリガーされる -
views.publish
メソッドで App Home ビュー表示を更新
さて、大まかなフローがわかったところで実際に Stickies アプリを作ってみましょう。 Glitch というサービス上にソースコードを置いてありますので "remix" してみましょう(リミックスとは GitHub の fork のような物、と思ってください)。このサービスではウェブ上でコードのエディットと実行ができますので、デプロイは不要なのでそのまま動かしてみましょう。
🎏🥫 Glitch でソースコードだけ覗いてみる
🎏🍴 Remix (fork) して自分で使う
⚙️ アプリのセットアップ
まずは Slack アプリの設定をしなければなりません。 Slack App マネージメント からアプリの作成をします。ポップアップが出ますのでそこでアプリの名称を設定し、アプリのインストール可の(=自分がアドミン権限を持つ)ワークスペースを選択してください。ない場合は新規でワークスペースを作成してから始めましょう。
今度は Features > OAuth & Permissions で Bot トークンのスコープを追加します。chat.write
を選択してください。 (実際にはこのサンプルアプリにはチャットの機能がありませんので、このスコープを使う必要がないのですが、とりあえず追加してください! この最近追加された、以前より細やかになった権限設定については OAuth 2.0, Version 2 ドキュメントを参照してください。)
次に Features > App Home (下のスクリーンショットの、ステップ1参照)へ行ってください。
このサンプルアプリではダイレクトメッセージは使用しませんが、Message タブはそのまま有効のままでも良いでしょう。
次に Features > Event Subscription 画面へ行き、イベントを有効にしてください。(下のスクリーンショットのステップ1参照)。そして Request URL (ステップ 2) を入力します。Glitch 上のコードをリミックスして作業を進めている方は、 Request URL は https://プロジェクト名.glitch.me/slack/events
のようになります。 (Glitch は新規でプロジェクトが作成される毎にプロジェクト名を自動生成します。 たいがいはハイフンで繋いだ2つの英単語からランダムに生成されるので、 fluffy-umbrella のようなものになっていると思います。自分でカスタムのプロジェクト名もつけられますので、その際はそのカスタム名を使ってください。自分のサーバを使用している際は、そのURL + /slack/events
にします。)
Request URL 入力が終わったら、Subscribe to bot events までスクロールし、 app_home_opened
イベントを加えてください (ステップ 3)。そして緑の Save Changes ボタンで保存します。(ステップ 4).
次は同じように Features > Interactive Components で Slack サーバにインタラクティブ・ペイロードの送信先を伝える必要があります。 ここでも Request URL を指定してください。URL は https://プロジェクト名.glitch.me/slack/actions
となります。そしてここでも Save Changes ボタンで変更を保存してください。
ここで一度インストールしましょう。 Features > OAuth & Permissions からインストールボタンで自分のワークスペースにこのアプリをインストールします。画面の指定にしたがってインストールしてください。一旦 OAuth を使ってのインストールプロセスが終了しましたら、次の場面でアクセス・トークンが発行されます。
さて、次はブラウザ上で使えるIDEの Glitch プロジェクト、またはお使いのコード・エディタに移りましょう。インストール終了時に発行された xoxb-
トークンをコピーし、環境変数ファイル、.env の SLACK_BOT_TOKEN
の値としてペーストしてください。
もう一つの環境変数である、 Signing Secret キーは、Slack App マネージメント画面の Settings > Basic information から取得することができます。
🖼 App Home を表示させよう
Express server で Node アプリをセットアップ
このチュートリアルでは、Node.js と Express サーバを使ってアプリを書いています。ここでは全ての API コールは、ごく一般的な HTTP リクエスト、レスポンスで行っていますので、Node 以外の言語をお使いの皆さんにも、ソースコードをみてもらえればどこでどのように API を呼び出しているかわかっていただけるかと思います。
⚡️ もっと簡単に Bolt フレームワークで書きたい!という方のためにも Bolt で書かれたソースコードも用意しています。しかしこのチュートリアルの説明そのものは Bolt や SDK、他のボット・フレームワークを使わない「バニラ」コードでの説明となります。
まず Node コードで、依存モジュールを追加して Express サーバを走らせます。そして raw リクエスト・ペイロードを使ってリクエスト情報の認証をします。詳しい説明は割愛しますが、index.js の 31 - 38 行目を参照してください。 143 -145 行目では Express サーバを実行しています。
リクエスト情報の認証についてもう少し詳しく知りたい方は、以前書いたチュートリアルの Slack メッセージ・アクション API を使ってディスカバラブルなアプリを作ろう の中のセクション、🔐 リクエスト情報の認証)を読んでみてください。
app_home_opened
イベント・ペイロードを受け取るアプリケーション・エンドポイント
次に HTTP POST のルーティングメソッドを使って、イベントペイロードを受け取るエンドポイントを定義します(前のステップで設定した、Request URL)。何かのイベントが発生した際にはこのエンドポイントに Slack API からの JSON ペイロード情報が届くので、そこでイベントが app_home_opened
であるかチェックし、そうであれば App Home ヴューを表示させる準備をします。
ここでは、読みやすさを考え、簡略化されたコード・スニペットを使っていますが、全てみたい方は、 index.js 45 - 70 行目)をみてください:
app.post('/slack/events', async(req, res) => {
const {type, user, channel, tab, text, subtype} = req.body.event;
if(type === 'app_home_opened') {
displayHome(user);
}
}
さて、ビューの表示には、リッチなコンテンツを Block Kit を使って構築しましょう:
const displayHome = async(user, data) => {
const args = {
token: process.env.SLACK_BOT_TOKEN,
user_id: user,
view: await updateView(user)
};
const result = await axios.post('/views.publish', qs.stringify(args));
};
Home App にコンテンツを表示させるには view.publish
メソッドを使います。 ここでは axios
モジュールをを使って HTTP POST 経由で API を呼び出しています。
Block Kit でリッチ・コンテンツを構築
ここでの例では、別の関数、updateView
を呼んでコンテンツを JSON で構築しています。この関数は Home ビュー UI を更新する毎に呼びだしています。
初期 UI の設定はこのようになります:
const updateView = async(user) => {
let blocks = [
{
// Section with text and a button
type: "section",
text: {
type: "mrkdwn",
text: "*Welcome!* \nThis is a home for Stickers app. You can add small notes here!"
},
accessory: {
type: "button",
action_id: "add_note",
text: {
type: "plain_text",
text: "Add a Stickie"
}
}
},
// Horizontal divider line
{
type: "divider"
}
];
let view = {
type: 'home',
title: {
type: 'plain_text',
text: 'Keep notes!'
},
blocks: blocks
}
return JSON.stringify(view);
};
blocks
配列部分は、Block Kit をつかったプロトタイプはこちらから見ることができます。
実際のコードでは、この関数では、モーダルからユーザ入力された値を使い動的なコンテンツを扱います。この部分は後ほど。
ユーザのボタンクリックのハンドリング
Block Kit メッセージ・ビルディングブロックには action_id
を定義してください。これはデータを受け取る識別子となります。(ここでは add_note
)。
ユーザがボタンをクリックすると API サーバから Request URL に送信されるこのアクションについてのペイロードには trigger_id
が含まれます。これはモーダルを開くための識別子となります。
app.post('/slack/actions', async(req, res) => {
const { token, trigger_id, user, actions, type } = JSON.parse(req.body.payload);
if(actions && actions[0].action_id.match(/add_/)) {
openModal(trigger_id);
}
});
モーダルを開く
次に入力フォーム・エレメントを、モーダルの中に表示しましょう。この例ではごくシンプルに、付箋にメモするテキストを入力するマルチライン(複数行)インプット・ボックスと、付箋の色を指定するドロップダウン・メニューを表示させます。
モーダルを表示させるには views.open
メソッドを呼びます:
const openModal = async(trigger_id) => {
const modal = {
type: 'modal',
title: {
type: 'plain_text',
text: 'Create a stickie note'
},
submit: {
type: 'plain_text',
text: 'Create'
},
blocks: [
// Text input
{
"type": "input",
"block_id": "note01",
"label": {
"type": "plain_text",
"text": "Note"
},
"element": {
"action_id": "content",
"type": "plain_text_input",
"placeholder": {
"type": "plain_text",
"text": "Take a note... "
},
"multiline": true
}
},
// Drop-down menu
{
"type": "input",
"block_id": "note02",
"label": {
"type": "plain_text",
"text": "Color",
},
"element": {
"type": "static_select",
"action_id": "color",
"options": [
{
"text": {
"type": "plain_text",
"text": "yellow"
},
"value": "yellow"
},
{
"text": {
"type": "plain_text",
"text": "blue"
},
"value": "blue"
}
]
}
}
]
};
const args = {
token: process.env.SLACK_BOT_TOKEN,
trigger_id: trigger_id,
view: JSON.stringify(modal)
};
const result = await axios.post('/views.open', qs.stringify(args));
};
一見長いコードですが、ほとんどは JSON で UI を描いているだけです。 Block Kit プロトタイプはここから見ることができます。
フォーム・サブミッションのハンドリング
ユーザからのフォーム・サブミッションのハンドリングは、ボタンクリックのハンドリングと同じようにすることができます。
モーダル内のフォームがサブミットされた際には、このアクションのエンドポイントにペイロードが届きます。ボタンクリック時と区別するにはペイロードに含まれる type
の値をチェックしてください:
app.post('/slack/actions', async(req, res) => {
const { type, user, view } = JSON.parse(req.body.payload);
else if(type === 'view_submission') {
res.send(''); // Make sure to respond to the server to avoid an error
const data = {
note: view.state.values.note01.content.value,
color: view.state.values.note02.color.selected_option.value
}
displayHome(user.id, data);
}
});
この部分のコード全てを見るには index.js 107 - 133 行を参照してください。
App Home ビューの更新
ここでユーザから追加されたデータを元のデータに追加して、 Home タブの内容を
views.publish
メソッドと使って書き換えます。
このサンプルコードでは、単純化するために永続データの格納に node-json-db
モジュールを使用しています。ユーザが新しいメモを追加する毎に、そのデータが下のデータ配列にプッシュされていきます。
その新しいデータを、元の JSON にアペンドしてできた新たな UI ブロックを、 views.publish
メソットで再表示しています。
実際のソースコードは appHome.js の 17 - 152 行をみてみてください。このあたりは自分の好きなように処理してみてください。
アプリを実行してみよう
さて、これで一通りアプリが動くはずですので試してみましょう。Slack クライアントのサイドメニューの App でみられるアプリ一覧からこの Stickies! アプリを探してクリックしてみてください。無事、App Home が表示されましたか?
Add a Stickie ボタンを押して、新しい付箋が Home ビューに反映されたか確認してみてください。🎉
よりよいユーザ・エクスプリエンスを確立するには
さて、このチュートリアルが、新しいアプリを作る、もしくは既存のアプリをアップデートするためのインスピレーションになっていただけたらうれしいです。
ここでは views
メソッドを用いた基本的な App Home 構築について書きましたが、次のチュートリアルでは、Shay DeWael (シェイ・デワエル)がベスト・プラクティスについて書いてゆきますので乞うご期待!
📄Related Slack API Documentation
- Surfaces for building Slack apps Slack Platform documentation
- app_home_opened Event type Slack Events API documentation
- [Using
app_home_opened
for onboarding] (https://api.slack.com/reference/app-home) Slack Platform documentation
ご質問などがありましたら、私、 Tomomi @girlie_mac か @SlackAPIへ日本語もしくは英語でツイートするか、feedback@slack.com に連絡ください!
原文(英語): Building a home for your app 🏡 by Tomomi Imura (Slack)