VonageコミュニケーションAPI使って、調整リマインドツールを作ってみた！

# はじめに
今回は、Vonage コミュニケーションAPIを使って、調整リマインドツールを作っていきます！

[Vonage](https://www.vonagebusiness.jp/communications-apis/)はCPaaS(Commnication Platform as a Service)を提供する会社の一つで、
前々から興味があり、今回、Advent Calendarで触る機会ができたので試してみます！

CPaaSについて詳しく知りたい方は、下記記事の説明が丁寧で詳しく解説されていたので、参照ください。

https://qiita.com/nishina555/items/36600e986ec0040c0bda

## Vonage コミュニケーションAPIでできること

Vonageでは、下記のAPIを提供しています。

* Vonage Video API：WebRTCプラットフォーム（APIとSDK）
* Vonage Verify API：二要素認証API
* Vonage Voice API：PSTN・SIP・Websocket対応できるプログラマブルボイスAPI
* Vonage SMS API：SMSの送受信API
* Vonage Messaging API：Facebook Messenger、WhatsApp、Viber等の送受信API
* Vonage Management API：上記APIの利用レポート・アカウント管理・電話番号管理API

今回はこの中のVonage SMS APIを使って、調整リマインドツールを作ります！

## 仕様策定
今回の設定を下記とします。

```
あなたは地元の友達を集めて同窓会をやることになりました。
出席管理をするためにスプレッドシートに名前を入れて、出席、欠席を入力してもらうようにあなたは連絡をしました。
しかし、先の予定なこともあり、なかなかみんなが出席を入れてくれません。
一人、リマインドをしたところ、入れてくれましたが、みんなにリマインドをするのは正直しんどいです。

どうにかみんなに自動で連絡を入れられないか？
そう考えたあなたは、悩みに悩んだ末、一つの案を思いつきます。

そうだ！みんなの電話番号は知ってるし、SMSでリマインドを一斉に送れる機能を作ればなんとかなるかも...

なにかいいAPIないかな....
Vonage SMS APIがあったぞ！！！！！これを使ってリマインドを一斉に送ろう！
```

* 現状のスプレッドシート
  * ![スクリーンショット 2022-12-24 0.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224825/265c4ec4-19f6-7db6-d66d-d1fee7002ad7.png)

* GASを使用して出席、欠席を入れてない人に個別連絡(SMS)をする。

## 実装
仕様を定めたので、GASでの実装を進めていきます。
アカウントの作成から、GASのコード実装までの説明をしていきます。

### アカウントの作成

まず、アカウントの作成を[こちら](https://vonage.dev/3SQlBdv)から作成します。
情報を入力すると、下記のようなダッシュボード画面が表示されるので、まずはここまで進んでください。
![スクリーンショット 2022-12-24 0.15.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224825/c913d43c-a0cf-28f9-d325-da546d04645f.png)

### SMS APIの使用
先ほどのダッシュボード画面の中に、SMSを送信というのがあるので、クリックすると、下記のように参考実装が出てきます。
(より詳しいガイドは[こちら](https://developer.vonage.com/messaging/sms/overview)を参照)

この参考実装を元に、コードを記載していきます。
今回はcURLの実装を参考にGASからAPIを叩いていきます。
![スクリーンショット 2022-12-24 0.17.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224825/985832ad-0b23-97a3-7466-20b900764115.png)

textに送りたいメッセージ、toに電話番号、api_key,secretには
それぞれダッシュボードの最初の画面にあるものを入れてください。

電話番号はE.164フォーマットで指定する必要があるので注意です。
(E.164フォーマットについて競合サービスの[Twilioの記事](https://support.twilio.com/hc/en-us/articles/1260803420489-Twilio%E3%81%8C%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B%E5%9B%BD%E9%9A%9B%E9%9B%BB%E8%A9%B1%E7%95%AA%E5%8F%B7%E3%81%AE%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88-E164-%E3%81%A8%E3%81%AF-)で申し訳ないですが分かりやすかったので掲載)

```curl
curl -X "POST" "https://rest.nexmo.com/sms/json" \
  -d "from=Vonage APIs" \
  -d "text=A text message sent using the Vonage SMS API" \
  -d "to=" \
  -d "api_key=" \
  -d "api_secret="
```

### GASの作成
シート > 拡張機能 > Apps Scriptから作成後、
プロジェクトの設定から下記のように、スクリプトプロパティを設定してください。
![スクリーンショット 2022-12-24 0.33.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224825/0983a2a3-6ff3-4ffc-4c34-7e41d519518f.png)

設定後、smsメッセージを送るだけのサンプル実装は下記のようになります。
typeは、日本語メッセージを送るために指定しておかないと、正しく日本語が表示されません。

```javascript
function sendSMS(phoneNumber) {
   const API_KEY = PropertiesService.getScriptProperties().getProperty('API_KEY')
   const API_SECRET = PropertiesService.getScriptProperties().getProperty('API_SECRET')

  const formData = {
    'from': 'Vonage APIs',
    'text': 'まだ入力されてないよー！入力お願いします！ spreadsheetのURL',
    'to': phoneNumber,
    'type': 'unicode',
    'api_key': API_KEY,
    'api_secret': API_SECRET
  };
   const options = {
     'method': 'post',
     'payload': formData

   }
   UrlFetchApp.fetch('https://rest.nexmo.com/sms/json', options)
}

```

このままでは、出席・欠席を入力してない人が誰か分からないので、toに誰を指定したら良いか分かりません。
続いて出席・欠席の判定スクリプトを作成します。

#### 出席・欠席の判定

二つの関数を作成して判定をさせます。
emptyIndexListでは、入力されていない行を取得します。
そして、emptyIndexListで取得した行を元に、誰が回答していないかの名前をnotAnswerMemberにて取り出します。
ここで取得したメンバーが回答をまだ行えていないメンバーです。
このメンバーに対してSMS通知を行います。

```javascript
// returnされるものの例: [1,3]
function emptyIndexList() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
  const startRow = 5
  const lastColumn = sheet.getLastColumn()
  const targetColumn = 3
  const answerList = sheet.getRange(startRow,targetColumn,lastColumn).getValues()
  return answerList.map((answer, index) => answer[0] === '' ? index : null).filter(Boolean)
}

// returnされるものの例: ['Aさん']
function notAnswerMembers() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
  const startRow = 5
  const lastColumn = sheet.getLastColumn()
  const targetColumn = 2
  const rowData = sheet.getRange(startRow,targetColumn,lastColumn).getValues()
  return emptyIndexList().map(emptyIndex => rowData[emptyIndex]).flat()
}
```

#### 電話番号の取得

個人情報なので、シート上など、他の人に見える場所には置くべきではありません。
簡易的に使うのであれば、APIのSecretKeyを入れたのと同じようにプロパティに入れるのが良いかと思います。
一気に入れるには[setProperties](https://developers.google.com/apps-script/guides/properties)を利用して、入れるのが良いです。
また、使用が終わったら必ず削除しましょう。
(そして、本来は使用する前に電話番号を通知などの目的で使用するなどの同意を得ておくべきです。)

今回は名前をkeyにして、valueを電話番号にしたものをサンプルで一つだけ設定しておきます。



#### メイン処理の実装

最後に、作成した関数をまとめて実行するメイン処理の実装に移ります。
やっていることは、取得したメンバーリストを元にプロパティに保存した電話番号を引っ張ってきて、smsを繰り返し送るだけです。

```javascript
function main() {
   const members = notAnswerMembers()
   members.forEach(member => {
     const phoneNumber = PropertiesService.getScriptProperties().getProperty(member)
     const result = JSON.parse(sendSMS(phoneNumber).getContentText())
     Logger.log(result)
   })  
}
```

#### トリガーの設定

最後に、トリガーの設定をします。
main関数を実行する関数に設定し、リマインドを送る日付を入力します！
![スクリーンショット 2022-12-24 4.34.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224825/636b9084-1a4a-feed-67e8-075cd98fbf43.png)

そして、試しに実行すると...こんな感じでできました！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224825/0c21a3ec-015d-3332-5111-903693ac4e4b.png" width="450px"/>


## まとめ
以上、VonageのSMS APIを使って、調整リマインドツールを作ってみました！

思っていた以上に簡単に使えて、ビックリしました。
これだけ実装コストが低いと、実務で取り入れるのも簡単そうです。

SMSを使う機会があれば、ぜひ検討したいと思いました。
他のAPIも面白いものが多そうなので、機会があれば使ってみたいと思います！！

Vonageさん、触る機会をいただきありがとうございました！
そして、ここまで読んでいただいた皆さん、ありがとうございました！