#!/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