スプレッドシートのセルに入力した日時からPushBulletに通知するGoogle Apps Script


- [Google Apps Scriptで指定時刻にメールを送信するシステムを作ってみた \- Qiita](https://qiita.com/KentoDodo/items/4839af8700742a646cea)
- [google apps script \- How can I group pushbullet notifications \- Stack Overflow](https://stackoverflow.com/questions/29986166/how-can-i-group-pushbullet-notifications)

↑の合わせ技。

タスク一覧にわーっと日時書いたらプッシュ通知してくれるシステムが欲しかった。
理想はプレーンテキストなんだけどGoogleスプレッドシート→Google Apps Scriptがカンタンなので妥協。

メールで通知でもいいんだけど、オールデバイスで確実に通知を受け取るには最終的な出力はPushBulletにしたい。
Gmail→IFTTTでもいいけど、メールが残るのもやだし。

というわけで、Google Apps ScriptでPushBulletに通知するシステムをやってみた。

## 手順とか
まず、[Connected Accounts](https://www.pushbullet.com/#settings/account)でアクセストークンを作成。

次に、Googleスプレッドシートでデータ入力用のシートを作る。

![](https://i.imgur.com/fyFeQ4I.jpg)

1列目が送信するテキスト、2列めが送信日時になる。

「ツール＞スクリプトエディタ」Google Apps Scriptのプロジェクトを作成。

下記コードを入力（取得したアクセストークンに置き換え）して保存。プロジェクト名もつける。

```JavaScript
// https://stackoverflow.com/questions/29986166/how-can-i-group-pushbullet-notifications
function pushNoteToPhone(title) {
  var digest = "Basic " + Utilities.base64Encode("<ACCESS TOKEN>" + ":"); // アクセストークンを設定
  var options = {
    method: "post",
    payload: {
      type: "note",
      title: title,
      notification_tag: "tag1"
      },
    headers: {
        Authorization: digest
    }
  };
  var push_bullet_url = "https://api.pushbullet.com/v2/pushes";
  UrlFetchApp.fetch(push_bullet_url, options);
  return 1
};

// https://qiita.com/KentoDodo/items/4839af8700742a646cea
// 1分毎に実行
function calledByCron() {
  var sheet = SpreadsheetApp.getActiveSheet();  // シートの取得
  var startRows = 2;  // 開始行数
  var sheetData = sheet.getSheetValues(startRows, 1, sheet.getLastRow(), sheet.getLastColumn());  // シートのデータを取得（2次元配列）
  var dtLimit = new Date();  // 現在時刻を取得

  // シートの各行ごとにデータを取り出す
  sheetData.forEach(function(value, index) {
    // 送信完了していない、かつ送信予定日時が現在時刻より前ならば、メールを送信する
    if (!value[2] && (new Date(value[1])).getTime() < dtLimit.getTime()) {
      pushNoteToPhone(value[0])
      sheet.getRange(startRows + index, 2 + 1).setValue(dtLimit);  // 送信完了日時をシートに書く
    }
  });
}
```

「関数を選択」で`calledByCron`のほうを選択。

三角の実行ボタンをクリックすると実行される。

時計マークの「現在のプロジェクトのトリガー」をクリックし、トリガーを追加すると自動で通知してくれる。

![](https://i.imgur.com/DVMnIiO.jpg)

### コードについて
通常PushBulletのNoteはtitleとbodyがあるのだが、これを両方与え、かつ送信先デバイスを省略（全デバイスに送信）すると、Windowsで通知が出ない。

全デバイスに送信は譲れないので、bodyを省くことにした（Windowsの通知にはtitleしか出ない）。

## PushBulletとメールを選択できるようにしてみた
そもそもこれを作ろうと思い立った理由がふたつあった。

1. 短気の予定について、ガサガサっとテキストで書いたら適当に通知してほしい
2. 長期の予定について、タスク管理システムを変えたりしても忘れずに通知してほしい

2については、1年後とかにPushBullet使ってるかはちょい微妙だし、時刻も厳密じゃなくていいしちゃんと通知が残ったほうがいいので、メールが望ましい。と思い出した。

というわけで修正コード。

シート構成はこんなん。

![](https://i.imgur.com/NDngrzW.jpg)

```JavaScript
// https://stackoverflow.com/questions/29986166/how-can-i-group-pushbullet-notifications
function pushNoteToPhone(title) {
  var digest = "Basic " + Utilities.base64Encode("o.kWrTcMXCUfy3Wwm0HVDrEWMRvOaoJjRb" + ":"); // アクセストークンを設定
  var options = {
    method: "post",
    payload: {
      type: "note",
      title: title,
      notification_tag: "tag1"
      },
    headers: {
        Authorization: digest
    }
  };
  var push_bullet_url = "https://api.pushbullet.com/v2/pushes";
  UrlFetchApp.fetch(push_bullet_url, options);
  return 1
};

// https://qiita.com/KentoDodo/items/4839af8700742a646cea
// 1分毎に実行
function calledByCron() {
  var sheet = SpreadsheetApp.getActiveSheet();  // シートの取得
  var startRows = 2;  // 開始行数
  var sheetData = sheet.getSheetValues(startRows, 1, sheet.getLastRow(), sheet.getLastColumn());  // シートのデータを取得（2次元配列）
  var dtLimit = new Date();  // 現在時刻を取得

  var subject = '[NotificationScheduler]'
  var header = 'from NotificationScheduler\n(https://docs.google.com/spreadsheets/d/1eThneqgn4haHg8u20yhuKFxxJA3za1sAVtrgDzzdlfo)\n-------------\n'
  var address = '<自分のメアド>'

  // シートの各行ごとにデータを取り出す
  sheetData.forEach(function(value, index) {
    // 送信完了していない、かつ送信予定日時が現在時刻より前ならば、通知を送信する
    if (!value[3] && (new Date(value[2])).getTime() < dtLimit.getTime()) {
      if (value[0] == "push") {
        pushNoteToPhone(value[1]) // PushBulletに通知を送信する
      } else if (value[0] == "mail") {
        MailApp.sendEmail(address, subject, header + value[1]);  // メールを送信する
      };
      sheet.getRange(startRows + index, 3 + 1).setValue(dtLimit);  // 送信完了日時をシートに書く
    }
  });
}
```