Twilio Functionsからkintoneのテーブルを操作する方法

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

# はじめに

この記事では、Twilioのサーバーレスプログラム実行環境である「Twilio Functions」から、kintoneのテーブルを操作する方法を説明しています。具体的には、kintoneのAPIを連携させて、Functionsからkintone上のテーブルデータにアクセスします。
kintoneアプリに関しての単純なAPIアクセスについては、以下の記事を参照してください。

[Twilio Functionsからkintoneに対して読み書きする方法](https://qiita.com/mobilebiz/items/59b9062d58ba03c18c88)

今回もkintoneのNode.jsライブラリ「[kintone-nodejs-sdk](https://developer.cybozu.io/hc/ja/articles/360000511243-kintone-API-SDK-%CE%B2-for-Node-js)」を利用します。
kintone-nodejs-sdkの概要については、[こちらのドキュメント](https://developer.cybozu.io/hc/ja/articles/360000511243-kintone-API-SDK-%CE%B2-for-Node-js)が参考になります。

## 必要なもの

- Twilioトライアルアカウント（取得方法は[こちら](https://www.youtube.com/watch?v=rNiaLjnhlB4)）
- kintone開発者ライセンス（取得方法は[こちら](https://developer.cybozu.io/hc/ja/articles/200929540-developer-network-%E3%81%B8%E3%82%88%E3%81%86%E3%81%93%E3%81%9D#step3)）

どちらも通常のアカウントでももちろん構いません。

## kintone側の準備

今回はサンプルデータとして準備されている「ファイル管理」アプリを使っていきます。

### 新しいアプリの作成

- 登録済みの開発者ライセンスを使ってkintoneにログインします。
- サービス画面が表示されたら、**kintone**に入ります。

<img width="831" alt="スクリーンショット 2018-08-06 08.45.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/86046/7db5ae0e-4854-5f09-5b11-5e9d8b9fb80d.png">

- **アプリ**の右側にある**+**アイコンを押して、新しいアプリを作成します。
- **kintoneアプリストア**が表示されたら、**おすすめのアプリ**の中の**ファイル管理**を選択します。

![kintone_subtable_applist.png](https://qiita-image-store.s3.amazonaws.com/0/86046/1d294572-b1f1-7b42-f229-ae17cb9c2cc0.png)


- 左側に表示されている**このアプリを追加**ボタンを押します。
- **アプリの追加**ダイアログが表示されたら、**追加**ボタンを押します。

<img width="602" alt="スクリーンショット 2018-08-06 08.49.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/86046/78b5db1a-0ee1-a91d-ced9-72c4a6d7e691.png">

- ポータル画面に戻り、アプリの欄に今追加した**ファイル管理**が表示されていることを確認します。

![スクリーンショット 2019-01-21 14.13.43.png](https://qiita-image-store.s3.amazonaws.com/0/86046/64c33e95-4b3a-e918-6f56-5e3e0ab0763a.png)


### APIトークンの取得

kintoneを外部からアクセスするためのAPIトークンを取得します。

- アプリの中から先程追加した**ファイル管理**を選択します。
- 右上に表示されている歯車アイコンを押して、アプリの設定画面に移動します。
- **設定**タブに移動し、**カスタマイズ/サービス連携**の中の**APIトークン**を選択します。
- **生成する**ボタンを押します。
- APIトークンが表示されます。**アクセス権**に元々チェックされている「レコード閲覧」以外に、「レコード追加」「レコード編集」「レコード削除」にもチェックを入れます。
- 後ほど使うので、表示されているAPIトークン（文字列）をメモ帳などに記録しておきます。
- 画面上部にある**保存**ボタンを忘れずに押します。

![kintone連携_APIトークン.png](https://qiita-image-store.s3.amazonaws.com/0/86046/188049f7-2155-5036-0986-67a71da949ef.png)

- アプリの設定画面に戻るので、右上にある**アプリを更新**ボタンを押します。

## Twilio側の準備

続いて、Twilio側の準備をしていきます。

- [こちらの画面](https://jp.twilio.com/login/kddi-web)からログインをして、Twilioの管理コンソールを開きます。

### Functionsの環境設定

- 左側に表示されているドットが３つ表示されているアイコンをクリックすると、スライドメニューが開きます。

![kintone連携_スライドメニューアイコン.png](https://qiita-image-store.s3.amazonaws.com/0/86046/52235af7-defd-26a6-ff62-571fb9047654.png)

- **DEVELOPER TOOLS**の中にある**Runtime**を選択します。
- その中の**Functions**を選択し、さらに**Configure**を選びます。
- **Enable ACCOUNT_SID and AUTH_TOKEN**のチェックを入れます。

<img width="329" alt="スクリーンショット 2018-08-08 15.34.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/86046/6d4c5440-3587-ab70-e70f-f7a78aaf6f88.png">

- **Environmental Variables**の中の赤い+アイコンを２回押して、枠を２行作ります。
- 以下の内容を記載します。

|KEY|VALUE|
|:--|:--|
|KINTONE_API_TOKEN|先程控えておいたAPIトークン（文字列）|
|KINTONE_APP_URI|kintoneのURLに含まれるドメイン文字列(xxxxx.cybozu.com)|

- **Dependencies**の設定内にある、「Twilio」の**VERSION**を「3.23.1」に変更します。

<img width="689" alt="スクリーンショット 2018-08-08 17.14.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/86046/aa04b6dc-0e76-999b-ddcc-48c112d61ec6.png">

- 更に、赤い+アイコンを2回押して、以下の内容を設定します。

|NAME|VERSION|
|:--|:--|
|kintone-nodejs-sdk|0.1.1|
|moment|2.24.0|

- **Save**ボタンを押して、設定を保存します。


## Functionsからkintoneへのアクセス

準備が整いましたので、いよいよTwilioからkintoneのテーブルデータにアクセスしてみましょう。
今回は、すべてサンプルコードを用意したので、基本的にはコピー＆ペーストでテストできるはずです。

### kintoneのテーブル（表）とは

kintoneアプリには、１つのレコード内に複数行に渡って紐づくデータを登録しておくことができます。
たとえば、今回利用するファイル管理アプリでは、更新日や更新内容などを管理するファイルごとに登録していくことができます。

![スクリーンショット 2019-01-21 14.57.57.png](https://qiita-image-store.s3.amazonaws.com/0/86046/4e8544d8-44af-7659-9d07-34df8ae8238c.png)

kintoneでいうテーブルとは、このようなアプリを指しています。
今回はこちらのアプリで作業を行いますが、事前にデータが入っていないとサンプルコードが動かないため、上記画面のようにまずはデータを登録しておいてください。

### テーブルデータの読み込み

まずは、kintone上に保存されているテーブルデータをTwilioから読み込むコードを書いてみます。
コードを書く前に必要な情報を整理してみます。

|項目|説明|
|:--|:--|
|kintoneアプリのドメイン名|先程Functionsの環境設定で、KINTONE_APP_URIで指定したもの|
|アプリID|kintoneのファイル管理アプリを開いた時に、URLの途中に指定されている数値（xxxxx.cybozu.com/k/1/ の「１」の部分）|
|クエリー|読み込むデータの条件を指定する文字列。例えば、タイトルが「備品管理表」のデータを検索するには、「Title = '備品管理表'」のように指定します。このときの「Title」は、kintoneアプリで各フィールドに設定したフィールドコードとなります。詳しいドキュメントは[このあたり](https://developer.kintone.io/hc/en-us/articles/213149287#getrecords)にあります|

ではまず、ファイル管理アプリを読み込んで、テーブルデータがどのように格納されているのかを確認してみたいと思います。

テーブル構造になっているデータであっても、検索には通常と同じく**getRecord**メソッドを利用します。
getRecordの使い方の詳細は、[こちら](https://kintone.github.io/kintone-nodejs-sdk/reference/record/#getrecordappid-recordid)を御覧ください。

- Twilioの管理コンソールで、先ほどと同じように**Runtime**の**Functions**を選択します。
- さらに**Manage**を選択し、**Create a new Function**もしくは、赤い＋アイコンを押して、新しいFunctionを作成します。
- テンプレートを選択するダイアログが表示されるので、**Blank**を選択した後、**Create**ボタンを押します。

<img width="802" alt="スクリーンショット 2018-08-08 21.56.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/86046/9fbea563-33cc-5480-c583-09f617e23339.png">

- **FUNCTION NAME**欄に「getSubTable」と入力します。
- **PATH**欄に「/get-sub-table」と入力します。

![スクリーンショット 2019-01-22 09.29.51.png](https://qiita-image-store.s3.amazonaws.com/0/86046/7666258e-e1b0-7fbe-3582-9046ce04cccb.png)


- **CODE**欄に予め書かれているコードをすべて削除し、以下のコードを貼り付けます。

```javascript
const kintone = require('kintone-nodejs-sdk');

exports.handler = function(context, event, callback) {
    // kintone認証設定（API KEY）
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);
    
    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);
    
    let appID = 1; // アプリID　※ここの値は皆さんの環境に合わせて変更してください
    let recordID = 1;  // 検索したいレコード番号

    kintoneRecord.getRecord(appID, recordID)
    .then(resp => {
        // ファイル管理アプリでは、テーブルのフィールドコードが「変更内容メモ」になっていて
        // その中に配列として各行が含まれている
        resp.record['変更内容メモ'].value.forEach(detail => {
           console.log(detail); 
        });
        callback(null, 'OK');
    })
    .catch(err => {
        const error = err.get();
        Object.keys(error).forEach(key => {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};
```

- **Save**ボタンを押します。
- デプロイが自動で実行され、しばらくするとデプロイ完了の緑色のバナーが表示されれば完成です。
- **PATH**欄の右側にあるコピーアイコンをクリックしてURLをコピーします。
- ブラウザで新しいタブを開き、URLを貼り付けて実行します。
- Function側の画面に以下のようなログが表示されれば成功です（URLを貼り付けた方のタブにはOKとだけ表示されています）。

![スクリーンショット 2019-01-21 15.34.07.png](https://qiita-image-store.s3.amazonaws.com/0/86046/362e2d29-27f0-08c4-5f4a-eb35c07087f8.png)

さらにそれぞれのテーブルの変更内容にアクセスするには、

```javascript
        resp.record['変更内容メモ'].value.forEach(detail => {
           console.log(detail.value.ModifiedContents.value); 
        });
```

とすればOKです。

### テーブルデータの追加

続けて、テーブルにデータを追加する方法を解説します。
通常アプリにレコードを追加する場合は、addRecordなどを利用しますが、テーブルに行を追加する場合はレコード自体を追加するわけではなく、レコードの中身を増やすことになりますので、updateRecordを利用します。
以下のサンプルはレコードIDが１のテーブルに行を追加するサンプルです。

```javascript
const kintone = require('kintone-nodejs-sdk');
const moment = require('moment');
moment().utcOffset("+09:00");   // タイムゾーンを日本に設定

exports.handler = function(context, event, callback) {
    // kintone認証設定（API KEY）
    let kintoneAuth = new kintone.Auth();
    kintoneAuth.setApiToken(context.KINTONE_API_TOKEN);
    
    // コネクション作成
    let kintoneConnection = new kintone.Connection(context.KINTONE_APP_URI, kintoneAuth);    

    // レコード作成
    let kintoneRecord = new kintone.Record(kintoneConnection);
    
    let appID = 1; // アプリID　※ここの値は皆さんの環境に合わせて変更してください
    let recordID = 1;  // 行を追加したいレコード番号
    
    // 追加したいテーブルデータ
    let addData = {
        value: {
            Date: {
                value: moment().format("YYYY-MM-DD")
            },
            ModifiedContents: {
                value: 'この行を追加します'
            },
            Modifiedby: {
                value: [{code: 'Administrator'}]
            }
        }
    };
    
    // レコードを読み込む
    kintoneRecord.getRecord(appID, recordID)
    .then(resp => {
        let data = {
            '変更内容メモ': resp.record['変更内容メモ']    
        };
        data['変更内容メモ'].value.push(addData);
        
        // レコードを更新する
        kintoneRecord.updateRecordById(appID, recordID, data)
        .then(res => {
            console.log('Sub Table Added.');
            callback(null, 'OK');
        });
    })
    .catch(err => {
        const error = err.get();
        Object.keys(error).forEach(key => {
            console.log(key, error[key]);
        });
        callback(error.message);
    });
};
```

このコードでは、レコードを読み込んだあとでテーブルのデータを一度dataという連想配列に格納し、予め用意しておいたテーブル用の追加データをpush（）を使って追加しています。ちょっと分かりづらいですが、この方法だと比較的シンプルにデータを追加できます。

# まとめ

kintoneのテーブルは便利なのでよく利用されますが、コードからアクセスするサンプルがあまりないので、ぜひ参考にしてみてください。

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

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