API クライアントの基本
slack-api-client は、シンプル、簡単、柔軟に設定可能な Slack API クライアント実装を提供します。
このページにあるサンプルを試す前に、Java プロジェクトを設定しておく必要があります。もしまだでしたら「API クライアントのセットアップ」にある手順に従ってください。
Slack オブジェクトの初期化
このライブラリの全ての機能は com.slack.api.Slack クラスに定義されている多様なインスタンスメソッドから始まります。
import com.slack.api.Slack;
Slack slack = Slack.getInstance();
サポートされている全ての API クライアントは、このインスタンスが提供する fluent インターフェース(メソッドチェイン)に従うだけで、初期化して利用することができます。これらの API クライアントの設定をカスタマイズするには SlackConfig の設定も必要です。このクラスについてはこのページの末尾にあるセクションを参考にしてください。
以下は Slack オブジェクトの API クライアントを生成するためのメソッドの一覧です。
メソッド | 戻り値の型 | 説明 |
---|---|---|
Slack#methods(String) | com.slack.api.methods.MethodsClient | API メソッドクライアント |
Slack#methodsAsync(String) | com.slack.api.methods.AsyncMethodsClient | Rate Limits を十分に考慮した API メソッド非同期クライアント |
Slack#socketMode(String) | com.slack.api.socket_mode.SocketModeClient | ソケットモード の WebSocket クライアント |
Slack#rtm(String) | com.slack.api.rtm.RTMClient | Real Time Messaging (RTM) API の WebSocket クライアント |
Slack#scim(String) | com.slack.api.scim.SCIMClient | SCIM API クライアント |
Slack#audit(String) | com.slack.api.audit.AuditClient | Audit Logs API クライアント |
Slack#status() | com.slack.api.status.v2.StatusClient | Slack Status API クライアント |
Incoming Webhooks の解説をお探しですか?もちろん、サポートされています!こちらのガイドを参考にしてください。
API メソッドを実行
最も人気のある Slack の API メソッドは chat.postMessage という API で、これはチャンネルなどにメッセージを投稿するために使用されます。
chat.postMessage のような API メソッドを実行するには MethodsClient をトークンを与えて初 期化する必要があります。トークンは xoxb-
(ボットトークン)や xoxp-
(ユーザートークン)で始まる文字列です。これらのトークンは Slack アプリがインストールされたそれぞれのワークスペース毎に払い出されるものです。とりあえず始めるにあたっては、Slack アプリの管理画面 から開発用ワークスペース(Development Workspace)のトークンを簡単に発行することができます。
注: トークンをソースコードにハードコードすることは望ましくありません。意図しない流出を防ぐために、環境変数やそれに類するより安全な方法でトークンを保持することを強くおすすめします。
import com.slack.api.methods.MethodsClient;
import com.slack.api.methods.request.chat.ChatPostMessageRequest;
import com.slack.api.methods.response.chat.ChatPostMessageResponse;
// 環境変数を読み込みます
// トークンがボットトークンであれば `xoxb-`、ユーザートークンであれば `xoxp-` で始まっているはずです
String token = System.getenv("SLACK_TOKEN");
// API メソッドのクライアントを上のトークンと共に初期化します
MethodsClient methods = slack.methods(token);
// API リクエスト内容を構成します
ChatPostMessageRequest request = ChatPostMessageRequest.builder()
.channel("#random") // ここでは簡単に試すためにチャンネル名を指定していますが `C1234567` のような ID を指定する方が望ましいです
.text(":wave: Hi from a bot written in Java!")
.build();
// API レスポンスを Java オブジェクトとして受け取ります
ChatPostMessageResponse response = methods.chatPostMessage(request);
うまくいっていれば Slack ワークスペースの #random チャンネルで以下のようなメッセージが投稿されていることを確認できるはずです。
ここで実際に何が行われたかをよりクリアに理解するために、上の Java コードと等価な curl コマンドの例を見てみましょう。Slack の Web API のコンセプトはとても素直なものなので、与えられたパラメーターがどのように実際の HTTP リクエストで送られるかを容易に理解していただけるかと思います。
curl -XPOST https://slack.com/api/chat.postMessage \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: Bearer xoxb-123-123-abcabcabc' \
-d 'channel=%23random&text=%3Awave%3A%20Hi%20from%20a%20bot%20written%20in%20Java%21'
これで上記の Java コードが実際に何をしていたかはおわかりいただけたかと思います!
ただ、上のコード例はちょっと冗長だなと感じた方もいるかもしれません。以下の ようにしてよりコードをシンプルにすることができます。ただし、あなたのアプリケーションが Java オブジェクトの生成数を抑える必要があるなら、最初の例のように MethodsClient を生成してそれを使い回す方がよいでしょう。
ChatPostMessageResponse response = slack.methods(token).chatPostMessage(ChatPostMessageRequest.builder()
.channel("#random")
.text(":wave: Hi from a bot written in Java!")
.build());
これで終わりではありません。リクエストの初期化を関数で行うようにすると、同じコードをよりシンプルにすることができます。
ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
.channel("#random")
.text(":wave: Hi from a bot written in Java!"));
この最後の例が最も手軽で簡潔なコードであることに異論のある方はほとんどいないはずです。これより先のコード例にはこのスタイルで記述していきます。
import com.slack.api.Slack;
import com.slack.api.methods.response.chat.ChatPostMessageResponse;
Slack slack = Slack.getInstance();
String token = System.getenv("SLACK_TOKEN");
ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
.channel("#random")
.text(":wave: Hi from a bot written in Java!"));
そして Kotlin を使えば、このコードはより一層簡潔になります。
import com.slack.api.Slack
val slack = Slack.getInstance()
val token = System.getenv("SLACK_TOKEN")
val response = slack.methods(token).chatPostMessage { it
.channel("#random")
.text(":wave: Hi from a bot written in Kotlin!")
}
さらに、リッチなメッセージを構築するためのより Kotlin ネイティブなやり方として Block Kit Kotlin DSL もチェックしてみてください。
レスポンスの扱い
Slack Web API のレスポンス形式にまだ馴染みがなければ「Evaluating responses(英語)」を読んでみてください。すべての Web API レスポンスは JSON オブジェクトを持ち、そのトップレベルに真偽型の "ok"
というリクエストの成功・失敗を伝えるためのプロパティがあります。
{
"ok": true,
"stuff": "This is good"
}
{
"ok": false,
"error": "something_bad"
}
ですので、レスポンスを処理するときは isOk()
メソッドで返されるこの真偽値を判定して、後続の処理を分岐することになります。
import com.slack.api.model.Message;
ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
.channel("C1234567")
.text("Write one, post anywhere"));
if (response.isOk()) {
Message postedMessage = response.getMessage();
} else {
String errorCode = response.getError(); // 例: "invalid_auth", "channel_not_found"
}
API メソッドを呼び出すとき、様々な理由からエラーが発生することがあります。
- 成功のレスポンスを受け取っても、そのレスポンスボディの
"ok"
プロパティが false で"error"
プロパティがchannel_not_found
のような値で設定されていることがあります。このエラーコードの意味・理由は API メソッドのドキュメントで確認できます。 - ネットワーク・Slack API サーバーとの接続の問題で java.io.IOException が throw されることがあります。
- Slack API サーバーから 20x 以外の HTTP ステータスで応答された場合に com.slack.api.methods.SlackApiException が throw されることがあります。
1. のパターンをどう処理するかを理解するには、このドキュメント(英語)を参考にしてください。
2. と 3. のパターンでは MethodsClient は 2 種類の例外を throw する可能性があります。この API クライアントを利用するアプリケーション側で、これらの例外を catch して適切に処理する必要があります。
例外の型 | 含まれる情報 | 発生理由 |
---|---|---|
java.io.IOException | 標準的な例外の情報(メッセージ文字列、原因となった例外) | この例外は、リクエストのキャンセル、コネクションの問題やタイムアウトによって発生する可能性があります。 |
com.slack.api.methods.SlackApiException | 生の HTTP レスポンスオブジェクト、文字列のレスポンスボディ、レスポンスボディからデシリアライズされた SlackApiErrorResponse オブジェクト | この例外は、Slack API サーバーが 20x 以外の HTTP ステータスで応答したときに発生する可能性があります。 |
十分に考慮されたエラーハンドリングの最終形はこのようになります。
import java.io.IOException;
import com.slack.api.methods.SlackApiException;
try {
ChatPostMessageResponse response = slack.methods(token).chatPostMessage(req -> req
.channel("C1234567")
.text("Write one, post anywhere"));
if (response.isOk()) {
Message postedMessage = response.getMessage();
} else {
String errorCode = response.getError(); // 例: "invalid_auth", "channel_not_found"
}
} catch (SlackApiException requestFailure) {
// Slack API が 20x 以外の HTTP ステータスで応答した
} catch (IOException connectivityIssue) {
// 何らかの接続の問題が発生した
}