概要
スプレッドシートをDB代わりにしてGASを使ったサーバーレスのLINEbotを作る
作るきっかけ
- 
恋人と同棲を始めたのですが、消耗品を買う際にお互いに買うものが被ったり、買い忘れが発生するのを防ぎたい
 ↑別れました!
- 
相手は非エンジニアだけどスプレッドシートくらい使いこなせる
 ↑もう私しか使う人居ませんけどね
- 
ならスプレッドシートを共有して買う予定の物を管理、買ったら消すという運用ができる
 ↑共有する人はもう居ません
- スプレッドシート確認するのは面倒臭いから特定ワードに反応するLinebotを作ってそいつに知らせてもらおう
完成図
ざっくり流れ
- スブレッドシートに買う予定の商品名、個数を入力する列をそれぞれ用意する(DBのカラムみたいなもの)
- LINEでbotに対して「買い物リスト」と送信する
- スプレッドシートから商品名列、個数列を取得してくる
- いい感じの文字列に整形して返信させる
LINEbotの作り方とかGASプロジェクトの作り方
調べればたくさん出てくるので割愛
コード
javascriptは殆ど書いたことが無いのでこう書いた方がいいよ、というのがあれば是非コメントしてください。
function doPost(e) {
  var contents = e.postData.contents;
  var obj = JSON.parse(contents);
  var events = obj["events"];
  for (var i = 0; i < events.length; i++) {
    if (events[i].type == "message") {
      reply_message(events[i]);
    }
  }
}
function reply_message(e) {
  if (e.message.type == "text") {
    var input_text = e.message.text;
    if (input_text == "買い物リスト") {
      var spreadsheet = SpreadsheetApp.openById("用意したスプレッドシートのID");
      var sheet = spreadsheet.getActiveSheet();
      var name_values = sheet.getRange("A:A").getValues();
      var quantity_values = sheet.getRange("B:B").getValues();
      
      var reply_text = "買い物リストをお知らせします!\n\n";
            
      for(var j = 1; j < name_values.length; j++) {
        if(name_values[j] == ""){
          break;
        }
        reply_text += "・" + name_values[j] + " " + quantity_values[j] + "\n";
      }
      reply_text += "\n以上です!";
     
    } else {
      reply_text = "「買い物リスト」と話しかけるとスプレッドシートに登録した買い物リストをお知らせします!";
    }
    
    
    var postData = {
      "replyToken": e.replyToken,
      "messages": [{
        "type": "text",
        "text": reply_text,
        "wrap": true
      }]
    };
  }
  var options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Bearer " + "自分のアクセストークン"
    },
    "payload": JSON.stringify(postData)
  };
  UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", options);
}
ちょっと解説するとユーザーがLINEbotに向けて送信したテキストが 買い物リスト と完全一致した場合、用意したスプレッドシートを取得します。
そのスプレッドシートのA列(商品名)とB列(商品の数)をさらに取得して入力されてる分だけループを回してます。
ちなみに1列目は所謂カラム名的な物を書いてあるのでループカウンターを1で初期化しています。
A列、B列共に全て取得しているせいで多分1000行くらい取ってきています・・・
なので商品名が空になった時ループは抜けるようにしていますが、明らかにイケてない書き方だと思っているのでマサカリ覚悟してます。
詰まったところ
最初はforEachを使っていましたが、ループ内で送信文字列を足し込みしている所に改行コードである\nを連結したところ何故かbotがうんともすんとも言わなくなってしまいました。
普通のforループにしてみたところ動きました。何故かはわかりません。
運用カバーで妥協した点
- LINEだけで買う物リストの追加、削除も完結させようかと思ったが、また特定ワードを送信して消す品目を送信して・・・というのは面倒臭い。というかパソコン開いてスプレッドシートを操作した方が早いのでその機能は実装しませんでした。
- 個数は入れなくても問題ないが、商品名はしっかり詰めてスプレッドシートに入力する必要がある(個数は省略することあっても商品名を省略して個数だけ入れるようなことは無いだろうという判断でコードを書きました)
所感
もっとjs勉強します。

