aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Segundo2024-07-23 21:43:05 +0200
committerChristian Segundo2024-07-23 21:43:05 +0200
commit362af4e16d7cdfa1512a6f2f154f055907b4d900 (patch)
treef0e8817df1cad49bd466c60016cdd8b70913690c /src
parent076b6aefd5b17cccc34cc403b7b4f2ba4f093a57 (diff)
downloadtransmission-hacks-362af4e16d7cdfa1512a6f2f154f055907b4d900.tar.gz
add ci
Diffstat (limited to 'src')
-rwxr-xr-xsrc/ask-tracker-for-more-peers.py21
-rw-r--r--src/cron.sh46
-rwxr-xr-xsrc/delete-based-on-tag.py42
-rw-r--r--src/delete-if-unlinked.py53
-rw-r--r--src/entrypoint.sh44
-rw-r--r--src/requirements.txt8
-rwxr-xr-xsrc/tag-based-on-dir.py30
7 files changed, 244 insertions, 0 deletions
diff --git a/src/ask-tracker-for-more-peers.py b/src/ask-tracker-for-more-peers.py
new file mode 100755
index 0000000..8b874f0
--- /dev/null
+++ b/src/ask-tracker-for-more-peers.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+import click
+from transmission_rpc import Client
+
+
+@click.command()
+@click.option('--port', default=9091)
+@click.option('--host', default="localhost")
+def main(host, port):
+ """ Reannounces all torrents that have not received any peers. """
+
+ c = Client(host=host, port=port)
+ torrents = c.get_torrents()
+ for torrent in torrents:
+ if torrent.progress == 0 and torrent.downloading:
+ print(f"Reannouncing {torrent.name}")
+ c.reannounce_torrent(torrent.id)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/cron.sh b/src/cron.sh
new file mode 100644
index 0000000..1ce9e65
--- /dev/null
+++ b/src/cron.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+set -euo pipefail
+
+declare -A tag_age
+i=0
+while true; do
+ key="DELETE_TAG_${i}"
+ val="DELETE_AGE_${i}"
+ if [ -z "${!key:-}" ]; then
+ break
+ fi
+ tag_age["${!key}"]="${!val}"
+ i=$((i + 1))
+done
+
+declare -A unlinked_tag_age
+i=0
+while true; do
+ key="DELETE_UNLINKED_TAG_${i}"
+ val="DELETE_UNLINKED_AGE_${i}"
+ if [ -z "${!key:-}" ]; then
+ break
+ fi
+ unlinked_tag_age["${!key}"]="${!val}"
+ i=$((i + 1))
+done
+
+timeout "${SCRIPT_TIMEOUT}" "${PYTHON_PATH}" "${SCRIPT_PREFIX}"/tag-based-on-dir.py \
+ --host "${TRANSMISSION_HOST}"
+
+timeout "${SCRIPT_TIMEOUT}" "${PYTHON_PATH}" "${SCRIPT_PREFIX}"/ask-tracker-for-more-peers.py \
+ --host "${TRANSMISSION_HOST}"
+
+for key in "${!tag_age[@]}"; do
+ timeout "${SCRIPT_TIMEOUT}" "${PYTHON_PATH}" "${SCRIPT_PREFIX}"/delete-based-on-tag.py \
+ --host "${TRANSMISSION_HOST}" \
+ --tag "${key}" \
+ --age "${tag_age[$key]}"
+done
+
+for key in "${!unlinked_tag_age[@]}"; do
+ timeout "${SCRIPT_TIMEOUT}" "${PYTHON_PATH}" "${SCRIPT_PREFIX}"/delete-if-unlinked.py \
+ --host "${TRANSMISSION_HOST}" \
+ --tag "${key}" \
+ --min-age "${unlinked_tag_age[$key]}"
+done
diff --git a/src/delete-based-on-tag.py b/src/delete-based-on-tag.py
new file mode 100755
index 0000000..37442cb
--- /dev/null
+++ b/src/delete-based-on-tag.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+import click
+from transmission_rpc import Client
+from datetime import timedelta, datetime
+
+
+def convert_to_seconds(s):
+ units = {"s": "seconds", "m": "minutes",
+ "h": "hours", "d": "days", "w": "weeks"}
+ count = int(s[:-1])
+ unit = units[s[-1]]
+ td = timedelta(**{unit: count})
+ return td.seconds + 60 * 60 * 24 * td.days
+
+
+@click.command()
+@click.option('--port', default=9091)
+@click.option('--host', default="localhost")
+@click.option('--tag', required=True)
+@click.option('--age', default='1w')
+def main(host, port, tag, age):
+ """ Deletes torrents older than the specified age. """
+
+ c = Client(host=host, port=port)
+ torrents = c.get_torrents()
+ for torrent in torrents:
+ if tag not in torrent.labels:
+ continue
+ if torrent.done_date is None:
+ continue
+
+ specified_age = convert_to_seconds(age)
+ age_in_seconds = int((datetime.today().timestamp() -
+ torrent.done_date.timestamp()))
+
+ if age_in_seconds > specified_age:
+ print(f"Deleting {torrent.name}")
+ c.remove_torrent(torrent.id, delete_data=True)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/delete-if-unlinked.py b/src/delete-if-unlinked.py
new file mode 100644
index 0000000..54df8ff
--- /dev/null
+++ b/src/delete-if-unlinked.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+import click
+import os
+from transmission_rpc import Client
+from datetime import timedelta, datetime
+
+
+def convert_to_seconds(s):
+ units = {"s": "seconds", "m": "minutes",
+ "h": "hours", "d": "days", "w": "weeks"}
+ count = int(s[:-1])
+ unit = units[s[-1]]
+ td = timedelta(**{unit: count})
+ return td.seconds + 60 * 60 * 24 * td.days
+
+def has_links(torrent):
+ for file in torrent.get_files():
+ file_path = torrent.download_dir + '/' + file.name
+ if not os.path.exists(file_path):
+ continue
+ if os.stat(file_path).st_nlink > 1:
+ return True
+ return False
+
+
+@click.command()
+@click.option('--port', default=9091)
+@click.option('--host', default="localhost")
+@click.option('--tag', required=True)
+@click.option('--min-age', default='1w')
+def main(host, port, tag, min_age):
+ """ Deletes torrents older than the specified age if no file has a link. """
+
+ c = Client(host=host, port=port)
+ torrents = c.get_torrents()
+ for torrent in torrents:
+ if tag not in torrent.labels:
+ continue
+
+ specified_age = convert_to_seconds(min_age)
+ age_in_seconds = int((datetime.today().timestamp() -
+ torrent.done_date.timestamp()))
+
+ if age_in_seconds < specified_age:
+ continue
+
+ if not has_links(torrent):
+ print(f"Deleting {torrent.name}")
+ c.remove_torrent(torrent.id, delete_data=True)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/entrypoint.sh b/src/entrypoint.sh
new file mode 100644
index 0000000..925afa1
--- /dev/null
+++ b/src/entrypoint.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+set -euo pipefail
+
+cat <<EOF >>/etc/cron.d/crontab
+PYTHON_PATH=/usr/local/bin/python3
+SCRIPT_PREFIX=/scripts
+SCRIPT_TIMEOUT=${SCRIPT_TIMEOUT:-300}
+TRANSMISSION_HOST=${TRANSMISSION_HOST:-localhost}
+TRANSMISSION_PORT=${TRANSMISSION_PORT:-9091}
+TRANSMISSION_DOWNLOAD_ROOT=${TRANSMISSION_DOWNLOAD_ROOT:-/downloads/complete}
+EOF
+
+i=0
+while true; do
+ key="DELETE_TAG_${i}_NAME"
+ val="DELETE_TAG_${i}_AGE"
+ if [ -z "${!key:-}" ]; then
+ break
+ fi
+ cat <<EOF >>/etc/cron.d/crontab
+DELETE_TAG_${i}=${!key}
+DELETE_AGE_${i}=${!val}
+EOF
+ i=$((i + 1))
+done
+
+i=0
+while true; do
+ key="DELETE_UNLINKED_${i}_NAME"
+ val="DELETE_UNLINKED_${i}_AGE"
+ if [ -z "${!key:-}" ]; then
+ break
+ fi
+ cat <<EOF >>/etc/cron.d/crontab
+DELETE_UNLINKED_TAG_${i}=${!key}
+DELETE_UNLINKED_AGE_${i}=${!val}
+EOF
+ i=$((i + 1))
+done
+
+echo "${CRON_EXPRESSION:-* * * * *} /bin/bash /scripts/cron.sh >/proc/1/fd/1 2>/proc/1/fd/2" >>/etc/cron.d/crontab
+cat /etc/cron.d/crontab
+crontab /etc/cron.d/crontab
+cron -f -l "${CRON_LOG_LEVEL:-0}"
diff --git a/src/requirements.txt b/src/requirements.txt
new file mode 100644
index 0000000..482070c
--- /dev/null
+++ b/src/requirements.txt
@@ -0,0 +1,8 @@
+certifi==2023.7.22
+charset-normalizer==3.1.0
+click==8.1.3
+idna==3.4
+requests==2.31.0
+transmission-rpc==4.3.0
+typing_extensions==4.6.3
+urllib3==2.0.3
diff --git a/src/tag-based-on-dir.py b/src/tag-based-on-dir.py
new file mode 100755
index 0000000..8cec41b
--- /dev/null
+++ b/src/tag-based-on-dir.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+import click
+from transmission_rpc import Client
+
+
+@click.command()
+@click.option('--port', default=9091)
+@click.option('--root-dir', default="/downloads/complete")
+@click.option('--host', default="localhost")
+def main(host, port, root_dir):
+ """Adds tags to torrents based on their download directory."""
+
+ c = Client(host=host, port=port)
+ torrents = c.get_torrents()
+ for torrent in torrents:
+ dir = torrent.download_dir.replace(root_dir, '')
+ label = 'none'
+ if dir != '':
+ label = dir.split('/')[1]
+
+ labels = list([label])
+ labels.extend(x for x in torrent.labels if x not in labels)
+
+ if set(labels) != set(torrent.labels):
+ print(f"Tagging {torrent.name}")
+ c.change_torrent(torrent.id, labels=labels)
+
+
+if __name__ == '__main__':
+ main()