見出し画像

ApexからSlack APIのfile.uploadを使って画像ファイルをアップロードしたい

そんな時ありませんか?僕はあったのです。

Tableauのダッシュボードをサブスクライブすると、メール添付で画像が降ってくるのですが、それをSlackに共有したい。そんなときに以下の方法が使えると思います。

SlackにはEmailインテグレーションっていうのがあって、設定時に発行されるメールアドレスにメールを送信するとチャンネルに投稿してくれるという機能があります。こんな感じで。

画像1

こちらのブロックを開くと添付ファイルの画像も見えます。

画像2

非常に便利な機能ではあるのですが、中身はワンクリックしないと展開できません。僕の中ではこのワンクリックが情報の浸透率に大きく関わると思っています。どうせだったらこの添付画像をそのままSlackにアップしたい、そうすれば開くまでもなくタイムライン上に画像が流れるはずであると。

しかし、色々やってみたもののうまくいかず嘆いていたのですが

神が降臨します

小坂さんから田実さんのblogをオススメいただきました。これだ!

Apexからmultipart/form-data形式でHTTPリクエストを行うときは自前でBodyをゴリゴリ書いていく必要があるのですが、その際にファイルなどのバイナリデータを含めるときの対応に関して書いていきます。

な…なるほどな?🤔

日本語でも英語圏でもApexからSlackにアップするというチャレンジをした人がいないようで、そのものズバリの知見は見つかりませんでした。小坂さんのナイスパスによって知見が得られたので共有。

SlackAPIへの投稿時はパターン2の方を使うこと

「パターン2: HTTP Request Bodyをバイナリとして送信」の方です。

動作確認済みのコードはこちら

boundary ってなんだよーと泣きながらググったら勉強になりました。データの境界を示す識別子なので揃っていれば何でもOKです。そのまま使いました。Slackの場合はTokenの部分をBearerにしないとauthエラーになるので注意しましょう。

AttachmentTrigger.trigger の冒頭でカスタムメタデータ型のデータを取得しています。環境変数というカスタムメタデータ型を作り、valueというカスタム項目を追加。ラベルを指定してその中にvalueを入れる形のシンプルなものを使っています。Slackのチャンネル投稿時にはチャンネルIDを取得しなければならないのですが、人間にフレンドリーな形にはなっていないので予めカスタムメタデータ型の中にレコードを作って入れてあります。

カスタムメタデータ型___Salesforce

実装方法について

今回は、メール-to-ケースを使って、画像添付されたメールをSalesforceに転送。メールメッセージについている添付ファイル(Attachment)が作成されたタイミングをトリガとしてSlackに投げる形にしています。

実装手順は以下の通り

1:Slackアプリを作ってbotの設定をする
2:メール-to-ケースの設定をする
3:カスタムメタデータ型を作成する
4:Apexトリガ/クラス/Testクラスを作成
5:テストする
6:問題なければ本番環境にデプロイ

1:Slackアプリを作ってbotの設定をする

SlackAPIの使い方が前と変わってきているようで、ひとまずアプリを作るという必要があります。

アプリ作成はこのページから。Create New Appボタンを押して作成しましょう。

画像4

まずはパーミッションの設定

画像5

Scopeの中にfiles.writeを入れましょう。

画像6

入れたらページ上部のInstall App to Workspaceボタンを押してインストールします。

画像7

インストールが完了したら、アップロードしたいチャンネルにこのアプリユーザを招待しておきます。これをしないとアップできないので注意。

インストールが終わった画面にAccess Tokenが表示されます。後でカスタムメタデータ型を作ったところで使います。

画像8

2:メール-to-ケースの設定をする

設定は調べてください。機能としては、設定時にSalesforceが発行してくれるメールアドレスにメールを送るとケースを起票してくれます。

ケース>メールメッセージ>添付ファイル

というデータ構造でレコードを格納してくれるので、それを使って処理をするという流れになります。

3:カスタムメタデータ型を作成する

SlackのチャンネルIDをApexクラスにハードコーディングなんてしていたらメンテナンス面倒すぎるよなという事で、皆さんどうしているのかと聞いてみたんですよね。

即レスいただきました

田中さん、小坂さんありがとうございます。

ということで、SalesCloudの設定画面に「カスタムメタデータ型」と入れると出てくるそれを開いて新規作成。初めて使いました。

環境変数:config_varsというカスタムメタデータ型を追加して中にレコードを入れました。

AttachmentTriggerHandler.clsの中でSlackBot_uploaderというものを判定に使っているのでこれだけは確実に入れてください。先程ゲットしたアクセストークンを入れます。

これを

画像9

こうやって入れる

カスタムメタデータ型___Salesforce

あとはチャンネルとその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:テストする

テスト環境でメールの添付ファイルのテストなんてどうやってやるんだよと思っていたのですが、レコード無理やり作ってやればいいやということでやってみました。

開発者コンソール開いて

スクリーンショット_2020-09-23_13_00_48

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にはこれまでの経験を綴っていこうかと思います。サポートによって思い出すモチベーションが上がるかもしれない。いや、上がるはずです。