こんちには、エバーセンスの江上です。
Slackつかってますか?僕は /remind
に幾度救われたかわかりません。最近1年前に設定したremindのおかげで、プロバイダーから3000円返ってきました。
そんなremindのメッセージにボタンがついてるの知ってますか?
(↓のMark as CompleteとかDeleteとか)
この超便利機能を、自分でも作れると聞いて、早速試してみました ^o^
ちなみに今回は、Botもサーバーも運用が大変なので、 Google App Script
に全てお任せしています。
よって、foreverがハングしたりec2が急に落ちたりする世界とは無縁で運用できます!
Googleさんありがとー。
必要なもの
- googleアカウント
- slackアカウント
参考情報
やってみる
とりあえず、『毎日「今日の小技」をSlackに共有して、それが役に立ったかどうかを回答してもらう』システムをつくることにしました。
やることはこんな感じ
1. Slackに「今日の小技」を通知する
2. ユーザーがボタンを押したらフィードバックが送信されてスプレッドシートにデータをためる
1. Slackに「今日の小技」を通知する
1. Slack Appを作成する
Slack Appの管理画面でサクッと作成します
2. Incoming Webhookを設定します
作成したSlack Appを選択して、通知したいチャンネルを選べばOKです。終わったら、自分のworkspaceにインストールします
3. GASでSlackに通知します
まずは「今日の小技」を書いたスプレッドシートを用意します
こんな感じ
次は、スプレッドシートのデータを取得して、Slackに通知します
(getColNumなどの関数は別途定義してます。こちらでソース公開してるのでそっちで確認してください )
// SpreadSheetに記載された小技を日々通知する
function notify(){
var row = getRowNumByDate(new Date())
// 該当がなければスキップ
if(row === 0){
return;
}
var elements = getNotifyMessageElements(row);
var title = getNotifyMessageForSlack(elements);
var attachments = getNotifyAttachments(elements);
sendToSlack(title, attachments)
}
function getNotifyMessageForSlack(e){
return "*" + e.title + "*" + "\n\n" +
e.description + "\n" +
"by" + e.author;
}
function getNotifyAttachments(e){
var actions = [
{
"name": "feedback",
"text": "役に立った",
"style": "primary",
"type": "button",
"value": FEEDBACK_TYPES.GREAT
},
{
"name": "feedback",
"text": "使えない",
"style": "danger",
"type": "button",
"value": FEEDBACK_TYPES.BAD
},
{
"name": "feedback",
"text": "知ってた",
"type": "button",
"value": FEEDBACK_TYPES.KNOWN
}
]
return [
{
"fallback": "もう一回おしてね",
"callback_id": e.id,
"color": "#3AA3E3",
"attachment_type": "default",
"actions": actions
}
]
}
function getNotifyMessageElements(row){
var sheet = SpreadsheetApp.getActive().getSheetByName(TARGET_SHEET);
var id = sheet.getRange(row, getColNum("id")).getValue()
var title = sheet.getRange(row, getColNum("title")).getValue()
var description = sheet.getRange(row, getColNum("description")).getValue()
var author = sheet.getRange(row, getColNum("author")).getValue()
return {id: id, title: title, description: description, author: author};
}
function sendToSlack(text, attachments){
// username, channel, iconはSlack App側で設定したもので上書きされるので書かない
var payload = {
"text": text,
"attachments": attachments,
"link_names": 1
};
var options = {
"method" : "post",
"payload" : JSON.stringify(payload)
};
UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);
}
で、 notify
関数を実行すると
きました!ボタン付きのメッセージが!!!
先ほど、attachmentsのactionで定義したものがボタンになってます。
次は、これらのボタンを押したら、スプレッドシートに「役に立ったかどうか?」がたまるようにしてみましょう
2. ユーザーがボタンを押したらフィードバックが送信されてスプレッドシートにデータがたまるようにする
1. GASをウェブアプリケーションとして公開します
スプレッドシートにデータをためるには、GASをウェブアプリとして公開します。
こちらがよくまとまっているので参考にしてみてください。
GASでwebアプリケーションを作る方法
ウェブアプリとして公開するとhttps://script.google.com/
から始まるurlが発行されるのでメモしておきます
2. Slack AppのInteractive Componentsを設定します
次に、Slack Appの Interactive Components
ページにおいて、Request URL
を設定します。urlは先ほど取得したhttps://script.google.com/
から始まるurlです
3. エンドポイントとなるGASを作成します
最後に、GASを作成しましょう
function doPost(e){
var json = JSON.parse(e.parameter.payload)
addFeedback(json)
var feedbackType = getFeedbackType(json.actions)
var responsePayload = getResponsePayloadByFeedbackType(feedbackType);
responseToSlack(json.response_url,responsePayload);
// テキストを返すと送ったメッセージが上書きされてしまうので空を返す
return ContentService.createTextOutput();
}
function addFeedback(json){
var feedbackType = getFeedbackType(json.actions)
var sheet = SpreadsheetApp.getActive().getSheetByName(TARGET_SHEET);
var row = getRowNumById(json.callback_id);
Object.keys(FEEDBACK_TYPES).forEach(function (key) {
var col = getColNum(FEEDBACK_TYPES[key]);
var range = sheet.getRange(row, col);
if(FEEDBACK_TYPES[key] === feedbackType){
appendName(range, json.user.name)
} else {
subName(range, json.user.name)
}
});
}
function appendName(range, name){
var original_value = range.getValue()
var names = original_value.split(",");
names.push(name)
var uniqueNames = names.filter(function (x, i, self) {
return self.indexOf(x) === i && x !== "";
});
range.setValue(uniqueNames.join(","))
}
function subName(range, name){
var original_value = range.getValue()
var names = original_value.split(",");
var index = names.indexOf(name);
if(index >= 0){
names.splice(index,1)
}
range.setValue(names.join(","))
}
function getFeedbackType(actions){
var type = FEEDBACK_TYPES.KNOWN;
if(actions.filter(function(e){ return e.name == "feedback" && e.value == FEEDBACK_TYPES.GREAT }).length > 0) {
type = FEEDBACK_TYPES.GREAT;
} else if(actions.filter(function(e){ return e.name == "feedback" && e.value == FEEDBACK_TYPES.BAD }).length > 0) {
type = FEEDBACK_TYPES.BAD;
}
return type;
}
function getRowNumById(id){
var sheet = SpreadsheetApp.getActive().getSheetByName(TARGET_SHEET);
var range = sheet.getRange("A2:A");
var values = range.getValues();
var row = 0;
for(i=0;i<values.length;i++){
if(values[i][0] == id){
row = i;
break;
}
}
return row + ROW_OFFSET;
}
function getResponsePayloadByFeedbackType(feedbackType){
var payload = {
"response_type": "ephemeral",
"replace_original": false,
"text": "text"
}
switch(feedbackType){
case FEEDBACK_TYPES.GREAT:
payload.text = "ありがとうございます。お役にたててよかったです :joy: ";
break;
case FEEDBACK_TYPES.BAD:
payload.text = "ありがとうございます。明日に期待してください :smile: ";
break;
case FEEDBACK_TYPES.KNOWN:
payload.text = "ありがとうございます。さすがです :laughing: ";
break;
}
return payload;
}
function responseToSlack(responseUrl, payload){
var options = {
"method" : "post",
"payload" : JSON.stringify(payload)
};
UrlFetchApp.fetch(responseUrl, options);
}
さぁ、準備は整いました。再度GASをウェブアプリとして公開し、Slack Appも再インストールしたら、notify
を実行して、メッセージを送ります。そして、「知ってた」を押すと。。。
見事Slack Appから返信がきました!他のボタンを押すとまた違ったメッセージがかえってきます
そして、スプレッドシートをみてみると
役に立ったか?のフィードバックも記録されてます!
最後に
めでたく毎日「今日の小技」がSlackに流れてきて、どれほど役に立ったのかを測るところまで仕組み化できました。
GASでは定期実行もできるので毎日流すことも可能です。githubでは最後に何人の役に立ったのかをSlackに投稿するところまで自動化しているのでみてみてください。
そして、今回は業務として投稿してるので、宣伝です。
エバーセンスでは、技術で家族を幸せにしてくれる仲間を募集しています。よかったら応募してね。おまちしてます
https://www.wantedly.com/companies/eversense-co/projects