こんにちは、Slack の公式 SDK 開発と日本の Developer Relations を担当している瀬良 (@seratch) と申します
Slack の次世代プラットフォーム機能を少しずつ試しながら、ゆっくりと理解していくシリーズを始めようと思います。「次世代プラットフォーム機能って何?」という方は、以下の記事で詳しく解説しましたので、まずはそちらをお読みください。
この記事では、最もシンプルな形で Hello World を試していきながら、このプラットフォームの基礎を理解していきましょう。
前提条件
初めて試される方は、こちらの記事の冒頭の注意点をお読みください。有料プランの Slack ワークスペースで、その管理者の方が機能を有効にしている必要があります。
それがすでに完了していれば、開発者の方は Slack CLI をインストールして、対象の Slack ワークスペースでの認証を完了する必要があります。詳しくは以下のページを参照ください。
この記事では、ここまでは完了している前提で進めます。
ブランクプロジェクトを作成
新しいプロジェクトを始めるには Slack CLI の slack create
を実行します。
$ slack create
? Select a template to build from:
> Hello World
A simple workflow that sends a greeting
Scaffolded project
A solid foundational project that uses a Slack datastore
Blank project
A, well.. blank project
To see all available samples, visit github.com/slack-samples.
実行すると「Hello World」というテンプレートが存在しています。これも良いサンプルプロジェクトなのですが、リンクトリガーを使って起動して、標準ファンクションの入力モーダルを起動、その入力値を使ってメッセージをチャンネルに投稿、とさまざまな要素が出てくる例となっています。
この記事では少しずつ理解していくために「Blank project」を選択して、ゼロからやっていきましょう。
プロジェクトが作成されたら、とりあえず slack run
で起動してみましょう。これをすることで、このアプリの開発版がワークスペースにインストールされます。
$ cd dreamy-gazelle-453
$ slack run
? Choose a workspace seratch T03E94MJU
App is not installed to this workspace
Updating dev app install for workspace "Acme Corp"
⚠️ Outgoing domains
No allowed outgoing domains are configured
If your function makes network requests, you will need to allow the outgoing domains
Learn more about upcoming changes to outgoing domains: https://api.slack.com/future/changelog
✨ seratch of Acme Corp
Connected, awaiting events
Connected, awaiting events
というメッセージが表示されて、そこで止まったらとりあえずは成功です。Ctrl + C で停止しても構いません。
次の手順からいよいよ設定を追加していきましょう。開発には Deno プラグインをインストールした VS Code で開発するのがおすすめです。
Incoming Webhooks で Hello World してみよう
まずは Incoming Webhooks を使ってワークフローを起動してみましょう。手順は以下の通りです。
-
hello_world.ts
を新しく作成する - チャンネル ID を入手して
hello_world.ts
を一行だけ書き換える - ワークフローを
manifest.ts
に追加する -
slack run
かslack install
してワークフロー設定を反映する -
slack triggers create --trigger-def ./hello_world.ts
でトリガーを作成する
となります。
より詳細な手順を以下にまとめます。
hello_world.ts
を新しく作成する
新しく hello_world.ts
というファイルを作って、以下の内容をそのまま貼り付けてください。
// -------------------------
// ワークフロー定義
// -------------------------
import { DefineWorkflow, Schema } from "deno-slack-sdk/mod.ts";
// この定義オブジェクトを manifest.ts で参照するのを忘れずに!
export const workflow = DefineWorkflow({
callback_id: "hello-world-workflow",
title: "Hello World Workflow",
input_parameters: {
properties: {},
required: [],
},
});
// 標準ファンクションを使ってメッセージを投稿
// channel_id は Slack UI 上から入手してください
workflow.addStep(Schema.slack.functions.SendMessage, {
channel_id: "C03E94MKS", // TODO: 変更する
message: "Hello World!",
});
// -------------------------
// トリガー定義
// -------------------------
import { Trigger } from "deno-slack-api/types.ts";
// Incoming Webhooks によるトリガー
const trigger: Trigger<typeof workflow.definition> = {
type: "webhook",
name: "Hello World Trigger",
// 上記のワークフローを参照する必要がある
workflow: `#/workflows/${workflow.definition.callback_id}`,
inputs: {},
};
// トリガーの作成には `slack triggers create --trigger-def [ファイルパス]` を実行する
// Trigger 形の定義オブジェクトを export default さえしていれば
// そのソースファイルを使用できる
export default trigger;
このファイルは、二つのことをやっています。
- このアプリに紐づくワークフローを新しく定義する
- そのワークフローを起動するためのトリガーを一つ定義する
ただ、これらをコードに書いただけではまだ設定は有効になりません。以下のステップで実際に使えるようにしていきます。
チャンネル ID を入手して hello_world.ts
を一行だけ書き換える
先ほど作成した hello_world.ts
のコードのうち、
channel_id: "C03E94MKS", // TODO: 変更する
という部分を変更します。
なお、この記事のサンプルの実行には、パブリックチャンネルを使ってください。
channel_id は Slack の UI 上でチャンネル名をクリックして表示されるモーダルの最下部にコピペできるように表示されている C 始まりの文字列を設定してください。
あるいは、そのチャンネルの任意のメッセージのメニューから Copy link して https://my.slack.com/archives/..
の次に表示されている階層をコピーする、でも OK です。
その文字列で上記のコードを書き換えてください。
ワークフローを manifest.ts に追加する
以下のように、定義したワークフローを Manifest オブジェクトに設定してください。
import { Manifest } from "deno-slack-sdk/mod.ts";
// 先ほど作ったワークフローを import する
import { workflow as HelloWorld } from "./hello_world.ts";
export default Manifest({
name: "dreamy-gazelle-453",
description: "Hello World",
icon: "assets/default_new_app_icon.png",
functions: [],
// 元々から配列だったここに import したワークフローを追加
workflows: [HelloWorld],
outgoingDomains: [],
botScopes: ["commands", "chat:write", "chat:write.public"],
});
slack run
か slack install
してワークフロー設定を反映する
この状態で slack run
コマンドを実行してください。これをすることで今作ったワークフローの設定内容が Slack のクラウド環境に反映されます。一旦 Ctrl + C で止めても大丈夫です。
・・というか、別のターミナルウィンドウを開いて、そこで slack run
を起動しっぱなしでもよいです。
slack triggers create --trigger-def ./hello_world.ts
でトリガーを作成する
上記ワークフローが反映されたので、そのワークフローのトリガーを作成できるようになります。もし上の手順をスキップするとワークフローが見つからないという旨のエラーになるので注意してください。
作成するときに選択肢が二つ出てくるかと思いますが、下の方の (dev)
という表記がついている方を選択してください。
$ slack triggers create --trigger-def ./hello_world.ts
? Choose an app [Use arrows to move, type to filter]
seratch T03E94MJU
App is not installed to this workspace
> seratch (dev) T03E94MJU
dreamy-gazelle-453 (dev) A04DHV08MPF
成功すると以下のような表示となります。
$ slack triggers create --trigger-def ./hello_world.ts
? Choose an app seratch (dev) T03E94MJU
dreamy-gazelle-453 (dev) A04DHV08MPF
⚡ Trigger created
Trigger ID: Ft04DLR5XXXX
Trigger Type: webhook
Trigger Name: Hello World Trigger
Webhook URL: https://hooks.slack.com/triggers/T11111/22222/xxxxx
この https://hooks.slack.com/triggers/T11111/22222/xxxxx
という URL を使うとワークフローが起動できるようになっています。以下の curl
コマンドでリクエストを送ってみましょう。
curl -XPOST https://hooks.slack.com/triggers/T11111/22222/xxxxx
{"ok":true}
と表示されれば成功です。Slack ワークスペースの指定したチャンネルを見てみてください。
以下のように「Hello World!」とメッセージが投稿されていれば成功です。おめでとうございます
で、何が起きたのか?
とりあえず手順に従って手を動かしたら、ワークフローが動きました。これによって何が起きたのかを少し整理しておきましょう。
-
slack create
でdreamy-gazelle-453
というアプリを作成した(この時点では雛形ができただけ) -
slack run
コマンドで起動したら、選択した Slack ワークスペース内に開発版のアプリがインストールされた(ただし、Blank project なので、まだ何の機能も持たない) -
hello_world.ts
とmanifest.ts
を書き換えてslack run
を実行することで、Slack のホスティング環境に反映された(ただし、この時点では起動する手段がない) - このワークフローを起動するためのトリガーを
slack triggers create
コマンドで作成した - 作成したトリガーの Webhook URL にリクエストを送ったらワークフローが実行された
という流れでした。
ワークフローを実行したときに slack run
で起動していなかった人も多かったのではないでしょうか?それでも「Hello World!」というメッセージが送信されたはずです。
それはなぜかというと、ワークフローの実行エンジン、標準ファンクションの部分は手元のプロセスではなく、全てホスティング環境側で実行されているからです。 このワークフローは標準ファンクションの SendMessage しか使っていないため、ローカルから接続していなくても最後に反映された設定で動作し続けるというわけです。
次回の記事ではカスタムのファンクションを実装する例も紹介していきますが、それを開発版アプリで実行する場合は slack run
で手元のプロセスも起動している必要があります。
リンクトリガーでワークフローを実行する
もう一つトリガーを作ってみましょう。次はリンクトリガーと呼ばれる、Slack 内でユーザーがクリックして起動するタイプのトリガーです。
先ほどのコードを以下のように書き換えます。
// -------------------------
// ワークフロー定義
// -------------------------
import { DefineWorkflow, Schema } from "deno-slack-sdk/mod.ts";
// この定義オブジェクトを manifest.ts で参照するのを忘れずに!
export const workflow = DefineWorkflow({
callback_id: "hello-world-workflow",
title: "Hello World Workflow",
input_parameters: {
properties: {
// リンクトリガーから受け取るチャンネル ID
channel_id: { type: Schema.slack.types.channel_id },
},
required: ["channel_id"],
},
});
// 標準ファンクションを使ってメッセージを投稿
workflow.addStep(Schema.slack.functions.SendMessage, {
// ワークフロー全体のトリガーからの入力を指定
// リンクトリガーの場合はそれを起動したチャンネルの ID が渡される
channel_id: workflow.inputs.channel_id,
message: "Hello World!",
});
// -------------------------
// トリガー定義
// -------------------------
import { Trigger } from "deno-slack-api/types.ts";
// リンクトリガー
const trigger: Trigger<typeof workflow.definition> = {
type: "shortcut",
name: "Hello World Trigger",
workflow: `#/workflows/${workflow.definition.callback_id}`,
inputs: {
// クリックしたチャンネルの ID が設定される
channel_id: { value: "{{data.channel_id}}" },
},
};
// トリガーの作成には `slack triggers create --trigger-def [ファイルパス]` を実行する
// Trigger 形の定義オブジェクトを export default さえしていれば
// そのソースファイルを使用できる
export default trigger;
先ほどと同様に slack run
でホスティング環境に設定を反映します(起動しっぱなしでも OK です)。
そして slack triggers create --trigger-def hello_world.ts
で、新しくリンクトリガーを作成しましょう。
$ slack triggers create --trigger-def hello_world.ts
? Choose an app seratch (dev) T03E94MJU
dreamy-gazelle-453 (dev) A04DHV08MPF
⚡ Trigger created
Trigger ID: Ft04DEBXXXX
Trigger Type: shortcut
Trigger Name: Hello World Trigger
URL: https://slack.com/shortcuts/Ft04DEBXXXXX/YYYY
この https://slack.com/shortcuts/Ft04DEBXXXXX/YYYY
という URL をワークフローを起動したいチャンネルにメッセージで投稿するか、チャンネルのブックマークに追加してください。そこから起動すると同様に Hello World! というメッセージが投稿されるはずです。
まとめ
この記事では以下のことをハンズオンで学びました。
- Blank project からワークフローを作成して実行できるようにする
- Incoming Webhooks トリガーを利用する
- リンクトリガーを利用する
できるだけシンプルにするために無理やり hello_world.ts
と manifest.ts
という二つのファイルだけを触る手順で説明しましたが、自前のファンクションを定義したり、トリガーやワークフローを複数定義するようになると、このやり方ではとっちらかってしまいます。
なので、slack create
で生成される他のテンプレートが行っているように、以下のディレクトリ構成で整理して、相対パスでファンクションやワークフローを import することを推奨しています。
$ tree
.
├── deno.jsonc
├── functions
│ ├── sample_function.ts
│ └── sample_function_test.ts
├── import_map.json
├── manifest.ts
├── slack.json
├── triggers
│ └── sample_trigger.ts
└── workflows
└── sample_workflow.ts
実際のプロジェクトでは、この方式に素直に従うようにしてみてください。
このシリーズはしばらく続きます。次回からは、自前のファンクションを開発したり、そのテストを書いたり、他の機能も少しずつ試していきましょう。
早くもっと完全なアプリの例を見たい!という方は、以下の記事からリンクされているものを色々見てみてください。
それでは!