Last active
October 5, 2019 22:29
-
-
Save deverton/e0a404a1c64bf9c24f8b207e458aa4da to your computer and use it in GitHub Desktop.
Download All Humble Bundle Packages and Trove
This file contains hidden or 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
#!/bin/bash | |
# TODO: Generate md5sums file to verify quicker | |
## | |
# Script to download everything you own from Humble Bundle. | |
# Writes to the current directory in folders named after the | |
# internal bundle name and product type. For example, Humble | |
# Bundle 1 product Aquaria would be under `hib1/aquarria`. | |
# | |
# Hard coded to skip other platforms than Windows but easy enough | |
# to change. | |
## | |
# Value of _simpleauth_sess cookie. | |
# Get this from your browser after logging in | |
# Remeber to include the " in the cookie value | |
AUTH='' | |
API_BASE="https://www.humblebundle.com/api/v1" | |
hb_get() { | |
curl $1 \ | |
--header 'Accept: application/json' \ | |
--cookie "_simpleauth_sess=${AUTH}" \ | |
$2 | |
} | |
download_link() { | |
hb_get "-s -X POST -d machine_name=$1 -d filename=$2" "${API_BASE}/user/download/sign" | jq -r '.signed_url' | |
} | |
rm md5sums | |
# Handle Trove | |
for page in {0..10}; do | |
echo -e "Processing trove page [${page}]:" | |
while read -r trove_json; do | |
TROVE_NAME=$(echo "${trove_json}" | jq -r '."human-name"') | |
TROVE_ITEM=$(echo "${trove_json}" | jq -r '.machine_name') | |
echo -e "\tProcessing trove item [${TROVE_NAME}]:" | |
# Windows only for now | |
TROVE_MACHINE_NAME=$(echo "${trove_json}" | jq -r '.downloads.windows.machine_name') | |
TROVE_FILE=$(echo "${trove_json}" | jq -r '.downloads.windows.url.web') | |
TROVE_SIZE=$(echo "${trove_json}" | jq -r '.downloads.windows.file_size') | |
TROVE_MD5=$(echo "${trove_json}" | jq -r '.downloads.windows.md5') | |
LOCAL_PATH="trove/${TROVE_ITEM}/windows/${TROVE_FILE}" | |
echo -n -e "\t\tFound download [${TROVE_MACHINE_NAME}] [windows] [${TROVE_FILE}] " | |
echo "${TROVE_MD5} *${LOCAL_PATH}" >> md5sums | |
DOWNLOAD_FILE_SIZE=$(stat --printf="%s" "${LOCAL_PATH}" 2> /dev/null || echo "0") | |
if [[ ! -f "${LOCAL_PATH}" ]] || [[ "${DOWNLOAD_FILE_SIZE}" != "${TROVE_SIZE}" ]]; then | |
echo "downloading " | |
TROVE_URL=$(download_link "${TROVE_MACHINE_NAME}" "${TROVE_FILE}") | |
hb_get "-# -o ${LOCAL_PATH} --create-dirs -C -" "${TROVE_URL}" | |
DOWNLOAD_FILE_MD5=$(md5sum "${LOCAL_PATH}" | cut -d ' ' -f 1) | |
if [[ "${DOWNLOAD_FILE_MD5}" == "${TROVE_MD5}" ]]; then | |
echo "matched MD5." | |
else | |
echo "ERROR MD5 does not match!" | |
fi | |
elif [[ "${DOWNLOAD_FILE_SIZE}" == "${TROVE_SIZE}" ]]; then | |
echo "matched expected file size." | |
else | |
echo "ERROR file size does not match!" | |
fi | |
done < <(hb_get -s "${API_BASE}/trove/chunk?index=${page}" | jq -rc '.[]') | |
done | |
## Handle Bundles | |
for gamekey in $(hb_get -s "${API_BASE}/user/order?ajax=true" | jq -r '.[].gamekey' | sort); do | |
BUNDLE_JSON=$(hb_get -s "${API_BASE}/order/${gamekey}?all_tpkds=true") | |
BUNDLE_NAME=$(echo "${BUNDLE_JSON}" | jq -r '.product.human_name') | |
BUNDLE_MACHINE_NAME=$(echo "${BUNDLE_JSON}" | jq -r '.product.machine_name') | |
echo "Processing bundle [${BUNDLE_NAME}]:" | |
for product in $(echo "${BUNDLE_JSON}" | jq -S -r '.subproducts[].machine_name' | sort); do | |
PRODUCT_JSON=$(echo "${BUNDLE_JSON}" | jq -r --arg machine_name "${product}" '.subproducts[] | select(.machine_name == $machine_name)') | |
PRODUCT_NAME=$(echo "${PRODUCT_JSON}" | jq -r '.human_name') | |
echo -e "\tProcessing product [${PRODUCT_NAME}]:" | |
for download in $(echo "${PRODUCT_JSON}" | jq -r '.downloads[].machine_name' | sort); do | |
DOWNLOAD_JSON=$(echo "${PRODUCT_JSON}" | jq -r --arg machine_name "${download}" '.downloads[] | select(.machine_name == $machine_name)') | |
DOWNLOAD_PLATFORM=$(echo "${DOWNLOAD_JSON}" | jq -r '.platform') | |
if [[ "android" == "${DOWNLOAD_PLATFORM}" ]]; then | |
continue | |
fi | |
if [[ "asmjs" == "${DOWNLOAD_PLATFORM}" ]]; then | |
continue | |
fi | |
if [[ "mac" == "${DOWNLOAD_PLATFORM}" ]]; then | |
continue | |
fi | |
if [[ "linux" == "${DOWNLOAD_PLATFORM}" ]]; then | |
continue | |
fi | |
DS=$(echo "${DOWNLOAD_JSON}" | jq -r '.download_struct | length') | |
for ((i=0;i<DS;i++)); do | |
DOWNLOAD_NAME=$(echo "${DOWNLOAD_JSON}" | jq -r --argjson index $i '.download_struct[$index].name') | |
DOWNLOAD_URL=$(echo "${DOWNLOAD_JSON}" | jq -r --argjson index $i '.download_struct[$index].url.web') | |
DOWNLOAD_SIZE=$(echo "${DOWNLOAD_JSON}" | jq -r --argjson index $i '.download_struct[$index].file_size') | |
DOWNLOAD_MD5=$(echo "${DOWNLOAD_JSON}" | jq -r --argjson index $i '.download_struct[$index].md5') | |
DOWNLOAD_FILE=$(echo "${DOWNLOAD_URL}" | cut -d '/' -f 4- | cut -d '?' -f 1) | |
LOCAL_PATH="${BUNDLE_MACHINE_NAME}/${product}/${DOWNLOAD_PLATFORM}/${DOWNLOAD_FILE}" | |
if [[ "null" == "${DOWNLOAD_SIZE}" ]]; then | |
continue | |
fi | |
echo -n -e "\t\tFound download [${DOWNLOAD_NAME}] [${DOWNLOAD_PLATFORM}] [${DOWNLOAD_FILE}] " | |
echo "${DOWNLOAD_MD5} *${LOCAL_PATH}" >> md5sums | |
DOWNLOAD_FILE_SIZE=$(stat --printf="%s" "${LOCAL_PATH}" 2> /dev/null || echo "0") | |
if [[ ! -f "${LOCAL_PATH}" ]] || [[ "${DOWNLOAD_FILE_SIZE}" != "${DOWNLOAD_SIZE}" ]]; then | |
echo "downloading " | |
hb_get "-# -o ${LOCAL_PATH} --create-dirs -C -" "${DOWNLOAD_URL}" | |
DOWNLOAD_FILE_MD5=$(md5sum "${LOCAL_PATH}" | cut -d ' ' -f 1) | |
if [[ "${DOWNLOAD_FILE_MD5}" == "${DOWNLOAD_MD5}" ]]; then | |
echo "matched MD5." | |
else | |
echo "ERROR MD5 does not match!" | |
fi | |
elif [[ "${DOWNLOAD_FILE_SIZE}" == "${DOWNLOAD_SIZE}" ]]; then | |
echo "matched expected file size." | |
else | |
echo "ERROR file size does not match!" | |
fi | |
done | |
done | |
done | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment