4
4

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-01-24

野望

相も変わらずNotionをDBに用いたLINE Bot的なものが作りたいです。
image.png

前回のあらすじ

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

今回やったこと

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

image.png

image.png

手順

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

①Notionでテーブルの準備

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

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

image.png

自分はこんな感じで作りました。
image.png

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

②Notionでトークンの設定

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

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

image.png

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

image.png

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

image.png
image.png

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

image.png
image.png

以下のように追加されます。
image.png

③Lambdaのコードを変更する

API Referenceからコードをおパクリ申し上げました。
https://developers.notion.com/reference/post-database-query

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

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. モジュールとかトークンとか

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

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

2. 本体

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の階層が必要かどうかは未検証です。

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

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

次回予告

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

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4