13
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

やり忘れのBacklog課題を定期的にSlackに通知してみる

Posted at

きっかけ

いつも見るのはSlack。メールもBacklogもあまり見ない。
そしてBacklogで振られている課題を忘れてしまう。。
よし、毎朝Slackに対応していないBacklog課題を連絡するようにしよう。
Google Apps ScriptからBacklogのAPIで該当の課題一覧を引っ張ってきて、それをSlackに投げればいいかな。

BacklogのAPIで課題情報を取得

Backlogの課題一覧取得方法は公式の課題一覧の取得ページに載っているので参考にGASで取得してみます。

BacklogのAPIキー

おっと、その前にBacklogのAPIキーを取得していきます。
Backlogページの右上にある自分のアイコンをクリックしたメニューの中の 個人設定 をクリックし、左のメニューの API から取得しておきます。
APIキーを取得したらGASから早速APIを叩いて課題一覧を取得してみましょう。

function myFunction() {
  const baseUrl = 'https://xxxxx.backlog.jp';  // 利用しているBacklogのドメイン
  const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';  // Backlogから取得したAPIキー
  const endpoint = '/api/v2/issues';  // 公式の課題一覧の取得に記載されているURL

  const url = baseUrl + endpoint + '?apiKey=' + apiKey;  // 問い合わせるURLにする
  const response = UrlFetchApp.fetch(url);  // fetchメソッドでHTTPリクエストを送る
  const json = JSON.parse(response.getContentText());  // テキストデータを取り出す

  Logger.log(json);  // ログに出力
}

色々ログに出力されました。
これだと各課題のログの量が多すぎて見にくいので一旦各課題の課題のIDだけ表示させることにします。

function myFunction() {
  const baseUrl = 'https://xxxxx.backlog.jp';  // 利用しているBacklogのドメイン
  const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';  // Backlogから取得したAPIキー
  const endpoint = '/api/v2/issues';  // 公式の課題一覧の取得に記載されているURL

  const url = baseUrl + endpoint + '?apiKey=' + apiKey;  // 問い合わせるURLにする
  const response = UrlFetchApp.fetch(url);  // fetchメソッドでHTTPリクエストを送る
  const json = JSON.parse(response.getContentText());  // テキストデータを取り出す
  
  for (let i in json) {  // 課題の数だけループを回して
    Logger.log(json[i]['issueKey']);  // ログに課題のIDを出力
  }
}

余計なログがなくなり見やすくはなりましたが、Backlog全体を対象にして取得しているので余計な課題が混ざってしまっています。
そのため以下の条件でフィルターをかけ必要な課題だけ取得します。

  • 指定の担当者
  • 指定の種別
  • 指定のステータス

担当者のユーザーIDを探す

担当者を絞り込むには担当者のユーザーIDが必要なようですが、どうもGASで担当者のユーザーIDを出力するのがうまくいかず...
仕方ないので BacklogでAPIを使ってユーザーのID(数値)を調べる方法 を参考にしてPythonからBacklogのAPIを叩いてユーザーIDを取得します。
この方法では課題を指定してその課題の担当者のユーザーIDを取得するので、課題を指定するために課題IDを取得します。
と言ってもこれは簡単で、課題を開いた時にURLの最後(xxxx-xx)になります。
具体的には課題URLの末尾の太字の部分になります。(後ろのxxは数字)
xxxxx.backlog.jp/view/xxxx-xx
課題IDが分かったらPythonで担当者のユーザーIDを取得します。

import requests

baseUrl = 'https://xxxxx.backlog.jp';  # 利用しているBacklogのドメイン
apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';  # Backlogから取得したAPIキー
ticket_id = 'xxxx-xx'  # 課題のID

url = base_url + ticket_id  # 問い合わせるURLにする
json = requests.get(url, {'apiKey': apiKey}).json() # テキストデータを取り出す

print(json['assignee']['id'])  # 取得結果の担当者のユーザーIDを出力

担当者で絞り込む

担当者のユーザーIDが分かったのでGASで担当者で絞り込みます。
下記の通り、問い合わせるURLのパラメータに &assigneeId[]=担当者のユーザーID を追加します。

function myFunction() {
  const baseUrl = 'https://xxxxx.backlog.jp';
  const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';
  const endpoint = '/api/v2/issues';

  const url = baseUrl + endpoint + '?apiKey=' + apiKey + '&assigneeId[]=' + xxxxxxx;  // 問い合わせるURLにする
  
// (以下略。上と同じ。)
}

課題の種別で絞り込む

次は種別(タスク、バグ、要望..)で絞り込みます。
種別は issueTypeId で絞り込みます。
issueTypeIdの確認も簡単で、Backlogの左メニューの プロジェクト設定種別 タブの確認したい種別をクリックします。
クリックして表示された種別の編集ページのURLの issueType.id がそれになります。
issueTypeIdが分かったのでGASで絞り込みます。
これは問い合わせるURLのパラメータに issueTypeId[]=issueType.id を追加します。

function myFunction() {
  const baseUrl = 'https://xxxxx.backlog.jp';
  const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';
  const endpoint = '/api/v2/issues';

  const url = baseUrl + endpoint + '?apiKey=' + apiKey + '&assigneeId[]=' + xxxxxxx + '&issueTypeId[]=' + xxxxxxx;  // 問い合わせるURLにする
  
// (以下略。上と同じ。)
}

課題のステータスで絞り込む

最後は課題のステータス(未対応、処理中、処理済み、完了)で絞り込みます。
ステータスは statusId で絞り込みます。
statusIdはAPIを使って調べられるのですが、多分以下で固定だと思います。

  • 未対応: 1
  • 処理中: 2
  • 処理済み: 3
  • 完了: 4
    これは問い合わせるURLのパラメータに statusId[]=x を追加します。
function myFunction() {
  const baseUrl = 'https://xxxxx.backlog.jp';
  const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';
  const endpoint = '/api/v2/issues';

  const url = baseUrl + endpoint + '?apiKey=' + apiKey + '&assigneeId[]=' + xxxxxxx + '&issueTypeId[]=' + xxxxxxx + '&statusId[]=' + 1;  // 問い合わせるURLにする
  
// (以下略。上と同じ。)
}

Slackに送信する

BacklogのAPIで必要な情報を取得できるようになったので、Slackに送信できるようにします。

SlackのIncoming Webhooksの設定

まずSlack送信に必要なWebhooksの設定を行います。
以前はSlackのカスタムインテグレーションでIncoming Webhookを作っていましたが、今はSlackアプリを作ってその中の機能としてIncoming Webhookを設定するらしいのでその方法で行います。
(参考:Slack カスタムインテグレーションが非推奨へslackのIncoming webhookが新しくなっていたのでまとめてみた
具体的には

  1. https://api.slack.com/apps にアクセス
  2. Create New App ボタンをクリック
  3. 作成するSlackアプリの情報を入力して Create App ボタンをクリック
     - App Name : 作成するSlackアプリ名
     - Development Slack Workspace : 作成するSlackアプリの設置先スペース(プルダウンメニューから選択)
  4. 左のメニューから Incoming Webhooks をクリック
  5. Activate Incoming Webhooks をONにする
  6. Add New Webhook to Workspace ボタンをクリック
  7. Slackを送信したいチャンネルかDMを選択し、許可する ボタンをクリック
  8. 該当のSlackチャンネルかDMに以下のメッセージが表示される

added an integration to this channel: 設定したアプリ名

Incoming Webhooksの設定が終わったらWebhookのURLをコピーしておきます。
このURLをGASで設定してSlack送信先にします。
なお、Incoming WebhooksでSlack通知される時のSlackアプリの表示名や画像は、左のメニューの Basic InformationDisplay Information で設定可能です。
Slackアプリを削除する時はBasic InformationDelete App から。

GASコード

取得したWebhook URLを postUrl に貼り、以下のように書きます。

function sendSlack() {
  const postUrl = '取得したWebhook URL';
  
  const json = {
    'text': 'Slackに送りたいメッセージ'
  };
  const payload = JSON.stringify(json);
  
  const options = {
    'method': 'post',
    'contentType': 'application/json',
    'payload': payload
  };
  
  UrlFetchApp.fetch(postUrl, options);
}

お約束なので説明は省略します。

スプレッドシートから設定変更

スプレッドシートのGASを使っていて、せっかくなのでスプレッドシート自体も使ってみました。
スプレッドシートで以下のように設定できるようにしました。
スクリーンショット 2020-04-26 22.00.14.png
スプレッドシート上でチェックを入れたもので絞り込むことにします。

// スプレッドシートから設定を取得
function getConfig() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const range = sheet.getRange(1, 1, 5, 2);
  const values = range.getValues();
  
  // ステータス設定を取得
  let statusId = '';
  for (let i in [...Array(4).keys()]) {
    let row = Number(i) + 1;
    if (true == values[row][0]) {
      statusId += '&statusId[]=' + row;
    }
  }
  return statusId;
}

完成

全部合わせるとこんな感じです。

const baseUrl = 'https://xxxxx.backlog.jp';
const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';

function myFunction() {
  const statusId = getConfig();
  issues(statusId)
}

// 課題一覧の取得
function issues(statusId) {
  // Backlogから課題一覧を取得
  const endpoint = '/api/v2/issues';
  const url = baseUrl + endpoint + '?apiKey=' + apiKey + statusId + '&issueTypeId[]=' + xxxxxx + '&assigneeId[]=' + xxxxxx;
  const resp = UrlFetchApp.fetch(url);
  const json = JSON.parse(resp.getContentText());
  
  // Backlogから取得した課題一覧から必要な情報(課題ID、課題の件名、課題のURL)を取り出す
  let message = '';
  for (let i in json) {
    const issueKey = json[i]['issueKey'];  // 課題のID
    const summary = json[i]['summary'];  // 課題の件名
    message += issueKey + ' ' + summary + '\n' + baseUrl + '/view/' + issueKey;
    // 課題が複数の場合、ループ毎に改行を入れる
    if (json[i] != json[json.length - 1]) {
      message += '\n';
    }
  }
  // Slackで送信したい内容(message)を渡す
  sendSlack(message);
}

// Slackに送信
function sendSlack(message) {
  // テスト用Webhook URL
  const postUrl = '取得したWebhook URL';
  const json = {
    'text': message
  };
  const payload = JSON.stringify(json);
  const options = {
    'method': 'post',
    'contentType': 'application/json',
    'payload': payload
  };
  UrlFetchApp.fetch(postUrl, options);
}

// スプレッドシートから設定を取得
function getConfig() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const range = sheet.getRange(1, 1, 5, 2);
  const values = range.getValues();
  
  // ステータス設定を取得
  let statusId = '';
  for (let i in [...Array(4).keys()]) {
    let row = Number(i) + 1;
    if (true == values[row][0]) {
      statusId += '&statusId[]=' + row;
    }
  }
  return statusId;
}

これをトリガーで毎朝9時起動とかにしておくと、毎朝Slackに以下のような通知が来るようになります。
スクリーンショット 2020-04-26 22.28.58.png

We're hiring!

AIチャットボットを開発しています。
ご興味ある方は Wantedlyページ からお気軽にご連絡ください!

参考記事

課題一覧の取得(公式)
課題情報の取得(公式)
Slack カスタムインテグレーションが非推奨へ
slackのIncoming webhookが新しくなっていたのでまとめてみた
BacklogでAPIを使ってユーザーのID(数値)を調べる方法
Pythonを使ってBacklog APIで課題を追加する

13
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?