[NotionAPI×LINEbot] APIをこねこねしてタスクお知らせくんを作った

# はじめに
こんにちは！早速ですが、みなさんNotion使ってますか？？
シンプルなデザインとスッキリ情報をまとめられる階層型のページレイアウトと自由度の高さとデータベースの優秀さに感動しつつ私は毎日お世話になっております。大好きNotion、ありがとうNotion。

というわけで、タスク管理にもNotionを導入してみましょう。具体的には、カレンダービューのデータベースを用意して締切日にタスク（アイテム）を追加し、完了したものにはチェックボックスにチェックを入れるといった感じです。サンプル↓
![スクリーンショット 2022-12-09 11.38.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/4005a477-1f4f-9244-a610-b5320bf5720a.png)
まぁ大抵真面目な人ならこれくらい管理ができれば問題なくタスクをこなせそうですがギリギリまでやらない人間なので、今回Notion APIとLINE Messaging APIの力を借りてさらにお尻を叩いてもらうことにしました。

# 今回作ったもの
タスクお知らせくん

# まずはそれぞれの準備から
## Notionでデータベースを準備
Notion側でデータベースを用意します。
今回使用するデータベースのプロパティは、以下の3つです。

|種類|プロパティ名|その他|
|:---:|:---:|:---:|
|Aa タイトル|Name|自動的に作られるプロパティ<br>ページタイトルのこと|
|日付|締切|日付の形式 年/月/日, 時刻の形式 24時間|
|チェックボックス|完了||

テーブルビューにして確認するとこんな感じ。マルチセレクトのプロパティは今回のタスクお知らせくんに直接関わらないのであってもなくてもいいです。これでNotionのデータベースの準備は完了！
![スクリーンショット 2022-12-09 13.35.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/287bbd4a-9a75-cf31-b535-00726177feb0.png)

## Notion APIの準備
https://www.notion.so/my-integrations

上記リンクにアクセスして新しいインテグレーションを作成します。
わかりやすい名前を指定して、間のチェックボックスは特に触らずページの最後の送信ボタンをクリック。するとトークンが発行されます。これでNotio APIの準備は完了！

## Notion APIとNotionのデータベースをコネクトする

Notionの方に戻ります。ページ右上の ••• から、下の写真の通りに操作していきます。コネクトの中に先ほど作ったインテグレーションが出てくると思うのでコネクトに追加してあげましょう。
この時もし出てこなかったら、NotionのワークスペースとNotion APIを作成したワークスペースが同じかどうか確認してください。
![スクリーンショット 2022-12-09 14.03.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/d330f343-424c-4790-ec9c-356d685b7e8b.png)
また、"リンクをコピー"からデータベースIDをメモしておきます。データベースIDは、以下の○○○の部分のことを指します。
```
https://www.notion.so/○○○?v= ...
```

## LINE Messaging APIの準備
https://developers.line.biz/en/services/messaging-api/

上記リンクにアクセスして"Start now"をクリック。必要事項を記入して"Create"しましょう。"Messaging API"のところをクリックしてスクロールするとチャンネルアクセストークンが発行されているのを確認できます。LINEでQRコードを読み取って、LINEbotとお友達になりましょう。また、"Basic settings"の中の"Your User ID"もコピーしておきます。これで準備完了！

# GAS
自分のGoogleドライブにアクセスします。"新規"から"その他"を選択し、その中にある"Google Apps Script"を開きます。

## GASでやっていること①
+ Notionのデータベースから<font color="Tomato">締切が今日かつ完了にチェックがついていない</font>ページを取り出す
+ 取り出したデータの中から<font color="Tomato">タイトルだけ</font>を取り出して配列に入れておく
+ メッセージを送信する関数に配列を入れる
+ メッセージを送信する


```javascript
const NOTION_DATABASE_ID = 'データベースIDを記入';
const NOTION_URL = 'https://api.notion.com/v1/databases/' + NOTION_DATABASE_ID + '/query';
const NOTION_API_KEY = 'Notion APIで発行したトークンを記入';

const LINE_URL = 'https://api.line.me/v2/bot/message/push';
const LINE_ACCESS_TOKEN = 'LINE Messaging APIで発行したトークンを記入';
const LINE_USER_ID = 'LINEのユーザーIDを記入';

const FUNCTION_NAME = 'createMessage';

// Notionのデータベースにアクセス
function getNotionData() {
 const today = new Date();
 const formattedToday = Utilities.formatDate(today, 'JST', 'yyyy-MM-dd');
 const query = {
    filter: {       //filterを使って該当するページを調べます
      and: [
      {
        property: '締切',     //'締切'はプロパティ名
        date: {
          equals: formattedToday,
        },
      },
      {
        property: '完了',     //'完了'はプロパティ名
        checkbox: {
          does_not_equal: true,
        }
      }]
    },
  };

  let headers = {
    'content-type': 'application/json; charset=UTF-8',
    'Authorization': 'Bearer ' + NOTION_API_KEY,
    'Notion-Version': '2022-06-28',
  };
 
  let options = {
    'method': 'post',
    'headers': headers,
    'payload': JSON.stringify(query),
    "muteHttpExceptions": true
  };
  
  let notion_data = UrlFetchApp.fetch(NOTION_URL, options);
  notion_data = JSON.parse(notion_data);
    
  // タイトルだけを取り出す 'Name'はプロパティ名
  let word = [];
  for(let i = 0; i < notion_data.results.length; i++) {
    word[i] = '\n・' + notion_data.results[i].properties.Name.title[0].plain_text;
  }

  // Logger.log(notion_data);
  Logger.log(word);
  return(String(word))
}

//送信するメッセージ定義する関数
function createMessage() {
  //メッセージを定義する
  const test = getNotionData();
  return push(test);
}

//実際にメッセージを送信する関数
function push(text) {
  var headers = {
    "Content-Type" : "application/json; charset=UTF-8",
    'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
  };

  //toのところにメッセージを送信したいユーザーのIDを指定する
  var postData = {
    "to" : LINE_USER_ID,
    "messages" : [
      {
        'type':'text',
        'text':'🌟  今日のタスク  🌟' + '\n' + text,
      }
    ]
  };

  var options = {
    "method" : "post",
    "headers" : headers,
    "payload" : JSON.stringify(postData)
  };

  return UrlFetchApp.fetch(LINE_URL, options);
}
```

GASの便利な機能を使って、右上のデプロイボタンからデプロイします。デプロイから"新しいデプロイ"を選択しましょう。以下の写真のように種類の選択を"ウェブアプリ"、アクセスできるユーザーを"全員"にします。
![スクリーンショット 2022-12-12 17.15.43.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/448edd36-9baf-72e6-844b-8062b2a4d7ae.jpeg)
デプロイを押してウェブアプリのURLをコピーします。
LINE Messaging APIのページに戻って、'Webhook URL'のところに今コピーしてきたURLを貼り付けます。
![スクリーンショット 2022-12-12 17.32.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/78520242-1dff-87a1-eeb2-ad3c9d0ac24e.png)
GASに戻って"createMessage"の関数を選択して実行してみると以下のようにLINEbotからメッセージが届きました！やった〜〜
ちゃんとその日の完了になっていないタスク名だけが表示されていますね
![スクリーンショット 2022-12-10 13.12.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/b3723be9-1db4-dd77-e648-2b2a988ffc2d.png)


## GASでやっていること②
+ 決まった時間に送るためにトリガーをセットする
+ 使用済みのトリガーを削除する<br>（トリガーは20個以上用意することができないので使ったものは削除する必要があります）
+ 新しいトリガーを用意する

```javascript
// 前述のコードの続きに書きます

function informTasks() {
  deleteTriggers(FUNCTION_NAME);
  const date = new Date();
  const time = '13:10';       // ここは自分で好きな時間に書き換えてください
  date.setHours(...time.split(':'));
  setTrigger(FUNCTION_NAME, date);
}

// 使用済みのトリガーを削除する関数
function deleteTriggers(functionName) {
  const triggers = ScriptApp.getProjectTriggers();
  triggers.forEach(trigger => {
    if (trigger.getHandlerFunction() !== functionName) return;
    ScriptApp.deleteTrigger(trigger);
  });
}

// 新たにトリガーをセットする関数
function setTrigger(functionName, date) {
  ScriptApp.newTrigger(functionName).
    timeBased().
    at(date).
    create();
}
```
続いて、GASでトリガーをセットしていきます。実験的に1分ごとに関数が呼び出される設定にしてみます。
GASの左側の時計マークをクリックしてトリガーを追加から以下の写真のように選択します。完了ボタンを押すとセット完了です。1分ごとに通知がくると思います。
![スクリーンショット 2022-12-10 13.43.23.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303938/ad2f8f52-1bd0-6583-c551-0b46814ab4cc.jpeg)
設定の変更はトリガーの右にあるペンのアイコンをクリックして好きな時間に設定してください。タスクお知らせくん完成！！✨

# おわりに
最後まで読んでいただきありがとうございました！NotionとLINEbotでもっとハッピーなタスク処理ライフが送れそうです😌
watnowのアドベントカレンダーまだまだ続くのでお楽しみに〜〜

# 参考にしたサイト
+ https://developers.notion.com/reference/post-page
+ https://front-works.co.jp/blog/gas-set-triggers-on-time/
+ https://qiita.com/faronan/items/f8b39cf2d35e0f33272c
+ https://zenn.dev/syfut/articles/4906816e6e9118
+ https://and-engineer.com/articles/Y2RUeRAAACIAJfs9#heading3-8
+ https://qiita.com/n_oshiumi/items/a1a02e03093825f41e01

# 余談
お好みのプロパティでフィルターをかけたい人はレファレンスの以下のページを参考にすると良いと思います！

https://developers.notion.com/reference/post-database-query-filter