LINE×GAS×Notion｜今日の気分をクイックリプライで回答し、Notionに記録

:::note warn
本記事に記載のコードは全てを1から私が記載したわけではありません。
参考記事をもとに作成・追加改造を記録した記事です。
:::


# ゴール
1. LINE MessageAPI、GASを用いて、今日の気分をクイックリプライで回答
1. スプレッドシートに記録
1. スプレッドシートに記録した内容をNotionにも記録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/68e0f952-2547-dadc-ef32-796d1638f1d9.png)

# 完成形

<details><summary>LINE</summary>

![LINE画面.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/917a346b-b65e-d3aa-ab23-f2d8dce75154.gif)

</details>


<details><summary>スプレッドシート</summary>

![貼り付けた画像_2024_11_09_17_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/73f4956d-3fca-fb45-9aef-1330a4479b11.png)



</details>

<details><summary>コード</summary>

```js:record_feeling_to_SpreadSheet.gs
// ------------------クイックリプライボタンを設定したメッセージを送る------------------ //
function askFeeling_quick_reply() {
	/* スクリプトプロパティのオブジェクトを取得 */
	const prop = PropertiesService.getScriptProperties().getProperties();
 
	/* クイックリプライボタンを設定したメッセージを送る */
	UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', {
		'headers': {
			'Content-Type': 'application/json',
			'Authorization': 'Bearer' + ' '+ prop.LINE_TOKEN, // スクリプトプロパティにトークンは事前に追加しておく
		},
		'method': 'POST',
		'payload': JSON.stringify({
			"to": prop.LINE_USER_ID, // スクリプトプロパティに送信先IDは事前に追加しておく　→https://tonari-it.com/gas-line-bot-friend-token/#toc2
			"messages": [
				{
        "type": "text", // ①
        "text": "今日の気分はどう？",
        "quickReply": { // ②
    "items": [
      {
        "type": "action", // ③
        "action": {
          "type": "message",
          "label": "晴れ",
          "text": "$Feeling:晴れ"
        }
      },
      {
        "type": "action",
        "action": {
          "type": "message",
          "label": "曇り",
          "text": "$Feeling:曇り"
        }
      },
      {
        "type": "action",
        "action": {
          "type": "message",
          "label": "雨",
          "text": "$Feeling:雨"
        }
      }
    ]
  }
}	],
			"notificationDisabled": false // trueだとユーザーに通知されない
		}),
	});
}



// ------------------クイックリプライで回答してスプレッドシートに記録する------------------ //
var sheet;

function doPost(e) {
  var userMessage = JSON.parse(e.postData.contents).events[0].message.text;
   
  if(userMessage.match(/^\$/)) {
    userMessage = userMessage.substr(1);
  } else {
    return;
  }
   
  var spreadsheetId = "16NNUTPhqIUbSBYNoN4BsdhPIjxxMjknjHkPSJtQd-3E";
  var sheetName = "Line_to_SpreadSheet";
  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  sheet = spreadsheet.getSheetByName(sheetName);
 
  // 書き込み処理
  setData(userMessage);

  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
 
}

function setData(msg)
{
  let data = msg.split(/\n/);
  let row = sheet.getLastRow() + 1;

  let playerNum = 30;
  let startCol = 2;
  let cells = sheet.getRange(1, startCol, 1, startCol + playerNum);

  // 日付
  let dateCell = sheet.getRange(row, 1);
  dateCell.setValue(new Date());

  // "Name"列に書き込み
  let nameCell = sheet.getRange(row, 2);
  nameCell.setValue("かたかた")


  // スコア書き込み
  data.forEach(function(key){
    let scores = key.split(/:/);
    let name = scores[0];
    let score = scores[1];
    let col = getPlayerCol(cells, name);

    setScore(col, row, score);
  });
}

function setScore(col, row, score)
{
  //  プレイヤー人数が想定を超えている
  if(col == 0){
    return;
  }

  let cell = sheet.getRange(row, col);
  cell.setValue(score);
}

function getPlayerCol(cells, name)
{
  let row = 1;
  for (var col = 1; col <= cells.getNumColumns(); col++) {
      var cell = cells.getCell(row, col);
      if (cell.getValue().match(name)) {
        return cell.getColumn();
      }else if(cell.getValue() == ""){
        // 新規プレイヤー
        cell.setValue(name);
        return cell.getColumn();
      }
  }
  return 0;
}



// ------------------スプレッドシートからNotionに記録する------------------ //


function doPostNotion() {
  const prop = PropertiesService.getScriptProperties().getProperties();

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const js = convertJson(ss.getDataRange().getValues());

  js.forEach(function (elem, index) {
    const obj = {
      "parent": {
        "database_id": prop.NOTION_DB_ID
      },
      "properties": {
        "Name": {
          "title": [
            {
              "text": {
                "content": elem.Name
              }
            }
          ]
        },
        "Feeling": {
          "rich_text": [
            {
              "text": {
                "content": elem.Feeling
              }
            }
          ]
        },
        "Date": {
          "type": "date",
          "date": {
            "start": Utilities.formatDate(elem.Date, "JST", "yyyy-MM-dd"),
            "end": null
          }
        }
      }
    };
    postNotion(obj);
    Utilities.sleep(1000);
  });

}

function postNotion(object){
  const prop = PropertiesService.getScriptProperties().getProperties();

  const options = {
  method: 'post',
  headers: {
    'Content-Type': 'application/json',
    'Notion-Version':'2021-05-13',
    'Authorization':"Bearer "+prop.NOTION_TOKEN
  },
  payload: JSON.stringify(object)
};
console.log(options)
  var response = UrlFetchApp.fetch('https://api.notion.com/v1/pages', options);

}

function convertJson(range) {
  const key = range[0];

  const js = range.slice(1).map(
    function (row) {
      const obj = {};
      row.map(function (item, index) {
        obj[String(key[index])] = item;
      }
      );
      return obj;
    });
  return js;
}




```


</details>


<details><summary>スクリプト プロパティ</summary>

![LINE→スプシ→notion_-_プロジェクトの設定_-_Apps_Script.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/9a236f6a-106c-d51b-bd80-05a5170b2e79.png)

</details>

<details><summary>Notion</summary>

![貼り付けた画像_2024_11_09_18_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/a2c5de4a-fd89-cec9-279f-a309152e2805.png)

</details>


# 感想・課題
### 課題
- トリガーを2つ設定しているが、「スプレッドシートにデータが記録・削除・編集されたら、Notionに転記」という形でひとまとめにしたい。
- 気分だけでなく、その日の出来事、画像、絵文字なども記録したい。
- 投稿者別に記録できる形に変えたい
    - 「Aさん」「Bさん：がそれぞれ名前を記入するだけで、別の列に記録される感じ。

### 感想
とりあえず、最低限ではあるが作りたい形はできた。
でも、やっぱり基本的な構文を覚えた方がもっと早く作成できるんだろうな。

# 参考
### LINEからスプレッドシートに記録

https://www.pnkts.net/2018/06/03/line-messaging-api/#LINE-Bot%E3%81%AE%E8%BF%94%E4%BF%A1reply%E3%82%92%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86

https://took.jp/line-spreadsheet/

### スプレッドシートからNotionに記録

https://www.pnkts.net/2021/05/16/gas-notion-api

https://heysho.com/notion-api-google-sheet/