Skip to content

Instantly share code, notes, and snippets.

@onedr0p
Last active October 21, 2023 19:04
Show Gist options
  • Save onedr0p/8fd8455f08f4781cad9e01a1d65bc34f to your computer and use it in GitHub Desktop.
Save onedr0p/8fd8455f08f4781cad9e01a1d65bc34f to your computer and use it in GitHub Desktop.
Transmission Garbage Collector
#!/bin/sh
#
# INFO
#
# This works if sonarr and radarr are set up to have a Category of sonarr and radarr respectively
# If you are using other Categories to save your automated downloads, update the script where you see:
# "radarr"|"sonarr")
# This script will not touch anything outside those Categories
# Set this file on a cron for every 5 minutes
# Using Docker? Make your cron something like this:
# /usr/bin/docker exec $(/usr/bin/docker ps | grep "linuxserver/transmission:latest" | awk '{print $1}') bash "/path/to/transmission-gc.sh"
# Set =~ to be insensitive
shopt -s nocasematch
TRANS_REMOTE_BIN=/usr/bin/transmission-remote
TRANS_HOST="127.0.0.1:9091"
# Amount of time (in seconds) after a torrent completes to delete them
RETENTION=2592000
# Delete torrents only when ratio is above
RATIO="1.5"
# Clean up torrents where trackers have torrent not registered
# filter list by * (which signifies a tracker error)
TORRENT_DEAD_LIST=($("${TRANS_REMOTE_BIN}" "${TRANS_HOST}" -l | sed -e '1d;$d;s/^ *//' | cut --only-delimited --delimiter=' ' --fields=1 | egrep '[0-9]+\*' | sed 's/\*$//'))
for torrent_id in "${TORRENT_DEAD_LIST[@]}"
do
# Get the torrents metadata
torrent_info=$("${TRANS_REMOTE_BIN}" "${TRANS_HOST}" --torrent "${torrent_id}" -i -it)
torrent_name=$(echo "${torrent_info}" | grep "Name: *" | sed 's/Name\:\s//i' | awk '{$1=$1};1')
torrent_path=$(echo "${torrent_info}" | grep "Location: *" | sed 's/Location\:\s//i' | awk '{$1=$1};1')
torrent_size=$(echo "${torrent_info}" | grep "Downloaded: *" | sed 's/Downloaded\:\s//i' | awk '{$1=$1};1')
torrent_label=$(basename "${torrent_path}")
case "${torrent_label}" in
"radarr"|"sonarr")
torrent_error=$(echo "${torrent_info}" | grep "Got an error" | cut -d \" -f2)
if [[ "${torrent_error}" =~ "unregistered" ]] || [[ "${torrent_error}" =~ "not registered" ]]; then
# Delete torrent
"${TRANS_REMOTE_BIN}" "${TRANS_HOST}" --torrent "${torrent_id}" --remove-and-delete > /dev/null
fi
esac
done
# Clean up torrent where ratio is > ${RATIO} or seeding time > ${RETENTION} seconds
# do not filter the list, get all the torrents
TORRENT_ALL_LIST=($("${TRANS_REMOTE_BIN}" "${TRANS_HOST}" -l | sed -e '1d;$d;s/^ *//' | cut --only-delimited --delimiter=' ' --fields=1))
for torrent_id in "${TORRENT_ALL_LIST[@]}"
do
# Get the torrents metadata
torrent_info=$("${TRANS_REMOTE_BIN}" "${TRANS_HOST}" --torrent "${torrent_id}" -i -it)
torrent_name=$(echo "${torrent_info}" | grep "Name: *" | sed 's/Name\:\s//i' | awk '{$1=$1};1')
torrent_path=$(echo "${torrent_info}" | grep "Location: *" | sed 's/Location\:\s//i' | awk '{$1=$1};1')
torrent_size=$(echo "${torrent_info}" | grep "Downloaded: *" | sed 's/Downloaded\:\s//i' | awk '{$1=$1};1')
torrent_label=$(basename "${torrent_path}")
torrent_seeding_seconds=$(echo "${torrent_info}" | grep "Seeding Time: *" | awk -F"[()]" '{print $2}' | sed 's/\sseconds//i')
torrent_ratio=$(echo "${torrent_info}" | grep "Ratio: *" | sed 's/Ratio\:\s//i' | awk '{$1=$1};1')
# Debug
# echo "${torrent_id} - ${torrent_ratio} - ${torrent_seeding_seconds} - ${torrent_label} - ${torrent_name}"
case "${torrent_label}" in
"radarr"|"sonarr")
# Torrents without a ratio have "None" instead of "0.0" let's fix that
if [[ "${torrent_ratio}" =~ "None" ]]; then
torrent_ratio="0.0"
fi
# delete torrents greater than ${TTL_SECONDS}
if [[ "${torrent_seeding_seconds}" -gt "${RETENTION}" ]]; then
"${TRANS_REMOTE_BIN}" "${TRANS_HOST}" --torrent "${torrent_id}" --remove-and-delete > /dev/null
fi
# delete torrents greater than ${RATIO}
if (( $(echo "${torrent_ratio} ${RATIO}" | awk '{print ($1 > $2)}') )); then
"${TRANS_REMOTE_BIN}" "${TRANS_HOST}" --torrent "${torrent_id}" --remove-and-delete > /dev/null
fi
esac
done
@marc0janssen
Copy link

The transmission-daemon resets the seeding time . So you will never get to the "RETENTION" seeding time.

This version of the script fixes that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment