PushbulletがiOS撤退したので、GASやIFTTTでPush7からプッシュ通知を送る確認をしておく

#はじめに

皆がIFTTTの有料化でボイコットしている時に、呑気に$1.99でProをサブスクライブしてエントリーしたのが自分だけだったのかもしれませんが……「[Applet of the Week](https://ifttt.com/explore/created_applet_of_the_week_2)」というIFTTが開催する小イベントで賞を頂きました。（日本のAmazonでは逆立ちしても使えないんですが）$500のAmazonギフト券をもらったので、気を良くして幾つかIFTTT絡みの記事を書いてみます。

#様々なPush通知

Push通知については既にご存じの方は多いと思います。現状は以下のように多様なプラットフォームでプッシュ通知に対応しており、これらを一括してサポートしている（た）サービスも多数あります（ました）

1. iOS（iPhone、iPad）
2. Android OS
3. Google Chrome（MacOS, Android OS, Windows, Linux/FreeBSD系OS）※ iOSは対応していない
4. Firefox

昨今のポイントとしては、やはりブラウザーが単独でプッシュ通知に対応してきている点（[Web Push](https://developer.mozilla.org/ja/docs/Web/API/Push_API)）でしょうか。iOSは残念ながらAppleが乗り気でないため非対応ですが、Android OSであればアプリをインストールしなくても通知をサブスクライブすることが出来ます。

#メジャーだったPush Bulletの終焉

一昔前、と言っても1〜2年前（2020夏から見て）まではマルチプラットフォーム対応の無料のプッシュ通知プラットフォームと言えば恐らく[Pushbullet](https://www.pushbullet.com/)だったろうと思います。
広く選択されるプッシュ通知プラットフォームとして求められる要件としては以下が挙げられます。

1. 無料である（少なくともある程度の利用用途までは）
2. 少なくともiOS、Android OSに対応しており昨今では[Web Push](https://developer.mozilla.org/ja/docs/Web/API/Push_API)にも対応していて欲しい
3. REST APIにて送信が出来ること（Webコンソールからちまちま送るだけという方が希有だとは思いますが）

こういった要件を満たすサービスとして筆頭に上げられていたのが[Pushbullet](https://www.pushbullet.com/)でした。所が昨年末から今年に掛けて突如としてiOS版のアプリがAppStoreから削除されてしまいました。経緯はともかく復活する予定は無いようです。詳細については[Redditの「Not Available on iOS」という書き込み](https://www.reddit.com/r/PushBullet/comments/eirc1m/not_available_on_ios/)に書かれているようです。

#和製の[Push7](https://push7.jp/)

特に個人ベースの開発者は代替となるサービスを探さねばなりませんでした。FirebaseやAWSのSNSなども候補にはなりそうですが、もっと手軽にプッシュ通知を利用したいという要望は強かったかと思います。そこで白羽の矢が立ったのが[Push7](https://push7.jp/)です。
[Push7](https://push7.jp/)の説明は省きますが前述の要件が押さえられていて[REST API](https://esa-pages.io/p/sharing/3426/posts/203/80ff5595487df69dfe38.html
)にて通知を送ることも出来ます、和製ベンダーということもあり日本語で問い合わせも出来ます。私も何度か問い合わせをさせて頂きましたが、非常に高品質な対応だと思いました。

#IFTTTから送れるようにしておく

REST APIなので普通にPOSTで送れるわけですが、一応IFTTTから送れることを確認しておきます。トリガーに対してアクションとしてPush7による送信を行うということです。最も汎用的に使えるのはトリガーとしてWebHookを採用し、Value1, 2, 3にプッシュ通知のタイトル、コンテンツ、アイコンURL、リンクURLなどを指定して使う方法でしょう。

```javascript:IFTTT-Filter-Code
// Value1: title
// Value2: body
// Value3: icon_url===link_url

const PUSH7_URL     = 'https://api.push7.jp/api/v1';
const APP           = 'App Numberを指定';
const API           = 'API Keyを指定';
const DEFAULT_ICON  = 'デフォルトのアイコンファイル名.png'
const ICON_BASE_URL = 'https://アイコン画像を置いてある場所/images';
let icon_url;
let link_url;

// icon, link
if (MakerWebhooks
    && MakerWebhooks.event
    && MakerWebhooks.event.Value3
    && MakerWebhooks.event.Value3.length > 0) {

  const VAL3 = MakerWebhooks.event.Value3;
  const DELIMITER = '===';
  if (VAL3.indexOf(DELIMITER) > -1) {
    icon_url = `${ICON_BASE_URL}/${VAL3.split(DELIMITER)[0]}`;
    link_url = `${VAL3.split(DELIMITER)[1]}`;

  } else {
    icon_url = `${ICON_BASE_URL}/${VAL3}`;
  }

} else {
  icon_url = `${ICON_BASE_URL}/${DEFAULT_ICON}`;
}

let payload = {
    "title" : `${MakerWebhooks.event.Value1}`,
    "body"  : `${MakerWebhooks.event.Value2}`,
    "icon"  : `${icon_url}`,
    "url"   : `${link_url && link_url.indexOf('http') == 0 ? link_url : icon_url}`,
    "apikey": `${API}`
};

MakerWebhooks.makeWebRequest.setContentType('application/json; charset=UTF-8');

// Payload
///////////////////////////////////////////////////////////////////////////
MakerWebhooks.makeWebRequest.setBody(`<<<${JSON.stringify(payload)}>>>`);

// URL
///////////////////////////////////////////////////////////////////////////
MakerWebhooks.makeWebRequest.setUrl(`${PUSH7_URL}/${APP}/send`);
```

value3までしか引数を取れないため、取り敢えず「`===`」をデリミターとしてアイコン画像のURLとタップした際のリンク先URLを同居させました。デリミター無しでアイコンだけ指定する事もできるようにはしてあります。残念ながらあまり（全てのパターンで）テストはしていません。バリデーションも最低限なので利用される方は自分色に染めてください。

今後の（私の）IFTTT関連の記事では、WebHook経由でPush7を叩いてプッシュ通知を送るというシーンが多く出てくると思います。都度実装するのではなくWebHookとして1つ用意しておくと便利かと思います。

#（余談）GASからIFTTTを叩く

ついでにGASから前段で用意したIFTTTのWebHookを叩くサンプルコードを共有しておきます。リンクURLに対応していませんが諸兄であれば簡単に追加出来るかと思いますあしからず。

```javascript:send.gs
// Actually send a reminder LINE or Notification (IFTTT webhook so up to you)
////////////////////////////////////////////////////////////////
function sendReminder(title, message) {
  if (IS_VERBOSE) console.log(`sendReminder(${title}, ${message})`);

  const WEB_HOOK_REMIND = PropertiesService.getScriptProperties().getProperty('remindWebHook');
  if ( ! WEB_HOOK_REMIND) return handleError('There is no remindWebHook setting in the project property!');

  // A message is related as value1, 2 and 3 parameter.
  title      = encodeURIComponent(title);
  message    = encodeURIComponent(message);
  const ICON = encodeURIComponent('デフォルトのアイコン画像ファイル名.png');
  var url    = `${WEB_HOOK_REMIND}?value1=${title}&value2=${message}&value3=${ICON}`;
  try {
    var response = UrlFetchApp.fetch(url, {"method" : "GET"});
    response.getContentText("UTF-8");
    return true;

  } catch (e) {
    return false;
  }
}
```

サンプルコード中のコメントが貧弱なので簡単に説明しておきます。

1. 引数はタイトル名`title`とコンテンツ`message`だけです。コンテンツなのかメッセージなのか統一されていない辺りはご了承下さい。
2. `IS_VERBOSE`と`IS_DEBUG`という定数が使われている可能性があります。意味はだいたいそのままです。
3. `WEB_HOOK_REMIND`という定数は呼び出したいIFTTTのWebHook URLとなります。GASのプロジェクトプロパティに`remindWebHook`というキー名で登録して挙げてください。
4. 今見返すと`GET`が使われていますね。ここをPOSTにしても動くと思われます。その場合payloadに各パラメーターを移動して`UrlFetchApp.fetch(url, {"method" : "GET", "payload": payload});`とした方が良いかも知れません。確かに、そのくらいテストしてから掲載して欲しいという方もいらっしゃるかと思います。