概要
メンションを元に外部APIを叩き、取得した情報を元にDBを更新するSlackアプリを作成しました。
Lambdaの準備
Node.jsでLambdaを作成しています。
const axios = require('axios');
const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN;
exports.handler = async (event) => {
console.log(`Event: ${JSON.stringify(event)}`);
let body = "";
if (event.isBase64Encoded) {
// ボタンを押された時のblock_actionsペイロードはbase64でエンコードされているのでそのまま使えない
const encodePayload = event.body;
const decodePayload = decodeURIComponent(Buffer.from(encodePayload, "base64").toString("utf-8")).replace('payload=', '');
body = JSON.parse(decodePayload);
} else {
// メンションや疎通確認はエンコードされていないのでそのまま使える
body = JSON.parse(event.body);
}
// Slackアプリからの疎通確認用
if (body.type === 'url_verification') {
return {
statusCode: 200,
body: body.challenge,
};
}
// Yes No ボタンクリックイベント
if (body.type === "block_actions") {
const actionId = body.actions[0].action_id;
// Yes No ボタンを再度押下されないようにボタンを削除したメッセージに元メッセージを更新する
const updatedText = decodeURIComponent(body.message.blocks[0].text.text.replace(/\+/g, ' '));
await updateMessage(body.channel.id, updatedText, body.message.ts);
// 押されたボタンによって処理の分岐
let message = "";
if (actionId === "yes_action") {
// Yes ボタンが押された場合の処理
// DB更新処理
message = "更新が完了しました。";
} else if (actionId === "no_action") {
// No ボタンが押された場合の処理
message = "更新をキャンセルしました。";
}
// 更新結果をスレッドに返信
await sendSlackMessage(body.channel.id, message, body.message.ts);
return {
statusCode: 200,
body: '',
};
}
// メンション時イベント
if (body.event.type === "app_mention") {
let message = `<@${body.event.user}>\nデータが見つかりません`;
let appendBlock = false;
// Slackから投稿されたidを正規表現を用いて取得
const matchResult = body.event.text.match(/\d{11}/);
if (matchResult) {
const companyId = matchResult[0];
try {
// APIから情報を取得処理
message = `<@${body.event.user}>\n更新対象は ${code}_${companyName} でよろしいですか?\nHubSpot Id : ${companyId}`;
appendBlock = true;
} catch (error) {
// APIのリクエスト形式に合わなかった場合
console.log("Failed. companyId : " + companyId);
}
}
// Slackに返信
await sendSlackMessage(body.event.channel, message, body.event.ts, appendBlock);
return {
statusCode: 200,
body: '',
};
}
};
async function sendSlackMessage(channel, text, thread_ts, appendBlock=false) {
let blocks = [];
if (appendBlock) {
// Yes No ボタンの追加
blocks = [
{
type: "section",
text: {
type: "mrkdwn",
text: text,
},
},
{
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
text: "YES",
},
"style": "primary",
value: "yes",
action_id: "yes_action",
},
{
type: "button",
text: {
type: "plain_text",
text: "NO",
},
value: "no",
action_id: "no_action",
},
],
},
];
}
const postData = {
token: SLACK_BOT_TOKEN,
channel,
text,
thread_ts,
blocks,
};
const response = await axios.post("https://slack.com/api/chat.postMessage", postData, {
headers: {
"Content-Type": "application/json; charset=utf-8",
"Authorization": `Bearer ${SLACK_BOT_TOKEN}`,
},
});
return response;
}
// Yes Noボタンを削除するためにメッセージを更新する
async function updateMessage(channel, text, ts) {
const postData = {
token: SLACK_BOT_TOKEN,
channel,
text,
ts,
blocks: JSON.stringify([
{
type: "section",
text: {
type: "mrkdwn",
text: text,
},
},
]),
};
const response = await axios.post("https://slack.com/api/chat.update", postData, {
headers: {
"Content-Type": "application/json; charset=utf-8",
"Authorization": `Bearer ${SLACK_BOT_TOKEN}`,
},
});
return response;
}
このLambdaをSlackアプリから発火させるために関数URLを紐付ける。