Notion API + LINE + AWS Lambda他でメモ内容をLINEにしゃべらせる

# 野望
相も変わらずNotionをDBに用いたLINE Bot的なものが作りたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/7acc353d-96ab-d5a0-8a5d-289b8e41e0c0.png)

# 前回のあらすじ
Notion APIの前にまずはLINE Messaging APIの検証から始めました。
どうやら用意したLINE公式アカウントで受信したテキストをもとに応答をすることができるようになったっぽいです。
https://qiita.com/DJROU/items/900e3c32b87b5d43d8ed

# 今回やったこと
いきなりNotionを繋げて読み込みと書き込みをできるようにするのは荷が重いので、LINE公式アカウントに対してユーザが送ったテキストをNotionで検索した結果を返せるようにしました。
指定したDBのキーに対する値がゲットできるところまでのお試しです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/b392aefc-7d34-ce50-80de-ecb5dc4ea80d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/0d0ba0e0-9402-5fa3-da6c-0f8cd724d8c3.png)

# 手順
①Notionでテーブルの準備
②Notionでトークンの設定
②Lambdaのコードを変更する

# ①Notionでテーブルの準備
まず、Notionのユーザ登録なりなんなりでリストやテーブルを使えるようにしましょう。
無料プランでOKです。

ここではデータの格納先となるテーブルを準備します。
Notionのメニュー > ワークスペースから新規作成して、テーブルを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/f334b0c7-28a9-cd48-759e-43d75706ff2e.png)

自分はこんな感じで作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/10b73509-03f2-8cf1-27ea-c2d64c656204.png)

以降、本記事ではkeyをキー、valueを値とします。

# ②Notionでトークンの設定
ここでは、テーブルが置いてあるところ（ワークスペースというらしい）単位で一意のトークンを払い出してみましょう。

Notion > メニュー > 設定 > インテグレーションを開きます。
さらに「独自のインテグレーションを開発する」からインテグレーション自体の設定画面に移ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/4a000935-30e5-728b-3417-2e96fca79468.png)

こんなページで設定します。
新しいインテグレーションを作成しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/6cd5abac-b39d-ebf4-b275-4f7c8ab0c806.png)

名前を付けて権限を設定します。私は今後書き込みもしたいので全部盛りにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/3085837f-7d53-6b93-9bc8-b46b973e6817.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/8ae8ee33-e38d-057d-d29d-6be2dc139c6e.png)

送信したらトークンができるはずです。
このトークンはあとでLambdaで使用するので控えておきます。
先ほどのテーブルに戻ってこのトークンでのアクセスを許可しましょう。
テーブル編集画面の右上にある「共有」から、先ほど作成したインテグレーションを招待します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/5f58e89a-0e32-3f38-ffab-d6aac85f71da.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/6922dace-c31f-755c-4569-00ebccd41fff.png)


以下のように追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/0c8766d3-235d-10b9-f168-cd16134730c8.png)

# ③Lambdaのコードを変更する
API Referenceからコードをおパクリ申し上げました。
https://developers.notion.com/reference/post-database-query

一部前話と重複する説明は省略します。
前話：https://qiita.com/DJROU/items/900e3c32b87b5d43d8ed

```javascript:routest.js
'use strict';
const line = require('@line/bot-sdk');
const { Client } = require("@notionhq/client");
const notionToken = "Notionで作成したトークン";
const databaseId = '後述するデータベースのID';
const notion = new Client({
  auth: notionToken,
});
const client = new line.Client({
  channelAccessToken: 'LINEのチャンネルアクセストークン'
});

exports.handler = (event, context, callback) => {
  console.log("event.body:", event.body);
  let requestMessage = JSON.parse(event.body).events[0].message.text;
  let replyToken =JSON.parse(event.body).events[0].replyToken;
  
  (async () => {
    const responseId = await notion.databases.query({
      database_id: databaseId,
      filter: {
        or: [
          {
            "property": "key",
            "text": {
              "contains": requestMessage
            }
          },
        ],
      },
    });
    let replyText =  responseId.results[0].properties.value.rich_text[0].text.content;
    let message = {
      type: 'text',
      text: replyText
    };
    client.replyMessage(replyToken, message).then((data) => {
      console.log(data);
      callback(null, "OK");
    }).catch((err) => {
      console.log("だめでし");
      callback(err, "NG");
    });
  })();
};
```


### 1. モジュールとかトークンとか

```javascript:routest.js
'use strict';
const line = require('@line/bot-sdk');
const { Client } = require("@notionhq/client");
const notionToken = "Notionで作成したトークン";
const databaseId = '後述するデータベースのID';
const notion = new Client({
  auth: notionToken,
});
const client = new line.Client({
  channelAccessToken: 'LINEのチャンネルアクセストークン'
});
```
Node.jsで使用するモジュールは「@line/bot-sdk」「@notionhq/client」です。
Lambdaのレイヤーで使えるようにしましょう。
（参考）
https://qiita.com/DJROU/items/bcdc2902757e606e9226

databaseIdはNotionで作成したデータベースを指定するIDです。
Notionの画面上から取得しましょう。
テーブル編集画面の右上にある「共有」から、「リンクをコピー」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/5f58e89a-0e32-3f38-ffab-d6aac85f71da.png)

ここでコピーされたURLのうち「notion.so/より後・?」より前がデータベースのIDです。
'後述するデータベースのID'のとこに書きましょう。
(例)太字のところ(URLを無効にするために空白を入れています)
https:// ww w.notion.so/**samplehogehoge12345aaaaa54321**?v=samplehugahuga98765bbbbb56789


### 2. 本体
```javascript:routest.js
exports.handler = (event, context, callback) => {
  
  let requestMessage = JSON.parse(event.body).events[0].message.text;
  let replyToken =JSON.parse(event.body).events[0].replyToken;
  
  (async () => {
    const responseId = await notion.databases.query({
      database_id: databaseId,
      filter: {
        or: [
          {
            "property": "key",
            "text": {
              "contains": requestMessage
            }
          },
        ],
      },
    });
    let replyText =  responseId.results[0].properties.value.rich_text[0].text.content;
    let message = {
      type: 'text',
      text: replyText
    };
    client.replyMessage(replyToken, message).then((data) => {
      console.log(data);
      callback(null, "OK");
    }).catch((err) => {
      console.log("だめでし");
      callback(err, "NG");
    });
  })();
};
```
async/awaitの使い方には自信がありません。
notion.databases.queryでNotionのページ（データベース）とキーを検索しています。
「key」という項目が「requestMessage」(LINEで受け取った文字列)を含むときでフィルタしています。orの階層が必要かどうかは未検証です。

```javascript:routest.js
      filter: {
        or: [
          {
            "property": "key",
            "text": {
              "contains": requestMessage
            }
          },
        ],
      },
```


notion.databases.queryでリクエストした値はresponseId.results[0].properties.value.rich_text[0].text.contentに入ってきます。奥ぃ。

最後に前回はLINEでオウム返ししていたところをNotionで受け取った値にしてreplyMessageしています。

# できあがり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455207/ae127605-29e5-0ac3-ebb8-3ed933750b21.png)

keyにない投稿を受け取ったときの処理を書いていないのが課題です。
(画像の「あ」「平井堅」のところ)

# 次回予告
今のNotionデータベースを使用して、keyとvalueのセットを書き込んでみるらしいです。