21
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

qnoteAdvent Calendar 2016

Day 12

弊社猫会長に日直当番を任命していただくbotを作った

Last updated at Posted at 2016-12-11

##概要

弊社は一軒家をオフィスにしており、自分たちでオフィスの掃除をしている。
最初の頃は毎月カレンダーを作って日直を決めていたのだが、カレンダーを作るのも、カレンダーを確認するのも手間だよねということになり、Slackに専用のチャンネルを作り、そこに日直当番を通知するようにした。
実は今回紹介するのはv2で、v1より格段に進化している(大げさ)

##参考にさせていただいた記事

手順はほぼこちらの記事と同じです。

掃除当番の割当を Google Apps Script で自動化して Slack の BOT として通知

##Googleスプレッドーシートで当番表を作る

弊社の場合は、下記のようなものを作った。

担当
<@milk>
<@hana>
<@chimaki>
<@ribbon>
<@sakura>
<@mii>

@hoge はSlackのユーザーアカウント名。
<@hoge> とすることで、Slack投稿時にメンションが飛ぶようになる。
ただし、そのアカウントが存在しないと . . . と投稿される模様。

##Slack Web API tokenを取得する

Slackの仕様が変わっていました。
詳しくは下記記事を参照ください。
Slack APIのTokenの取得・場所
Slack API 推奨Tokenについて

##Google Apps Scriptでプログラムを書く

Googleスプレッドシートを開いて、「メニュー>ツール>スクリプトエディタ...」を選択。
スクリプトエディタが開くので、そこにプログラムを書く。

###SlackAppライブラリを導入

どんなものかは下記を参照。
Slack BotをGASでいい感じで書くためのライブラリを作った

スクリプトエディタの「リソース>ライブラリ...」を選択。
「ライブラリを検索」の入力欄に下記のLibrary Keyをコピペ。

LibraryKey
M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO

バージョンを選択して「保存」をクリック。
私はバージョン22を使用しています。

###ソースコード

参照させていただいた記事をベースにしているので、メソッド名がそのままです。。。
変数名も適当。

コード
//slack定義
var slack = {
    postUrl: "https://slack.com/api/chat.postMessage",
    token: "xoxp-your-token",  //取得したSlackWebAPIのtoken
    ChannelId: "general",  //投稿するチャンネルのChannelId
    userName: "Futaba",  //botの名前
    iconEmoji: ":futaba:"  //botのアイコン
}

//メンバー・役割のデータをスプレッドシートから取得
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastrow = sheet.getLastRow();

var members = sheet.getSheetValues(2, 1, lastrow-1, 1);  //データ行のみを取得する

var days = ["月:", "火:", "水:", "木:", "金:"];

//当日の日直を通知
function notifyTodayCleaningRole() {
  //平日のみ実行
  var currentDate = new Date();
  if (!isWeekDay(currentDate)) {
    return;
  }

  //祝日は実行しない
  if (isEventsForDay(currentDate)) {
    return;
  }

  var title = " 本日の日直よ! 私の遊び相手も忘れずにね!\n\n";
  var member = selectMember();
  updateMembersSheet();
  sendMessageToSlack(title, member);
}

//明日の日直を通知
function notifyTomorrowCleaningRole() {
  //平日のみ実行
  var currentDate = new Date();
  if (!isWeekDay(currentDate)) {
    return;
  }

  //祝日は実行しない
  if (isEventsForDay(currentDate)) {
    return;
  }
  var title = " 次の日直は貴方よ! みるくに食べさせすぎないでね!\n\n";
  var member = selectMember();
  sendMessageToSlack(title, member);
}

// 今週の日直一覧を通知(トリガーで月曜日に起動するようにしている)
function notifyCurrentWeekCleaningRole() {
  var member = "";
  for (var i = 0; i < 5; i++) {
      var currentDate = new Date();
      currentDate.setDate(currentDate.getDate() + i);
      if (isEventsForDay(currentDate)) {
        member += days[i] + "休日のためなし" + "\n";
      } else {
        var rotateMembers = rotate(members);  
        member += days[i] + rotateMembers[0] + "\n";
      }
  }
  var title = " 今週の日直一覧よ! みんながんばってね!\n\n";
  sendMessageToSlack(title, member);
}


function selectMember() {
  //当番を割り当てる
  var selectMembers = ""; 
  var rotateMembers = rotate(members);  
  selectMembers = selectMembers + rotateMembers[0] + "\n";

  return selectMembers;
}

//配列の要素を後ろにずらして、最後の要素を先頭に移動する
function rotate(array){
  array.unshift(array[array.length-1])
  array.pop();
  return array;
}

// 平日か判定
function isWeekDay(currentDate) {
  var weekday = currentDate.getDay();
  if (weekday == 0 || weekday == 6) {
    return false;
  }
  return true;
}

// 祝日か判定
function isEventsForDay(currentDate) {
  var calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
  if (calendar.getEventsForDay(currentDate, {max: 1}).length > 0) {
    return true;
  }
  return false;
}

//Slackにメッセージを送る
function sendMessageToSlack(title, member) {
  var testSuffix = "";
  var slackApp = SlackApp.create(slack["token"]);
  var Message = slackApp.postMessage(
      slack["ChannelId"], testSuffix + title + member + "", {
      username : slack["userName"],
      icon_emoji: slack["iconEmoji"]
    } 
  ); 
}

//割り当てた結果をスプレッドシートにも反映させる
function updateMembersSheet() {
//  var rotateMembers = rotate(members);  
  for(var i = 0; i < members.length; i++){
    sheet.getRange(i+2, 1).setValue(members[i]);
  } 
}

###機能説明

説明というほどのものでもないけど。

notifyTodayCleaningRole()
当日に通知を行うためのメソッド。
平日のみ稼働。

notifyTomorrowCleaningRole
明日の当番の通知を行うためのメソッド。
平日のみ稼働。

notifyCurrentWeekCleaningRole
一週間分の当番の通知を行うためのメソッド。
祝日が含まれる場合は「休日のため当番なし」といった形で通知を行う。

v1は notifyTodayCleaningRole() だけだったんだけど、v2で機能を追加した。

###実行はトリガーで行う

スクリプトエディタの「リソース>現在のプロジェクトのトリガー」を選択。
弊社の場合は下記のように設定。

スクリーンショット 2016-12-08 19.21.00.png

トリガーの時間指定はほんとに一時間の間のどこか、なので、10:59に通知が行われてドギマギすることもあるw

##実行してみた

猫社員のアカウントがないので、メンションじゃないけど。

スクリーンショット 2016-12-08 19.19.09.png

##まとめ

ふたば会長に任命いただき光栄であります!
きりきり掃除いたします!

21
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?