extension作ったことない奴がバックログのデスクトップ通知を作った話

Backlogってとても便利なはずなんだけど、デスクトップ通知機能がないせいで社内ではチャットツールだけで完結してしまおうということがたまにあります。
チャットツールだとタスクごとの管理がうまくできなかったりするので、どうにか業務に関することはBacklogに集約したい！と思い、作ったことないけどChromeExtensionでデスクトップ通知を作ってみよう！ということになりました。
まずは作ったものを紹介しておきます。

# どんなもの？
誰かがBacklog上で自分宛てにお知らせすると、そのお知らせをデスクトップ通知してくれるものです。

<img width="338" alt="スクリーンショット 2017-11-04 18.37.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/91369/e308f2e0-5a58-e856-06fb-6a2cb3be9998.png">


https://github.com/akoarum/backlog-notification

現状まだStoreには上げられていないので、上記のリポジトリを公開しておきます。このリポジトリをチェックアウトするかダウンロードすることで使用できます。

## 使い方
リポジトリのREADMEを読んでもらえれば大体わかるかと思いますが、割と簡単に使用することができます。

+ リポジトリをチェックアウトするかダウンロードする
+ Google Chromeの拡張機能のページ（ `chrome://extensions` ）でデベロッパーモードをオンにする
+ 「パッケージ化されていない拡張機能を読み込む」ボタンから、ダウンロードしたフォルダを指定する  
例：`downloads/backlog-notification`
+ 有効化するとオプションページが開くので、スペース名、TLD、APIキーを入力して保存
+ 「登録しました！」が出たら完了

## どうやったのか
オプションページで入力された情報を基にBacklogAPIを使ってお知らせの件数を取得していて、件数が増えていたら最新のお知らせの内容を取得して通知させているだけです。
短期間に複数のお知らせが入ると最新のものだけを通知して他は取り逃がしてしまうかもしれません。ここは要改善点かも。

## 使ったAPIについて

### BacklogAPI
[BacklogAPI](https://developer.nulab-inc.com/ja/docs/backlog/)

今回はお知らせ周りの取得なので、下記を使用しました。

- [お知らせ数の取得](https://developer.nulab-inc.com/ja/docs/backlog/api/2/count-notification/)
- [お知らせ一覧の取得](https://developer.nulab-inc.com/ja/docs/backlog/api/2/get-notification/)
- [お知らせの既読化](https://developer.nulab-inc.com/ja/docs/backlog/api/2/read-notification/)

### ChromeAPI
このAPIは後述のmanifest.jsonの「permissions」に追加しないと動きません。最初知らなくて焦りました。

- [alarms](https://developer.chrome.com/extensions/alarms)
- [notifications](https://developer.chrome.com/apps/notifications)
- [storage](https://developer.chrome.com/extensions/storage)
- [tabs](https://developer.chrome.com/extensions/tabs)

# 実装で躓いたところ・工夫したポイント
分からないなりに色々調べて作ったのですが、その中のポイントをいくつか晒しておこうと思います。

## manifest.jsonの設定
manifest.jsonはChromeExtensionを作る時に必ず必要となるものです。
ChromeExtensionのアイコンなどの設定のほか、permissionの設定やオプションページなどの設定をここで行います。

```json
{
  "manifest_version": 2,
  "name": "Backlog Notification",
  "description": "バックログのお知らせ通知が来た場合に、デスクトップに通知します。",
  "version": "1.0",
  "browser_action": {
    "default_icon": "app/icon.png"
  },
  "background": {
    "scripts": ["app/js/background.js"]
  },
  "permissions": [
    "tabs", "notifications", "storage", "alarms", "https://*.backlog.jp/*", "https://*.backlog.com/*"
  ],
  "icons": {
    "128": "app/icon.png"
  },
  "options_page": "app/options.html"
}
```

`permissons` に `https://*.backlog.jp/*` や `https://*.backlog.com/*` を追加してますが、このような指定がないとそのURL（パス）から画像などのファイルを引っ張ってこれなくなります。
今回のBacklog NotificationではアイコンをBacklogのスペースで設定されているファビコンを取得しているので、この指定が入っています。

## 設定とお知らせの数を保存する
storageを使用しました。
storageは下記のような形で使えば簡単にset、getできます。

### setする
```js
const data = {
  name: 'hoge',
  ...
};
chrome.storage.sync.set(data, () => {
  console.log('設定しました');
});
```

### getする
```js
chrome.storage.sync.get(['name', ...], (value) => {
    const data = value;
    console.log(data); // { data.name: 'hoge', ...}
```

## お知らせの数を定期的に見に行く
ChromeExtensionでは `setTimeout` や `setInterval` のようなものは使えないので、alarmsの出番です。
定期的に何かを実行したい時に使います。

### アラームを作成する
```js
chrome.alarms.create('ALARM_NAME', {periodInMinutes: 1});
```
これで `ALARM_NAME` という名前を持ったアラームが1分間隔で発行されます。
alarmsの定期実行は1分間隔が一番速い設定になるようです。

### アラームの発行ごとに何かする
```js
chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name === 'ALARM_NAME') {
    console.log('ALARM_NAMEが実行されました');
  }
});
```
このように `onAlarm.addListener` で購読できます。
`alarm.name` で判別しておかないと、別のalarmで実行されてしまう可能性があるので注意が必要です。
Backlog Notificationではこの中でお知らせの件数を取得して、storageの件数と比較し、変更されていたらデスクトップ通知するようにしています。

### 通知する
```js
chrome.notifications.create('NOTIFICATION_NAME', {
  type: 'basic',
  iconUrl: 'icon.png',
  title: data.title,
  message: data.message,
  contextMessage: data.contextMessage,
  priority: 1
}, (notificationId) => {
  console.log(notificationId);
});
```

通知はこんな感じのものを書いてあげればできるはずです。
細かい設定はAPIの説明ページを読んでくださいw
ちなみに同じ名前（ `NOTIFICATION_NAME` の部分）で連続して通知することができないようで、そのままだと一度通知したらしばらく通知が来ない状態になってしまいます。
なのでBacklog Notificationでは下記のような感じにしています。

```js
const id = Math.floor(Math.random() * 9007199254740992) + 1;
chrome.notifications.create(`NOTIFICATION_NAME_${id}`, {
  type: 'basic',
  iconUrl: 'icon.png',
  title: 'デスクトップ通知',
  message: 'メッセージが入ります',
  contextMessage: 'コンテクストメッセージ（弱めのテキスト）',
  priority: 1
}, (notificationId) => {
  console.log(notificationId);
});
```

単にランダムでIDを生成して繋いでるだけです。
あとは、 `console.log(notificationId);` の部分に通知をクリックした時の動作とかを書いてますが、ここでは割愛します。

## まとめ

自分が引っかかったポイントをかいつまんで書いているので、おそらくわかりにくい、むしろ余計混乱させているかもしれませんが、よかったら[リポジトリ](https://github.com/akoarum/backlog-notification)を見てみてください。

# 最後に
まとまりのない文章で非常に申し訳ありません。
Storeに載せるかどうするかについては、今後改めて考えようと思っています。
もし何かあればコメントかGitHubのIssueをいただければ幸いです。