From 362af4e16d7cdfa1512a6f2f154f055907b4d900 Mon Sep 17 00:00:00 2001 From: Christian Segundo Date: Tue, 23 Jul 2024 21:43:05 +0200 Subject: add ci --- .scripts.d/20-build.sh | 20 +++++++++++++ .scripts.d/30-test.sh | 28 ++++++++++++++++++ .scripts.d/40-publish.sh | 45 +++++++++++++++++++++++++++++ Dockerfile | 2 +- Jenkinsfile | 24 ++++++++++++++++ scripts/ask-tracker-for-more-peers.py | 21 -------------- scripts/cron.sh | 46 ------------------------------ scripts/delete-based-on-tag.py | 42 --------------------------- scripts/delete-if-unlinked.py | 53 ----------------------------------- scripts/entrypoint.sh | 43 ---------------------------- scripts/requirements.txt | 8 ------ scripts/tag-based-on-dir.py | 30 -------------------- src/ask-tracker-for-more-peers.py | 21 ++++++++++++++ src/cron.sh | 46 ++++++++++++++++++++++++++++++ src/delete-based-on-tag.py | 42 +++++++++++++++++++++++++++ src/delete-if-unlinked.py | 53 +++++++++++++++++++++++++++++++++++ src/entrypoint.sh | 44 +++++++++++++++++++++++++++++ src/requirements.txt | 8 ++++++ src/tag-based-on-dir.py | 30 ++++++++++++++++++++ 19 files changed, 362 insertions(+), 244 deletions(-) create mode 100644 .scripts.d/20-build.sh create mode 100644 .scripts.d/30-test.sh create mode 100644 .scripts.d/40-publish.sh create mode 100644 Jenkinsfile delete mode 100755 scripts/ask-tracker-for-more-peers.py delete mode 100644 scripts/cron.sh delete mode 100755 scripts/delete-based-on-tag.py delete mode 100644 scripts/delete-if-unlinked.py delete mode 100644 scripts/entrypoint.sh delete mode 100644 scripts/requirements.txt delete mode 100755 scripts/tag-based-on-dir.py create mode 100755 src/ask-tracker-for-more-peers.py create mode 100644 src/cron.sh create mode 100755 src/delete-based-on-tag.py create mode 100644 src/delete-if-unlinked.py create mode 100644 src/entrypoint.sh create mode 100644 src/requirements.txt create mode 100755 src/tag-based-on-dir.py diff --git a/.scripts.d/20-build.sh b/.scripts.d/20-build.sh new file mode 100644 index 0000000..6f8beb9 --- /dev/null +++ b/.scripts.d/20-build.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# vim: ai:ts=8:sw=8:noet +set -EeufCo pipefail +export SHELLOPTS # propagate set to children by default +IFS=$'\t\n' + +# check required commands are in place +command -v docker >/dev/null 2>&1 || { + echo 'please install docker-client' + exit 1 +} + +docker buildx build \ + --no-cache \ + --pull \ + --load \ + --tag "chn2guevara/transmission-hacks:${BUILD_ID}" \ + . + + diff --git a/.scripts.d/30-test.sh b/.scripts.d/30-test.sh new file mode 100644 index 0000000..16c4fac --- /dev/null +++ b/.scripts.d/30-test.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# vim: ai:ts=8:sw=8:noet +set -EeufCo pipefail +export SHELLOPTS # propagate set to children by default +IFS=$'\t\n' + +# check required commands are in place +command -v docker >/dev/null 2>&1 || { + echo 'please install docker-client' + exit 1 +} + +# install goss +curl -fsSL https://goss.rocks/install | sh + +export GOSS_SLEEP=${GOSS_SLEEP:-5} +export GOSS_VARS=${GOSS_VARS:-} +export GOSS_ADDITIONAL_COPY_PATH=${GOSS_ADDITIONAL_COPY_PATH:-} +export GOSS_OPTS="--format junit --no-color" +export CONTAINER_LOG_OUTPUT=${CONTAINER_LOG_OUTPUT:-} +export GOSS_FILES_STRATEGY=cp + +goss --gossfile goss.yaml render >goss-full.yaml +mv goss-full.yaml goss.yaml + +rm -rf build/reports/ +mkdir -p build/reports/ +dgoss run "chn2guevara/transmission-hacks:${BUILD_ID}" "/usr/bin/sleep" "infinity" >build/reports/goss.xml diff --git a/.scripts.d/40-publish.sh b/.scripts.d/40-publish.sh new file mode 100644 index 0000000..4f5f4d4 --- /dev/null +++ b/.scripts.d/40-publish.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# vim: ai:ts=8:sw=8:noet +set -EeufCo pipefail +export SHELLOPTS # propagate set to children by default +IFS=$'\t\n' + +# check required commands are in place +command -v docker >/dev/null 2>&1 || { + echo 'please install docker-client' + exit 1 +} + +docker login --username "chn2guevara" \ + --password-stdin <<<"$DOCKERHUB_TOKEN" + +BUILDER_SUFFIX=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5 ; echo '') +docker run --privileged --rm tonistiigi/binfmt --install arm64 +docker buildx create --use --name "multi-arch-builder-${BUILDER_SUFFIX}" +trap "docker buildx rm 'multi-arch-builder-""${BUILDER_SUFFIX}""'" EXIT + +DOCKER_TAG="latest" +if [ "$GIT_BRANCH" != "master" ]; then + DOCKER_TAG="${GIT_BRANCH//\//-}" +fi + +if [ "$(git tag --contains)" = "" ]; then + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --builder "multi-arch-builder-${BUILDER_SUFFIX}" \ + --no-cache \ + --pull \ + --push \ + --tag "chn2guevara/transmission-hacks:${DOCKER_TAG}" \ + . +else + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --builder "multi-arch-builder-${BUILDER_SUFFIX}" \ + --no-cache \ + --pull \ + --push \ + --tag "chn2guevara/transmission-hacks:${DOCKER_TAG}" \ + --tag "chn2guevara/transmission-hacks:$(git tag --contains | head -1)" \ + . +fi diff --git a/Dockerfile b/Dockerfile index a52c49b..35af27c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM python:slim-bullseye -COPY scripts /scripts +COPY src /scripts # hadolint ignore=DL3008 RUN \ apt-get update && \ diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..1293357 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,24 @@ +String cron_string = BRANCH_NAME == "master" ? "@weekly" : "" + +pipeline { + agent any + triggers { cron(cron_string) } + options { ansiColor('xterm') } + stages { + stage('Build') { steps { sh 'bash .scripts.d/20-build.sh' } } + stage('Test') { steps { sh 'bash .scripts.d/30-test.sh' } } + stage('Publish') { + environment { DOCKERHUB_TOKEN = credentials('DOCKERHUB_TOKEN') } + steps { sh 'bash .scripts.d/40-publish.sh' } + } + } + post { + always { + junit 'build/reports/*.xml' + step([$class: 'Mailer', + notifyEveryUnstableBuild: true, + recipients: "christian+jenkins@segundo.io", + sendToIndividuals: true]) + } + } +} diff --git a/scripts/ask-tracker-for-more-peers.py b/scripts/ask-tracker-for-more-peers.py deleted file mode 100755 index 8b874f0..0000000 --- a/scripts/ask-tracker-for-more-peers.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/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/scripts/cron.sh b/scripts/cron.sh deleted file mode 100644 index 1ce9e65..0000000 --- a/scripts/cron.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/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/scripts/delete-based-on-tag.py b/scripts/delete-based-on-tag.py deleted file mode 100755 index 37442cb..0000000 --- a/scripts/delete-based-on-tag.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/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/scripts/delete-if-unlinked.py b/scripts/delete-if-unlinked.py deleted file mode 100644 index 54df8ff..0000000 --- a/scripts/delete-if-unlinked.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/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/scripts/entrypoint.sh b/scripts/entrypoint.sh deleted file mode 100644 index 93c248d..0000000 --- a/scripts/entrypoint.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -set -euo pipefail - -cat <>/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} -EOF - -i=0 -while true; do - key="DELETE_TAG_${i}_NAME" - val="DELETE_TAG_${i}_AGE" - if [ -z "${!key:-}" ]; then - break - fi - cat <>/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 <>/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/scripts/requirements.txt b/scripts/requirements.txt deleted file mode 100644 index 482070c..0000000 --- a/scripts/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -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/scripts/tag-based-on-dir.py b/scripts/tag-based-on-dir.py deleted file mode 100755 index 8cec41b..0000000 --- a/scripts/tag-based-on-dir.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/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() 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 <>/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 <>/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 <>/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() -- cgit v1.2.3