Salesforce Apex SDK for Slackの使い方3 Slack解析アプリを作ってみる

オリジナルのアプリを作っていきましょう。

## 今回作るアプリ
今回は、SlackのpostをSalesforceに記録するアプリケーションを作ってみたいと思います。
これができると何が捗るかと言うと、誰がどのチャンネルでどれくらい発言しているかとか、それに対して返信がどの程度あるかといった情報をSalesforceのレポートで解析できるようになります。

## Salesforce側にオブジェクトを作る
２つのカスタムオブジェクトを作成します

- Slack Channels
- Slack Posts

です。

## Slack_Channels__c
チャンネル側はシンプルです

![Slack_Channels___Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/d4a6c314-eb43-4ec3-fefb-aae70f047418.png)


## Slack_Posts__c
Posts側は少し項目が増えます

![Slack_Posts___Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/a5e517cc-17f8-d54e-e7e0-ce1973f3deec.png)

主従関係でSlack Channelを参照しています

## Apexアプリを作ろう
これは、前回のものを流用しましょう。

https://qiita.com/geeorgey/items/65a512abbcce2a39e49e#message%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E5%8F%96%E3%82%8A%E6%96%B9

ここで書いた、無限ループしてしまうやつを応用します。

```classes/EventDispatcherEventExample.cls
            } else if (event instanceof Slack.MessageEvent) {
                Slack.MessageEvent messageEvent = (Slack.MessageEvent) event;
                channelId = messageEvent.getChannel();
                LIST<Slack_Channels__c> channels = new LIST<Slack_Channels__c>();
                channels = [SELECT ID, Channel_ID__c FROM Slack_Channels__c WHERE Channel_ID__c = :channelId];
                String channel_sfid;
                if(channels.size()==0){
                    Slack_Channels__c add_channel = new Slack_Channels__c(Name = channelId, Channel_ID__c = channelId);
                    insert add_channel;
                    channel_sfid = add_channel.id;
                }else{
                    channel_sfid = channels[0].id;
                }
                String msg_text = messageEvent.getText();
                String EventTs = messageEvent.getEventTs();
                String Ts = messageEvent.getTs();
                String ThreadTs = messageEvent.getThreadTs();
                String slackUserID = messageEvent.getUser();
                Slack_Posts__c newpost = new Slack_Posts__c(Slack_Channels__c = channel_sfid, Slack_User_ID__c = slackUserID, Text__c = msg_text, Ts__c = Ts);
                if(ThreadTs!=NULL){
                    newpost.ThreadTs__c = ThreadTs;
                    LIST<Slack_Posts__c> parents = new LIST<Slack_Posts__c>();
                    parents = [SELECT ID FROM Slack_Posts__c WHERE Slack_Channels__c = :channel_sfid AND Ts__c = :ThreadTs];
                    if(parents.size()>0){
                        newpost.Parent_post__c = parents[0].id;
                    }
                }
                insert newpost;

            }
            /* これ入れるとアプリが反応してチャンネルにpostしまくってしまうのでコメントアウトしておきます
            Slack.ChatPostMessageResponse response = botClient.chatPostMessage(
                Slack.ChatPostMessageRequest.builder().channel(channelId).text(text).build()
            );

            if (response.getError() != null) {
                System.debug(response.getResponseMetadata().getMessages());
            }
            */
```

ということで完成です。シンプルですね。

## 試してみましょう
アプリが入ってるチャンネルでなにか発言をしてみます。
続いて、スレッドにコメントを入れてみましょう。

![Slack_____05-george___Leave_a_Nest_Co__ltd____1_個の新しいアイテム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/f1026841-6cf9-f7d7-0f01-c59f04b1511f.png)

うまく行っていれば、これがそのままSalesforce側に同期されます。
見てみましょう。

### Salesforce 側のレコードを見てみる

![すべて選択___Slack_Channels___Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/ba479ffb-c563-1551-da02-c8872a7777cd.png)

Channel IDが保存されています。
本当はName欄にはチャンネル名を取得して入れたかったのですが、やり方が分からなかったので今回はIDを入れちゃってます。
それでは待望のPostはどうでしょう。

![すべて選択___Slack_Posts___Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/dbe67638-68ca-e905-cabf-e6a1a3a6f8f4.png)

はい。こんな感じになりました。
スレッド内のコメントの場合はParent post欄にリンクが貼られています。
text欄はビューで見ると改行コードが抜けて見えますが、レコード側を開くと改行されていることが分かります。

![Post-0007___Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/1dbf704e-977c-ae3b-6f15-a04849047a14.png)

## オプション事項
- チャンネル名を取得する方法が分かったらChannels__c.Name にはチャンネル名を入れたい
- アプリのホーム画面に、公開チャンネル全てにjoinするボタンを作って、それが押されたらアプリが全チャンネルに入るようにする必要がある
- Slack のユーザーIDからユーザーを検索してメールアドレスを取得する事ができれば、それを使ってpostの所有者をそのユーザーに変更する処理が書けるのだが、ユーザー情報の取得方法が今の所不明

## 注意点
メッセージイベントはSalesforceの開発者コンソールにログが流れないみたいです。
デバッグが出来ませんのでご注意ください。
こんなのログに流しちゃったら開発者コンソール死んじゃうよなと思ってたのですが、そもそも表示しないという選択になっていたのか…なるほどね。

## まとめ
ということで、実はこのアプリ自体は、以前にSlackアプリとして作成したもので、Heroku上にデータを蓄積し、そのデータをTableauで解析するという仕組みになっていました。
Salesforce Apex SDK for Slackを使うことでHerokuにおくアプリが不要になります。
実装自体は、デバッグが出来ないくらいですが中身が簡単なのでなんとかなっちゃいました。
以上です！

## 関連リンク
- [Salesforce Apex SDK for Slackの使い方1](https://qiita.com/geeorgey/items/dbfa430b78c8f43cd88d)
- [Salesforce Apex SDK for Slackの使い方2](https://qiita.com/geeorgey/items/65a512abbcce2a39e49e)