Slack APIで「いいね!」リアクションを集計するシェルスクリプト
動機
社内でも利用しているチャットツールSlackで2015年7月9日からメッセージに絵文字リアクションがつけられるようになりました。
「Slack」に投票や参加表明に使える絵文字利用の新ツール「Emoji Reactions」 - ITmedia ニュース
絵文字リアクションを使ってお互いに「いいね!」というイイ感じの文化が生まれてきたので、さらなる活性化を目論んで、全員が参加するチャンネルで一番「いいね!」のリアクション(+1またはthumbsup)を獲得しているメッセージをSlack APIを使って集計して報告する仕組みをcron+シェルスクリプトで作ってみました。
準備
まず、Slack APIで使うトークンを以下のページから取得してきます。
また、集計するチャンネル・報告するチャンネルのIDが必要なので、以下のページからIDを確認します。
cron+シェルスクリプトを実行するLinuxマシンを用意します。以下のものをインストールします。curlとjqにパスが通っているか確認してください。
- cron
- curl
- jq
シェルスクリプト
以下のスクリプトをcronで一日一回実行するようにします。
#!/bin/bash
# 作業用の一時ファイル格納先を設定します
MY_WORKSPACE=/tmp
# 取得したトークンを設定します
MY_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 集計対象のチャンネルのID・名称を設定します
MY_CHANNEL=yyyyyyyyy
MY_CHANNEL_NAME=all
# 集計対象の期間はスクリプト実行時の前日になります
MY_DATE=$(date +"%Y年%m月%d日" --date "1 day ago")
MY_LATEST=$(date +"%s" --date "$(date +"%Y-%m-%d 00:00:00")")
MY_OLDEST=$(date +"%s" --date "$(date +"%Y-%m-%d 23:59:59" --date "2 day ago")")
# 集計結果を報告するチャンネルのIDを設定します
MY_POST_CHANNEL=zzzzzzzzz
# 前日のメッセージを取得してファイルに保存します
\rm -f ${MY_WORKSPACE}/my_history_${MY_CHANNEL_NAME}.json
curl -s -F token=${MY_TOKEN} -F channel=${MY_CHANNEL} -F latest=${MY_LATEST} -F oldest=${MY_OLDEST} https://slack.com/api/channels.history > ${MY_WORKSPACE}/my_history_${MY_CHANNEL_NAME}.json
# 変数初期化
MY_TOP_LINK=
MY_TOP_COUNT=0
while :
do
# 取得したメッセージごとに処理
for i in $(cat ${MY_WORKSPACE}/my_history_${MY_CHANNEL_NAME}.json | jq -r '.messages[].ts'); do
# APIの実行制限回避のために1秒スリープします
sleep 1
# メッセージのリアクションを取得してファイルに保存します
\rm -f ${MY_WORKSPACE}/my_reactions_get_${MY_CHANNEL_NAME}.json
curl -s -F token=${MY_TOKEN} -F channel=${MY_CHANNEL} -F timestamp=${i} https://slack.com/api/reactions.get > ${MY_WORKSPACE}/my_reactions_get_${MY_CHANNEL_NAME}.json
# リアクションから:+1:または:thumbsup:の数を取得します
MY_TMP_COUNT=
MY_TMP_COUNT=$(cat ${MY_WORKSPACE}/my_reactions_get_${MY_CHANNEL_NAME}.json | jq '.message | select(has("reactions")).reactions[] | select(.name=="+1" or .name=="thumbsup").count')
# 最大数を更新します
if test -n "${MY_TMP_COUNT}" ; then
if test ${MY_TMP_COUNT} -gt 0 -a ${MY_TOP_COUNT} -lt ${MY_TMP_COUNT} ; then
MY_TOP_LINK=$(cat my_reactions_get_${MY_CHANNEL_NAME}.json | jq -r '.message.permalink')
MY_TOP_COUNT=${MY_TMP_COUNT}
elif test ${MY_TMP_COUNT} -gt 0 -a ${MY_TOP_COUNT} -eq ${MY_TMP_COUNT} ; then
MY_TOP_LINK="${MY_TOP_LINK}
$(cat ${MY_WORKSPACE}/my_reactions_get_${MY_CHANNEL_NAME}.json | jq -r '.message.permalink')"
fi
fi
done
# メッセージに続きがなければ終了します
if test "$(cat ${MY_WORKSPACE}/my_history_${MY_CHANNEL_NAME}.json | jq '.has_more')" != "true" ; then
break
fi
# メッセージに続きがあれば続きを取得します
MY_TMP_OLDEST=$(cat ${MY_WORKSPACE}/my_history_${MY_CHANNEL_NAME}.json | jq -r '.messages[].ts' | tail -n1)
\rm -f my_history.json
curl -s -F token=${MY_TOKEN} -F channel=${MY_CHANNEL} -F latest=${MY_TMP_OLDEST} -F oldest=${MY_OLDEST} https://slack.com/api/channels.history > ${MY_WORKSPACE}/my_history_${MY_CHANNEL_NAME}.json
done
# 報告するメッセージをファイルに準備します
\rm -f ${MY_WORKSPACE}/my_post_message_${MY_CHANNEL_NAME}.txt
if test ${MY_TOP_COUNT} -gt 0 ; then
echo "${MY_DATE}のベスト:+1:獲得数 in #${MY_CHANNEL_NAME}: ${MY_TOP_COUNT}
${MY_TOP_LINK}" > ${MY_WORKSPACE}/my_post_message_${MY_CHANNEL_NAME}.txt
else
echo "${MY_DATE}のベスト:+1:獲得数 in #${MY_CHANNEL_NAME}: 0" > ${MY_WORKSPACE}/my_post_message_${MY_CHANNEL_NAME}.txt
fi
# 報告するメッセージを送信します
curl -s --data-urlencode token=${MY_TOKEN} --data-urlencode channel=${MY_POST_CHANNEL} --data-urlencode text@${MY_WORKSPACE}/my_post_message_${MY_CHANNEL_NAME}.txt --data-urlencode username=reaction_report --data-urlencode as_user=false --data-urlencode icon_emoji=:+1: --data-urlencode unfurl_links=true https://slack.com/api/chat.postMessage >/dev/null 2>&1
実行結果
報告メッセージがこんな感じになります。
注意点
メッセージごとにリアクションを取得するAPIを実行するので、メッセージ数が多くなると集計が遅くなるのと、APIの実行制限(1リクエスト/秒)にひっかかりやすくなるのでご注意ください。