Google Apps Scriptでスプレレットシートのタスクをslackにリマインドしてくれるbotを作ってみた
背景
- スプレットシートのチームのタスクを管理していたのだが、タスクの期限切れが多く、タスク自体を失念しているケースが多かったため、出社時と退社時にリマンドしてくれるボットを作った。
結果
- タスク確認のMTGがなくなった。
- 期限切れは無くならなかったが、タスク遅延期間が長くても1日遅れくらいに収まった
- タスクの内容も記載しているため、マネージャーとのコミュニケーションがいい意味で減った。(状況把握に時間がかからない。)
コード
タスク管理しているスプレットシートによって、少々修正を加えなければならないです。ご注意ください。
// トリガーする時間を設定
var postTimes = [
[9, 45],
[18, 30]
];
(function(global){
var Slack = (function() {
function Slack(options){
var options = options || {};
this.url = options.url || "https://slack.com/api/chat.postMessage";
this.token = options.token || UserProperties.getProperty('SlackAccessToken');
this.channel = options.channel || "#" + UserProperties.getProperty('PostedChannelName');
this.username = options.username || UserProperties.getProperty('SlackBotName'); // ボットの名前 (デフォルト値を設定)
this.icon_emoji = options.icon_emoji || UserProperties.getProperty('SlackBotIcon'); // ボットのアイコン画像を指定 (デフォルト値を設定)
}
Slack.prototype.send = function(text) {
var self = this;
UrlFetchApp.fetch(self.url, {
"method" : "POST",
"payload" : {
token: self.token,
channel: self.channel,
username: self.username,
icon_emoji: self.icon_emoji,
text: text
}
});
};
return Slack;
})();
global.Slack = Slack;
})(this);
// triggerTimesに設定された全ての時間のトリガーを設定
function setTrigger() {
var triggerDay = new Date();
for(var i = 0; i < postTimes.length; i++) {
triggerDay.setHours(postTimes[i][0], postTimes[i][1]);
ScriptApp.newTrigger("main").timeBased().at(triggerDay).create();
}
}
// その日のトリガーを削除する関数(消さないと残る)
function deleteTrigger() {
var triggers = ScriptApp.getProjectTriggers();
for(var i=0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() == "main") {
ScriptApp.deleteTrigger(triggers[i]);
}
}
}
function isJapaneseHoliday(date) {
var startDate = new Date(date.getTime());
var endDate = new Date(date.getTime());
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
var holidays = cal.getEvents(startDate, endDate);
return holidays.length != 0;
}
function isHoliday(date) {
return date.getDay() == 0 // 日曜かどうか
|| date.getDay() == 6 // 土曜かどうか
|| isJapaneseHoliday(date); // 日本の祝日かどうか
}
function getMsgBody(data) {
var line = "------------------------------------------\n";
var msg = line + ":sunny:*本日期限のアクション一覧は以下の通りです。*:sunny:\n";
if (data.today.length != 0) { // 今日のアクションがある場合
msg += (data.today.join("\n"));
} else { // 今日のアクションがない場合
msg += ":tada: なし :tada:\n";
}
if (data.past.length != 0) {
msg += (
"\n\n\n\n:zap::smiling_imp:*期限切れのアクション一覧は以下の通りです。*:smiling_imp::zap:\n" +
data.past.join("\n")
);
} else { // 今日のアクションがない場合
msg += "\n\n\n\n:zap::smiling_imp:*期限切れのアクション一覧は以下の通りです。*:smiling_imp::zap:\n"
+ "\n" + ":tada::tada::tada: なし :tada::tada::tada:\n";
}
msg += line;
return msg;
}
function main() {
// 土日祝日はこの先の処理を行わない
var today = new Date();
today.setHours(0, 0, 0, 0);
if (isHoliday(today)) return;
// ここからの列を定義する変数は、各自調整が必要になります。
var spreadsheetId = UserProperties.getProperty('SpreadsheetId');
var sheetName = UserProperties.getProperty('SheetName');
var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
var lastRowIndex = sheet.getLastRow(); // データが入力されている最終行の行番号を取得
var dateColumnIndex = 22; // 「期限」カラムの列番号
var clientColumnIndex = 2; // 「顧客正式名称」カラムの列番号
var siteColumnIndex = 3; // 「サイト名称」カラムの列番号
var managerColumnIndex = 7; // 「担当者」カラムの列番号
var actionColumnIndex = 21; // 「ネクストアクション」カラムの列番号
var mentionColumnIndex = 56; // 「メンションアクション」カラムの列番号
var data = { today: [], past: [] }; // slackに送信するメッセージを保持
for(rowIndex = 1; rowIndex <= lastRowIndex; rowIndex++) {
var displayedDate = sheet.getRange(rowIndex, dateColumnIndex).getDisplayValue();
// セルの値が日付のフォーマット(xxxx/xx/xx)かどうか
if(!/\d{4}\/\d{2}\/\d{2}/.test(displayedDate)) continue;
var parsedDate = new Date(displayedDate);
if (parsedDate.getTime() <= today.getTime()) { // 期限が今日以前の場合
var clientName = sheet.getRange(rowIndex, clientColumnIndex).getDisplayValue();
var siteName = sheet.getRange(rowIndex, siteColumnIndex).getDisplayValue();
var managerName = sheet.getRange(rowIndex, managerColumnIndex).getDisplayValue();
var action = sheet.getRange(rowIndex, actionColumnIndex).getDisplayValue();
var mention = sheet.getRange(rowIndex, mentionColumnIndex).getDisplayValue();
var item = "
+ "クライアント名:" + clientName + "\n"
+ "サイト名:" + siteName + "\n"
+ "担当者:" + managerName + "( " + mention + " )" + "\n"
+ "アクション内容:\n" + action + "\n"
+ "\n";"
var type = parsedDate.getTime() == today.getTime() ? 'today' : 'past';
data[type].push(item);
}
}
var slack = new Slack();
var msg = getMsgBody(data);
slack.send(msg);
}