LoginSignup
5
4

More than 1 year has passed since last update.

LINENotify・IFTTT・GooleAppScriptでお手軽LineBotを作った

Last updated at Posted at 2021-05-22

概要

LINENotify・IFTTT・GooleAppScriptを使って、明日のゴミとその担当をお知らせするBOTの作り方。

正確には、ボット: BOT(双方向のコミュニケーション)ではなく通知。

これを応用すれば、ゴミ捨て当番の担当のお知らせだけではなく、
好きなお知らせをLINEに送付できるようになるかと。

やりたかったこと

私の家では、週次でこみ捨ての当番が変わります。

ただ、「今日誰がゴミ当番だったか」、「明日のゴミはなんだったか」、忘れられちゃうので、それを防止するために、LINEグループに明日のゴミを通知できればいいなという話になりました。

できるようになったこと

  • 毎日決まった時間に、LineNotifyから明日のLine通知を送る。

  • 日曜日になったら、ゴミ捨て担当を変えて通知する。

ざっくりした構成

使用したものは、LineNotify・ITFFF・GoogleAppScript・GoogleSpreadSheetです。

  • GoogleSpreadSheet: データベース。今週の当番を保存しておく
  • GoogleAppScript: ロジックの作成。データベースの書き換え。時間ごとの実行。URLのフェッチ。
  • IFTTT: WebhooksとLineNotify(ルームかグループチャット)の連携
  • LineNotify: 招待されているルームかチャットに内容を通知。

ちなみに、Webhooksはほぼ、ルームごとにメッセージを投げるためにしか使っていません。
APIというわけではありません。。。。

GoogleSpreadSheetの内容

名前の一覧と、今週の担当者にTRUEを振っておく

Name isPIC
NAME1 FALSE
NAME2 TRUE
NAME3 FALSE
*** FALSE
*** FALSE

また、URLの末尾から、SpreadSheetのKeyを取得しておく。

GoogleAppScriptの内容

はじめてGASを作成したので汚さ満載ですが、動けばいいということで。

(本来はGASではあまりClassとか使わないらしいですね)

やっていることは

  • 明日の曜日を取得する
    • 日曜日ならスプレッドシートの担当者を変えて通知する
    • 登録されたゴミがあれば通知する
  • この関数をケジュールで毎日18-19時に実行設定しておく
class Trash {
    constructor() {
      this.monday = "<月曜日のゴミ>";
      this.tuseday = "<火曜日のゴミ>";
      this.wednesday = "<水曜日のゴミ>";
      this.thursday = "<木曜日のゴミ>";
      this.friday = "<金曜日のゴミ>";
      this.saturday = "<土曜日のゴミ>";
      this.sunday = "<日曜日のゴミ>";
    }

  getTrash(weekNum) {
      let trash = ""
      if (weekNum === 1) {
        trash = this.monday}
      else if (weekNum === 2) {
        trash = this.tuseday}
      else if (weekNum === 3) {
        trash = this.wednesday}
      else if (weekNum === 4) {
        trash = this.thursday}
      else if (weekNum === 5) {
        trash = this.friday}
      else if (weekNum === 6) {
        trash = this.saturday}
      else{
        trash = this.sunday}
      return(trash)
    }

    getTomorrowTrash(weekNum)
    {return this.getTrash(weekNum + 1)}
  }

function getTodayWeekNum() {
  const date = new Date();
  const dayOfWeek = date.getDay();
  return dayOfWeek
  }

function getThisWeekPerson(sheet, nameColumn, trashColumn) {
  const lastRow = sheet.getLastRow();
  let thisWeekPerson = "";
  for(let i = 2; i <= lastRow; i++) {
    let cell = sheet.getRange(i, trashColumn)
    let cellValue = cell.getValue()
    if(cellValue === true){ 
      let cellOfThisWeekPerson = sheet.getRange(i, nameColumn);
      thisWeekPerson = cellOfThisWeekPerson.getValue();
    }
  }
  return thisWeekPerson
}

function changePersonToNext(sheet, nameColumn, trashColumn) {
  const lastRow = sheet.getLastRow();
  let currentTrueTrashCell = null;
  for(let i = 2; i <= lastRow; i++) {
    let cell = sheet.getRange(i, trashColumn)
    let cellValue = cell.getValue()
    if(cellValue === true){ 
      currentTrueTrashCell = cell
      cell.setValue(false)
    }
  }
  let isBottomCell = currentTrueTrashCell.activate().offset(1,0).isBlank();
  if (isBottomCell) {
    sheet.getRange(2, trashColumn).setValue(true);
    }
  else {
    currentTrueTrashCell.offset(1, 0).setValue(true);
  }
}

function notifyChangePerson(url, pic) {
  const data = {
    'value1': 'ゴミ当番交代のお知らせです。<br> 来週のゴミ当番: ' + pic,
  };
  const options = {
    'method' : 'post',
    'contentType': 'application/json',
    'payload' : JSON.stringify(data)
  };
  UrlFetchApp.fetch(url, options);
  Logger.info("[info]  URL FETCHED:" + url)
}

function notifyTomorrowTrash(url, trash, pic){
  const data = {
    'value1': '明日のゴミのお知らせです。<br> 明日のゴミ: ' + trash + '<br>現在のゴミ当番:' + pic,
  };
  const options = {
    'method' : 'post',
    'contentType': 'application/json',
    'payload' : JSON.stringify(data)
  };
  UrlFetchApp.fetch(url, options);
  Logger.info("[info]  URL FETCHED:" + url)
}

function getSpreadSheetKey () {
  return "SPREAD_SHEET_KEY"
}

function getIftttKey() {
  return "IFTTT_KEY"
}

function getEventName(event_name) {
  const EVENT_NAME1 = "EVENT_NAME1";
  if (event_name === EVENT_NAME1) {
    return EVENT_NAME1; 
  }
}

function myFunction() {
  const SPREAD_SHEET_TAB_NAME = 'Residents';
  const EVENT_NAME = "message_to_me";

  const nameColumn = 1;
  const trashColumn = 2;

  const spreadSheetKey = getSpreadSheetKey();
  const residentsSheet = SpreadsheetApp.openById(spreadSheetKey).getSheetByName(SPREAD_SHEET_TAB_NAME);
  const lineUrl = "https://maker.ifttt.com/trigger/" + getEventName(EVENT_NAME) + "/with/key/" + getIftttKey();

  const trash = new Trash();
  const todayWeekNum = getTodayWeekNum();
  tomorrowTrash = trash.getTomorrowTrash(todayWeekNum);

  let thisWeekPerson = "";
  if (todayWeekNum === 0) {
    changePersonToNext(residentsSheet, nameColumn, trashColumn);
    thisWeekPerson = getThisWeekPerson(residentsSheet, nameColumn, trashColumn);
    notifyChangePerson(lineUrl, thisWeekPerson);
    Logger.log("[info] ChangedPIC")
  }

  thisWeekPerson = getThisWeekPerson(residentsSheet, nameColumn, trashColumn);

  Logger.log("[WeekNum] " + todayWeekNum) ;
  Logger.log("[TomorrowTrash] " + tomorrowTrash);
  Logger.log("[ThisWeekPIC] " + thisWeekPerson);

  if (!tomorrowTrash == ""){ 
    notifyTomorrowTrash(lineUrl, tomorrowTrash, thisWeekPerson);
  }
}

IFTTTとLineNotifyの連携

IFTTT -> Create -> AppletsでWebhooksとLine検索してそれぞれアカウント設定連携させる。

この時点で、通知したいトークルームを選ぶ。また、Webhooksの設定から自分のKeyが取得できる。

Lineのメッセージの欄を下記にしておく。

【Bot】<br>
{{Value1}}<br>

あとはLineNotifyをグループチャットやグループLINEに招待すればOKですね。

IFTTTのKeyはトークルームの変更など設定を変えると変わるので注意です。

できたもの

スクリーンショット 2021-05-23 8.11.15.png

スクリーンショット 2021-05-23 8.12.24.png

あとがき

本当は、ドメインを取得して、FlaskでAPIを書いて、サーバーにデプロイして、LineMessangerを使って完全なBOTを作りたかった。が、そこまでやる気力がなくなってしまった。

(追記)WebhookがRunしなくなったら

Keyは合っているはずなのにPOSTしてもActivitiyログにもRunされた様子がなかった。
この場合はWebhooks Settingから
Keyを再発行させるのが正解。

スクリーンショット 2021-05-31 20.16.57.png

参考にしたもの

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4