チームの期限切れタスクを運んでくるサンタクロース🎅🎁

# まえがき
[株式会社ピーアールオー（あったらいいな！を作ります） Advent Calendar 2021](https://qiita.com/advent-calendar/2021/pro-japan1) の10日目になります。
前日は @tajima_haru さんの「[CloudFormationを使ってみる](https://qiita.com/tajima_haru/items/f143e0806b0621bb50a0) 」でした。

### 今回の内容について
まだクリスマスは先ですが、クリスマスなノリにしちゃいました(実際はクリスマス関係なく、いつでも利用できます)
参照できるものは極力外部リンクにしております
ソースコードはあまり公開致しません(加工する時間が惜しまれました)
このような狙いでこんなものを作ってみたということと、作っていった過程をご紹介したいと思います

#:bulb:狙い:bulb:
チームの期限切れタスクを把握する
チームで期限切れタスクをどうにかする

#:laughing:やりたいこと:laughing:
* Backlogスペースを複数指定可
* それぞれのBacklogスペースにあるプロジェクトを複数指定可(関係のないプロジェクトは含みたくない)
* タスクの期限切れチェック対象は完了以外のカスタム状態を含む全て(意外と手間だった:smiling_imp:)
* タスクの期限切れのタスクはslackに一覧にして通知したい
    * 営業日に通知したい
    * 一覧で通知する内容
        * タスクへのリンクが欲しい
        * 担当者名が欲しい(slack側にマイキーワード設定しておけば通知される)
        * 期限切れの総件数
    * slackに通知するキャラを変更したい(通知がうざくなり過ぎない工夫が欲しい)
    * あまりにも多い場合は怒り気味の発言のみとしたい(とんでもない数のタスクを羅列されても・・・)
        * ページングの仕組みも迷ったけど、頑張っても報われそうになかったので止めた
* 1人用じゃなくて、チーム用として使いたい(1人用は探せばありそう)
    * そのため、担当者で抽出はしない

##:muscle:まずは流れを作ってみる:muscle:
###BacklogでAPIキー作成

https://support-ja.backlog.com/hc/ja/articles/360035641754-API%E3%81%AE%E8%A8%AD%E5%AE%9A

###Google スプレッドシートで環境変数を定義
* Backlogのスペース
    * BacklogのURL
    * BackLogで発行したAPIキー

###slackでWebhook URLを作成

https://api.slack.com/apps

* Create New Appでslackアプリ作成
* Incoming Webhooksを有効化
* Add New Webhook to WorkspaceでWebhook URLを作成

###GAS(Google Apps Script)でBacklogから情報取得→slack通知
* 流れを作成するので、現時点ではBacklogのAPIで取得する情報は何でもいい
* 課題一覧を取得する

https://developer.nulab.com/ja/docs/backlog/#

* GASでアプリ作成

https://www.google.com/script/start/

* 作成するロジック
    * Google スプレッドシートから環境変数を取得する
    * Backlogから課題一覧を取得する
    * slack通知用に成形する
    * slackに通知する

* 作成したアプリを実行
タスクが一覧化して出力されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320579/e9bc11d7-4b83-a3e6-781c-278344368da3.png)

##:airplane:流れができたので、機能を追加していきます:airplane:
###1. 複数のBacklogスペース、それぞれのプロジェクト指定ができるように
####Google スプレッドシートで環境変数をパワーアップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320579/7c6c8343-db96-1f88-2455-67d0d1608485.png)

* スペース単位の設定(複数設定可にする)
    * BacklogのURL
    * BackLogで発行したAPIキー

hogeスペース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320579/742de7eb-445b-e38c-0d87-5ea31fd43c65.png)
piyoスペース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320579/5f9eb73e-f4c0-7026-6f93-373b6640134a.png)

* スペースに紐づくプロジェクト単位の設定(複数設定可にする)
    * プロジェクトID

####GASアプリでGoogle スプレッドシートから読み込む部分を修正
#####とても参考にさせていただいたページ:bow:

https://www.redamoon.net/log/post/000069/

https://moripro.net/gas-object-key/

###2. 各プロジェクトの状態を取得して、完了を除く全ての状態を指定して課題を取得する
各プロジェクトにはカスタムされた状態もあるため、完了状態だけチェック対象から除くということが容易にできず
各プロジェクトごとに状態を取得して、完了状態のみを指定しないようにした

```
      // 各プロジェクト毎の状態を取得(完了以外、オリジナルの状態も含めて対象としたいため)
      let resStatuses = UrlFetchApp.fetch(space['baseUrls'] + statusesEndpointBefore + project + statusesEndpointAfter + '?apiKey=' + space['apiKey']);
      let statuses = JSON.parse(resStatuses.getContentText());

      // 対象の状態を羅列(完了を除く)
      let statusIds = [];
      for (var i = 0; i < statuses.length; i++) {
        if (statuses[i]['id'] != STATUS_COMPLETED){
          statusIds.push(statuses[i]['id']);
        }
      }
```

* 状態一覧の取得

https://developer.nulab.com/ja/docs/backlog/api/2/get-status-list-of-project/#

* 完了を除く状態を指定して、課題一覧を取得

###3. 期限切れタスクを抽出する

```
      // 期限切れ抽出設定
      let sysdate = new Date();
      sysdate.setDate(sysdate.getDate() - 1);
      let params = {
        'apiKey': space['apiKey'],
        'dueDateUntil': formatDate(sysdate),
        'count': ISSUE_MAX_COUNT
      };
```

* 課題一覧取得時に期限日をパラメータに指定する

###4. 期限切れタスクが多過ぎたら、途中で止める機能を追加
件数を取得して、100件以上取得したら途中で止めてslack投稿するようにした

```
      // 件数取得
      let responseCnt = UrlFetchApp.fetch(space['baseUrls'] + issuesCntEndpoint + '?' + paramString);
      let issuesCnt = JSON.parse(responseCnt.getContentText());
      issueAllCnt += issuesCnt['count'];

      // ページング機能は作らない(最大件数以上取得できたら出直し)
      if (issuesCnt['count'] > ISSUE_MAX_COUNT){
        // slackに投稿する
        message = '<!here> :ondokan3: 期限切れタスクの件数が' + ISSUE_MAX_COUNT + '件超えてます。さすがに整理してから実行しましょう:gekioko: \n';
        sendSlack(message);
        return;
      }
```

* 課題数の取得を行い件数が多い場合、途中停止して怒り気味のコメントをslackに通知する:imp:

https://developer.nulab.com/ja/docs/backlog/api/2/count-issue/#

###5. slackに通知する内容をカスタマイズする
* タスクへのリンク、担当者を一覧化する
* 期限切れの件数を表示する
* 通知する担当者をキャラを設定する(文言、アイコン)
* 定期的に自動で通知するように修正する(営業日判定付き)

#####とても参考にさせていただいたページ:bow:

https://inet-engineer.hatenablog.com/entry/2018/12/26/092016

https://api.slack.com/messaging/webhooks#posting_with_webhooks

https://zenn.dev/hotaka_noda/articles/4a6f0ccee73a18

###6.これでサンタクロースから期限切れタスクが連携される:santa::gift:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320579/c8968afb-6568-53ea-ab0b-5839ca6a56f4.png)

##:sparkles:あとはチームで運用する:sparkles:

> チームの期限切れタスクを把握する
> チームで期限切れタスクをどうにかする

* 狙い通りになりますように:pray: