KING OF TIMEで打刻をしたらSlackで自動的にリアクションをするChrome拡張を作ってみた

2020.06.25

こんにちは、CX事業本部の若槻です。

今回は、KING OF TIMEで出勤/退勤ボタンをクリック(打刻)したらSlackでメッセージにスタンプを自動で押す(リアクションする)Chrome拡張を作ってみたのでご紹介します。

背景

次の記事でも紹介されている通り、弊社では勤怠管理システムとしてKING OF TIME(KoT)を導入しています。

そのため日々の業務開始時および終了時に次のようなレコーダー画面で[出勤]および[退勤]ボタンをクリック(打刻)して勤怠を記録しています。 スクリーンショット 2020-06-24 22.06.37.png

加えて、私が所属しているチームでは、Slackに毎日投稿される次のようなメッセージにリモートワーク開始時および終了時にりも開およびりも終スタンプで報告をするルールとなっています。(誰がいつ何のスタンプを押したかはスレッドに自動で追加される)

スクリーンショット 2020-06-24 22.10.21.png

このルールによりメンバーのうち誰がいつリモートワークをしているのかチーム内で把握できるので便利なのですが、現在の状況下だと当分のあいだは原則的にリモートワークによる勤務であるためKoTとSlackの両方での出退勤時のルーチンが手間というのがありました。

これらを両方まとめてドーンと出来る方法がないか調べてみると、先人がAWS IoT Buttonを使ってKoTでの打刻とSlackでの報告をLambda上で実装していました。

しかし、LambdaにSelenium+Headlessブラウザによる処理を乗せるのは実装が重い、IoT Button持ってない、処理失敗に気づきにくい…等の理由により、この方法は断念しました。

そこで更に良い方法がないか調べてみたところ、KoTでの打刻時にSlack APIを叩くChrome拡張を作るのが良さそう!となり今回のChrome拡張の作成に至りました。

作ったもの

下記の2ファイルから成るGoogle Chrome拡張です。

script.js

// Slack AppのOAuth Access Tokenを指定
const slack_app_token = 'xoxp-0123456789-012345678901-012345678901-012345xxxxxx678901xxxxxx012345xxxxxx678901xxxxxx'

// Reaction対象のメッセージを検索するQueryを定義
search_word = 'Reminder: :rimokai: :rimoshu: はこのスレで!'
channel = '<チャネル名>'
from = 'slackbot'
encoded_query = encodeURI(`${search_word} in:${channel} from:${from}`)

// Reactionでスタンプする絵文字を定義
emoji_in = 'rimokai'
emoji_out = 'rimoshu'

// Reaction対象のメッセージのchannelのIDを定義
channel_id = '<チャネルID>'

// 最新のReminderメッセージにrimokai/rimoshuをReactionする
function reaction_to_reminder(emoji_name){

    // Slack API(search.messages)のURIを定義(Queryにヒットするtimestampが最新のメッセージを1つ取得する)
    var search_uri = `https://slack.com/api/search.messages?\
      token=${slack_app_token}&\
      query=${encoded_query}&\
      sort=timestamp&\
      sort_dir=desc&\
      count=1`;

    // Reaction対象のメッセージのtsをSlackから取得
    fetch(search_uri)
    .then(function(response) {
      return response.json();
    })
    .then(function(myJson) {
      var json = JSON.parse(JSON.stringify(myJson))
      var ts = json.messages.matches[0].ts;

      // Slack API(reactions.add)のURIを定義
      var reaction_uri = `https://slack.com/api/reactions.add?\
        token=${slack_app_token}&\
        channel=${channel_id}&\
        name=${emoji_name}&\
        timestamp=${ts}`;

      // Reactionの実行
      fetch(reaction_uri);

    window.alert(`メッセージ"${ts}"に"${emoji_name}"がリアクションされました。`);
    });
}

// KoTのタイムレコーダーページでイベントリスナーを設定
function set_event_listener(){

    // 出勤ボタンに reaction_to_reminder('rimokai') を設定
    var syukkin_elem = document.getElementsByClassName('record-btn-inner record-clock-in');
    syukkin_elem[0].addEventListener('click', function(){reaction_to_reminder(emoji_in)}, false);

    // 退勤ボタンに reaction_to_reminder('rimoshu') を設定
    var taikin_elem = document.getElementsByClassName('record-btn-inner record-clock-out');
    taikin_elem[0].addEventListener('click', function(){reaction_to_reminder(emoji_out)}, false);

    window.alert(`打刻すると${channel}チャネルのReminderメッセージに"${emoji_in}"/"${emoji_out}"がリアクションされます。`);
};

// ボタンパーツの読み込みを1秒待つ
setTimeout("set_event_listener()", 1000);

manifest.json

{
    "name": "slackot",
    "short_name": "slackot",
    "version": "1.0",
    "manifest_version": 2,

    "content_scripts": [
        {
            "matches": [ "https://s2.kingtime.jp/independent/recorder/personal/" ],
            "js": [ "script.js" ]
        }
    ]
}

ファイルの内容の説明

script.js

  • Functionreaction_to_reminder(emoji_name)により、リアクション先のメッセージの検索(Queryに一致、Timestampが最新)と、スタンプによるリアクションを行っている。
  • Functionset_event_listener()により、KoTのレコーダー画面上の出勤ボタンと退勤ボタンにクリックでreaction_to_reminder(emoji_name)が発火するリスナーを設定している。
  • setTimeout("set_event_listener()", 1000)により、出勤/退勤ボタンがDOMに読み込まれてからリスナーを設定するようにしている。

manifest.json

  • KoTのレコーダー画面(https://s2.kingtime.jp/independent/recorder/personal/)でのみChrome拡張が有効になるようにしている。

使い方

設定

  1. 次の記事を参考に、search.messagesreactions.addのSlack APIを使用可能なAppをSlackワークスペース上に作成します。
  2. 端末ローカルで任意の名前のディレクトリを作成し、前述のscript.jsmanifest.jsonの2ファイルを配置します。
  3. script.jsを以下の要領で編集して変数を指定します。
    • 2行目slack_app_token:手順1で作成したAppのOAuth Access Tokenを指定
    • 5行目search_word:リアクションするメッセージを検索するワードを指定
    • 6行目channel:リアクションするメッセージが投稿されているチャネル名を指定
    • 7行目from:リアクションするメッセージを投稿したユーザー名を指定
    • 11行目emoji_in:出勤時にリアクションするスタンプ名を指定
    • 12行目emoji_out:退勤時にリアクションするスタンプ名を指定
    • 15行目channel_id:リアクションするメッセージが投稿されているチャネルIDを指定
  4. Google Chromeでchrome://extensions/にアクセスし、デベロッパーモードを有効にし、[パッケージ化されていない拡張機能を読み込む]をクリック。 スクリーンショット 2020-06-25 0.25.00.png
  5. 作成したファイルを選んで[選択]。 スクリーンショット 2020-06-25 0.27.23.png
  6. 拡張機能として以下のように追加されたら設定は完了です。 スクリーンショット 2020-06-25 0.34.52.png

使ってみる

Slackにbotで投稿されている次のメッセージが本日のリモートワーク開始/終了時にリアクションによる報告が必要なメッセージとなります。
スクリーンショット 2020-06-24 21.46.27.png

KoTのレコーダー画面(https://s2.kingtime.jp/independent/recorder/personal/)を開くと、次のようにボタンにリスナーを設定した旨のダイアログが出ます。[OK]をクリックします。 8cc72eea-c46e-43eb-8b0c-26c6fbd3e672.png

退勤ボタンをクリックします。 スクリーンショット 2020-06-24 21.45.08.png

メッセージにリアクションした旨のダイアログが出ます。[OK]をクリックします。 e7ba9b08-d179-4e58-ac33-ebcd9da51ae8.png

Slack側でメッセージを見るとユーザー自身により指定のスタンプがリアクションされていることが確認できます。
スクリーンショット 2020-06-24 21.49.33.png

おわりに

KING OF TIMEで出勤/退勤ボタンをクリック(打刻)したらSlackでメッセージにスタンプを自動で押す(リアクションする)Chrome拡張を作ってみました。

今回初めてChrome拡張を作りましたが案外かんたんなことが分かったので今後も色々作ってみたいです。

参考

以上