#!/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 error_exit() { cat - >&2 echo 'bash -c "exit $1"' exit $1 } # 変数の初期化 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"]' RESPONSE=$(curl -s -X GET -H 'Authorization: Bearer '"${API_TOKEN}" "https://slack.com/api/channels.history?channel=$(last_channel)&latest=$(last_ts)&inclusive=true&count=1") jq -ne "${RESPONSE}"' | .ok == true' >/dev/null || echo Failed get last message from slack: "${RESPONSE}" | error_exit 2 jq -nscM "${RESPONSE} | .messages[0]" } last_permalink() { RESPONSE=$(curl -s -X GET -H 'Authorization: Bearer '"${API_TOKEN}" "https://slack.com/api/chat.getPermalink?channel=$(last_channel)&message_ts=$(last_ts)") jq -ne "${RESPONSE}"' | .ok == true' >/dev/null || echo Failed get last message from slack: "${RESPONSE}" | error_exit 2 jq -nscMr "${RESPONSE} | .permalink" } 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. | error_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}" | error_exit 2 exit 0 elif [ "${1}" = "--reply" ]; then MODE="${1}" LAST_RESPONSE="${2}" shift 2 # チャンネルとボット名をレスポンスから引っ張る BOT_NAME="$(jq -ncMr "${LAST_RESPONSE}"' | .["message"]["username"]')" CHANNEL="$(last_channel)" elif [ "${1}" = "--permalink" ]; then MODE="${1}" LAST_RESPONSE="${2}" shift 2 RES="$(last_permalink)" RET=$? echo "$RES" exit $RET 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. | error_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}" | error_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() { /bin/bash "${SCRIPT_PATH}" --update "\${SLACK_SH_LAST_POST_RESPONSE}" \$* } slack_append_to_message() { /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 $? } slack_permalink() { /bin/bash "${SCRIPT_PATH}" --permalink "\${SLACK_SH_LAST_POST_RESPONSE}" \$* } EOD echo 'bash -c "exit 0"' exit 0