読書の振り返りが驚くほど簡単に：NotionAPIとSlackAPIで作ったシステム

## 概要


読書での学びを簡単に記録でき、記録内容を自動でslackに送信するシステムを作成しました!!!


![ 2023-06-18 22.53.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/e29fd0f1-b948-6e76-9167-fbf46d41a8ea.png)


:::note
お気に入りポイント
:::

1. 日々の読書体験からの学びを手間なく記録できます。
1. 単に読むだけでなく、本のハイライト箇所をslackで復習できます。
1. 自分がどれだけ本に触れているかを確認できます。



読書は好きだけど、記録するのが面倒な方は必見です！！！

## 内容
本システムは2つのパートに分かれています。

1. 読書の記録
1. 記録内容をslackに自動送信

### 読書の記録
読書の記録では[BookNotion](https://booknotion.site/)を用います。

https://booknotion.site/

BookNotionとは、KindleのハイライトをNotionに自動保存するアプリケーションであり、読書の記録を簡単に保存できる点が非常に優れています。

BookNotionを用いるための詳細な手順は以下です。(全てリンクが付与されています。)

1. [BookNotionのダウンロード](https://apps.apple.com/jp/app/booknotion/id1619994087)
1. [インテグレーションの取得と設定](https://booknotion.site/setting-integration)
1. [ページのシェア設定](https://booknotion.site/setting-share)
1. [ページIDの取得と設定](https://booknotion.site/setting-pageid)

ここでは、Notionのデータベースを作成し、Notion APIでデータベースにアクセスできるように設定しています。BookNotionはNotionAPIを用いて、Notionデータベースにアクセスします。


:::note warn
手順2のインテグレーションの取得と設定で取得した「Secretsからインテグレーショントークン」（後のAPIトークン）と手順4のページIDの取得と設定で取得した「PAGE ID」(後にデータベースID。)は、以降で用いるのでメモしておいてください！！
:::

BookNotionの使い方は簡単で、Kindleでメモしたい文章を長押しで選択し(ハイライトし)、シェア->テキストの引用でBookNotionを選択し、保存します。今回は触れませんが、ハイライトにタグをつけたり、コメントをつけたりもできます。

![ 2023-06-18 22.49.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/88c25979-b179-547e-cf22-628100f71d38.png)



BookNotionでは保存の際に、自動で著者名と本のタイトルを保存してくれます。本当に便利です！
![ 2023-06-18 22.15.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/a793daf0-a627-4da1-3745-1e69b5c9c4ae.png)



### 記録内容をslackに自動送信
BookNotionで記録した内容をスラックに自動送信するためには、以下の３つの流れが必要です。

1. NotionAPIを用いてNotionデータベースから情報を取得する
1. SlackAPIを用いてslackにデータを送信する
1. 1と2を記述したプログラムを定期実行する

1と2を記述したプログラムの完成版をまずご覧になりたい方は[こちら](#NotionAPIとSlackAPIを用いたslack送信)へ


#### NotionAPI
まずプログラムでNotionAPIと使うためにAPIトークン、Notionのデータベースに接続するためにデータベースのIDを環境変数に設定します。APIトークンはインテグレーショントークンであり、データベースのIDは控えておいたPAGE IDです。

環境変数は以下のようにターミナルで設定します。

```bash
% export NOTION_API_TOKEN="{インテグレーショントークン}"
% export NOTION_DATABASE_ID="{PAGE ID}"
```

Notionのデータベースにアクセスするためには以下のようにプログラムを記述します。

```Python
import os
import requests

API_TOKEN = os.environ["NOTION_API_TOKEN"]
DATABASE_ID = os.environ["NOTION_DATABASE_ID"]

headers = {
    "Authorization": "Bearer " + API_TOKEN,
    "Content-Type": "application/json",
    "Notion-Version": "2022-06-28",
}

url = f"https://api.notion.com/v1/databases/{DATABASE_ID}/query"

response = requests.post(url, headers=headers)
```

`headers`の`Authorization`にはNotionのAPIトークンが記述されており、`requests`の際のURLにデータベースIDが記述されています。

上記で得られた`response`はそのままでは使えないので、以下のように情報を取り出せる形にします。

```python
data = response.json()
results = data["results"] #データベースの行1つ1つが入っている
```

こうして取り出した`result`にはデータベースの行1つ1つが入っています。

BookNotionで自動生成したデータベースのカラム（本のタイトル、ハイライト箇所、登録日時）にアクセスするには以下のように記述します。

```Python
page = results[0]
props = page['properties']

title = props['📙  Book Title']['select']['name']
memo = props['📝  Highlight']['title'][0]['text']['content'] # ハイライトの箇所
raw_created_time = props['Created At']['created_time']
```

for文を用いることで全てのデータにアクセスできます。

#### SlackAPI

SlackAPIの使い方は以下の記事で解説しております。

https://zenn.dev/sergicalsix/articles/f7ad91d1d7cd04

SlackAPIを用いるための設定と使い方について記述されています。

SlackAPIを用いてslackを送信するプログラムは以下です。

```python
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

def send_slack_message(text = "Hello from your app! :tada:", channel = "random"):
    slack_token = os.environ["SLACK_API_TOKEN"]
    client = WebClient(token=slack_token)

    try:
        response = client.chat_postMessage(
            channel=channel,
            text=text
        )
    except SlackApiError as e:
        # You will get a SlackApiError if "ok" is False
        assert e.response["error"] 
```

#### NotionAPIとSlackAPIを用いたslackの送信

NotionAPIとSlackAPIの設定ができたので、次にslackに送信するメッセージを決めます。

（1）週、月、年あたりにどのくらいの本に触れたか、(2)毎週の気づき(本のハイライト)の2点を振り返りたいため、以下のようなメッセージが送られて欲しいです。

```bash
あなたの読書記録は以下です。

今週: 2冊
今月: 10冊
今年: 30冊

あなたの今週の気づきは以下です。

1: 気づき1
2: 気づき2
```



NotionAPIを用いてNotionデータベースから情報を取得し、SlackAPIを用いて上記のようなslackを送信するプログラムは以下です。

:::note 
完成版(コピペ用)
:::

```python
import os
from datetime import datetime
import requests
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

def send_slack_message(text = "Hello from your app! :tada:", channel = "random"):
    slack_token = os.environ["SLACK_API_TOKEN"]
    client = WebClient(token=slack_token)

    try:
        response = client.chat_postMessage(
            channel=channel,
            text=text
        )
    except SlackApiError as e:
        # You will get a SlackApiError if "ok" is False
        assert e.response["error"] 
	

def get_pages(DATABASE_ID, headers):
    url = f"https://api.notion.com/v1/databases/{DATABASE_ID}/query"
    response = requests.post(url, json=payload, headers=headers)
    data = response.json()
    results = data["results"]
    return results


API_TOKEN = os.environ["NOTION_API_TOKEN"]
DATABASE_ID = os.environ["NOTION_DATABASE_ID"]

headers = {
    "Authorization": "Bearer " + API_TOKEN,
    "Content-Type": "application/json",
    "Notion-Version": "2022-06-28",
}


pages = get_pages(DATABASE_ID=DATABASE_ID, headers=headers )

today = datetime.now()
weekly_count = 0
weekly_memos  = ""
weekly_titles, monthly_titles, yearly_titles = [],[],[]

for i,page in enumerate(pages):
    props = page['properties']

    title = props['📙  Book Title']['select']['name']
    memo = props['📝  Highlight']['title'][0]['text']['content']
    raw_created_time = props['Created At']['created_time']
    datetime_object = datetime.strptime(raw_created_time , "%Y-%m-%dT%H:%M:%S.%fZ")
    day_diff = (today - datetime_object).days

    if day_diff <= 7:
        weekly_count += 1
        weekly_memos += f"{weekly_count}: {memo}\n"
        weekly_titles.append(title)
    if day_diff <= 31:
        monthly_titles.append(title)
    if day_diff <= 365:
        yearly_titles.append(title)

weekly_memos = weekly_memos[:-1] #文末の\nを削除

message = f"""あなたの読書記録は以下です。

今週: {len(set(weekly_titles))}冊
今月: {len(set(monthly_titles))}冊
今年: {len(set(yearly_titles))}冊

あなたの今週の気づきは以下です。

{weekly_memos}
"""

print(message) #ターミナルでも確認するため
send_slack_message(text=message)
print("Success!!")
```

このプログラムを実行すると、slackに以下のようなメッセージが送られてきます。

![ 2023-06-18 18.14.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/1d04b12f-64a2-e3b6-e900-894c81ec67a9.png)

バッチリです！！:tada:

#### 自動実行 
最後にこれらのプログラムを自動実行させます。

自動実行させるには、(1)ローカルPCで自動実行(2)サーバーで自動実行の２通りが考えられます。
今回は(1)のローカルPCで自動実行させます。

私はMacユーザーなのでAutomatorを用いて自動実行させます。(Windowsの方はタスクスケジューラで代替できます。)


https://di-acc2.com/system/rpa/21699/

https://di-acc2.com/system/rpa/21764/

:::note warn
一点注意点があって、今回は環境変数を事前に設定しているため、pythonファイルの定期実行はうまくいきません。
:::

Automatorやcronなどで自動実行する際は、ローカルPCの環境とは異なる環境でプログラムが実行されるので、プログラムを実行する前に環境変数を設定するシェルスクリプトを書き、そのシェルスクリプトを自動実行させます。

シェルスクリプトの例はこちらです。

```bash
export NOTION_API_TOKEN="{インテグレーショントークン}"
export NOTION_DATABASE_ID="{PAGE ID}"
export SLACK_API_TOKEN="{設定したslackのAPIトークン}"
source {仮想環境の名前(SlackAPIを用いるために設定)}
cd {プログラムの絶対パス}
python {ファイル名}
```


## まとめ
このように、NotionとSlackを組み合わせたこのシステムを用いれば、読書の学びを簡単に振り返ることが可能になります！

最後に、このシステムがあなたの読書体験をより豊かなものにできれば幸いです！！