#!/usr/bin/env bash
# Get channel history for a Slack channel
# 
# Copyright (C) 2015 Kolbe Kegel <kolbe@kolbekegel.com>
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

# this script gets channel history from a Slack channel. give the channel nae as an argument.
# you need to also have the slack_fetch_list script available, so that it can fetch lists
# of users and channels to map your channel name to a channel ID and then map user IDs back to
# nicknames
# 
# you must define and export SLACK_API_TOKEN in your shell's environment. get a token here: https://api.slack.com/web
# you must have jq installed: http://stedolan.github.io/jq/

usage() {
    printf "Usage: [SLACK_API_TOKEN=<token>] %s <channel_name>\n" "$0"
}

abort() {
    printf "[ERROR]: %s. Aborting.\n" "$1" >&2
    [[ $- = *i* ]] || exit 1
    return 1 
}

(($# == 1)) || abort "$(usage)"

channel_name=$1
channel_name="${channel_name#*#}"
shift

[[ $SLACK_API_TOKEN ]] || abort "you must define and export SLACK_API_TOKEN before executing $0"

type jq &>/dev/null || abort "you don't appear to have the jq tool: http://stedolan.github.io/jq/"

# check environment for slack_users_list. if you source the slack_users_list script 
# in your shell, it'll save the user list in your environment and save having 
# to fetch it again every time you execute *this* script
if [[ -z $slack_users_list ]]; then
    slack_users_list=$(slack_fetch_list users) || abort "couldn't fetch users list"
else
    echo "[INFO]: using slack_users_list from environment." >&2
fi

# check environment for slack_channels_list. if you source the slack_channels_list script 
# in your shell, it'll save the user list in your environment and save having 
# to fetch it again every time you execute *this* script
if [[ -z $slack_channels_list ]]; then
    slack_channels_list=$(slack_fetch_list channels) || abort "couldn't fetch channels list"
else
    echo "[INFO]: using slack_channels_list from environment." >&2
fi

declare -A slack_users
while IFS=: read -r id name; do 
    slack_users[$id]=$name
done <<<"$slack_users_list"

declare -A slack_channels
while IFS=: read -r name id; do 
    slack_channels[$name]=$id
done <<<"$slack_channels_list"

declare -A slack_reverse_channels
for cname in "${!slack_channels[@]}"; do
    cid=${slack_channels["$cname"]}
    slack_reverse_channels["$cid"]=$cname
done

[[ ${slack_channels[$channel_name]} ]] || abort "couldn't resolve channel name '$channel_name' to channel id"

#echo "[INFO]: $channel_name is ${slack_channels[$channel_name]}" >&2

count=100

curl --silent "https://slack.com/api/channels.history?token=${SLACK_API_TOKEN}&channel=${slack_channels[$channel_name]}&count=$count" | 
jq -e -r '.messages | sort_by(.ts) | .[] | .ts+"\t<"+(.user//.username)+(if .subtype=="bot_message" then "(bot)" else "" end)+"> "+.text+"\u0000"' | 
{ 
    user_re='U[0-9A-Z]{8}'
    channel_re='<#(C[0-9A-Z]{8})>'
    while IFS=$'\t' read -r -d '' ts ln; do 
        while [[ $ln =~ $user_re ]]; do 
            for m in "${BASH_REMATCH[@]}"; do 
                v=${slack_users["$m"]}
                ln=${ln//$m/$v}
            done
        done
        while [[ $ln =~ $channel_re ]]; do
            #for m in "${BASH_REMATCH[@]}"; do
                m=${BASH_REMATCH[0]}
                c=${BASH_REMATCH[1]}
                v="#${slack_reverse_channels["$c"]}"
                ln=${ln//$m/$v}
            #done
        done
        printf "%(%m/%d %H:%S)T %s\n" "${ts%.*}" "$ln"
    done

}
