3
1

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の通知をWebhookを利用してSlackに通知する

Posted at

概要

会社のBacklogがSlack連携を利用できなかったので、WebhookとGoogle Cloud Functionsを利用して、Slackへ通知する仕組みを作成した。

流れ

  1. SlackのAppを作成する。
  2. Cloud Functionsにコードを設置する。その際、SlackのAppのURLを作成したAppのURLに置き換える。
  3. Backlogの管理画面から、Webhookの通知先にCloud FunctionsのURLを登録する。

Cloud Functionsのコード

以下のコードをCloud Functionsに設置します。
適当に作っただけなので、改善の余地が多いにあります。

改善案があれば、コメント頂けると助かります。

index.js

const { IncomingWebhook } = require("@slack/client");

/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.helloWorld = async (req, res) => {
  console.log('Do helloWorld')

  if (req.method !== 'POST') {
    console.log('Method Not Allowed')

    res.status(405).send('Method Not Allowed');
    return;
  }
  
  if (!req.body) {
    console.log('Request Body Not Found')
    res.status(400).send('Request Body Not Found');
    return;
  }

  // メッセージ生成
  const message = makeMessage(req);

  // Slack 通知部分
  // Slack の Webhooks URL を代入
  const slack_webhook = "https://hooks.slack.com/services/hoge/fuga/hogehoge"
  
  // こちらのURLを、各自のIncoming webhookのURLに置き換えてください。
  const webhook = new IncomingWebhook(slack_webhook);
  await webhook.send(message);
  
  res.send(200);

};

// メッセージ生成部分
// 通知タイプ
// 1:課題追加
// 2:課題更新
// 3:コメントのみ追加
// 5:Wikiの追加
// 6:Wikiの更新
// 7:Wikiの削除
function makeMessage(req) {

  const projectKey = req.body["project"]["projectKey"];

  const type = req.body["type"];
  const id = req.body["id"];

  const notifications = req.body["notifications"];
  const createdUser = req.body["createdUser"];
  const createdUserName = createdUser['name'];

  const summary = req.body['content']['summary'];
  const content_id = req.body['content']['id'];
  const key_id = req.body['content']['key_id'];
  const dueDate = req.body['content']['dueDate'];
  const description = req.body['content']['description'];


  const content = {
    'type': type,
    'id': id,
    'summary': summary,
    'key_id': key_id,
    'dueDate': dueDate,
    'description': description
    'createdUserName' : createdUserName
  };
  console.log(JSON.stringify(content))

  // リンク先URLに必要な要素、BacklogのURLとプロジェクトキーと課題idを取得する
  const projectBaseURL = "https://bklg.xxxx.com/backlog/view/";
  const projectBaseURLwiki = "https://bklg.xxxx.com/backlog/wiki/";
  
  const slack_user_map = new Map([["hoge", "@hogehoge"], ["fuga", "fugafuga"]]);
  const slack_user = slack_user_map.get(createdUserName);

  if (type == 1) { //1:課題の登録の場合
    //課題の詳細から情報を取得する
    const issueType = req.body['content']['issueType']['name'];
    const status = req.body['content']['status']['name'];

    //URLにプロジェクトKeyと課題Keyをセットし、課題にアクセスできるURLを生成する
    const projectURL = projectBaseURL + projectKey + "-" + key_id;

    //Slackに通知するメッセージの作成
    return [
    createdUserName + ' さんが「' + summary + '」を登録しました',
    '',
    ':date: 期限日: ' + dueDate || 'なし',
    ':memo: 詳細: ' + description,
    ':earth_asia: 課題URL: ' + projectURL,
    ':label: 種別: ' + issueType,
    '',
    ].join('\n');

  } else if(type == 2 || type == 3){ //2:課題更新+3:コメント追加の場合
    //課題更新とコメント追加共通で取得するコメント内容とコメントKeyを取得する
    const comment = req.body["content"]["comment"]["content"];
    const commentKey = req.body["content"]["comment"]["id"];

    //URLにプロジェクトKeyと課題KeyとコメントKeyをセットし、課題にアクセスできるURLを生成する
    const projectURL = projectBaseURL + projectKey + "-" + key_id + "#comment-" +commentKey;

    if (type == 2){ //2:課題更新のみ、更新された情報を取得する

      //Slackに通知するメッセージの作成
      return [
      createdUserName + ' さんが「' + summary + '」を更新しました',
      '',
      ':date: 期限日: ' + dueDate || 'なし',
      ':email: コメント: ' + comment,
      ':earth_asia: 課題URL: ' + projectURL,
      '',
      ].join('\n');


    } else { //3:コメント追加の場合のみの更新情報を取得する

      //Slackに通知するメッセージの作成
      return [
      createdUserName + ' さんが「' + summary + '」にコメントしました',
      '',
      ':date: 期限日: ' + dueDate || 'なし',
      ':email: コメント: ' + comment,
      ':earth_asia: 課題URL: ' + projectURL,
      '',
      ].join('\n');      
    }


  } else if(type == 4){ //4:課題の削除
    //URLにプロジェクトKeyと課題KeyとコメントKeyをセットし、課題にアクセスできるURLを生成する
    const projectURL = projectBaseURL + projectKey + "-" + key_id;

    //Slackに通知するメッセージの作成
    return [
    createdUserName + ' さんが課題を削除しました',
    '',
    ':earth_asia: 課題URL: ' + projectURL,
    '',
    ].join('\n');
  
  } else if (type == 5 || type == 6 || type == 7){ //5:Wikiの追加, 6:Wikiの更新, 7:Wikiの削除
    const wiki_name = req.body["content"]["name"];
    // const wiki_content = req.body["content"]["content"];  

    //URLにプロジェクトKeyと課題KeyとコメントKeyをセットし、課題にアクセスできるURLを生成する
    const projectURL = projectBaseURL + projectKey + "-" + key_id + "#comment-" +commentKey;

      return [
        createdUserName + ' さんが「' + wiki_name + '」に追加/更新/削除しました',
        '',
      ].join('\n');

  } else if (type == 8 || type == 9 || type == 10){ //8:ファイルの追加, 9:ファイルの更新, 10:ファイルの削除
      const actions_map = new Map([
      [8, "ファイルの追加"],
      [9, "ファイルの更新"],
      [10, "ファイルの削除"]
      ]);

      const action_message = actions_map.get(type);

      const content_name = req.body["content"]["name"];
      const content_dir = req.body["content"]["dir"];  

      return [
        createdUserName + ' さんが' + action_message + 'しました。',
        '',
        'ファイル名: ' + content_name,
        '場所: ' + content_dir,
        '',
      ].join('\n');

  } else {

    const actions_map = new Map([[14, "課題をまとめて更新"], 
    [17, "お知らせの追加"],
    [11, "Subversionコミット"],
    [12, "Gitプッシュ"],
    [13, "Gitリポジトリの作成"],
    [15, "プロジェクトに参加"],
    [16, "プロジェクトから脱退"],
    [18, "プルリクエストの追加"],
    [19, "プルリクエストの更新"],    
    [20, "プルリクエストにコメント"],    
    [22, "発生バージョン/マイルストーンの追加"],    
    [23, "発生バージョン/マイルストーンの更新"],    
    [24, "発生バージョン/マイルストーンの削除"]
    ]);
    const action_message = actions_map.get(type);

      return [
        createdUserName + ' さんが' + action_message + 'しました。',
        '',
        'summary: ' + summary || 'なし',
        '',
      ].join('\n');

  }

}

終わりに

リモートで会社のメールを見る機会が少なくなったので、Slackに通知を飛ばせることができて、大変助かっている。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?