ストリーミングAPIで受信したイベントの絞込み

#やりたいこと
自分がケース登録後、発番されたケース番号をOpenCTIソフトフォン（左下のやつ）に伝えたい
自分以外がケース登録したものは伝えない

#実現イメージ
同一組織に田中と上川を作成して、別ブラウザで同時に開き上川でケースを作成したスクショです。
上川にのみ通知が来てるかと思います。
###★上川にのみ通知
![PushTopic1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337592/5e8020af-b235-ec73-3932-b81500de81f8.png)
###★田中に通知はこない
![pushtopic2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337592/b189fb64-29b3-0e51-b2eb-fe7c63c040fa.png)

#実現方法
参考:[例: 再生なしの対話型 Visualforce ページ](https://developer.salesforce.com/docs/atlas.ja-jp.api_streaming.meta/api_streaming/code_sample_interactive_vfp_intro.htm)
##PushTopicの作成
ケース作成時のみ通知してほしいので、NotifyForOperationCreate=trueにします。QueryのSelectには自分が作成したケースか判定に使用するためCreatedByIdを含めます。Salesforceの画面から作成できないため、開発者コンソールから作成します。

```Apex
PushTopic pushTopic = new PushTopic();
pushTopic.Name = 'CaseCreated';
pushTopic.Query = 'SELECT Id, CaseNumber, CreatedById FROM Case';
pushTopic.ApiVersion = 50.0;
pushTopic.NotifyForOperationCreate = true;
pushTopic.NotifyForOperationUpdate = false;
pushTopic.NotifyForOperationUndelete = false;
pushTopic.NotifyForOperationDelete = false;
pushTopic.NotifyForFields = 'Referenced';
insert pushTopic;
```

##静的リソースを作成
[こちら](https://developer.salesforce.com/docs/atlas.ja-jp.api_streaming.meta/api_streaming/code_sample_interactive_vfp_create_static_resources.htm)を参考に静的リソースを作成してください。
demo.jsの以下の部分を変更します。

```js
function subscribe(topic) {  
//...
//CreatedByIdで受信メッセージを絞込み
  channel = topic + '?CreatedById=' + userId;
//...     
}
```

##ソフトフォン（VF）の作成
先ほどのdemo.jsと併せて以下の様な形で受信の絞込を設定します。
[登録の際の絞り込み条件の設定](https://developer.salesforce.com/docs/atlas.ja-jp.api_streaming.meta/api_streaming/using_filtered_subscriptions.htm)

```js
const userId = '{!$User.Id}';
/topic/CaseCreated?CreatedById=userId
```

###ソフトフォン（VF）
[こちら](https://developer.salesforce.com/docs/atlas.ja-jp.api_streaming.meta/api_streaming/code_sample_interactive_vfp_create_VF_page.htm)を参考にVFを作成してください。コメントの部分を追加してください。

```html

<apex:page>
<apex:includeScript value="{!$Resource.json2_js}"/>
<script type="text/javascript" src="{!URLFOR($Resource.cometd_zip, 'dojo/dojo.js')}" data-dojo-config="async: 1"></script>
<apex:stylesheet value="{!$Resource.demo_css}"/>
<script>var token = '{!$Api.Session_ID}';</script>
        <div id="demo">
            <div id="datastream"></div>
        <script type="text/javascript" src="{!$Resource.demo_js}">
</script>
<script>
   //画面側でuseidを取得し、jsでチャネルのパラメータに設定
   const userId = '{!$User.Id}';
   console.log(userid);
</script> 
       <div id="input">
                <div id="join">
                    <table>
                        <tbody>
                            <tr>
                                <td>&nbsp;</td>
                                <td> Enter Topic Name </td>
                                <td>
                                    <input id="topic" type="text" />
                                </td>
                                <td>
                                    <button id="subscribeButton" 
                                        class="button">Subscribe</button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                <div id="joined">
                    <table>
                        <tbody>
                            <tr>
                                <td>
                                    <button id="leaveButton" 
                                        class="button">Unsubscribe</button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
    </div>
</apex:page>
```

#プラットフォームイベントではできないのか？
ドキュメント見るとだいたい似たようなことは出来そうな気がしますが、自分のケース作成時だけ通知するのが出来なさそうです。
>登録の際の絞り込み条件の設定
プラットフォームイベントでは、ストリーミング API における登録の際の絞り込み条件の設定はサポートされません。
https://developer.salesforce.com/docs/atlas.ja-jp.platform_events.meta/platform_events/platform_events_api_considerations.htm

プラットフォームイベントの場合は画面側で通知されたCreatedByIDで判定が必要かと思います。

あと、プラットフォームイベントを公開するのにケース作成時にトリガやプロセスビルダー等が必要なのがストリーミングAPIとの違いですね。
インテグレーションアーキテクトの資格試験ですと、こういうケースはストリーミングAPIが推奨されていました。

#制限事項
制限もストリーミングAPIとこの部分は同じでした。
すべてのチャネルおよびすべてのイベント種別での、同時 CometD クライアント (登録者) の最大数	2,000（Performance Edition および Unlimited Edition）	1,000（Enterprise Edition）
https://developer.salesforce.com/docs/atlas.ja-jp.platform_events.meta/platform_events/platform_event_limits.htm

#最後に
CTI周りで以下の記事も書いてみたのでどうぞ！
[Open CTI で Lightning Message Service を使用してみる](https://qiita.com/laughingman/items/36823e819e026d16c826)