Last active
August 14, 2025 03:41
-
-
Save brandonb927/652ecf1bb23dc7a94e140c95a9e7b5e1 to your computer and use it in GitHub Desktop.
Transmission mover.py for unRAID — Based on qbit_manage mover.py https://github.com/StuffAnThings/qbit_manage/blob/master/scripts/mover.py
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
#!/usr/bin/env python3 | |
# This standalone script is used to pause torrents older than last x days, | |
# run mover (in unRAID) and start torrents again once mover has completed. | |
import argparse | |
import logging | |
import os | |
import sys | |
import time | |
from datetime import datetime | |
from datetime import timedelta | |
from urllib import parse as urllib_parse | |
# Configure logging | |
logging.basicConfig( | |
level=logging.DEBUG, | |
format="%(asctime)s - %(levelname)s - %(message)s", | |
datefmt="%Y-%m-%d %H:%M:%S", | |
handlers=[logging.StreamHandler(sys.stdout)], | |
) | |
parser = argparse.ArgumentParser(prog="Transmission mover", description="Stop torrents and kick off Unraid mover process") | |
parser.add_argument("--host", help="Transmission host including port", required=True) | |
parser.add_argument("-u", "--user", help="Transmission user", default="admin") | |
parser.add_argument("-p", "--password", help="Transmission password", default="adminadmin") | |
parser.add_argument( | |
"--cache-mount", | |
help="Cache mount point in Unraid. This is used to additionally filter for only torrents that exists on the cache mount" | |
"Use this option ONLY if you follow TRaSH Guides folder structure. (For default cache drive set this to /mnt/cache)", | |
default=None, | |
) | |
parser.add_argument( | |
"--days-from", "--days_from", help="Set Number of Days to stop torrents between two offsets", type=int, default=0 | |
) | |
parser.add_argument("--days-to", "--days_to", help="Set Number of Days to stop torrents between two offsets", type=int, default=2) | |
parser.add_argument( | |
"--mover-old", | |
help="Use mover.old instead of mover. Useful if you're using the Mover Tuning Plugin", | |
action="store_true", | |
default=False, | |
) | |
parser.add_argument( | |
"--status-filter", | |
help="Define a status to limit which torrents to pause. Useful if you want to leave certain torrents unpaused", | |
choices=[ | |
"check pending", | |
"checking", | |
"downloading", | |
"download pending", | |
"seeding", | |
"seed pending", | |
"stopped", | |
], | |
default="stopped", | |
) | |
# --DEFINE VARIABLES--# | |
# --START SCRIPT--# | |
try: | |
from transmission_rpc import TransmissionConnectError, Client, TransmissionAuthError | |
except ModuleNotFoundError: | |
logging.error( | |
'Requirements Error: transmission-rpc not installed. Please install using the command "pip install transmission-rpc"' | |
) | |
sys.exit(1) | |
def filter_torrents(torrent_list, timeoffset_from, timeoffset_to, cache_mount): | |
result = [] | |
for torrent in torrent_list: | |
torrent_added_date = torrent.added_date.timestamp() | |
if torrent_added_date >= timeoffset_to and torrent_added_date <= timeoffset_from: | |
if not cache_mount or exists_in_cache(cache_mount, os.path.join(torrent.download_dir, torrent.name)): | |
result.append(torrent) | |
elif torrent_added_date < timeoffset_to: | |
break | |
return result | |
def exists_in_cache(cache_mount, content_path): | |
cache_path = os.path.join(cache_mount, content_path.lstrip("/")) | |
return os.path.exists(cache_path) | |
def stop_start_torrents(client, torrent_list, pause=True): | |
ids = [t.id for t in torrent_list] | |
if pause: | |
for torrent in torrent_list: | |
logging.info(f"Pausing: {torrent.name} [{torrent.added_date}]") | |
client.stop_torrent(ids) | |
else: | |
for torrent in torrent_list: | |
logging.info(f"Resuming: {torrent.name} [{torrent.added_date}]") | |
client.start_torrent(ids) | |
if __name__ == "__main__": | |
current = datetime.now() | |
args = parser.parse_args() | |
if args.days_from > args.days_to: | |
raise ("Config Error: days_from must be set lower than days_to") | |
timeoffset_from = current - timedelta(days=args.days_from) | |
timeoffset_to = current - timedelta(days=args.days_to) | |
try: | |
host = urllib_parse.urlparse(args.host) | |
port = 9091 | |
if host.scheme == 'http': | |
port = 80 | |
if host.scheme == 'https': | |
port = 443 | |
if host.scheme and host.netloc: | |
client = Client(protocol=host.scheme, host=host.netloc, port=port, username=args.user, password=args.password) | |
else: | |
client = Client(host=args.host, username=args.user, password=args.password) | |
except TransmissionAuthError: | |
raise Exception("Transmission Error: Failed to login, invalid username/password.") | |
except TransmissionConnectError: | |
raise Exception("Transmission Error: Unable to connect to the client, connection error.") | |
except Exception: | |
raise Exception("Transmission Error: Unable to connect to the client, unknown error") | |
torrent_list = [t for t in client.get_torrents() if t.status == args.status_filter] | |
torrent_list.sort(key=lambda t: t.added_date) | |
torrents = filter_torrents(torrent_list, timeoffset_from.timestamp(), timeoffset_to.timestamp(), args.cache_mount) | |
if len(torrents) == 0: | |
logging.info(f"No torrents found within range, exiting") | |
exit(0) | |
# Pause Torrents | |
logging.info(f"Pausing [{len(torrents)}] torrents from {args.days_from} - {args.days_to} days ago") | |
stop_start_torrents(client, torrents, True) | |
time.sleep(10) | |
# Or using mover tunning | |
if args.mover_old: | |
# Start mover | |
logging.info("Starting mover.old to move files in to array disks") | |
os.system("/usr/local/sbin/mover.old start") | |
else: | |
# Start mover | |
logging.info("Starting mover to move files in to array disks based on mover tuning preferences") | |
os.system("/usr/local/sbin/mover start") | |
# Start Torrents | |
logging.info(f"Resuming [{len(torrents)}] paused torrents from {args.days_from} - {args.days_to} days ago") | |
stop_start_torrents(client, torrents, False) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment