#GoogleAppsScript で自分好みの買い物メモを作ってみた #リテールテックハッカソン

## 買い物メモアプリ、使いにくい！
ご丁寧に**カテゴリ分け機能**、**レシピ連携機能**などを付けてくれているものがありますが、**使いません**！！機能が多いと**使いたい機能がわかりにくかったり、アプリが重くなったりする**ので不便です:no_good:

そもそもあまりいろいろアプリをインストールしたくないので、私たち夫婦はいつも**LINEで買い物メモ**を作っています。買うものを思いついたときにLINEで送りあうスタイルです。
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958610/dd4cc37f-285e-8dbd-ae57-8e4c4ba517d1.jpeg" />
しかし、**トークをさかのぼって買い物メモを見つけるのが面倒**なのが難点:no_good:

**そこで！**

**思いついたときすぐに買うものをメモ**でき、**あとで見やすい**LINE Bot「**思いつき買い物メモ**」を作りました:information_desk_person:

## 思いつき買い物メモ
<p>
  <img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958610/23f1e60b-db74-eb38-c8e2-96aaf3c8bb79.jpeg" />
  <img width=250  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958610/6c8b2ae7-153f-24d3-c78e-392cb725fa7b.jpeg">
</p>
買い物メモとして必要最低限の機能のみ搭載したシンプルかつ軽量な買い物メモLINE Botです！

- メモを登録
- メモを見る
- メモを削除

## 使った技術
- LINE Messaging API
- Google Apps Script（GAS）
- Googleスプレッドシート

## つくりかた
### ①事前準備
まずは以下の記事を参考に、**オウム返しBotが完成**するところ（「AIの設定」の前）まで実施します！手順通りに進めればOKなのでとっても簡単です！
- [5分でできるLINE Bot + AI応答](https://qiita.com/cog1t0/items/cc7779345a01192d8f01)

### ②GASのコードを以下のものにまるっと差し替える
**CHANNEL_ACCESS_TOKEN**は自分のものに書き換えます。
<details><summary>GASのコード</summary>

```JavaScript:思いつき買い物メモ
// ↓↓↓↓↓ 自分で書き換えるところ ↓↓↓↓↓　=========================================================================================================
// LINE Bot 設定
const CHANNEL_ACCESS_TOKEN = '[自分のCHANNEL_ACCESS_TOKEN]';

// ↑↑↑↑↑ 自分で書き換えるところ ↑↑↑↑↑ =========================================================================================================

// その他設定
const logSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('log');
var replyToken, json

//ポストで送られてくるので、ポストデータ取得
function doPost(e) {
  // 動作確認用のログ出力
  // log_to_sheet("A", "doPost")

  // LINEBotから送られてきたデータを、プログラムで利用しやすいようにJSON形式に変換する
  json = JSON.parse(e.postData.contents);

  //返信するためのトークン取得
  replyToken = json.events[0].replyToken;
  if (typeof replyToken === 'undefined') {
    return;
  }

  // 返信するメッセージを作成
  if (json.events[0].message.text == 'メモを見る') {
    const data = getColData();
    messages = reply_message(data);
  } else if (json.events[0].message.text == '買えた') {
    deleteColData();
    messages = reply_message('メモを消したよー！');
  } else {
    writeLogToSheet(json.events[0].message.text);
    messages = reply_message('買うものをおぼえたよー！');
  }

  // line-bot-sdk-gas のライブラリを利用しています ( https://github.com/kobanyan/line-bot-sdk-gas )
  const linebotClient = new LineBotSDK.Client({ channelAccessToken: CHANNEL_ACCESS_TOKEN });

  // メッセージを返信
  try {
    linebotClient.replyMessage(replyToken, messages);
  } catch (e) {
    // うまく動作しない場合は、エラーが発生していないか確認してみましょう
    // log_to_sheet("A", e)
  }

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

// 動作確認用のオウム返しのメッセージを作成する関数
function test_message() {
  //送られたLINEメッセージを取得
  var user_message = json.events[0].message.text;

  //送られたメッセージをそのままオウム返し
  var reply_messages = [user_message];

  // メッセージを返信
  var messages = reply_messages.map(function (v) {
    return { 'type': 'text', 'text': v };
  });

  return messages
}

function reply_message(message) {
  var user_message = message;

  // 引数で渡されたメッセージを返す
  var reply_messages = [user_message];

  // メッセージを返信
  var messages = reply_messages.map(function (v) {
    return { 'type': 'text', 'text': v };
  });

  return messages
}

function writeLogToSheet(message = 'x') {
  // シート取得
  const sheet = SpreadsheetApp.getActiveSheet();
  // ループを回して1行ずつすでに記録されていないか確認していく
  let currentRow = 1;
  while (true) {
    // 記録されていない行が見つかったとき：
    if (!sheet.getRange(currentRow, 1).getValue()) {
      // 1列目に日付時刻を記録
      sheet.getRange(currentRow, 1).setValue(Utilities.formatDate((new Date()), 'Asia/Tokyo', 'yyyy/MM/dd hh:mm:ss'));
      // 2列目にメッセージ（引数値）を記録
      sheet.getRange(currentRow, 2).setValue(message);
      // ループ中断
      break;
    }
    // 次の行へ
    currentRow++;
  }
}

// 買い物メモを取得する
function getColData() {
  let colData = '買うものはこれだよー！';
  // シート取得
  const sheet = SpreadsheetApp.getActiveSheet();
  //シート最終行の値を取得する
  const lastRow = sheet.getLastRow();
  //指定したセル範囲を取得する
  try {
    const range = sheet.getRange(2, 2, lastRow - 1);
    //セル範囲の値を取得する
    const values = range.getValues();
    for (let value in values) {
      colData = colData + '\n' + values[value];
    }
  // メモが登録されていない場合
  } catch (e) {
    colData = 'メモはないよー！';
  }

  return colData;
}

// 買い物メモを削除する
function deleteColData() {
  // シート取得
  const sheet = SpreadsheetApp.getActiveSheet();
  //シート最終行の値を取得する
  const lastRow = sheet.getLastRow();
  sheet.deleteRows(2, lastRow);
}

// 処理の確認用にログを出力する関数
function log_to_sheet(column, text) {
  if (logSheet.getRange(column + "1").getValue() == "") {
    lastRow = 0
  } else if (logSheet.getRange(column + "2").getValue() == "") {
    lastRow = 1
  } else {
    var lastRow = logSheet.getRange(column + "1").getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
    // 無限に増えるので1000以上書き込んだらリセット
    console.log("lastRow", lastRow)
    if (lastRow >= 1000) {
      logSheet.getRange(column + "1:" + column + "10").clearContent()
      lastRow = 0
    }
  }
  var putRange = column + String(lastRow + 1)
  logSheet.getRange(putRange).setValue(text);
}
```
</details>

### ③Googleスプレッドシートに以下のようなヘッダを付ける
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958610/6c68fe48-3dc3-5184-afbe-fc9a867f949a.png" />

以上！完成です:clap:

## 使ってみた
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【🛍️思いつき買い物メモ📝】<br>思いついたときにすぐ買うものをメモでき、あとで見やすい <a href="https://twitter.com/hashtag/linebot?src=hash&amp;ref_src=twsrc%5Etfw">#linebot</a> を作りました！<br>シンプルかつ軽量！使いやすい🙌<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/linedc?src=hash&amp;ref_src=twsrc%5Etfw">#linedc</a> <a href="https://t.co/24RURM0pS0">pic.twitter.com/24RURM0pS0</a></p>&mdash; ちーろってぃ🐶通勤をハッピーに (@chiiirotty) <a href="https://twitter.com/chiiirotty/status/1667804223092948993?ref_src=twsrc%5Etfw">June 11, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

- メモを登録：買う予定の商品を投稿
- メモを見る：「メモを見る」ボタンを押下
- メモを消す：「買えた」ボタンを押下

**すごい**！想像以上に欲しかったものそのものができてうれしい:raised_hands:
こういう余計な機能がなくてわかりやすく、LINEで使える買い物メモを求めてたんですよ！！！
自分が欲しいものは自分で作る、まさに**自給自足**の時代ですね:fist:

夫と一緒に使うこともできて便利！
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958610/9e0cc570-baa5-91de-2465-b38a09eb69fa.jpeg" />

今のままでも十分満足ですが、今後は「買えた」ボタンでメモを一括削除する機能だけでなく、**商品ごとにメモを削除する機能**を作ってもいいかも～！と思いました:grin:

## ちなみに
ChatGPTとつなげて、買い物メモなのに何も覚えてくれない「[偏差値3の買い物メモ](https://qiita.com/chiiirotty/items/fdd1b1b9267394cf0bc2)」を作っていますので、そちらもぜひご覧ください:information_desk_person:
<img width="400" alt="S__389530192.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958610/b4770d2c-074a-9edd-e456-0ae60e2a6105.jpeg">