4
4

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 3 years have passed since last update.

Slackとgoogleカレンダーで勤怠記録をしよう

Last updated at Posted at 2020-06-04

はじめに

新型コロナウイルスの影響で自粛期間が長らく続いていましたが,6月あたりから感染対策を実施した上で各大学,企業でのが行われるようになりましたね.

僕の大学では研究室の入退室時間を管理することが義務付けられました.これは感染者が出た場合に,感染経路及び感染した可能性のある人を特定するためだと思われます.
他の大学や企業でもこのような感染対策を実施しているのではないでしょうか.

特に管理法についての指定はなかったので,googleカレンダーに記入することで入退室時間を記録することになったのですが,研究室全員で使用するアプリはできる限り少ない方が効率的であるため,指導教員の先生からSlackだけで入退室時間を管理できるようにうまいことやってくれないかと依頼されました.

そこでSlackに勤怠管理チャンネルを作り,「おはよう」や,「さようなら」と呟けばgoogleカレンダーに予定が追加されるプログラムを作成しました.

初投稿であることと,GAS経験が少ないことをご容赦ください.

ユーザーが行う操作のイメージ
slack.PNG

googleカレンダーに名前,時間,場所が登録される
カレンダー.PNG

スプレッドシートにも登録される
spread.PNG

用意するものと使ったツール

  • チームで共有しているgoogleカレンダー
  • 勤怠管理用のSlackのチャンネル
  • Outgoing webhook
  • Incoming webhook
  • Google Apps Script

Outgoing webhook

トリガーワードが呟かれたら反応して色々するアプリです
こちらからSlackの勤怠管理用のチャンネルにOutgoing webhookを追加します.
中身はGoogleAppsScriptで書いていきます.
outgoing.PNG
引き金となる言葉は自由に変更できます.inとoutだけで構いませんが,味気ないので多めに設定しました.
URLは,GoogleAppsScriptのアプリのURLを張り付けるので,この時点では空欄で構いません.
トークンはGoogleAppsScriptで使います.

Incoming webhook

呟いてレスポンスが無かったらカレンダーに追加されたのか懐疑的になるのと,味気ないので,反応してくれるアプリを追加します.
さきほどと同様にこちらから勤怠管理用のチャンネルにIncoming webhookを追加します.
incoming.PNG
レスポンスしてくれるbotのアイコンはここで設定できます.

Google Apps Script

googleドライブから,Googleスプレッドシートを新規作成します.
(1, 1)から(1, 6)セルに
カレンダーへの登録,日付,タイトル(人),開始時間,終了時間,場所,
と記入します.スプレッドシートでも勤怠管理を登録していきます.
次にツールタブのスクリプトエディタを開きます.
以下のソースコードをコピペします.

SlackToCalendar.gs
function doPost(e) {
  //シート1はシート名に応じて変更
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  
  // googleカレンダーのID
  const calendar = CalendarApp.getCalendarById("[googleカレンダーの設定からIDをコピペ]")

  //Outgoing Webhookのトークン
  var token = '[Outgoing webhookのトークンをコピペ]'

  //送られてきたトークンが正しければ勤怠を記録
  //parameterは必要に応じて変更
  if (token == e.parameter.token){
    var id_to_name = {"U0*********":"金子","U0*********":"本多","U0*********":"阿部"}
    var datetime     = new Date();
    var date         = (datetime.getFullYear()  + ('0' + (datetime.getMonth() + 1)).slice(-2) + ('0' + datetime.getDate()).slice(-2))
    var user_name    = id_to_name[e.parameter.user_id];
    var trigger_word = e.parameter.trigger_word;
    var text         = e.parameter.text;
  // 入室に反応する言葉(Outgoing webhookで設定した物)をリストに追加
    var list = ["in","おはよう","出勤","こんにちは"]
    var message
    
    if (list.includes(trigger_word)) {
      // 出勤時のプログラム
      
      // 場所を追加
      text = text.replace("_","_")
      var mark = "_"
      var index = text.indexOf(mark)
      text = text.slice(index + 1)
      
      
      //追加する配列を作成
      array = ["",date,user_name,datetime,"",text];
      //シートの最下行に配列を記述
      sheet.appendRow(array);
      
      message = Utilities.formatString("%sさんが%sに%sしました",user_name,text,trigger_word)
      
    } else {
      // 退勤時のプログラム
      message = Utilities.formatString("%sさん%s",user_name,trigger_word)
      
      for(var i=2; i<= sheet.getLastRow(); i++) {
        // カレンダーに登録済みならパス
        if (sheet.getRange(i, 1).getValue().toString() == "") {
          continue;
        }
        // 日付とuser_nameが一致しているものを探す
        var in_date = sheet.getRange(i,2).getValue()
        var in_datetime = sheet.getRange(i,4).getValue()
        var in_name = sheet.getRange(i,3).getValue().toString()
        var in_location = sheet.getRange(i,6).getValue().toString()
        
        // 一致していたらoutの時間を登録,カレンダーにも登録
        if (( in_date == date ) && ( in_name == user_name )) {
          
          sheet.getRange(i,5).setValue(Utilities.formatDate(datetime,"JST", "yyyy/MM/dd HH:mm:ss"))
          var startTime = new Date(in_datetime)
          var endTime = datetime
          var options = {
            location: in_location
          }
          calendar.createEvent(user_name, startTime, endTime, options)
          sheet.getRange(i,1).setValue("")
          break
          
        }
      }
    }
    var payload = {
      "text" : "\n" + message, // メッセージの本文
      "channel" : "#勤怠管理", // チャネルの指定
      "username" : "勤怠管理クマ", // Botの名前
      }
    postSlack(payload);
  }
  return
}

// Slackでレスポンスする関数
function postSlack(payload)
{
  var options = {
    "method" : "POST",
    "payload" : JSON.stringify(payload)
  }

  var url = "[Incoming webhookのURL]"; // Webhook URL
  var response = UrlFetchApp.fetch(url, options);
  var content = response.getContentText("UTF-8");

}

コピペしたらこちらを参考にアプリケーションのURLを取得し,Outgoingq webhookのURL欄に入力します.

急ぎで作ったので仕様として次のような欠陥がありますので,実装する際は注意してください.

  • 入室記録を忘れると退室記録をしても登録されない
  • 0時をまたぐ入退室記録に対応していない
  • Googleスプレッドシートの日付,開始時間,終了時間の見た目が頭悪そう

場所を指定するのに普通は@を使いますが,slackは"@"を入力するとメンションが入力されてしまい煩わしいので"_"を採用しました.
messageは所属するチームの雰囲気に合わせて調整してください.
user_idは,Slackのプロフィール欄からコピペできます.大人数のチームだと大変ですが,Outgoing webhookの仕様で名前を取得できないため,ひと手間かかります.

おわりに

最後まで読んでいただきありがとうございました.
質問やコメントお待ちしております.

以下のページを参考にしました.
Slackで簡単に勤怠管理!【GAS】

4
4
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
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?