forked from onedr0p/qbittorrent-prune
-
Notifications
You must be signed in to change notification settings - Fork 0
/
qbittorrent-prune.sh
executable file
·153 lines (129 loc) · 5.96 KB
/
qbittorrent-prune.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/bin/bash -e
# shellcheck shell=bash
# Allow this script to be run without Docker
# shellcheck disable=SC1091
test -f .env && source .env
# Set default values if not defined
DRY_RUN=${DRY_RUN:-"true"}
LOG_LEVEL=${LOG_LEVEL:-1}
QB_DELETE_FILES=${QB_DELETE_FILES:-"true"}
PUSHOVER_PRIORITY=${PUSHOVER_PRIORITY:-1}
DISABLE_SSL_VERIFY=${DISABLE_SSL_VERIFY:-"false"}
# Exit script if we don't have the necessary environment variables
if
[[ -z "${QB_URL}" ]] ||
[[ -z "${QB_USERNAME}" ]] ||
[[ -z "${QB_PASSWORD}" ]];
then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - ERROR: Missing environment variables, see README.md"
exit 1
fi
# Exit script if there are not qBittorrent categories enabled
if
[[ "${QB_CATEGORIES}" == "" ]];
then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - ERROR: No categories are present, add one to enable the script"
exit 1
fi
# Exit script if QB_CATEGORIES is not a valid comma delimited list
category_regex="([A-Za-z0-9\-_]+)(,\s*[A-Za-z0-9\-_]+)*"
if [[ ! "${QB_CATEGORIES}" =~ ${category_regex} ]]; then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - ERROR: Categories is not in the right syntax"
exit 1
fi
# Warn about dry run environment variable being set
if [ "${DRY_RUN}" == "true" ]; then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - INFO: DRY_RUN set, this script will not actually delete anything from qBittorrent"
fi
# Set the curl command
CURL_CMD="curl -s"
if
[[ "${DISABLE_SSL_VERIFY}" == "true" ]];
then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - INFO: DISABLE_SSL_VERIFY set, SSL verification is disabled"
CURL_CMD="curl -s -k"
fi
# Append the qBittorrent API path
api_url="${QB_URL}/api/v2"
# Log into qBittorrent and save the cookie in a variable
response=$( ${CURL_CMD} --fail -i --header "Referer: ${QB_URL}" --data "username=${QB_USERNAME}&password=${QB_PASSWORD}" "${api_url}/auth/login" 2>&1 )
curl_status=$?
if [[ ${curl_status} -ne 0 ]]; then
echo "$(date -u) - ERROR: cURL command failed with status ${curl_status}. Problem with host, port, or credentials?"
echo "cURL response: ${response}"
exit 1
fi
cookie_line=$( echo "${response}" | grep "set-cookie: SID" )
grep_status=$?
if [[ ${grep_status} -ne 0 ]]; then
echo "$(date -u) - ERROR: Failed to find 'set-cookie: SID' in the response."
exit 1
fi
cookie=$( echo "${cookie_line}" | awk -F'[=";"]' '{print $2}' )
awk_status=$?
if [[ -z "${cookie}" ]]; then
echo "$(date -u) - ERROR: Failed to extract cookie from the response. AWK command exit status: ${awk_status}"
exit 1
else
echo "$(date -u) - SUCCESS: Logged into qBittorrent, using cookie: ${cookie}"
fi
# Check the API Version
api_version=$(${CURL_CMD} --fail --cookie "SID=${cookie}" "${api_url}/app/webapiVersion")
valid_api_version_regex="^2\.."
if [[ ! "${api_version}" =~ ${valid_api_version_regex} ]]; then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - ERROR: qBittorrent version '${api_version}' is not supported by this script"
exit 1
fi
# Iterate thru each comma delimited value in QB_CATEGORIES and append torrent hash to array based on filters
torrent_hashes=()
for category in ${QB_CATEGORIES//,/ }; do
hash=$(${CURL_CMD} --fail --cookie "SID=${cookie}" "${api_url}/torrents/info?filter=completed" | jq -r --arg CATEGORY "${category}" '.[] | select( (.category==$CATEGORY) and (.state=="stalledUP") ) | .hash' && printf '\0')
torrent_hashes+=("${hash}")
done
# Exit if no torrents are found in categories
if [ "${#torrent_hashes[@]}" -eq 0 ]; then
[[ ${LOG_LEVEL} -ge 2 ]] && echo "$(date -u) - INFO: No torrents were found in your categories"
exit 1
else
[[ ${LOG_LEVEL} -ge 2 ]] && echo "$(date -u) - INFO: Found ${#torrent_hashes[@]} torrents matching your categories and in a stalledUP state"
fi
# Verify the torrent in the list defined above has an error
failed_torrent_hashes=()
for torrent_hash in "${torrent_hashes[@]}"
do
has_error=$(${CURL_CMD} --fail --cookie "SID=${cookie}" "${api_url}/torrents/trackers?hash=${torrent_hash}" | jq -r '.[] | select(.msg | test("(not registered)|(unregistered)";"i"))')
if [ "${has_error}" != "" ]; then
failed_torrent_hashes+=("${torrent_hash}")
fi
done
# # If torrents were found but the API hates us, die
if [ "${#failed_torrent_hashes[@]}" -eq 0 ]; then
[[ ${LOG_LEVEL} -ge 2 ]] && echo "$(date -u) - INFO: No torrents matching 'registered' or 'unregistered' were found in your categories"
exit 1
fi
# Delete the torrent
for failed_torrent_hash in "${failed_torrent_hashes[@]}"
do
# Get the torrent name
torrent_name=$(${CURL_CMD} --fail --cookie "SID=${cookie}" "${api_url}/torrents/files?hash=${failed_torrent_hash}" | jq -r '.[] | .name')
# Delete the torrent
if [ "${DRY_RUN}" == "false" ]; then
http_response_code=$(${CURL_CMD} -o /dev/null -w "%{http_code}" --cookie "SID=${cookie}" "${api_url}/torrents/delete?hashes=${failed_torrent_hash}&deleteFiles=${QB_DELETE_FILES}")
valid_response_regex="(2|3)[\d]{2}"
if [[ ! "${http_response_code}" =~ ${valid_response_regex} ]]; then
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - ERROR: Unable to delete torrent ${torrent_name}"
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - ERROR: Invalid HTTP Status Code: ${http_response_code}"
else
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - SUCCESS: Torrent ${torrent_name} deleted"
# Send Pushover notification if enabled
if [[ "${PUSHOVER_USER_KEY}" ]] && [[ "${PUSHOVER_TOKEN}" ]]; then
title="Torrent deleted from qBittorrent"
${CURL_CMD} -X POST -d "token=${PUSHOVER_TOKEN}&user=${PUSHOVER_USER_KEY}&title=\"${title}\"&message=\"${torrent_name}\"&priority=${PUSHOVER_PRIORITY}" \
'https://api.pushover.net/1/messages.json'
fi
fi
else
[[ ${LOG_LEVEL} -ge 1 ]] && echo "$(date -u) - INFO: Found torrent '${torrent_name}' to delete but did not because of the DRY_RUN flag being set"
fi
done
exit 0