Backlogの未読通知をすべて既読にするスクリプトを書いてみた

普段から業務でBacklogを使用しているのですが、ふと気付くとお知らせ通知の未読メッセージがたまっていました。手動で既読にするのが面倒だったので、Backlog APIを利用してスクリプトにしてみましたので紹介します。
2018.11.07

こんにちは。サービスグループの武田です。

普段から業務でBacklogを使用しているのですが、ふと気付くとお知らせ通知の未読メッセージがたまっていました(ベルアイコンを開いたところです)。私個人の傾向としてPull Requestをマージした際のメッセージが未読として残る傾向にあるようです。

GUI上で一括既読できればよかったのですが、ちょっと触った感じでは見当たりませんでした(あったら教えてください)。一件一件開いて既読にするのが面倒だったので、Backlog APIを利用してスクリプトにしてみましたので紹介します。

検証環境

次の環境で検証しています。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.1
BuildVersion:	18B75

$ echo $BASH_VERSION
4.4.23(1)-release

$ jq --version
jq-1.5

事前の準備

まずはBacklog APIを使用するためにAPI Keyを取得する必要があります。未取得の場合は次のエントリなどを参考に取得してください。

Backlog APIを使って自分のアクティビティを調べよう

API Keyが取得できたら環境変数に設定しておきます。同様にBacklogのURLも設定してください。.bashrcなどに設定しておくとbash起動時に設定されるため楽できます。

export BACKLOG_API_KEY=qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM123456789000
export BACKLOG_API_ENDPOINT=https://xxx.backlog.jp/api/v2

すべて既読にするスクリプト

今回は次のようなスクリプトを作成してみました。

#!/bin/bash -eu

declare -xr api_key="apiKey=${BACKLOG_API_KEY}"

function get_unread_notifications_count() {
  curl -s -X GET "${BACKLOG_API_ENDPOINT}/notifications/count?${api_key}&resourceAlreadyRead=false"
}

function get_notifications() {
  declare max_id=${1:+&maxId=$1}
  curl -s -X GET "${BACKLOG_API_ENDPOINT}/notifications?${api_key}${max_id}"
}

function mark_as_read() {
  declare id=$1
  curl -s -X POST "${BACKLOG_API_ENDPOINT}/notifications/${id}/markAsRead?${api_key}"
}

declare -xf mark_as_read

declare -i unread_count=$(get_unread_notifications_count | jq '.count')
echo "未読通知は${unread_count}件です"
(( unread_count == 0 )) && exit 0

declare last_id
while :; do
  declare ns=$(get_notifications "$last_id")
  [[ "$ns" == "[]" ]] && break

  last_id=$(echo "$ns" | jq 'last | .id')
  if [[ -n "$ns" ]]; then
    echo "$ns" | jq '.[] | select(.resourceAlreadyRead==false) | .id' | tee /dev/tty | xargs -I{} -P 5 bash -c "mark_as_read {}"
  fi
done

スクリプト作成にあたって調べたことなど

お知らせ関係のBacklog API

Backlog APIのドキュメントには次の4つのAPIが記載されていました。

  • お知らせ一覧の取得
    • 今回使用しています
    • 未読のお知らせのみ取得したかったのですが、パラメーターになかったため今回は既読も含め全件取得しています
  • お知らせの既読化
    • 今回使用しています
    • お知らせ一覧を取得した際のidを指定して既読にできます
  • お知らせ数の取得
    • 今回使用しています
    • そもそも一覧取得するかどうかの判定として、最初に未読通知の件数(resourceAlreadyRead=false)を取得して0ではなかったら処理するようにしました
    • パラメーターとしてalreadyReadresourceAlreadyReadがあります。alreadyReadはお知らせそのものを見たかどうかのフラグ、resourceAlreadyReadはお知らせ元の本体を見たかどうかのフラグのようです
  • お知らせ数のリセット
    • 使用していません
    • ドキュメントを見てもよくわからなかったんですが、試した限りは前述のalreadyReadをまるっとtrueにしてくれるAPIのようです

今回やりたかったことはresourceAlreadyReadフラグをすべてtrueにしたかったわけですが、それをよしなにやってくれるAPIが今のところないようです。

ディスプレイに出力しつつパイプで次のコマンドにも標準出力を渡す

未読のお知らせを既読にするにあたって、何も画面に表示されないと本当に進んでいるのか不安になるので既読にしたお知らせのidを出したいなと考えました。一度変数に入れて、出力してからxargsすればいいんですが、うまいことワンラインで実現できないか試行錯誤したところ/dev/ttyteeすればいけそうということになりました。

echo "$ns" | ... | tee /dev/tty | xargs ...

ただこの部分はあまり自信がない部分ですので、もっとうまいやり方があれば教えてください。

xargsで定義関数を使用する

シェルスクリプト内でmark_as_readという関数を定義しています。これをxargsコマンドで使用するために少し工夫が必要でした。単に呼んだだけでは No such file or directory となってしまいます。それが次の部分です。

...

declare -xf mark_as_read

...

  if [[ -n "$ns" ]]; then
    echo "$ns" | jq '.[] | select(.resourceAlreadyRead==false) | .id' | tee /dev/tty | xargs -I{} -P 5 bash -c "mark_as_read {}"
  fi

...

定義したmark_as_readdeclare -xfでエクスポートしています(export -fでも同様)。さらに関数を呼び出すときにbash -c "mark_as_read {}"としています。この2つをすることで、シェルスクリプト内で宣言した関数をxargsで使用できます。

まとめ

クリック連打するのが面倒だったのでスクリプトを書いてみましたが、bashもまだまだ知らないことが多いなと実感しました。また、こうやってAPIが公開されていることで運用の自動化ができるので便利ですね。