ApexからSlack APIのfile.uploadを使って画像ファイルをアップロードしたい
そんな時ありませんか?僕はあったのです。
Tableauのダッシュボードをサブスクライブすると、メール添付で画像が降ってくるのですが、それをSlackに共有したい。そんなときに以下の方法が使えると思います。
SlackにはEmailインテグレーションっていうのがあって、設定時に発行されるメールアドレスにメールを送信するとチャンネルに投稿してくれるという機能があります。こんな感じで。
こちらのブロックを開くと添付ファイルの画像も見えます。
非常に便利な機能ではあるのですが、中身はワンクリックしないと展開できません。僕の中ではこのワンクリックが情報の浸透率に大きく関わると思っています。どうせだったらこの添付画像をそのままSlackにアップしたい、そうすれば開くまでもなくタイムライン上に画像が流れるはずであると。
しかし、色々やってみたもののうまくいかず嘆いていたのですが
神が降臨します
小坂さんから田実さんのblogをオススメいただきました。これだ!
な…なるほどな?🤔
日本語でも英語圏でもApexからSlackにアップするというチャレンジをした人がいないようで、そのものズバリの知見は見つかりませんでした。小坂さんのナイスパスによって知見が得られたので共有。
SlackAPIへの投稿時はパターン2の方を使うこと
「パターン2: HTTP Request Bodyをバイナリとして送信」の方です。
動作確認済みのコードはこちら
boundary ってなんだよーと泣きながらググったら勉強になりました。データの境界を示す識別子なので揃っていれば何でもOKです。そのまま使いました。Slackの場合はTokenの部分をBearerにしないとauthエラーになるので注意しましょう。
AttachmentTrigger.trigger の冒頭でカスタムメタデータ型のデータを取得しています。環境変数というカスタムメタデータ型を作り、valueというカスタム項目を追加。ラベルを指定してその中にvalueを入れる形のシンプルなものを使っています。Slackのチャンネル投稿時にはチャンネルIDを取得しなければならないのですが、人間にフレンドリーな形にはなっていないので予めカスタムメタデータ型の中にレコードを作って入れてあります。
実装方法について
今回は、メール-to-ケースを使って、画像添付されたメールをSalesforceに転送。メールメッセージについている添付ファイル(Attachment)が作成されたタイミングをトリガとしてSlackに投げる形にしています。
実装手順は以下の通り
1:Slackアプリを作ってbotの設定をする
2:メール-to-ケースの設定をする
3:カスタムメタデータ型を作成する
4:Apexトリガ/クラス/Testクラスを作成
5:テストする
6:問題なければ本番環境にデプロイ
1:Slackアプリを作ってbotの設定をする
SlackAPIの使い方が前と変わってきているようで、ひとまずアプリを作るという必要があります。
アプリ作成はこのページから。Create New Appボタンを押して作成しましょう。
まずはパーミッションの設定
Scopeの中にfiles.writeを入れましょう。
入れたらページ上部のInstall App to Workspaceボタンを押してインストールします。
インストールが完了したら、アップロードしたいチャンネルにこのアプリユーザを招待しておきます。これをしないとアップできないので注意。
インストールが終わった画面にAccess Tokenが表示されます。後でカスタムメタデータ型を作ったところで使います。
2:メール-to-ケースの設定をする
設定は調べてください。機能としては、設定時にSalesforceが発行してくれるメールアドレスにメールを送るとケースを起票してくれます。
ケース>メールメッセージ>添付ファイル
というデータ構造でレコードを格納してくれるので、それを使って処理をするという流れになります。
3:カスタムメタデータ型を作成する
SlackのチャンネルIDをApexクラスにハードコーディングなんてしていたらメンテナンス面倒すぎるよなという事で、皆さんどうしているのかと聞いてみたんですよね。
即レスいただきました
田中さん、小坂さんありがとうございます。
ということで、SalesCloudの設定画面に「カスタムメタデータ型」と入れると出てくるそれを開いて新規作成。初めて使いました。
環境変数:config_varsというカスタムメタデータ型を追加して中にレコードを入れました。
AttachmentTriggerHandler.clsの中でSlackBot_uploaderというものを判定に使っているのでこれだけは確実に入れてください。先程ゲットしたアクセストークンを入れます。
これを
こうやって入れる
あとはチャンネルとそのIDも入れておきましょう。チャンネルIDはここからTester使えばゲット出来るはずです。
リモートサイトの設定をする
設定>リモートサイトの設定にslack.com を追加しましょう
4:Apexトリガ/クラス/Testクラスを作成
コードはこちらから
https://github.com/geeorgey/Apex_to_Slack_API_file_upload
AttachmentTrigger.trigger
AttachmentTriggerHandler.cls
AttachmentTriggerHandler_Test.cls
の3つをそのままコピペで構いません。
AttachmentTriggerHandlerの中では、メール-to-ケースに入ってくるメールのサブジェクトを分解して投稿先のチャンネルを判定しています。こちら
識別子の部分は何でも良いです。メールのプリフィクスになるようなものを考えて入れてください。スラッシュ区切りでチャンネル名を記入してメールを送信すればOKという形になっています。
テストクラス:AttachmentTriggerHandler_Test.cls の中で、静的リソースの画像を使っています。これは予めアップロードしておいてください。
WHERE Name = 'addPlatform'
のaddPlatform部分は静的リソース名なので任意で置き換えてください。
5:テストする
テスト環境でメールの添付ファイルのテストなんてどうやってやるんだよと思っていたのですが、レコード無理やり作ってやればいいやということでやってみました。
開発者コンソール開いて
Debug>Open Execute Anonymous Window
テストコードをそのまま実行すればOK。
Case c = new Case(subject = 'test');
insert c;
EmailMessage newemail = new Emailmessage(Subject = '識別子/チャンネル名',PARENTID = c.id);
insert newemail;
StaticResource sr = [SELECT Id, Body FROM StaticResource WHERE Name = 'addPlatform' LIMIT 1];
Attachment newAT = new Attachment(Name = 'Attachment_2.jpeg',Parentid = newemail.id,CONTENTTYPE = 'image/jpeg',body = sr.body);
insert newAT;
目的のチャンネルに画像はアップされましたでしょうか?
6:問題なければ本番環境にデプロイ
ということで本番リリースしましょう。
以上です。協力いただいた皆様に大感謝。
noteにはこれまでの経験を綴っていこうかと思います。サポートによって思い出すモチベーションが上がるかもしれない。いや、上がるはずです。