will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

IFTTT経由の柔軟な定期リマインダーをつくる

軽いライフハック

作ったのは翌日がなんのゴミの日か?を前日の23時頃に通知するシステム

ここ2ヶ月位前にIFTTTを知ってポピュラーなレシピだけじゃ限界あるし自分の生活にとって最適なレシピを作りたいと思ってやってみた。 JSもExcelも初心者だけど、それほど手間をかけたわけでもないのに自分が求めてるものを作れるなと実感したのでメモ。

構成

Spreadsheet, Google App Script, IFTTT, slack

f:id:matsuokah:20151027000656p:plain

手順としては以下の通り

  1. Spreadsheetにゴミの日情報を記載
  2. Spreadsheetからゴミの日情報をGoogleAppScriptで抽出してメールでIFTTTのトリガーをフック
  3. IFTTTの連携先にブロードキャスト
  4. 今回はslackにメールの題名と本文を通知

IFTTTを挟むことによって連携先が柔軟になるので、あとから他のサービスに連携したくなった時もポチポチしていくだけでいい。IFTTT便利。

マスタ管理はSpreadsheet

日付計算、文字の使い回しなどは関数が揃っているSpreadsheetがおすすめ。

自分が会社で所属しているプロジェクトでもゲームのマスタ管理をSpreadsheetで行い、GoogleAppScript(以下、GAS)で整形してJSON化するといったことをしている。 マスタ管理をSpreadsheetでする最大のメリットは勝手に編集履歴を作ってくれることとGoogleAppsとの連携が強力であること。Spreadsheetにマスタ情報を定義しておけばあとは取り出すだけ。 ライトなデータベース的に使えるので今回の様な場合にも無料でデータベースとして使える。

実際に定義したのは...
  • マスタ(ゴミの種別、何週目の何曜日が収集日か、メール送信先、メール題名、メール本文)
  • 条件マッチ用の正規表現
  • 日付計算情報(明日は何週目の何曜日か?)

https://docs.google.com/spreadsheets/d/1e-PkwcZmZg8qZj4TB95woJv_GRjd2VwePTNSHL8UOOs/edit?usp=sharing

今後は引っ越してもここの収集日をメンテするだけで通知が飛んでくれる。 何週目マッチ && 曜日マッチがメールのカラム。メール送信条件が満たされていればtrueになる。 つまり、true行のメールを送るというロジックをGASで組めばいいことになる。

フックするGASはIFTTTと連携させているGmailのアカウントで

IFTTTを連携しているメールの場合のみリアルタイムなメールトリガーが使える。

これがまた便利。

  GmailApp.sendEmail('trigger@recipe.ifttt.com', sub, body);

とメールするだけで題名と本文を連携先に流すことができる。メールの送り主はGmailのアカウントになる。

また、GASの最大のメリットは定期実行が可能なところ!!!cronが不要でとてもよろしい。

f:id:matsuokah:20151027003839p:plain

メイン関数を毎日1回23時から24時の間に実行するという設定の例。

下記がスクリプト.

function getMainSheet() {
  var url = "https://docs.google.com/spreadsheets/d/1e-PkwcZmZg8qZj4TB95woJv_GRjd2VwePTNSHL8UOOs/edit#gid=0";
  var spreadsheet = SpreadsheetApp.openByUrl(url);
  var sheets = spreadsheet.getSheets();
  for ( var i in sheets ){
    if ( sheets[i].getSheetName() != "settings" ) {
      continue;
    }
    
    return sheets[i];
  }
}

function getColumnMap(data) {
  var header = data[0];
  var info = {};
  for (var j = 0; j < header.length; j++) {
    var cell = header[j];
    switch (cell) {
      case 'mail':
        info.mail = j;
        break;
      case 'to':
        info.to = j;
        break;
      case 'sub':
        info.sub = j;
        break;
      case 'body':
        info.body = j;
        break;
      default:
        break;
    }
  }
  return info;
}

function getMailTo(data, columnMap) {
  var toArray = [];
  for (var row = 0; row < data.length; row++) {
    if (row && data[row][columnMap.to]) {
      toArray.push(data[row][columnMap.to]);
    }
  }
  return toArray.join(',');
} 

function getSendMailInfo(data) {
  var columnMap = getColumnMap(data);
  var sendIndex = 0;
  for (var row = 0; row < data.length; row++) {
    var mail = data[row][columnMap.mail];
    if (mail && row != 0) {
      sendIndex = row;
      break;
    }
  }
  
  if (!sendIndex) {
    return sendIndex;
  }
  
  var info = {
    to: getMailTo(data, columnMap),
    sub: data[sendIndex][columnMap.sub],
    body: data[sendIndex][columnMap.body]
  };
  
  return info;
}

function main(){
  var sheet = getMainSheet();
  var data = sheet.getDataRange().getValues();
  
  var info = getSendMailInfo(data);
  if (!info) {
    return;
  }

  GmailApp.sendEmail(info.to, info.sub, info.body);
}

IFTTTを挟む

IFTTTの挟む最大の利点はメールを抽象化してタイトルと本文という概念にできること。

つまりハブとして流せるのがいい。 さらにメールに対してはほぼリアルタイムにトリガーが起動するということ。なぜならメールの受信がトリガーだから。 なので、連携しているメールアドレスからtrigger@recipe.ifttt.comにメールが送られれば最大15分のタイムラグをなくせる。

(GASの定期実行がpm11~pm12とアバウトなので意味ないけど。)

slackにポストする

ここまで来たら後はIFTTTの設定画面でポチポチするだけ。

明日がゴミの日となればslackに通知が飛ぶ。ここで家族slackを提案したい。

slackは数名程度なら無料で使えるので家族でチャンネルをシェアすることができる。 したがって、同居人に同じチャンネルを見れるようにしておけば、「明日は燃えないゴミの日」と二人に伝えることができる。ああ、なんて便利なんだ。

IFTTTはTrelloとも連携できるのでTrelloのカードを作ってもいい。Trelloの更新を検知してslackに通知をすることもできる。家族trelloもよい。(筆者は買い物リストやデートに行くところなどTODOをTrelloで共有している)

まとめ

筆者は引っ越したてで、ゴミの出し方が変わったためこういうものを作れて少し幸福度が上がっている。

今回のようにマスタ・送信ロジック・通知連携・通知サービスとマイクロサービス化っぽくしていれば、マスタの内容を書き換えるだけで他の通知もできるだろうし、土台となりうる。 送信ロジックをもう少しインテリジェンスにしてもいい。

ちょっと手をくわえただけで無料で自動化できるDocsのアプリ群、IFTTT、それと連携しているサービス様たちは偉大だ。 ほぼ、JSの経験、Excelの経験がない自分でもそれなりに便利なものができた。