LINE チャンネルの友達登録や投稿情報を kintone に保管

## 概要
先月に [SORACOM LTE-M Button Plus と kintone で高齢者を見守るシステムの試作](https://qiita.com/yukataoka/items/4eb48bcbc8890b5b2277) で情報収集を始めましたが、毎日の確認は家族の LINE でできると便利そうです。これまで LINE 開発は未経験のため、先ずはラインチャンネルの作成と、友達登録や投稿情報を kintone に保管する方法を調査し実装を始めました。
![スライド5a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/47898f75-22e8-50aa-a350-9549293675db.png)
調査を始めてみると一連の手順を記録したこの手の情報が少なく、自分の備忘録も兼ねてこちらにまとめてみます。

今回は LINE Bot を登録し、LINE チャンネルの友達登録や投稿のイベントを Webhook で通知し、投稿内容などの情報を kintone に保管するまでを実装してまとめました。

kintone には Webhook からの通知を受信することができませんので、LINE Bot からの Webhook 通知は AWS API Gateway で受信し、受信した内容を AWS Lambda から投稿内容などを kintone アプリのレコードに追加します。AWS Lambda からは同時に LINE Bot の簡単な返信を投稿します。
![スライド4b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/294c045b-e06d-7b27-9c81-e2b30d6f3882.png)

## LINE チャンネルの登録
LINE チャンネルを利用するためのチャンネル登録の手順を説明します。
### LINE developersアカウントの登録
LINE チャンネルの利用には、LINE developersアカウントの登録が必要です。
__LINE Developers__
https://developers.line.biz/ja/

以下の情報を参考に、LINE developers サイトにログインできるようにしました。
__LINE developersアカウントの登録とMessaging APIの基本設定__
https://symfoware.blog.fc2.com/blog-entry-2166.html

### プロバイダーの設定
LINE developers サイトにログイン後は、最初にプロバイダー（提供者）を登録します。
![line02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/daba4a74-f5ae-0a5a-d3a1-59d3103ed44d.png)
プロバイダーの画目で「作成」を開始し、適切なプロバイダー名を登録するだけの作業です。
![line03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/2c0a0a24-af9a-4799-75ff-fe2e21dd7e76.png)

### チャンネルの設定
プロバイダーの作成後に LINE チャンネルを登録を行います。
LINEユーザの友達登録や投稿情報を収集などを行うためには、LINE の Messaging API を利用しますので、チャンネルの種類は Messaging API を選択します。 
![line05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/a9a8dc0f-3fcf-dc53-1537-fed8ba0a7b02.png)
チャンネルアイコン、チャンネル名、チャンネル説明、メールアドレスを入力し、利用規約の同意をチェックしてチャンネルを作成します。任意項目は入力しなくても問題ないです。
![line06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/84574cd8-54a0-33d6-ddbf-3fe42b758e2c.png)
チャンネル作成の完了後 Messaging API設定 で、__チャンネルアクセストークン__を発行し、控えておきます。この__チャンネルアクセストークン__は以降の AWS Lambda のプログラム内で利用します。
![line12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/dd5c33fa-6ea4-6671-b308-a7afddf5f32f.png)
続きの設定は kintone アプリと AWS Lambda、AWS API Gateway の設定が完了してから行います。

## kintone アプリの作成
LINE の友達登録や投稿情報を保管する kintone アプリを追加します。
アプリに以下のフィールドを配置します。
![line22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/095f2507-c571-7b1a-9ed7-3fde04066b2f.png)

| フィールド名 | タイプ | フィードコート・要素ID |
|--------------|--------|----------------|
| lineユーザID | 文字列（1行） | lineUserId |
| 日時 | 日時 | lineDateTime |
| lineタイプ | 文字列（1行） | lineType |
| lineモード | 文字列（1行） | lineMode |
| lineメッセージ | 文字列（複数行） |lineMessage |

その他には、Lamda から kintone にレコードを追加できるように、__APIトークン__を発行し、控えておきます。この__APIトークン__は以降の AWS Lambda のプログラム内で利用します。
![line23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/65af2f28-b411-45bc-7351-97ad95ebf8ae.png)

## AWS Lambda と AWS API Gateway
LINE Bot からの Webhook 通知を受け取り、受信した内容を kintone アプリのレコードに追加し、返信メッセージを投稿するまでの一連の処理を、AWS Lambda と AWS API Gateway で行います。

適切な関数名を入力、ランタイムは Node.js 12.x を選択して、AWS Lambda の関数を作成します。
![line15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/883b6e04-8f52-f852-b364-87029d79ee45.png)
以下は必須ではないですが、私の場合は以下のように設定しています。
メモリは初期値でも問題ないと思いますが念のため 256MB に、タイムアウトの初期値3秒は短過ぎますので今回は15秒に設定しました。
![line20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/c3fe51c4-f341-5815-8f90-30113fd2b76c.png)

続いて、トリガーに AWS API Gatway を追加します。 
![line16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/b2a32676-dd20-f8bd-b3a8-87c9b09032e6.png)
APIには Create an API を選択、API type は REST API を選択、セキュリティは オープン を選択します。
![line17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/ddca3e49-2e94-d387-1778-493b1fc239c8.png)
セキュリティは オープン にしていますが、後でIPアドレスを限定するなどの追加措置を検討すべきですね。（今回は省略）
![line18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/52d8a520-1545-68ba-dbdf-d59a531a7abc.png)
AWS API Gatway の追加完了後、上記の__APIエンドポイント__をメモしておきます。この URL を後で LINE のチャンネルの Webhook に設定します。

今回は以下の node.js のプログラムを Lamda に設定しました。（説明は省略）
以下は過去の環境を流用したため sync-request で実装しています。

```index.js
'use strict';

const request = require('sync-request');
const Protocol   = "https://";

// LINE 送信設定
const LineHost   = "api.line.me";
const LinePath   = "/v2/bot/message/reply";
const LineToken  = "LINEのチャンネルアクセストークン";

// kintone 送信設定
const Domain     = "cybozu.com";
const Subdomain  = "サブドメインを設定";
const Path       = "/k/v1/record.json";
const AppId      = "アプリIDを設定";
const Token      = "アプリのトークンを設定";

exports.handler = async (event) => {

    // LINE から受信したデータをデバッグ表示
    console.log('EVENT.BODY:', JSON.stringify(event.body, null, 2));
    
    console.log('Function Start.');
    
    // LINE から受信したデータ
    let eventData = JSON.parse(event.body);
    let type  = eventData.events[0].type;
    let mode  = eventData.events[0].mode;
    let token = eventData.events[0].replyToken;
    let user  = eventData.events[0].source.userId;
    let text  = "";
    let response = {};
    
    // LINE メッセージの返信を送信
    if(type == "message"){
        text  = eventData.events[0].message.text;
        response = {
            replyToken: token,
            to:[user],
            messages:[
                {
                    "type":"text",
                    "text":"Re:" + text
                }
            ]
        };
        let url = Protocol + LineHost + LinePath;
        let res = funcPostLine(request, url, LineToken, response);
        console.log(res);
    }

    // LINE から受信したデータを kintone アプリに追加 
    require('date-utils');
    let dt = new Date();
    let url = Protocol + Subdomain + '.' + Domain + Path;
    let data = {
        "lineDateTime": { "value" : dt.toFormat("YYYY-MM-DDTHH24:MI:SSZ") },
        "lineUserId":   { "value" : user },
        "lineType":     { "value" : type },
        "lineMode":     { "value" : mode },
        "lineMessage":  { "value" : text },
    };
    let res = funcPostKintoneRecode(request, url, AppId, Token, data);
    console.log(res);
    
    console.log('Function end.');
    
    // line の Webhook にレスポンスを返す
    return {
        'statusCode': 200,
        'body': JSON.stringify(response)
    };
};

// LINE にメッセージを送信
function funcPostLine(request, url, token, json)
{
	let response = request('POST',url,{
        headers: {
            "Content-type": "application/json",
            "Authorization": " Bearer " + "{" + token + "}"
        },
        json: json,
    });
    return response;
}

// kintone アプリのデータ追加
function funcPostKintoneRecode(request, url, appId, token, json)
{
	let response = request('POST',url,{
        headers: {
            'Content-type': 'application/json',
            'X-Cybozu-API-Token': token
        },
        json: { app : appId, record: json },
    });
    return JSON.parse(response.getBody('utf8'));
}
```

AWS Lamda の開発等についての詳細は、以下などの情報を参考に。
__【AWS入門】Lambdaの概要とサンプルコードで手を動かしながら実践入門__
https://fukatsu.tech/aws-lambda
__AWS Lambda 開始方法__
https://aws.amazon.com/jp/lambda/getting-started/
__Lambda の Node.js でもっといろんなパッケージを使いたいとき__
https://tech-lab.sios.jp/archives/9017
__AWS Lambda Layersでnode_modulesを使う__
https://xp-cloud.jp/blog/2019/01/12/4630/

## LINE チャンネルの Webhook の設定と試験
AWS API Gateway の設定が完了した時に控えた__APIエンドポイント__を、LINE チャンネル Messaging API 設定の Webhook に設定します。
LINE に登録や投稿などのイベントが発生した場合、この Webhook に設定したURL（今回は AWS API Gateway）に情報を送信します。
![line26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/6064b409-68c6-c290-3b85-e3ed8ba72de6.png)
検証を行って「成功」が表示されれば、運用できますので Webhookの利用で設定します。成功が返ってこない場合は AWS Lambda で何等かのエラーが発生していますので、CloudWatch のログを確認します。
![line28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/4d211dd8-57f4-04cb-f0e4-e33a8823d71c.png)
検証が成功すると、kintone のアプリに以下のレコードが追加されます。
![line29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/c171a3d0-6064-4bac-2655-2d5943c26d11.png)

## スマホの LINE アプリで試験 
### LINE チャンネルのお友達登録
スマホの LINE アプリで試験するためには、LINE チャンネル Messaging API 設定に表示されているQRコードを、スマホの LINE アプリで読み込ませます。
![line30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/8a205cf1-91e7-1014-f16a-50ed13ea8dca.png)
以下の「お友達を追加」画面で追加すると、お友達登録の返信を受け取り、トーク一覧に表示されます。
![新規 Microsoft PowerPoint プレゼンテーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/6f2ea73b-ff38-cfbf-2157-4e5ff0747497.png)
kintone のアプリで LINE チャンネルの follow　の連絡が無事届きました。
![line31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/e57ab46f-c150-95ff-8f0b-b1a46064c666.png)

### LINE チャンネルにメッセージ送信
スマホの LINE アプリでメッセージを送信してみます。
![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/05626333-15df-2871-e357-e158034f2b57.png)
メッセージの返信は無事送付されていますが、LINE チャンネルのデフォルト設定ではお問い合わせを受け付けてないとのメッセージも返信されています。これを避けるためには、LINE チャンネルの チャンネル基本設定 に表示されている LINE Offical Acccount Manager で設定を変更します。
![line33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/d9c94d83-ca45-93a6-3f08-898391402899.png)
LINE Offical Acccount Manager 応答設定の詳細設定で、応答メッセージをオフにします。
![line36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/1e472c78-acb1-ac16-d80d-d3c63c5ac454.png)
再度メッセージを送ると、メッセージの返信のみが送付されます。
kintone のアプリにも一連の投稿が保管されていることが確認できました。
![line38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75892/72448e19-bf94-448d-b578-8438e1907bd9.png)

### 参考
AWS Lamda で LINE の投稿から受信したデータをデバッグ表示した内容は以下です。

```
{
	"events":[
		{
			"type":"message",
			"replyToken":"<------Token----->",
			"source":{
				"userId":"<------userId----->",
				"type":"user"
			},
			"timestamp":1591799835660,
			"mode":"active",
			"message":{
				"type":"text",
				"id":"<------id----->",
				"text":"今度はどうかな？"
			}
		}
	],
	"destination":"<------destination----->"
}
```

今回は利用しませんでしたが LINE Messaging API SDK for nodejs もあるようです。
__LINE Messaging API SDK for Node.js__
https://github.com/line/line-bot-sdk-nodejs

## 参考情報
__LINE Developersに登録しよう！__
https://www.techpit.jp/courses/google-apps-script-linebot-todo-bot/lectures/8934614

__Messaging API__
https://developers.line.biz/ja/docs/messaging-api/