FlexプラグインTips（通話終了時のWebhook）

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

# はじめに

みなさん、こんにちは。
KDDIウェブコミュニケーションズ、Twilioエバンジェリストの高橋です。

今回もまたまた Twilio Flex プラグインネタです。
Twilio Flex で内部的に使われている Twilio Voice には、ステータスコールバックという機能があります。これにより、たとえば通話が終了したときに、Webhook を投げてもらうことができます。

着信については、電話番号の設定で StatusCallback URL を指定できます。
![スクリーンショット 2022-06-29 11.09.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/bfe44d8c-a511-0db5-d919-ae6e9cac35d7.png)

がしかし、Flex プロジェクトではここの設定は Studio Flow の呼び出しに使われてしまっていて、独自の設定ができません。しかも発信のときはどうすればいいのかという問題もあります。

そこで、Flex Plugins の登場です（またプラグインかよｗ）

## 設計方針

まず、本来の StatusCallback は使えそうもないので、別のイベントをフックする必要がありそうです。
Flex のイベントと聞くと、以下の2つが思い浮かびます。
- Action Framework
- Flex Events

Action Framework のメンバーを見ていると、WrapupTask というのがありました。

https://assets.flex.twilio.com/docs/releases/flex-ui/1.31.1/Actions.html#.WrapupTask

これをイベントとしてリスナーを取得できないか。

```javascript
flex.Actions.addListener('afterWarpupTask', (payload) => {});
```

結論。
できませんでした。そもそもイベントとして使えないみたいです。

じゃ、Flex Eventsには何かないかなー。

https://assets.flex.twilio.com/docs/releases/flex-ui/1.31.1/FlexEvent.html

結論。
ありませんでした。Flex UI 1.x の Flex Events はあまりイケてないです。

さて困ったよ。そもそも Flex の挙動をコンソールで見ていると、DISCONNECTED とかの文字も見られるので、回線が切れたことはイベントとして拾えそうなんだけどなー。
ん？待てよ。
Voice Clientの Device の disconnect イベントは拾えないかな。

https://jp.twilio.com/docs/voice/sdks/javascript/overview-1x-deprecated/device#events

Deviceオブジェクトは、 Flex Manager 経由で取得ができる。

```javascript
manager.voiceClient.on('disconnect', async (conn) => {});
```

ここでさらなる問題が発生。

- 取得した Connection では、切断されたコール（この場合は、Twilio→オペレータのブラウザ）の情報しか取れない。
- Flex UI 2.xでは、そもそも disconnect イベントが発火しない（バグなのかも）。

前者については、Twilio→ブラウザの CallSid がわかるので、そこから Conference を探して親コールを探すことでなんとかなりそうだけど、Conferenece を探すのが超絶面倒なので却下。
であれば、事前に TaskSid とかを探しておいて、それを disconnect のタイミングで Webhook 先に渡してあげるのがよさそう。
後者については、2.0から新設された FlexEvents の taskWrapup イベントが使えそう。

https://assets.flex.twilio.com/docs/releases/flex-ui/2.0.0-beta.1/ui-actions/FlexEvent#taskWrapup

## 完成したコード

```javascript
  async init(flex, manager) {
    console.log('🐸 🐸 🐸 🐸');
    console.log(`Ver. ${VERSION}`);
    console.log('🐸 🐸 🐸 🐸');
    let taskSid = '';
    const { FLEX_APP_FUNCTIONS_DOMAIN } = process.env;
    const url = `https://${FLEX_APP_FUNCTIONS_DOMAIN}/webhook`;
    if (VERSION.split('.')[0] === '2') {
      manager.events.addListener('taskWrapup', async (task) => {
        console.log(`🐞🐞🐞 disconnect`);
        taskSid = task.taskSid || '';
        await axios.post(url, { taskSid });
      });
    } else {
      manager.voiceClient.on('disconnect', async (conn) => {
        console.log(`🐞🐞🐞 disconnect`);
        await axios.post(url, { taskSid });
      });

      flex.Actions.addListener('afterAcceptTask', async (payload) => {
        console.log(`🐞🐞🐞 accepted task.`);
        taskSid = payload.task.taskSid || '';
      });
    }
  }
```

FlexUIのバージョンで処理を切り替えています。
2.x系では、taskWrapup イベントから taskSid を取得して Webhook 先に渡しています。
1.x系では、Action Framework で、afterAcceptTask イベントを取得して、そこで取得した taskSid を voiceClient の disconnect イベントで Webhook するようにしました。

# まとめ

完成してみるとすごくシンプルなのですが、調査実装には結構時間かかりました。
Flexあるあるですね。

でもお陰様で、Action Framework や Manager などの使い方もだいぶ慣れてきました。

---
### Twilio（トゥイリオ）とは

https://cloudapi.kddi-web.com
Twilio は音声通話、メッセージング（SMS /チャット）、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウド API サービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。

Twilioに関するご相談などがございましたら、ぜひ毎週水曜日の午後に開催しております相談会をご利用ください。
[Twilio相談会（毎週水曜日）](https://cloudapi.kddi-web.com/contact/consultation?hsLang=ja-jp)

自己紹介|　
:--|:--
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/b51a8b88-abd5-ce5e-195a-de3564ba2ae6.png" height='200' width='150'/>|高橋克己（Katsumi Takahashi） 自称「<font color='red'>赤い芸人</font>」<br />グローバル・インターネット・ジャパン株式会社　代表取締役<br />株式会社KDDIウェブコミュニケーションズ　Twilio事業部エバンジェリスト<br /><br />2001年より大手通信事業者の法人サービスの教育に携わり、企業における電話のしくみや重要性を研究。2016年よりTwilio事業部にジョインし、Twilioを使ったスマートコミュニケーションの普及活動を精力的に行っている。<br />2015 Hall of Doers<br />2019 Twilio Champions