#!/bin/bash API_TOKEN="!!! set api token here !!!" set -u -e usage_exit() { cat <<EOD 1>&2 Usage: eval "\$(${0} [-u bot_name] [-c channel] [-m message | -f message_filename | -j json_filename])" Wrapper mode: ${0} [-u bot_name] [-c channel] -w -- command [arguments...] Append to post: slack_append_to_message [-m message | -f message_filename | -q jq_command] Update post with jq: slack_update_message [-q jq_command] ---- Samples ---- 単純なテキストを投稿する eval "\$(${0} -m "test" -c "#general")" 投稿したテキストに追記する echo test | slack_append_to_message -f - attachmentsの色を赤くする slack_update_message -q '.["attachments"][0]["color"]="#ff0000"' 実行中のファイル名、引数、日時、ホスト名を投稿する eval "\$((echo "\$(cd \$(dirname \$0); pwd)/\$(basename \$0) \$*"; echo \$(date "+%Y/%m/%d")" "\$(date "+%H:%M:%S"); hostname) | ${0} -f - -u "\$(hostname)" -c "#general")" EOD exit 1 } if [ $# -eq 0 ]; then usage_exit fi # 変数の初期化 ATTACHMENT=1 MODE= BOT_NAME= CHANNEL= MESSAGE= JSON= # 内部モード last_channel() { jq -ncMr "${LAST_RESPONSE}"' | .["channel"]' } last_ts() { jq -ncM "${LAST_RESPONSE}"' | .["ts"]' } last_message() { jq -ncM "${LAST_RESPONSE}"' | .["message"]' } if [ "${1}" = "--append" ]; then MODE="${1}" LAST_RESPONSE="${2}" shift 2 # 引数をパースする MESSAGE= while getopts m:f: OPT do case $OPT in m) MESSAGE="$(echo -n "${OPTARG}" | jq -RscM .)" ;; f) MESSAGE="$(cat "${OPTARG}" | jq -RscM .)" ;; esac done shift $((OPTIND - 1)) if [ -z "${MESSAGE}" ]; then echo No message specified. >&2 echo 'bash -c "exit 1"' exit 1 fi QUERY='.["attachments"][0]["text"]+='"${MESSAGE}" # 更新する /bin/bash ${0} --update "${LAST_RESPONSE}" -q "${QUERY}" exit $? elif [ "${1}" = "--update" ]; then MODE="${1}" LAST_RESPONSE="${2}" shift 2 # 引数をパースする while getopts q: OPT do case $OPT in q) JSON="$(jq -nscM "$(last_message) | ${OPTARG}")" ;; esac done shift $((OPTIND - 1)) # 更新する REQUEST_JSON=$(jq -ncM --arg channel "$(last_channel)" --arg ts "$(last_ts)" "${JSON}"' | .["ts"]=$ts | .["channel"]=$channel') #echo -n "${REQUEST_JSON}" | jq . 1>&2; exit 1 RESPONSE=$(echo -n "${REQUEST_JSON}" | curl -s -X POST -H 'Content-Type: application/json; charset=utf8' -H 'Authorization: Bearer '"${API_TOKEN}" --data @- 'https://slack.com/api/chat.update') jq -ne "${RESPONSE}"' | .ok == true' >/dev/null || (echo Failed post message to slack: "${RESPONSE}}," >&2; echo 'bash -c "exit 2"'; exit 2) echo 'SLACK_SH_LAST_POST_RESPONSE='"'${RESPONSE}'" echo 'bash -c "exit 0"' exit 0 elif [ "${1}" = "--reply" ]; then MODE="${1}" LAST_RESPONSE="${2}" shift 2 # チャンネルとボット名をレスポンスから引っ張る BOT_NAME="$(jq -ncMr "${LAST_RESPONSE}"' | .["message"]["username"]')" CHANNEL="$(last_channel)" fi # 初期モード # 引数をパースする while getopts u:c:m:f:j:hw OPT do case $OPT in u) BOT_NAME=$OPTARG ;; c) CHANNEL=$OPTARG ;; m) MESSAGE="$(echo -n "${OPTARG}" | jq -RscM .)" ;; f) MESSAGE="$(cat "${OPTARG}" | jq -RscM .)" ;; j) JSON="$(cat "{$OPTARG}" | jq -scM .)" ;; h) usage_exit ;; w) # Wrapper mode set +u ARGS= while [ -n "$1" ]; do if [ "$1" = "-w" ]; then : fi if [ "$1" = "--" ]; then shift break fi ARGS="${ARGS} ${1}" shift done COMMAND= while [ -n "$1" ]; do COMMAND="${COMMAND} "'"'"${1}"'"' shift done set -u MESSAGE=$(echo $(date "+%Y/%m/%d")" "$(date "+%H:%M:%S"); hostname; echo "${COMMAND}") eval "$(echo "${MESSAGE}" | /bin/bash slack.sh -f - ${ARGS})" slack_update_message -q '.["attachments"][0]["color"]="#fff0c1"' set +e OUT=$(eval ${COMMAND} 2>&1) RET=$? set -e if [ "$RET" -eq 0 ]; then slack_update_message -q '.["attachments"][0]["color"]="#00ff00"' else slack_update_message -q '.["attachments"][0]["color"]="#ff0000"' fi if [ -n "${OUT}" ]; then echo -n "${OUT}" | slack_reply -f - fi exit $RET ;; esac done shift $((OPTIND - 1)) if [ -z "$JSON" ]; then # 本文をJSONに入れる if [ -z "${MESSAGE}" ]; then echo No message specified. >&2 echo 'bash -c "exit 1"' exit 1 fi JSON_TEMPLATE='{"channel": "#general", "attachments":[{"text":$msg}]}'; if [ ${ATTACHMENT} -eq 0 ]; then JSON_TEMPLATE='{"channel": "#general", "text":$msg}'; fi JSON=$(jq -ncM --argjson msg "${MESSAGE}" "${JSON_TEMPLATE}") fi # ユーザー名 if [ -n "${BOT_NAME}" ]; then JSON=$(jq -ncM --argjson username "$(echo -n "${BOT_NAME}" | jq -RscM .)" "${JSON}"' | .["username"]=$username') fi # チャンネル if [ -n "${CHANNEL}" ]; then JSON=$(jq -ncM --argjson channel "$(echo -n "${CHANNEL}" | jq -RscM .)" "${JSON}"' | .["channel"]=$channel') fi # reply if [ "$MODE" = "--reply" ]; then JSON=$(jq -ncM --argjson thread_ts "$(last_ts)" "${JSON}"' | .["thread_ts"]=$thread_ts') fi # POSTする #jq -n "${JSON}" 1>&2; exit 1 RESPONSE=$(jq -ncM "$JSON" | curl -s -X POST -H 'Content-Type: application/json; charset=utf-8' -H 'Authorization: Bearer '"${API_TOKEN}" --data @- 'https://slack.com/api/chat.postMessage') jq -ne "${RESPONSE}"' | .ok == true' >/dev/null || (echo Failed post message to slack: "${RESPONSE}" >&2; echo 'bash -c "exit 2"'; exit 2) # 更新用の設定を出力する echo 'SLACK_SH_LAST_POST_RESPONSE='"'$(jq -ncM "${RESPONSE}")'" # 更新用の関数を定義する SCRIPT_PATH="$(cd $(dirname $0); pwd)/$(basename $0)" cat <<'EOD' slack_view_last_response() { jq -n "${SLACK_SH_LAST_POST_RESPONSE}" } EOD cat <<EOD slack_update_message() { eval "\$(/bin/bash "${SCRIPT_PATH}" --update "\${SLACK_SH_LAST_POST_RESPONSE}" \$*)" } slack_append_to_message() { eval "\$(/bin/bash "${SCRIPT_PATH}" --append "\${SLACK_SH_LAST_POST_RESPONSE}" \$*)" } slack_reply() { /bin/bash "${SCRIPT_PATH}" --reply "\${SLACK_SH_LAST_POST_RESPONSE}" \$* >/dev/null return $? } EOD echo 'bash -c "exit 0"' exit 0