GoogleForm->GAS->Notion

Notion APIを叩いてみたかったから、ちょっと試した感じです。

また、下記アドベントカレンダー4日目の記事です。

https://qiita.com/advent-calendar/2022/okinakajyuku


# 構成はこんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/691700e3-2b72-252b-0a2c-3b3e60e72811.png)


フォームで送信した内容がスプレッドシートに自動的に追加されていきますので、トリガー設定をしてGASを発動。その中でNotion APIを叩く流れです。

# Notion Developersにてインテグレーションを作成

https://www.notion.so/my-integrations より新規インテグレーションを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/f321d14a-2785-b708-6406-eb2449c02c59.png)

#### トークンをメモ

GASで指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/ee148237-7a09-23b1-9b1b-a3f48a8fa2bb.png)



# Notionでページを作成

事前にページは作成した状態で、APIでブロックをどんどん追加していくイメージです。
主に以下を参照しました。

- Append block children

https://developers.notion.com/reference/patch-block-children

- Block object

https://developers.notion.com/reference/block


# GASの中身

トークンなど秘匿性のあるものは GAS の `PropertiesService.getScriptProperties` が使えますのでコードに直書きしない方が良いですね。 `NOTION_BOOK_PAGE` とありますが、NotionのブロックIDですね。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/29045120-90d0-379a-2a54-e7982dce0640.png)

トリガーは、「イベントの種類」を「フォーム送信時」に設定することで、フォーム送信があるたびに所定の関数を実行できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/8717d617-f4e3-735d-c87a-587b9afa8008.png)


また、パラメーターが渡されてくるので、 `event.range.getRow();` とすることで、フォーム送信で追加されたスプレッドシートの行番号を取得できます。

```
const NOTION_TOKEN = PropertiesService.getScriptProperties().getProperty("NOTION_TOKEN")
const NOTION_BOOK_PAGE = PropertiesService.getScriptProperties().getProperty("NOTION_BOOK_PAGE")
const SpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const Sheet = {
  Books: SpreadSheet.getSheetByName("books")
};
const ClmIndex = {
  RegisterDateTime: 0,
  Mail: 1,
  Title: 2,
  Link: 3,
  Rank: 4,
  Comment: 5,
}

const ClmLast = ClmIndex.Comment + 1

/**
 * フォーム送信時のハンドラ
 */
const acceptedForm = (event) => {
  const registerDataRowId = event.range.getRow();
  const orders = Sheet.Books.getRange(
    registerDataRowId,
    1,
    1,
    ClmLast
  ).getValues();

  if (!orders || orders.length == 0) {
    return;
  }

  addBookToNotion(orders[0])
}

const addBookToNotion = (order) => {
  const now = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd');
  const object = {
    "children": [
      {
        // 見出しにタイトル
        "type": "heading_3",
        "heading_3": {
          "rich_text": [{
            "type": "text",
            "text": {
              "content": `${order[ClmIndex.Title]}`,
              "link": null
            }
          }],
          "color": "default",
          "is_toggleable": false
        }
      },
      {
        // リンクとキャプション
        "object": "block",
        "type": "bookmark",
        "bookmark": {
          "url": `${order[ClmIndex.Link]}`,
          "caption": [
            {
              "type": "text",
              "text": {
                "content": `${order[ClmIndex.Comment]} ${now}`
              }
            }
          ]
        }
      },
      {
        // ブランク行
        "type": "paragraph",
        "paragraph": {
          "rich_text": [{
            "type": "text",
            "text": {
              "content": ""
            }
          }]
        }
      }
    ]
  }

  const options = {
    method: 'PATCH',
    headers: {
      'Content-Type': 'application/json',
      'Notion-Version': '2022-06-28',
      'Authorization': `Bearer ${NOTION_TOKEN}`
    },
    payload: JSON.stringify(object)
  };

  UrlFetchApp.fetch(`https://api.notion.com/v1/blocks/${NOTION_BOOK_PAGE}/children`, options)
}
```


# ということで

Notionも気になってたのですがあまり触ってなかったので良い機会を頂けました！
GASも入口としては触りやすいので、連携するとアイデア次第で色々できそうな感じですね。