Skip to content

Instantly share code, notes, and snippets.

@morganestes
Last active June 3, 2022 21:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save morganestes/242cb28d73fcff094e64e93f106906d2 to your computer and use it in GitHub Desktop.
Save morganestes/242cb28d73fcff094e64e93f106906d2 to your computer and use it in GitHub Desktop.
Download files uploaded to a Slack instance using data from a Slack JSON export file.
#!/bin/bash
#
# Parses Slack JSON exports for files and downloads them.
#
# Requires 'jq' (https://stedolan.github.io/jq/) and 'httpie' (https://httpie.org/).
#
##
# Checks for a single dependency.
#
# @param string DEP The function name to check.
##
function check_dep() {
local DEP="${1}"
local HAS_DEP
[ -z "${DEP}" ] && printf "No function name given to check.\n" && exit 0
printf "Checking for %s...\n" "${DEP}"
HAS_DEP="$(
type "${DEP}" >/dev/null 2>&1
echo $?
)"
if [ "${HAS_DEP}" -eq 1 ]; then
printf "%s not found.\n" "${DEP}"
exit 1
else
printf "%s found. Continuing...\n" "${DEP}"
fi
echo '----------------'
printf '\n'
}
##
# Checks the dependencies used for the script.
##
function check_deps() {
declare -A deps
deps["jq"]="https://stedolan.github.io/jq/"
deps["http"]="https://httpie.org/"
for dep in "${!deps[@]}"; do
check_dep "${dep}"
if [ "$?" -eq 1 ]; then
printf "%s missing. Download from %s and install before continuing.\n" "${dep}" "${deps[$dep]}"
fi
done
}
##
# Parses the Slack export JSON for uploaded files and downloads them to the current directory.
#
# @param string source_file Path to the Slack export JSON file.
##
function main() {
local source_file="${1}"
local link_count=0
declare links=()
local output_path # @todo Make this a parameter and configure it for httpie's --continue flag.
local session_file
local file_hash
check_deps
if [[ ! -f "${source_file}" ]]; then
printf "%s not found.\nPlease check the filename and try again.\n" "${source_file}"
exit 0
else
printf "Parsing %s for files to download...\n" "${source_file}"
fi
# Parse the JSON using jq, combining them into a list of URLs for uploaded files.
while read -r url; do
links+=("${url}")
done < <(
jq -rc '.[]?.subtype="file_share" |
[.[]?.files[]?.url_private_download] |
unique |
.[]' \
"${source_file}"
)
link_count="${#links[@]}"
if [[ "${link_count}" -gt 0 ]]; then
output_path="$(pwd)" # @todo make this a variable parameter.
file_hash="$(md5 -q "${source_file}")"
session_file="${output_path}/httpie-session-${file_hash}.json"
# this doesn't do anything yet, since we're alreay starting in an existing directory
mkdir -p "${output_path}"
printf "Downloading %d files to %s\nusing httpie session from %s\n" "$link_count" "${output_path}" "${session_file}"
echo '----------------'
printf '\n'
for link in "${links[@]}"; do
printf "\nTrying %s\n" "${link}"
if http --check-status --ignore-stdin --timeout=2.5 HEAD "${link}" &>/dev/null; then
http --session "${session_file}" --ignore-stdin -xbd "${link}"
else
case $? in
2) printf 'Request timed out!\n\n' ;;
3) printf 'Unexpected HTTP 3xx Redirection!\n\n' ;;
4) printf 'HTTP 4xx Client Error!\n\n' ;;
5) printf 'HTTP 5xx Server Error!\n\n' ;;
6) printf 'Exceeded --max-redirects=<n> redirects!\n\n' ;;
*) printf 'Other Error!\n\n' ;;
esac
fi
done
else
printf 'Nothing found to download.\n\n'
fi
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment