概要
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はトークルームの変更など設定を変えると変わるので注意です。
できたもの
あとがき
本当は、ドメインを取得して、FlaskでAPIを書いて、サーバーにデプロイして、LineMessangerを使って完全なBOTを作りたかった。が、そこまでやる気力がなくなってしまった。
(追記)WebhookがRunしなくなったら
Keyは合っているはずなのにPOSTしてもActivitiyログにもRunされた様子がなかった。
この場合はWebhooks Settingから
Keyを再発行させるのが正解。