moto blog

コミュニケーション活性化に一役!SlackとGASで誕生日Botを作ってみた

f:id:nmmmk:20180503225734j:plain

GAS(Google Apps Script)を使用して、Slackの誕生日おめでとうBotを作成します。 Slackでのコミュニケーション活性化のために作ってみてはいかがでしょうか?

構造

  • GASからSlackへ誕生日メッセージを送信する

f:id:nmmmk:20180504145056p:plain

Botの仕様

  • 名前と誕生日をスプレッドシートで管理する。
  • 当日誕生日の人がいる場合は、午前9時〜10時の間に誕生日メッセージを投稿する。
  • 土日には投稿しない。土日が誕生日の場合は、金曜日に「明日は」、「あさっては」という表現で投稿する。(祝日には対応しない)
  • 投稿時にはおめでとう画像をあわせて投稿し、かつ、画像はランダムにする。

Slackの設定

こちらの記事の「Incoming Webhooksの設定」を参考にして、Incoming Webhooksの設定を行ってください。

nmmmk.hatenablog.com

誕生日リストの準備(スプレッドシート

誕生日のリストをスプレッドシートに、以下の様に定義します。

  • シート名を「誕生日」にする
  • 2列目に名前
  • 3列目に誕生日

f:id:nmmmk:20180504150917p:plain

おめでとう画像の準備

Google Drive上におめでとう画像をアップロードします。
投稿する画像や枚数は自由に決めてください。

今回は、8枚の画像を準備しました。

f:id:nmmmk:20180504151540p:plain

ファイルIDが必要となりますので、以下の手順で取得しておいてください。

  1. 対象ファイルを右クリックして、共有を選択します。
    f:id:nmmmk:20180505110434p:plain

  2. 詳細設定を押下します。
    f:id:nmmmk:20180505110551p:plain

  3. ファイルIDを取得します。(黒で塗りつぶしている箇所)
    f:id:nmmmk:20180525002205p:plain

  4. 共有設定画面で、アクセスできるユーザーの変更を行い、以下の設定を表示します。
    オン-リンクを知っている全員 を選択します。
    f:id:nmmmk:20180525002509p:plain

ソースコード

スプレッドシートの行列情報を定義

// スプレッドシートの行列情報
var StartRow = 2;         // 開始行
var NameCol = 1;          // 名前列
var BirthdayCol = 2;      // 誕生日列

メインルーチン

XXXXXの部分は誕生日リストのスプレッドシートのIDを指定してください。

スプレッドシートのIDは、スプレッドシートのURLの下記の部分です。
https://docs.google.com/spreadsheets/d/スプレッドシートのID/edit#gid=0

function main() {
  // 今日の日付を取得
  var nowDate = new Date();
  
  // 今日の曜日を取得
  var todayDayOfWeek = nowDate.getDay();

  // 土曜、日曜は投稿しない
  if (isSatOrSun(todayDayOfWeek) === true) {
    return;
  }
  
  // 誕生日リストのスプレッドシートを参照
  var spreadsheet = SpreadsheetApp.openById('XXXXX');
  
  // シートにアクセス
  var sheet = spreadsheet.getSheetByName('誕生日');
  
  // データ取得
  var data = sheet.getDataRange().getValues();
  
  for (var i = 0; i < data.length; i++) {
    if (i < StartRow) {
      continue;
    }
    
    // 名前を取得
    var name = data[i][NameCol];
    
    // 誕生日を取得
    var birthday = data[i][BirthdayCol];
    
    // 誕生日を日付でパースし、日付が正しく入力されているかチェック
    var isDate = !isNaN(Date.parse(birthday));

    // 誕生日入力済みであることをチェック
    if (isDate === true) {
      // 投稿処理
      postProc(name, birthday, nowDate); 
    }
  }
}

土日判定

function isSatOrSun(todayDayOfWeek)
{
  // 土曜、日曜は投稿しない
  if ((todayDayOfWeek === 0) || (todayDayOfWeek === 6)) {
    return true;
  }
  
  return false;
}

投稿処理メイン

function postProc(name, birthday, nowDate)
{
  var todayDayOfWeek = nowDate.getDay();
  var message = "";

  // 金曜日
  if (todayDayOfWeek === 5){
    
    // 1日後(土曜日)
    var dtSat = new Date();
    dtSat.setDate(dtSat.getDate() + 1);
    
    // 2日後(日曜日)
    var dtSun = new Date();
    dtSun.setDate(dtSun.getDate() + 2);
    
    if (isSend(dtSat, birthday) === true) {
      message = createMessage(name, "明日");
    }
    else if (isSend(dtSun, birthday) === true) {
      message = createMessage(name, "あさって");
    }
    else if (isSend(nowDate, birthday) === true) {
      message = createMessage(name, "今日");
    }
  }
  else
  {
    if (isSend(nowDate, birthday) === true) {
      message = createMessage(name, "今日");
    }      
  }

  // メッセージが生成されていれば、Slackに投稿  
  if (message != "") {
    // おめでとう画像を取得
    var fileId = getRandomImageID();
        
    // Slackへ投稿
    postSlack(message, fileId);
  }
}

送信有無判定

function isSend(compareDate, birthdayDate)
{
  // 月、日が一致するかをチェックする
  if ((compareDate.getMonth() === birthdayDate.getMonth()) && 
    (compareDate.getDate() === birthdayDate.getDate()))
    {
      return true;
    }
  
  return false;
}

おめでとう画像取得

imageFileArrayの"AAAAA"〜"HHHHH"は、おめでとう画像の準備Google DriveにアップロードしたファイルのIDを定義してください。
8枚の画像からランダムに取得する様にしています。

function getRandomImageID() {
  var imageFileArray = [
    "AAAAA",
    "BBBBB",
    "CCCCC",
    "DDDDD",
    "EEEEE",
    "FFFFF",
    "GGGGG",
    "HHHHH",
  ];

  // 0~7の値を取得
  var randomValue = Math.floor( Math.random() * 8 );
  
  return imageFileArray[randomValue];
}

メッセージ作成処理

//------------------------------
// メッセージ作成
//------------------------------
function createMessage(name, dayMessage)
{
  var message = dayMessage + 'は, `' + name + '`さんの誕生日です :birthday:' + '\r\n' + 
    'おめでとうございます :tada: :tada: :tada:'
    
  return message;  
}

Slackへの投稿処理

YYYYYの部分は、Incoming Webhooksの設定時に取得した投稿先のチャンネルのURLを設定してください。

function postSlack(text, fileId) {
  
  var payload = {
    text: text,
    attachments: [
        {
            color: "#2eb886",
            pretext: "",
            image_url: "http://drive.google.com/uc?export=download&id=" + fileId,
        }      
      ]
  };
 
  // Incoming WebhooksのURL
  var url = "YYYYY";
  
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload": JSON.stringify(payload)
  };
  UrlFetchApp.fetch(url, options); 
}

最終ソースコード

// スプレッドシートの行列情報
var StartRow = 2;         // 開始行
var NameCol = 1;          // 名前列
var BirthdayCol = 2;      // 誕生日列

//------------------------------
// main処理
//------------------------------
function main() {
  // 今日の日付を取得
  var nowDate = new Date();
  
  // 今日の曜日を取得
  var todayDayOfWeek = nowDate.getDay();

  // 土曜、日曜は投稿しない
  if (isSatOrSun(todayDayOfWeek) === true) {
    return;
  }
  
  // 誕生日リストのスプレッドシートを参照
  var spreadsheet = SpreadsheetApp.openById('XXXXX');
  
  // シートにアクセス
  var sheet = spreadsheet.getSheetByName('誕生日');
  
  // データ取得
  var data = sheet.getDataRange().getValues();
  
  for (var i = 0; i < data.length; i++) {
    if (i < StartRow) {
      continue;
    }
    
    // 名前を取得
    var name = data[i][NameCol];
    
    // 誕生日を取得
    var birthday = data[i][BirthdayCol];
    
    // 誕生日を日付でパースし、日付が正しく入力されているかチェック
    var isDate = !isNaN(Date.parse(birthday));

    // 誕生日入力済みであることをチェック
    if (isDate === true) {
      // 投稿処理
      postProc(name, birthday, nowDate); 
    }
  }
}

//------------------------------
// 投稿処理
//------------------------------
function postProc(name, birthday, nowDate)
{
  var todayDayOfWeek = nowDate.getDay();
  var message = "";

  // 金曜日
  if (todayDayOfWeek === 5){
    
    // 1日後(土曜日)
    var dtSat = new Date();
    dtSat.setDate(dtSat.getDate() + 1);
    
    // 2日後(日曜日)
    var dtSun = new Date();
    dtSun.setDate(dtSun.getDate() + 2);
    
    if (isSend(dtSat, birthday) === true) {
      message = createMessage(name, "明日");
    }
    else if (isSend(dtSun, birthday) === true) {
      message = createMessage(name, "あさって");
    }
    else if (isSend(nowDate, birthday) === true) {
      message = createMessage(name, "今日");
    }
  }
  else
  {
    if (isSend(nowDate, birthday) === true) {
      message = createMessage(name, "今日");
    }      
  }

  // メッセージが生成されていれば、Slackに投稿  
  if (message != "") {
    // おめでとう画像を取得
    var fileId = getRandomImageID();
        
    // Slackへ投稿
    postSlack(message, fileId);
  }
}

//------------------------------
// 土曜日 or 日曜日判定
//------------------------------
function isSatOrSun(todayDayOfWeek)
{
  // 土曜、日曜は投稿しない
  if ((todayDayOfWeek === 0) || (todayDayOfWeek === 6)) {
    return true;
  }
  
  return false;
}

//------------------------------
// 送信有無取得
//------------------------------
function isSend(compareDate, birthdayDate)
{
  // 月、日が一致するかをチェックする
  if ((compareDate.getMonth() === birthdayDate.getMonth()) && 
    (compareDate.getDate() === birthdayDate.getDate()))
    {
      return true;
    }
  
  return false;
}

//------------------------------
// メッセージ作成
//------------------------------
function createMessage(name, dayMessage)
{
  var message = dayMessage + 'は, `' + name + '`さんの誕生日です :birthday:' + '\r\n' + 
    'おめでとうございます :tada: :tada: :tada:'
    
  return message;  
}

//------------------------------
// 誕生日おめでとう画像のIDを取得
//------------------------------
function getRandomImageID() {
  var imageFileArray = [
    "AAAAA",
    "BBBBB",
    "CCCCC",
    "DDDDD",
    "EEEEE",
    "FFFFF",
    "GGGGG",
    "HHHHH",
  ];

  // 0~7の値を取得
  var randomValue = Math.floor( Math.random() * 8 );
  
  return imageFileArray[randomValue];
}

//------------------------------
// Slackへ投稿
//------------------------------
function postSlack(text, fileId) {
  
  var payload = {
    text: text,
    attachments: [
        {
            color: "#2eb886",
            pretext: "",
            image_url: "http://drive.google.com/uc?export=download&id=" + fileId,
        }      
      ]
  };
 
  // Incoming WebhooksのURL
  var url = "YYYYY";
  
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload": JSON.stringify(payload)
  };
  UrlFetchApp.fetch(url, options); 
}

実行してみる!

  1. 現在の日付と誕生日が一致する様に、スプレッドシートに定義した、いずれかの誕生日を修正してください。

  2. スクリプトエディタにて実行 -> 関数を実行 -> main を選択します。 f:id:nmmmk:20180505103013p:plain

  3. 以下の様な感じで、投稿されます(^ ^) f:id:nmmmk:20180504155422p:plain

対象者が複数いる場合は、連続投稿する様になっています。

実行トリガーを設定する

毎日スクリプトが決まった時間に実行される様に実行トリガーを設定します。

  1. スクリプトエディタにて編集 -> 現在のプロジェクトのトリガー -> main を選択します。
    f:id:nmmmk:20180504155627p:plain

  2. トリガーを追加します。
    f:id:nmmmk:20180505103642p:plain

  3. 毎日9時から10時の間にmain()が実行される様に設定します。
    f:id:nmmmk:20180504155638p:plain