Skip to content

Instantly share code, notes, and snippets.

@YoshiteruIwasaki
Last active March 15, 2021 02:32
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YoshiteruIwasaki/420aa7c9473a3adf35d9f209b24e4ee9 to your computer and use it in GitHub Desktop.
Save YoshiteruIwasaki/420aa7c9473a3adf35d9f209b24e4ee9 to your computer and use it in GitHub Desktop.
fondeskの投稿に対してメンションを追加するGoogle Apps Script
function doPost(e) {
var channel = 'XXXXXXXX'; // fondeskの通知先チャンネル
var url = 'https://hooks.slack.com/services/XXXXXXXX'; // Incoming Webhook URL
var TOKEN = 'XXXXXXXX'; // Verification Token
var botId = 'XXXXXXXX'; //fondeskのアプリのBOT ID
var historySave = true; //データをスプレッドシートに保存する
var sheetName = 'list'; //名簿リストのスプレッドシート名
var historySheetName = 'history'; //入電履歴のスプレッドシート名
var suppressedSheetName = 'suppressed'; //営業電話のスプレッドシート名
var postData = {};
var jsonData = {};
var isPost = false;
// subscribe posted messages
try {
var decodeData = unescapeUnicode(e.postData.getDataAsString());
postData = JSON.parse(decodeData);
isPost = true;
} catch (ex) {
// debug(ex);
}
// Interactive messages
try {
if (e.parameter) {
var parameter = e.parameter;
var payload = parameter.payload;
jsonData = JSON.parse(decodeURIComponent(payload));
}
} catch (ex) {
// debug(ex);
}
// 認証
if (isPost && postData.type == 'url_verification' && postData.token == TOKEN) {
var res = {
'challenge': postData.challenge
};
return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON);
}
// fondeskのチャンネルを監視
if (isPost && postData.token == TOKEN && postData.type == "event_callback" && postData.event.type == "message" && postData.event.channel == channel && postData.event.bot_id == botId) {
var getContents = "";
var getSender = "";
var historyData = [];
var message = '';
var nobody = true;
var array = [];
var options = {};
//投稿内容の取得
var thread = postData.event.event_ts;
var time = thread.split(".");
var date = new Date(time[0] * 1000);
historyData.push(formatDate(date));
var text = postData.event.text;
historyData.push(text);
try {
if(postData.event.blocks) {
// 発信者 あて先
var attachments = postData.event.blocks[0].text.text.split(/\r\n|\n/);
for (var i = 0; i < attachments.length; i++) {
var sender = attachments[i].indexOf("*発信者*");
if (sender !== -1) {
getSender = attachments[i].replace("*発信者* ", "");
}
var address = attachments[i].indexOf("*あて先*");
if (address !== -1) {
getContents = attachments[i].replace("*あて先* ", "");
}
}
// 内容
getContents += "\n" + postData.event.blocks[postData.event.blocks.length - 1].text.text;
}
} catch(ex) {
debug(ex);
}
// 受電履歴を保存
if (historySave) {
var historySheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(historySheetName); //シートを取得
historySheet.appendRow(historyData);
}
//営業電話リストのチェック
var suppressedSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(suppressedSheetName);
var textFinder = suppressedSheet.createTextFinder(getSender);
var ranges = textFinder.findAll();
var isSuppressed = ranges.length > 0 ? true : false;
if (isSuppressed) {
//営業電話
message = "営業電話がありました。";
options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify({
"text": message,
"thread_ts": thread,
"reply_broadcast": true,
})
};
} else {
//該当するユーザーの検索
var recordsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var sheetValues = recordsheet.getRange('A:A').getValues(); //A列の値を全て取得
var lastRow = sheetValues.filter(String).length; //空白の要素を除いた長さを取得
var sheetRange = 'A2:C' + lastRow; //名簿リストのスプレッドシートデータ取得範囲
var range = recordsheet.getRange(sheetRange);
var data = range.getValues();
for (var k = 0; k < data.length; k++) {
if (data[k][0] != null && data[k][0] != "") {
var result1 = getContents.indexOf(data[k][0]);
var result2 = getContents.indexOf(data[k][1]);
if (result1 !== -1 || result2 !== -1) {
if (array.indexOf(data[k][2]) == -1) {
// メンションを追加
message = "<@" + data[k][2] + "> " + message;
nobody = false;
array.push(data[k][2]);
}
}
}
}
if (nobody) {
//該当者がいない場合
message = "<!here> *" + getSender + "* 様から 宛先不明のお電話です。 対応したら「OK」をお願いします。";
} else {
message = message + " *" + getSender + "* 様から お電話がありました。対応したら「OK」をお願いします。";
}
//返信投稿
options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify({
"text": message,
"thread_ts": thread,
"reply_broadcast": true,
"attachments": [{
"text": "",
"callback_id": "callback_button",
"attachment_type": "default",
"actions": [{
"name": "ok",
"text": "OK",
"type": "button",
"style": "primary",
"value": "ok"
},
{
"name": "suppressed",
"text": "営業電話",
"type": "button",
"style": "danger",
"value": getSender,
"confirm": {
"title": "営業電話",
"text": "*" + getSender + "* 様からの電話を今後誰にもメンションしないようにしてもよろしいですか?",
"ok_text": "はい",
"dismiss_text": "いいえ"
}
}
]
}]
})
};
}
UrlFetchApp.fetch(url, options);
} else if (!isPost && jsonData.token == TOKEN && jsonData.type == "interactive_message" && jsonData.channel.id == channel) {
// ボタンクリック時のアクション
var buttonName = '';
var buttonValue = '';
var text = '';
if (jsonData.actions[0].type == "button") {
buttonName = jsonData.actions[0].name;
buttonValue = jsonData.actions[0].value;
}
var actionUserName = jsonData.user.name;
var originalText = jsonData.original_message.text;
if (buttonName == 'ok') {
//電話応対済
text = actionUserName + " :telephone_receiver:が対応しました。";
} else if (buttonName == 'suppressed') {
//営業電話リスト追加
text = actionUserName + " が営業電話リスト:no_bell:に追加しました。";
var suppressedData = [];
suppressedData.push(formatDate(new Date()));
suppressedData.push(buttonValue);
suppressedData.push(actionUserName);
var suppressedSheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(suppressedSheetName); //シートを取得
suppressedSheet2.appendRow(suppressedData);
}
var replyMessage = {
"replace_original": true,
"response_type": "in_channel",
"text": originalText,
"attachments": [{
"text": text,
}],
};
return ContentService.createTextOutput(JSON.stringify(replyMessage)).setMimeType(ContentService.MimeType.JSON);
}
}
/**
* デコード
* @param {[String]} string
* @return {[String]}
*/
function unescapeUnicode(string) {
return string.replace(/\\u([a-fA-F0-9]{4})/g, function(matchedString, group1) {
return String.fromCharCode(parseInt(group1, 16));
});
}
/**
* 日付のフォーマッター
*
* @param {[Date]} date
* @param {[String]} format
* @return {[String]}
*/
function formatDate(date, format) {
if (!format) format = 'YYYY-MM-DD hh:mm:ss';
format = format.replace(/YYYY/g, date.getFullYear());
format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
format = format.replace(/DD/g, ('0' + date.getDate()).slice(-2));
format = format.replace(/hh/g, ('0' + date.getHours()).slice(-2));
format = format.replace(/mm/g, ('0' + date.getMinutes()).slice(-2));
format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2));
if (format.match(/S/g)) {
var milliSeconds = ('00' + date.getMilliseconds()).slice(-3);
var length = format.match(/S/g).length;
for (var i = 0; i < length; i++) format = format.replace(/S/, milliSeconds.substring(i, i + 1));
}
return format;
}
/**
* スプレッドシートに出力
*
* @param {[Object]} postData
*/
function debug(postData) {
var debugSheetName = 'debug'; //デバッグ出力先のスプレッドシート名
var data = [];
data.push(formatDate(new Date()));
data.push(postData);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(debugSheetName);
sheet.appendRow(data);
}
@YoshiteruIwasaki
Copy link
Author

YoshiteruIwasaki commented Nov 14, 2019

デバッグ用のPOSTデータ例

PAYLOAD=`cat << EOS
    payload={
        "channel": "#fondesk",
        "username": "fondesk post tester",
        "attachments":[
      {
         "color":"good",
         "fields":[
            {
               "title":"発信者",
               "value":"株式会社テスト ヤマダ",
               "short":false
            },
            {
               "title":"折り返し先の電話番号",
               "value":"00-0000-0000",
               "short":true
            },
            {
               "title":"折り返しの連絡",
               "value":"必要",
               "short":true
            },
            {
               "title":"内容",
               "value":"XXXXX様宛。メールご確認くださいとのことでした。",
               "short":false
            }
         ]
      }
   ],
        "icon_emoji": ":iphone:"
    }
EOS`

curl -X POST --data-urlencode "$PAYLOAD" https://hooks.slack.com/services/XXXXXXXXX

@YoshiteruIwasaki
Copy link
Author

YoshiteruIwasaki commented Dec 1, 2020

2020/12/01のfondesk仕様変更に合わせてBOTを調整しました。

変更箇所はこちら
https://gist.github.com/YoshiteruIwasaki/420aa7c9473a3adf35d9f209b24e4ee9/revisions#diff-83d992e9b6d130685d1f90d81bec58c0213629999394b0429794b4bf9de8d4c8

検証用POSTデータ

curl -X POST -H 'Content-type: application/json' --data '{"text":"*発信者*  株式会社テスト ヤマダ\n*あて先*  佐藤\nメールご確認くださいとのことでした。"}' https://hooks.slack.com/services/XXXXXXXXX

解説記事
https://qiita.com/neeton_iwasaki/items/f32baa321e3353263b18

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