娘の育児をきっかけに夫婦の共同生活時間が激増しました。情報共有を徹底するために各種クラウドアプリを駆使し始めたわけですが、置き場所がバラバラなので、やっぱり色々と漏れが出ます。
健やかなる家事育児生活のためには、まとまった形での定期報告があると楽なので、明日の予定とか天気予報とか残タスクとかを、Google Apps Script(GAS)を使ってサーバーレスかつ出銭ゼロでLINEに定期送信させる仕組みを作ってみました。
公式マニュアルを参照しながら、LINE DevelopersからMessaging APIの新規チャネルを『Developer Trialプラン』にて作成します。どうせ夫婦2人に、多くて一日数回のプッシュ通知を送るだけなので、このプランで全く問題ないです。
注意①:LINE@アカウントのフリープランとは別なので要注意。
注意②:初めてログインする場合はスマホのLINEアプリで認証が必要です。
注意③:スマホのLINEアプリでアカウントのログイン許可をしていないと、ログインできません。
作成した新規チャネルもといLINEボットを、さっそくスマホのLINEアプリでフォローします。LINE Developersのコンソール画面を開き、取得したアカウントにログインして、『プロバイダーリスト』から所定のプロバイダーを選び、ステップ1で作成したMessaging APIを選びます。
『チャネル基本設定』を見ると、プランが『For Developer』となっており、利用可能な機能に『REPLY_MESSAGE』,『PUSH_MESSAGE』が確認できれば、問題なく処理を進めることができます。
画面の一番下にあるQRコードをスマホで読み取ると、LINEボットが表示されるのでフォローができます。このタイミングで、妻のLINEでもフォローをしておきます。
Messaging API設定の前に、とりあえずWebhookに設定するURLを取得したいので、Google DriveからGoogle Apps Scriptファイルを新規作成します。
作成したら、上部メニューの『公開』から『ウェブアプリケーションとして導入』を行い、『アプリケーションにアクセスできるユーザー』を『全員(匿名ユーザーを含む)』に変更してから『更新』を押します。これでURLを取得できます。
GASと連携するために、改めてステップ2で確認した『チャネル基本設定』を開きます。中段にある『メッセージ送受信設定』にて『アクセストークン』を発行します。このアクセストークンは後で使うので、コピーしておきます。
続いて『Webhook送信』を『利用する』に変更し、『Webhook URL』にステップ3で取得したURLを登録します。すると『接続確認』ボタンが出てくるので、ボタンを押して「成功しました。」と出れば接続完了です。
ここが今回一番ハマったところです。
GASからプッシュ通知を送るには、送り先のLINEユーザーのユーザーIDが必要でして、今回は夫婦二人に送るため、二人のユーザーIDが必要になったのです。
ユーザーID自体は、Messaging APIの『チャネル基本設定』の一番下に『Your user ID』として表示されるのですが、この欄で手に入ったユーザーIDは私のものだけでした。そう、妻のユーザーIDはどうやって取ればいいのか、という問題が発生したのです。
最終的には、『権限管理』機能で妻を『Admin』として追加し、妻のアカウントでログインしたうえで『Your user ID』を確認しました。妻のアカウントでログインすれば妻のユーザーIDが取得できる、という種明かしですが、ちょっと面倒すぎ・・・
一応、フォローイベントの中にあるユーザーIDを取得するAPIもありますが、たかだか固定のユーザーID一つを取得するためにスクリプトを書き上げるのも微妙ですよね。なんとかならないのかなぁ・・・
注意④:『テスター管理』機能でテスターとして追加した場合、ログインしてもユーザーIDが確認できず、上位権限への変更もできないため、一度アカウント削除してからAdmin登録することになります。
必要な情報が揃ったので、リファレンスを見ながら実際にGAS上でスクリプトを書いていきます。
注意しないといけないのは、今回は夫婦二人に同時送信するということです。一人であればpush APIで大丈夫ですが、複数なのでmulticast APIを使ってプッシュ通知を送る関数を作ります。なお、pushとの差分は、①ユーザーIDの変数が文字列から文字列配列に変わった、②ポスト先のURLがpushからmulticastに変わった、の2点ですね。
指定した文字列をプッシュ通知する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
function PushMessage(buf) { var accessToken = '{access_token}'; var userIds = ['{user_id1}', '{user_id2}']; var url = 'https://api.line.me/v2/bot/message/multicast'; var headers = { 'Content-Type' : 'application/json; charset=UTF-8', 'Authorization': 'Bearer ' + accessToken; }; var postData = { 'to' : userIds, 'messages' : [{'type':'text', 'text':buf}] }; var options = { 'method' : 'post', 'headers' : headers, 'payload' : JSON.stringify(postData) }; return UrlFetchApp.fetch(url, options); } |
これで適当に作った文字列を引数に放り込んで実行すれば、二人のLINEにプッシュ通知を送ることができるようになりました。関数に時間主導型のトリガーを設定すると、定期的に送信することができます。これで土台はバッチリですね。
肝心の定期送信するコンテンツですが、基本的な考え方としては、
(1) G Suite => GASの各種クラスを使う
(2) APIのあるサービス => APIを使う
(3) APIのないサービス => スクレイピングする
という感じです。今回は、『CalendarApp』クラスを使ってGoogleカレンダーから明日の予定を、『Tasks』クラスを使ってGoogleタスクから残タスクを、『UrlFetchApp』クラスを使ってtenki.jpから明日の天気予報を取得しつつ、曜日による分岐でゴミ出し情報なんかを届ける感じですね。
参考までに、基本的な構文だけ掲載します。
Googleカレンダーから明日の予定を取得する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
function GetGoogleCalendar(){ var date = new Date(); date.setDate(date.getDate() + 1); var startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0); date.setDate(date.getDate() + 1); var endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0); var events = CalendarApp.getDefaultCalendar().getEvents(startDate, endDate); if (events.length == 0){return 'なし';} var texts = [], hasDateText; for (var i = 0; i < events.length; i++){ hasDateText = (events[i].getStartTime().getDate() != events[i].getEndTime().getDate()); texts.push(DateFormat(events[i].getStartTime(),hasDateText) + '-' + DateFormat(events[i].getEndTime(),hasDateText) + ' ' + events[i].getTitle()); } return texts.join('\n'); } function DateFormat(date, hasDateText){ var buf = ''; if (hasDateText){ buf += (date.getMonth() + 1) + '/' + date.getDate() + '(' + [ "日", "月", "火", "水", "木", "金", "土" ][date.getDay()] + ')'; } var hours = date.getHours(); var minutes = date.getMinutes(); return buf + (hours < 10 ? '0' : '') + hours + ':' + (minutes < 10 ? '0' : '') + minutes; } |
注意⑤:基本は時刻と件名のみの表示ですが、日をまたぐイベントの場合は日にちも表示したいため、DateFormatという関数を作成しました。
Googleタスク(ToDoリスト)の指定リストから残タスクを取得する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function GetGoogleTasks(listTitle) { var texts = []; var lists = Tasks.Tasklists.list().getItems(); for (var i = 0; i < lists.length; i++){ if (lists[i].getTitle() == listTitle){ var tasks = Tasks.Tasks.list(lists[i].getId()).getItems(); for (var j = 0; j < tasks.length; j++){ if (tasks[j].getStatus() == 'needsAction'){ texts.push(tasks[j].getTitle()); } } } } if (texts.length == 0){return 'なし';} return texts.join('\n'); } |
注意⑥:Googleタスクのクラス『Tasks』はGASのリソース拡張をしたうえで、Google Cloud Platformに登録し、Google API側で利用規約に同意する必要があります。
指定したURLにおいて、指定した正規表現に合致するHTML群を返す(いわゆるスクレイピング)
1 2 3 4 5 6 7 |
function Scrape(url, regularExpression) { var text = UrlFetchApp.fetch(url).getContentText(); var match = text.match(regularExpression); return match; } |
注意⑦:具体的に自然なLINEメッセージに落とし込むには、ある程度HTMLを読むスキルを持った前提で、正規表現等を使いこなせる必要があります。APIを使おうと思いつく人にとっては、まあ問題ないかとは思いますが・・・。
ここに書いていないものでは、APIが公開されている家計簿アプリのZaimあたりが、家事育児のサポートという面ではアツい領域です。Zaim APIはリファレンスが(英語だけど)細かく書かれているので導入しやすく、一通りのCRUD機能が惜しみなく提供されているので好感が持てます。こんな感じに、色々なアプリと連携できると夢が広がりますね。
どういうコンテンツを何時に送るかによってご家庭に合ったお助けLINEボットが作れるかと思いますので、興味のある方は是非お試しください。