Skip to content

Instantly share code, notes, and snippets.

@k4zuki02h4t4
Last active May 10, 2024 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save k4zuki02h4t4/b9855d3aa0aa77daa3287aad1c96fad9 to your computer and use it in GitHub Desktop.
Save k4zuki02h4t4/b9855d3aa0aa77daa3287aad1c96fad9 to your computer and use it in GitHub Desktop.
From backlog to chatwork.

使用方法

バックログからチャットワークに通知を送りたいユーザーを仮にAさんとする

  1. チャットワークで通知専用アカウントを作成
  2. 1で作成したアカウントで、チャットワークの API Token を取得
  3. 1で作成したアカウントと、Aさんのチャットワーク ID を友だち登録し、友だち登録した際にできたチャット room の ID(数字のみ)をメモ
  4. 1で作成したアカウントで、チャットワークの API Token を取得
  5. Aさんのバックログアカウントと Nulab アカウントを連動し、Aさんの Nulab ユニーク ID をメモ
  6. Google スプレッドシートを作成(シートの内容はコメント欄のスクショを参照)
  7. 4で作成したスプレッドシートでスクリプトエディター(ツール→スクリプトエディター)を開き、app.gs をコピペし保存
  8. そのままの画面で、公開→ウェブアプリケーションとして公開を選択、「Current web app URL」の URL をメモ、「Who has access to the app = Anyone, even anonymous」を選択し更新をクリック
  9. バックログにログインし、通知を送りたいプロジェクト→プロジェクトの設定→インテグレーション→Webhook→6でメモした URL を登録
/**
* 文字列の末尾からスラッシュを削除する
*
* @param {string} str
* @returns {string}
*/
function delete_trailing_slash(str) {
if (str.slice(-1) === '/') {
str = str.slice(0,-1);
}
return str;
}
/**
* type 番号に合った通知内容のカテゴリ名を返す
*
* @param {int} type
* @returns {string}
*/
function get_backlog_type(type) {
var types = {
1:'課題の追加',
2:'課題の更新',
3:'課題にコメント',
4:'課題の削除',
5:'Wikiを追加',
6:'Wikiを更新',
7:'Wikiを削除',
8:'共有ファイルを追加',
9:'共有ファイルを更新',
10:'共有ファイルを削除',
11:'Subversionコミット',
12:'GITプッシュ',
13:'GITリポジトリ作成',
14:'課題をまとめて更新',
15:'ユーザーがプロジェクトに参加',
16:'ユーザーがプロジェクトから脱退',
17:'コメントにお知らせを追加',
18:'プルリクエストの追加',
19:'プルリクエストの更新',
20:'プルリクエストにコメント',
21:'プルリクエストの削除',
22:'マイルストーンの追加',
23:'マイルストーンの更新',
24:'マイルストーンの削除',
25:'グループがプロジェクトに参加',
26:'グループがプロジェクトから脱退'
};
return types[parseInt(type,10)];
}
/**
* 値から行番号を調べる
*
* @see https://tonari-it.com/gas-spreadsheet-find/
*/
function findRow(sheet,col,val){
var dat = sheet.getDataRange().getValues();
for(var i=1;i<dat.length;i++){
if(dat[i][col-1] === val){
return i+1;
}
}
return 0;
}
/**
* ChatWork に送信するメッセージを生成する
*
* @param {object} data
* @param sheet
* @returns {string}
*/
function create_message(data,sheet) {
var blProjectKey = data.project.projectKey;
var blContentID = data.content.key_id;
var blSpaceUrl = delete_trailing_slash(sheet.getRange(1, 2).getValue());
var blContentUrk = blSpaceUrl + '/view/' + blProjectKey + '-' + blContentID;
var category = get_backlog_type(data.type);
var title = data.content.summary;
var isComment = data.content.comment && data.content.comment.content;
var body = '';
if (data.type === 1) {
body = [
'【種別】' + data.content.issueType.name + '\n',
'【優先度】' + data.content.priority.name + '\n',
'【期限】' + data.content.dueDate + '\n\n',
data.content.description
].join("");
} else if (isComment) {
body = data.content.comment.content.replace(/^@\S+\s/, '');
body = body.trim().replace(/^[\s\u3000]+|[\s\u3000]+$/g, '');
}
if (body !== '') {
body = body + '\n\n[hr]\n';
}
var message = [
'[info]',
'[title]【Backlog からの通知】' + data.createdUser.name + 'さんが' + category + 'を行いました[/title]',
body,
blProjectKey + '-' + blContentID + ' ' + title + '\n',
blContentUrk,
//'\n\n\n' + JSON.stringify(data),
'[/info]'
].join("");
return message;
}
/**
* ChatWork にメッセージを送信する
*/
function send2chatwork(room, token, body) {
var result;
var options;
var result = false;
if (typeof room !== null && typeof token !== null && typeof body !== null) {
options = {
'method': 'post',
'headers': {'X-ChatWorkToken': token},
'payload': {
'body': body,
'self_unread': '0'
}
};
fetchResult = UrlFetchApp.fetch('https://api.chatwork.com/v2/rooms/' + room + '/messages', options);
if (fetchResult.getResponseCode() == 200) {
result = true;
}
}
return result;
}
/**
* POST 送信を受け取る
*/
function doPost(e) {
var body;
var index;
var row;
var cwRoom;
var cwToken;
var blSpaceUrl;
var blProjectKey;
var blContentID;
var blContentUrk;
var message;
var ss = SpreadsheetApp.openById(SpreadsheetApp.getActiveSpreadsheet().getId());
var sheetBinde = ss.getSheetByName('bind');
var sheetConf = ss.getSheetByName('conf');
var output = ContentService.createTextOutput();
output.setMimeType(ContentService.MimeType.JSON);
if (e.postData.contents) {
body = JSON.parse(e.postData.contents);
if (body.notifications !== null) {
cwToken = sheetConf.getRange(2, 2).getValue();
index = body.notifications.length;
message = create_message(body,sheetConf);
for (i = 0;i < index;i++) {
if (body.notifications[i].user.nulabAccount !== null) {
row = findRow(sheetBinde, 1, body.notifications[i].user.nulabAccount.uniqueId);
if (row > 0) {
cwRoom = sheetBinde.getRange(row, 2).getValue();
if (send2chatwork(cwRoom, cwToken, message) === false) {
console.log('チャットワークへメッセージを送信時にエラーが発生しました。');
output.setContent(JSON.stringify({ message: 'error' }));
} else{
console.log('チャットワークへメッセージを送信しました。');
output.setContent(JSON.stringify({ message: 'success' }));
}
} else {
console.log('スプレッドシート内でアカウントを発見できませんでした。');
output.setContent(JSON.stringify({ message: 'error' }));
}
} else {
console.log('Nulab アカウントが設定されていません。');
output.setContent(JSON.stringify({ message: 'error' }));
}
}
} else {
console.log('通知なし');
output.setContent(JSON.stringify({ message: 'success' }));
}
} else {
Logger.log('データが取得できませんでした。');
output.setContent(JSON.stringify({ message: 'error' }));
}
return output;
}
@k4zuki02h4t4
Copy link
Author

スプレッドシートの例

シート1 シート名:bind

2019-12-26 (2)

シート2 シート名:conf

2019-12-26 (3)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment