ゴミ出しをGASとLINE Botで定期通知し母親に親孝行する

# 問題定義
**ゴミ出し**は第n水曜日などと分かりにくい曜日設定であり、
かつ、ゴミの種類によりゴミの置き場などが異なる。
これにより、**ゴミ出しの役割が母親に属人化しがち**である。

一方、母親は家事や子育てや仕事で忙しい。
そして、**ゴミ出しを覚えてなければならないストレス**や
**忘れたときのストレス**など精神的な負担も大きい。
<img width="200"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/2c958a10-7c5f-1ec8-c0cd-a4c988eb1b0b.png">
大学生のボクは、母親に最初で最後の親孝行をすることにした。


# 解決策
こうした負担を減らすために、***ゴミ捨ての日時と置き場所を
家族のグループLINEに自動的に通知し、ゴミ捨て役割の分担を促すような
LINE Botの仕組み作りをする。***

# 使用技術
・Google Apps Script
・LINE Messaging API

# 期待できる効果
**・ゴミ捨てのユーザー体験が改善され、母親の負担が減り、家庭がより明るくなる**
・LINE Messaging APIの仕様について学べる
・Google Apps Scriptの定期実行の仕組みを学べる
**・現実世界の向上にテクノロジーが役立つことを実感できる**


# 手順

## 1.LINE公式アカウントの作成
LNE公式アカウントの未認証アカウントを開設する
https://www.linebiz.com/jp/entry/

LINE Official Account Managerにログイン
https://manager.line.biz/

## 2.LINE Messaging APIの初期化
まず、LINE Official Account Managerの右上の「設定」を押します

<img width="200"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/2e432302-f684-373a-711d-eae4d6ef0ae8.png">
次にMessaging APIの項目に移動します

<img width="300"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/b77fcfaf-473e-6ee5-4d02-3fa5d96c2564.png">
「Messaging APIを利用する」を押して初期化完了。

## 3.LINE Botの応答のデフォルト設定の変更
次にLINE Official Account Managerで以下を無効にする。
・友達追加メッセージ
・応答メッセージ
これで家族グループにデフォルトメッセージが行かないようになる

また、「設定」→「アカウント設定」→「チャット」より、グループチャットへの参加を有効化する。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/3a780452-40f8-d04b-53b4-1e40eab72ebb.png">
**これを設定しないと、グループにLINE Botを招待しても参加ない。**

## 4.LINE Botと家族を入れるグループの作成

家族とLINE Botが入ったLINEグループを作成
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/d8e8fcd7-201b-0265-e06d-5e551db51f25.png">

## 5.グループIDの特定

LINE Messaging APIではグループにメッセージを送るコードを書く前に、
**全てのグループに一意に紐づけられているグループIDを特定する作業が必要。**


以下のサイトの手順でするのが最も簡単。
（理由は、最後の「付録」のセクションで後述）
https://cyuraharuto.com/gas-line-gid-get/
Google Sheetsでシートを作成し、
「ツール」→「スクリプトエディタ」
からGASのプロジェクトを作成し、上記のWEBサイトに従う。
**ここでのポイントは、Google Drive経由で作成するのではなく、Google Sheets経由で作成する点。**


## 5-Tips1 グループID確認用のGASプロジェクトの初期化
webhook用URLの作成時に注意する点を補足する。
上記のWEBサイトに従い、グループID確認用のプロジェクトを作成した後は
「公開」→"Anyone, even anonymous"により権限を設定。
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/42937ab1-dd66-af95-a3ba-a87b6134d727.png">
次に"Deploy"し、次の画面で出るURLをコピーする。
**これがwebhookでの設定で用いるURLである。**

**ちなみにwebhookの関わるGASのプロジェクトを編集する場合は
GASのコードの更新ごとにバージョンをNewにする作業を毎回行う。**

そうしなければ、LINE Botに変更が反映されない！

## 5-Tips2 webhookの設定

LINE Developers Consoleで、LINE公式アカウントのwebhookを有効にする。

<img width="200"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/09ea9971-13f3-277c-d9b8-04fa3db750e9.png">

この時点で該当するライングループにメッセージを送信すると
瞬時に、Google SheetにグループIDが表示される。これをコピペする。

## 6.メッセージ自動送信用のGASプロジェクトの実装
メッセージ自動送信用のGASのプロジェクトを以下に従い作成。

**以下では、個人情報保護の観点から一部内容を変更している箇所有り！**

```js

// 与えられたDateオブジェクトのインスタンスの時刻が第n何曜日であるかを返す
function getDayCount(date) {
    return Math.floor((date.getDate() - 1) / 7) + 1;
}
// -> http://snowsunny.hatenablog.com/entry/2014/01/18/214751
// を参考にさせていただいました

// 指定のごみ収集曜日の前日の通知のためにトリガーする関数
function notifyTheNightBefore() {
    // LINE Messaging APIの利用のための下準備
    var ACCESS_TOKEN = 'ここにアクセストークンを入力';
    var url = 'https://api.line.me/v2/bot/message/push';
    var groupID = 'ここにグループIDを入力';
    // メッセージ本文を格納する変数
    var body = '';

    // Dateオブジェクト関連の処理の準備
    var date = new Date();
    // 特定の曜日の前日に通知するために、Dateオブジェクトのインスタンスdateの日時を１日早める
    date.setDate(date.getDate() + 1);
    var dayIndex = date.getDay()
    var day = ["日", "月", "火", "水", "木", "金", "土"][dayIndex];


    //--ゴミ出しの曜日のパターンと前日に送信するメッセージの定義--//
    //   火曜日・金曜日 ペットボトル
    if (day == '金') {
        body += '明日金曜日はペットボトルの収集日です。準備はOKですか？'
    } else if (day == '火') {
        body += '明日火曜日はペットボトルの収集日です。準備はOKですか？'
    }
    //   月曜日 缶・びん
    if (day == '月') {
        body += '明日月曜日は缶・びんの収集日です。準備はOKですか？';
    }
    //   1･3回目木曜日 プラ容器包装
    var is1stThur = (day == '木') && (getDayCount(date) == 1)
    var is3rdThur = (day == '木') && (getDayCount(date) == 3)
    if (is1stThur || is3rdThur) {
        body += '明日はプラ容器包装の収集日です。準備はOKですか？'
    }
    //   2･4回目木曜日 生活ゴミ
    var is2ndThur = (day == '木') && (getDayCount(date) == 2)
    var is4thThur = (day == '木') && (getDayCount(date) == 4)
    if (is2ndThur || is4thThur) {
        body += '明日は生活ゴミの収集日です。準備はOKですか？'
    }


    //LINE Messaging APIでの実際のグループへのメッセージ送信処理
    //現在時刻から見た明日が、何もゴミ出し日に該当しなければ、メッセージは送信されない。
    if ((day == '金') || (day == '月') || is1stThur || is3rdThur || is2ndThur || is4thThur) {

        UrlFetchApp.fetch(url, {
            'headers': {
                'Content-Type': 'application/json; charset=UTF-8',
                'Authorization': 'Bearer ' + ACCESS_TOKEN,
            },
            'method': 'POST',
            'payload': JSON.stringify({
                'to': groupID,
                'messages': [{
                    'type': 'text',
                    'text': body,
                }]
            })
        })
    }
}


```

送信部分は以下を参照しました
https://cyuraharuto.com/gas-line-sendmessage/


## 7.GASでの関数の定期実行を設定する
上述のコードのnotifyTheNightBefore()は
前日に明日がゴミ出しの日であればメッセージを送信する関数。
この内部には実行時の時点の翌日の曜日判定が既に含まれている。
なので、この関数を毎日夜の8時に実行すれば、所望の機能が実現できる。

まず、以下の定期実行の設定ボタンをクリック。
<img width="200"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/0e488e29-20a4-ecae-a349-8bae3704255b.png">

「トリガーを追加」を押し、以下のトリガーを設定する。
<img width="300"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/91cbf462-16fe-c0db-65c1-06ab8f219e47.png">

# 実際の運用報告

あるゴミ出しの前日にGASが自動的に家族グループに送った内容はこちらです。
母からは「もちろん」との返信が帰ってきました。
![Screenshot_20201106-073740_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614389/f21c7dd7-5335-0fd6-ef00-c475ded6ba58.jpeg)
## 母の感想
***収集日を覚えていなければならないというストレスから解消された***
***おかげでゴミ出しを忘れることはなくなるだろう***
と今晩の夕食では語っていました。

## 今後の展望
母は最近膝を一時的に痛めているので、ゴミ出しは結構な負担です。
また、リハビリをする必要があるので、ゴミ出しを初めいろいろな家事に時間がかけられません。

今回のシステムでは次のようないい循環が生まれるのではないかと予測しています。
***家族グループでゴミ出し情報が共有されることで
他の家族メンバーがゴミ出しをするきっかけにもつながりうる***

さて、このシステムを、例えば、ゴミ出しだけでなく、他の定期的に必要な家事労働にも応用し、
家事の負担や実行時間を家族全員で最適化することで、家族は幸せになることができるのではないでしょうか。
このため、いろいろな方法を模索していこうと思います。

# 付録

## webhookが絡むGASプロジェクトでコンソールを使うのは面倒

グループIDの出力を**Logger.log** or **console.log**を用いて行おうとしたが
思うようなデバッグができなかった。

**結論から言うと、webhookで呼ばれる関数のログは上述の簡単に確認できない**

「表示」→「ログ」や「表示」→Stackdriver Loggingなどでログが見れると思ったが、
**・GASのログはウェブアプリからのログを表示できない**
**・Stackdriver Loggingはウェブアプリの場合、ログの詳細を簡単に確認できない**
→**Google Cloud Platformのプロジェクト設定が面倒**
ということが判明しました。
（StackOverFlow:　https://stackoverflow.com/questions/60140757/why-cant-i-view-stackdriver-logs-for-web-apps-in-google-apps-script　）

ですので、本記事で取得したグループIDを見るために、Google Sheetsを使っていたのは
このような手間を省いて、なるべく簡単にグループIDを手に入れるためだったというわけです。