こんにちは、id:c-terashimaです。
技術書典11で無料配布している「Holmes Tech Book」ですが、多くの方にダウンロードしていただいております!ありがとうございます!!
ドメイン駆動設計やmiroアプリの作成などバラエティに富んだ内容になっていますので、ぜひダウンロードしていただけると幸いです。
さて、今回はJava(SpringBoot)からSlackへメッセージ送信を試してみました。
Slackアプリを作る
Slackとアプリのやり取りを行うためのアプリを作成します。作成するSlackアプリからDMが届くことを想定しています。
- SlackAPIのアプリページに移動して、「Create New App」をクリックします
- 「App Name」に作成するアプリ名、「Pick a workspace to develop your app in:」に使用するワークスペースを選択し、「Create App」ボタンをクリックします
- 「OAuth&Permissions」にアプリに許可させたい権限を付与させます。今回は「chat:write」を付与します
- 「Redirect URLs」に認証時に呼び出されるエンドポイントを指定します。後述で作成する「/slack/oauth」を指定します。SSL化されたエンドポイントを指定する必要があるのでご注意ください。(画像はダミー)
- 「App Home」に移動して「Display Name」と「Default username」を入力します
- 「OAuth&Permissions」の設定が完了したら、作ったアプリをワークスペースにインストールします
- 「Basic Information」に移動して「Client ID」と「Client Secret」をメモします。この2つはホームズクラウドなどのアプリケーションからメッセージを書き込む際に必要となります
アプリとの認証
サンプルは以下の環境で動作確認をしております。
- Java8
- SpringBoot 2.3
Slack SDK
build.gradle
の dependencies
に以下を追加してSlack SDKをインストールします。
dependencies {
implementation 'com.slack.api:slack-api-client:1.7.1'
}
アプリケーションとの認証
Slackユーザとアプリケーションユーザの紐付けを行います。まずは認証用のボタンを表示します。
<a href="https://slack.com/oauth/v2/authorize?client_id=「Client ID」&scope=chat:write&state=「任意のデータ」"> <img alt="Add to Slack" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x" /> </a>
client_id
には作成したSlackアプリの「Client ID」を指定します。
state
はSlackからアプリケーションの認証エンドポイントが実行された際に設定される値になります。認証用エンドポイントの呼び元がこのアプリによって実行されたのかをチェックするのに利用します。
次にSlackから呼ばれるエンドポイントを作成します。
@RestController @RequiredArgsConstructor @Slf4j public class SlackController { private static final String STATE = "state_id"; private final String slackClientId = "client_id"; private final String slackClientSecret = "client_secret"; @GetMapping("/slack/oauth") @SneakyThrows public ResponseEntity<Void> oauth(@RequestParam("code") String code, @RequestParam("state") String state) { // stateの確認 if (!Objects.equals(state, STATE)) { log.error("stateが一致しません。{}", state); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } try (Slack slack = Slack.getInstance()) { // Slackアプリとの認証 OAuthV2AccessResponse response = slack.methods() .oauthV2Access(req -> req.code(code).clientId(slackClientId).clientSecret(slackClientSecret)); if (!response.isOk()) { log.error("認証に失敗しました。{}", response.getError()); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } // SlackユーザID、Slackアプリのトークンを取得 // メッセージを送信するのに必要になるため、DBかファイルに保存しておこう String slackUserId = response.getAuthedUser().getId(); String slackAccessToken = response.getAccessToken(); } // 認証後のリダイレクト先を指定する HttpHeaders headers = new HttpHeaders(); UriComponentsBuilder builder = UriComponentsBuilder.fromUri(URI.create("http://localhost:8080/slack")); headers.setLocation(URI.create(builder.toUriString())); return new ResponseEntity<>(headers, HttpStatus.MOVED_PERMANENTLY); } }
「Add to Slack」ボタンをクリックすると次の画面が表示されますので、「許可をする」ボタンをクリックすることで上で作ったエンドポイントが呼び出されます。
Slackへ通知
通知するメッセージはJSON形式で指定します。(Block Kit Builder)https://app.slack.com/block-kit-builder/T3HBJHYRHを利用するとかんたんに作ることができます。
以下のメッセージを送ってみたいと思います。
認証を行ったユーザにメッセージを送るソースは次になります。
private String slackAccessToken = "accessToken"; private String slackUserId = "userId"; @SneakyThrows public void postApprovalRequestMessage() { try (Slack slack = Slack.getInstance()) { MethodsClient client = slack.methods(slackAccessToken); ConversationsOpenResponse openResponse = client.conversationsOpen(req -> req.users(Arrays.asList(slackUserId))); if (!openResponse.isOk()) { throw new Exception("DMを開くことができませんでした"); } String message = "[\n" + " {\n" + " \"type\": \"section\",\n" + " \"text\": {\n" + " \"type\": \"mrkdwn\",\n" + " \"text\": \"こんにちは!メッセージを送るよ!!\"\n" + " }\n" + " }\n" + "]\n"; ChatPostMessageResponse messageResponse = client.chatPostMessage(req -> req.channel(openResponse.getChannel().getId()) .blocksAsString(message) ); if (!messageResponse.isOk()) { throw new Exception("DMを送ることができませんでした." + messageResponse.getError()); } ConversationsCloseResponse closeResponse = client.conversationsClose(req -> req.channel(openResponse.getChannel().getId())); if (!closeResponse.isOk()) { throw new Exception("DMを閉じることができませんでした"); } } }
実行するとメッセージが!!
まとめ
Slackは情報も豊富でかんたんにDMを送ることが出来ました。
Block Kitのテンプレートを見ていただくとボタンやテキストボックスをメッセージで送ることができますので、ぜひ色々試していただければ楽しいと思います。
参考にさせていただいた資料は下記に載せておきます。
参考資料
Holmesではエンジニア・デザイナーを募集しております。ご興味がある方はこちらからご連絡ください。