Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
inc-meta/tools/slacktee/bin/slacktee.sh
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
executable file
608 lines (550 sloc)
16.1 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# ---------- | |
# Default Configuration | |
# ---------- | |
webhook_url="" # Incoming Webhooks integration URL | |
upload_token="" # The user's API authentication token, only used for file uploads | |
channel="general" # Default channel to post messages. '#' is prepended, if it doesn't start with '#' or '@'. | |
tmp_dir="/tmp" # Temporary file is created in this directory. | |
username="slacktee" # Default username to post messages. | |
icon="ghost" # Default emoji to post messages. Don't wrap it with ':'. See http://www.emoji-cheat-sheet.com; can be a url too. | |
attachment="" # Default color of the attachments. If an empty string is specified, the attachments are not used. | |
# ---------- | |
# Initialization | |
# ---------- | |
me=$(basename "$0") | |
title="" | |
mode="buffering" | |
link="" | |
textWrapper="\`\`\`" | |
parseMode="" | |
fields=() | |
# Since bash 3 doesn't support the associative array, we store colors and patterns separately | |
cond_color_colors=() | |
cond_color_patterns=() | |
found_pattern_color="" | |
# This color is used when 'attachment' is used without color specification | |
internal_default_color="#C0C0C0" | |
# Since bash 3 doesn't support the associative array, we store prefixes and patterns separately | |
cond_prefix_prefixes=() | |
cond_prefix_patterns=() | |
found_title_prefix="" | |
function show_help() | |
{ | |
echo "usage: $me [options]" | |
echo " options:" | |
echo " -h, --help Show this help." | |
echo " -n, --no-buffering Post input values without buffering." | |
echo " -f, --file Post input values as a file." | |
echo " -l, --link Add a URL link to the message." | |
echo " -c, --channel channel_name Post input values to specified channel or user." | |
echo " -u, --username user_name This username is used for posting." | |
echo " -i, --icon emoji_name|url This icon is used for posting. You can use a word" | |
echo " from http://www.emoji-cheat-sheet.com or a direct url to an image." | |
echo " -t, --title title_string This title is added to posts." | |
echo " -m, --message-formatting format Switch message formatting (none|link_names|full)." | |
echo " See https://api.slack.com/docs/formatting for more details." | |
echo " -p, --plain-text Don't surround the post with triple backticks." | |
echo " -a, --attachment [color] Use attachment (richly-formatted message)" | |
echo " Color can be 'good','warning','danger' or any hex color code (eg. #439FE0)" | |
echo " See https://api.slack.com/docs/attachments for more details." | |
echo " -e, --field title value Add a field to the attachment. You can specify this multiple times." | |
echo " -s, --short-field title value Add a short field to the attachment. You can specify this multiple times." | |
echo " -o, --cond-color color pattern Change the attachment color if the specified Regex pattern matches the input." | |
echo " You can specify this multile times." | |
echo " If more than one pattern matches, the latest matched pattern is used." | |
echo " -d, --cond-prefix prefix pattern This prefix is added to the message, if the specified Regex pattern matches the input." | |
echo " You can specify this multile times." | |
echo " If more than one pattern matches, the latest matched pattern is used." | |
echo " --config config_file Specify the location of the config file." | |
echo " --setup Setup slacktee interactively." | |
} | |
function send_message() | |
{ | |
message="$1" | |
# Prepend the prefix to the message, if it's set | |
if [[ -z $attachment && -n $found_pattern_prefix ]]; then | |
message="$found_pattern_prefix$message" | |
# Clear conditional prefix for the nest send | |
found_pattern_prefix="" | |
fi | |
escaped_message=$(echo "$textWrapper\n$message\n$textWrapper" | sed 's/"/\\"/g' | sed "s/'/\\'/g" ) | |
message_attr="" | |
if [[ $message != "" ]]; then | |
if [[ -n $attachment ]]; then | |
# Set message color | |
message_color="$attachment" | |
if [[ -n $found_pattern_color ]]; then | |
message_color="$found_pattern_color" | |
# Reset with the default color for the next send | |
found_pattern_color="$attachment" | |
fi | |
message_attr="\"attachments\": [{ \"color\": \"$message_color\", \"mrkdwn_in\": [\"text\", \"fields\"], \"text\": \"$escaped_message\" " | |
if [[ -n $found_pattern_prefix ]]; then | |
orig_title=$title | |
title="$found_pattern_prefix $title" | |
# Clear conditional prefix for the nest send | |
found_pattern_prefix="" | |
fi | |
if [[ -n $title ]]; then | |
message_attr="$message_attr, \"title\": \"$title\" " | |
# Clear conditional prefix from title | |
title=$orig_title | |
fi | |
if [[ -n $link ]]; then | |
message_attr="$message_attr, \"title_link\": \"$link\" " | |
fi | |
if [[ $mode == "file" ]]; then | |
fields+=("{\"title\": \"Access URL\", \"value\": \"$access_url\" }") | |
fields+=("{\"title\": \"Download URL\", \"value\": \"$download_url\"}") | |
fi | |
if [[ ${#fields[@]} != 0 ]]; then | |
message_attr="$message_attr, \"fields\": [" | |
for field in "${fields[@]}"; do | |
message_attr="$message_attr $field," | |
done | |
message_attr=${message_attr%?} # Remove last comma | |
message_attr="$message_attr ]" | |
fi | |
# Close attachment | |
message_attr="$message_attr }], " | |
else | |
message_attr="\"text\": \"$escaped_message\"," | |
fi | |
icon_url="$icon" | |
#icon_emoji="" | |
#if echo "$icon" | grep -q "^https\?://.*"; then | |
# icon_url="$icon" | |
#else | |
# icon_emoji=":$icon:" | |
#fi | |
json="{\"channel\": \"$channel\", \"username\": \"$username\", $message_attr \"icon_emoji\": \"$icon_emoji\", \"icon_url\": \"$icon_url\" $parseMode}" | |
post_result=$(curl -X POST --data-urlencode "payload=$json" "$webhook_url" 2> /dev/null) | |
exit_code=1 | |
if [[ $post_result == "ok" ]]; then | |
exit_code=0 | |
fi | |
fi | |
} | |
function process_line() | |
{ | |
echo "$1" | |
line="$(echo "$1" | sed $'s/\t/ /g')" | |
# Check the patterns of the conditional colors | |
# If more than one pattern matches, the latest pattern is used | |
if [[ ${#cond_color_patterns[@]} != 0 ]]; then | |
for i in "${!cond_color_patterns[@]}"; do | |
if [[ $line =~ ${cond_color_patterns[$i]} ]]; then | |
found_pattern_color=${cond_color_colors[$i]} | |
fi | |
done | |
fi | |
# Check the patterns of the conditional titles | |
# If more than one pattern matches, the latest pattern is used | |
if [[ ${#cond_prefix_patterns[@]} != 0 ]]; then | |
for i in "${!cond_prefix_patterns[@]}"; do | |
if [[ $line =~ ${cond_prefix_patterns[$i]} ]]; then | |
found_pattern_prefix=${cond_prefix_prefixes[$i]} | |
if [[ -n $attachment || $mode != "no-buffering" ]]; then | |
# Append a line break to the prefix for better formatting | |
found_pattern_prefix="$found_pattern_prefix\n" | |
else | |
# Append a space to the prefix for better formatting | |
found_pattern_prefix="$found_pattern_prefix " | |
fi | |
fi | |
done | |
fi | |
if [[ $mode == "no-buffering" ]]; then | |
prefix='' | |
if [[ -z $attachment ]]; then | |
prefix=$title | |
fi | |
send_message "$prefix$line" | |
elif [[ $mode == "file" ]]; then | |
echo "$line" >> "$filename" | |
else | |
if [[ -z "$text" ]]; then | |
text="$line" | |
else | |
text="$text\n$line" | |
fi | |
fi | |
} | |
function setup() | |
{ | |
if [[ -z "$HOME" ]]; then | |
echo "\$HOME is not defined. Please set it first." | |
exit 1 | |
fi | |
local_conf="$HOME/.slacktee" | |
if [[ -e "$local_conf" ]]; then | |
echo ".slacktee is found in your home directory." | |
read -p "Are you sure to overwrite it? [y/n] :" choice | |
case "$choice" in | |
y|Y ) | |
# Continue | |
;; | |
* ) | |
exit 0 # Abort | |
;; | |
esac | |
fi | |
# Load current local config | |
. $local_conf | |
# Start setup | |
read -p "Incoming Webhook URL [$webhook_url]: " input_webhook_url | |
if [[ -z "$input_webhook_url" ]]; then | |
input_webhook_url=$webhook_url | |
fi | |
read -p "Upload Token [$upload_token]: " input_upload_token | |
if [[ -z "$input_upload_token" ]]; then | |
input_upload_token=$upload_token | |
fi | |
read -p "Temporary Directory [$tmp_dir]: " input_tmp_dir | |
if [[ -z "$input_tmp_dir" ]]; then | |
input_tmp_dir=$tmp_dir | |
fi | |
read -p "Default Channel [$channel]: " input_channel | |
if [[ -z "$input_channel" ]]; then | |
input_channel=$channel | |
fi | |
read -p "Default Username [$username]: " input_username | |
if [[ -z "$input_username" ]]; then | |
input_username=$username | |
fi | |
read -p "Default Icon: [$icon]: " input_icon | |
if [[ -z "$input_icon" ]]; then | |
input_icon=$icon | |
fi | |
read -p "Default color of the attachment. (empty string disables attachment) [$attachment]: " input_attachment | |
if [[ -z "$input_attachment" ]]; then | |
input_attachment=$attachment | |
elif [[ $input_attachment == '""' || $input_attachment == "''" ]]; then | |
input_attachment="" | |
fi | |
cat <<- EOF | sed 's/^[[:space:]]*//' > "$local_conf" | |
webhook_url="$input_webhook_url" | |
upload_token="$input_upload_token" | |
tmp_dir="$input_tmp_dir" | |
channel="$input_channel" | |
username="$input_username" | |
icon="$input_icon" | |
attachment="$input_attachment" | |
EOF | |
} | |
# ---------- | |
# Parse command line options | |
# ---------- | |
OPTIND=1 | |
while [[ $# -gt 0 ]]; do | |
opt="$1" | |
shift | |
case "$opt" in | |
-h|\?|--help) | |
show_help | |
exit 0 | |
;; | |
-n|--no-buffering) | |
mode="no-buffering" | |
;; | |
-f|--file) | |
mode="file" | |
;; | |
-l|--link) | |
link="$1" | |
shift | |
;; | |
-c|--channel) | |
opt_channel="$1" | |
shift | |
;; | |
-u|--username) | |
opt_username="$1" | |
shift | |
;; | |
-i|--icon) | |
opt_icon="$1" | |
shift | |
;; | |
-t|--title) | |
title="$1" | |
shift | |
;; | |
-d|--cond-prefix) | |
case "$1" in | |
-*|'') | |
# Found next command line option or empty. Error. | |
echo "a prefix of the conditional title was not specified" | |
show_help | |
exit 1 | |
;; | |
*) | |
# Prefix should be found | |
case "$2" in | |
-*|'') | |
# Found next command line option or empty. Error. | |
echo "a pattern of the conditional title was not specified" | |
show_help | |
exit 1 | |
;; | |
*) | |
# Set the prefix and the pattern to arrays | |
cond_prefix_prefixes+=("$1") | |
cond_prefix_patterns+=("$2") | |
shift | |
shift | |
;; | |
esac | |
;; | |
esac | |
;; | |
-m|--message-formatting) | |
case "$1" in | |
none) | |
parseMode=', "parse": "none"' | |
;; | |
link_names) | |
parseMode=', "link_names": "1"' | |
;; | |
full) | |
parseMode=', "parse": "full"' | |
;; | |
*) | |
echo "unknown message formatting option" | |
show_help | |
exit 1 | |
;; | |
esac | |
shift | |
;; | |
-p|--plain-text) | |
textWrapper="" | |
;; | |
-a|--attachment) | |
case "$1" in | |
-*|'') | |
# Found next command line option | |
opt_attachment="$internal_default_color" # Use default color | |
;; | |
\#*|good|warning|danger) | |
# Found hex color code or predefined colors | |
opt_attachment="$1" | |
shift | |
;; | |
*) | |
echo "unknown attachment color" | |
show_help | |
exit 1 | |
;; | |
esac | |
;; | |
-o|--cond-color) | |
case "$1" in | |
-*|'') | |
# Found next command line option or empty. Error. | |
echo "a color of the conditional color was not specified" | |
show_help | |
exit 1 | |
;; | |
\#*|good|warning|danger) | |
# Found hex color code or predefined colors | |
case "$2" in | |
-*|'') | |
# Found next command line option or empty. Error. | |
echo "a pattern of the conditional color was not specified" | |
show_help | |
exit 1 | |
;; | |
*) | |
# Set the color and the pattern to arrays | |
cond_color_colors+=("$1") | |
cond_color_patterns+=("$2") | |
shift | |
shift | |
;; | |
esac | |
;; | |
*) | |
echo "unknown attachment color $1" | |
show_help | |
exit 1 | |
;; | |
esac | |
;; | |
-e|-s|--field|--short-field) | |
case "$1" in | |
-*|'') | |
# Found next command line option or empty. Error. | |
echo "field title was not specified" | |
show_help | |
exit 1 | |
;; | |
*) | |
case "$2" in | |
-*|'') | |
# Found next command line option or empty. Error. | |
echo "field value was not specified" | |
show_help | |
exit 1 | |
;; | |
*) | |
if [[ $opt == "-s" || $opt == "--short-field" ]]; then | |
fields+=("{\"title\": \"$1\", \"value\": \"$2\", \"short\": true}") | |
else | |
fields+=("{\"title\": \"$1\", \"value\": \"$2\"}") | |
fi | |
shift | |
shift | |
;; | |
esac | |
esac | |
;; | |
--config) | |
CUSTOM_CONFIG=$1 | |
shift | |
;; | |
--setup) | |
setup | |
exit 1 | |
;; | |
*) | |
echo "illegal option $opt" | |
show_help | |
exit 1 | |
;; | |
esac | |
done | |
# --------- | |
# Read in our configurations | |
# --------- | |
if [[ -e "/etc/slacktee.conf" ]]; then | |
. /etc/slacktee.conf | |
fi | |
if [[ -n "$HOME" && -e "$HOME/.slacktee" ]]; then | |
. "$HOME/.slacktee" | |
fi | |
if [[ -e "$CUSTOM_CONFIG" ]]; then | |
. $CUSTOM_CONFIG | |
fi | |
# Overwrite webhook_url if the environment variable SLACKTEE_WEBHOOK is set | |
if [[ "$SLACKTEE_WEBHOOK" != "" ]]; then | |
webhook_url="$SLACKTEE_WEBHOOK" | |
fi | |
# Overwrite upload_token if the environment variable SLACKTEE_TOKEN is set | |
if [[ "$SLACKTEE_TOKEN" != "" ]]; then | |
upload_token="$SLACKTEE_TOKEN" | |
fi | |
# Overwrite channel if it's specified in the command line option | |
if [[ "$opt_channel" != "" ]]; then | |
channel="$opt_channel" | |
fi | |
# Overwrite username if it's specified in the command line option | |
if [[ "$opt_username" != "" ]]; then | |
username="$opt_username" | |
fi | |
# Overwrite icon if it's specified in the command line option | |
if [[ "$opt_icon" != "" ]]; then | |
icon="$opt_icon" | |
fi | |
# Overwrite attachment if it's specified in the command line option | |
if [[ "$opt_attachment" != "" ]]; then | |
attachment="$opt_attachment" | |
fi | |
# Set the default color to attachment if it's still empty and the length of the cond_color_patterns is not 0 | |
if [[ -z $attachment ]] && [[ ${#cond_color_patterns[@]} != 0 ]]; then | |
attachment="$internal_default_color" | |
fi | |
# ---------- | |
# Validate configurations | |
# ---------- | |
if [[ $webhook_url == "" ]]; then | |
echo "Please setup the webhook url of this incoming webhook integration." | |
exit 1 | |
fi | |
if [[ $upload_token == "" && $mode == "file" ]]; then | |
echo "Please provide the authentication token for file uploads." | |
exit 1 | |
fi | |
if [[ $channel == "" ]]; then | |
echo "Please specify a channel." | |
exit 1 | |
elif [[ ( "$channel" != "#"* ) && ( "$channel" != "@"* ) ]]; then | |
channel="#$channel" | |
fi | |
if [[ -n "$icon" ]]; then | |
icon=${icon#:} # remove leading ':' | |
icon=${icon%:} # remove trailing ':' | |
fi | |
# ---------- | |
# Start script | |
# ---------- | |
text="" | |
if [[ -n "$title" || -n "$link" ]]; then | |
# Use link as title, if title is not specified | |
if [[ -z "$title" ]]; then | |
title="$link" | |
fi | |
# Add title to filename in the file mode | |
if [[ "$mode" == "file" ]]; then | |
filetitle=$(echo "$title"|sed 's/[ /:.]//g') | |
filetitle="$filetitle-" | |
fi | |
if [[ -z "$attachment" ]]; then | |
if [[ "$mode" == "no-buffering" ]]; then | |
if [[ -n "$link" ]]; then | |
title="<$link|$title>: " | |
else | |
title="$title: " | |
fi | |
elif [[ "$mode" == "file" ]]; then | |
if [[ -n "$link" ]]; then | |
title="<$link|$title>" | |
fi | |
else | |
if [[ -n "$link" ]]; then | |
text="-- <$link|$title> --\n" | |
else | |
text="-- $title --\n" | |
fi | |
fi | |
fi | |
fi | |
timestamp="$(date +'%m%d%Y-%H%M%S')" | |
filename="$tmp_dir/$filetitle$$-$timestamp.log" | |
if [[ "$mode" == "file" ]]; then | |
touch $filename | |
fi | |
exit_code=0 | |
while IFS='' read line; do | |
process_line "$line" | |
done | |
if [[ -n $line ]]; then | |
process_line "$line" | |
fi | |
if [[ "$mode" == "buffering" ]]; then | |
send_message "$text" | |
elif [[ "$mode" == "file" ]]; then | |
if [[ -s "$filename" ]]; then | |
channels_param="" | |
if [[ ( "$channel" == "#"* ) ]]; then | |
# Set channels for making the file public | |
channels_param="-F channels=$channel" | |
fi | |
result="$(curl -F file=@"$filename" -F token="$upload_token" $channels_param https://slack.com/api/files.upload 2> /dev/null)" | |
access_url="$(echo "$result" | awk 'match($0, /url_private":"([^"]*)"/) {print substr($0, RSTART+14, RLENGTH-15)}'|sed 's/\\//g')" | |
download_url="$(echo "$result" | awk 'match($0, /url_private_download":"([^"]*)"/) {print substr($0, RSTART+23, RLENGTH-24)}'|sed 's/\\//g')" | |
if [[ -n "$attachment" ]]; then | |
text="Input file has been uploaded" | |
else | |
if [[ "$title" != "" ]]; then | |
title=" of $title" | |
fi | |
text="Input file$title has been uploaded.\n$access_url\n\nYou can download it from the link below.\n$download_url" | |
fi | |
send_message "$text" | |
fi | |
# Clean up the temp file | |
rm "$filename" | |
fi | |
exit $exit_code |