Compare commits

...

7 Commits

Author SHA1 Message Date
af5873f37a Use qbittorrentapi 2024-11-05 17:59:58 -06:00
61b057505a Use qbittorrentapi 2024-11-05 17:59:30 -06:00
1c4d3cd333 Remove seed_armbian_torrents.py 2024-11-05 17:57:24 -06:00
77b86fddae Use qbittorrentapi 2024-11-05 17:56:46 -06:00
70740ba949 Use qbittorrentapi 2024-11-05 16:46:23 -06:00
38ffe9e963 Use context manager 2024-11-05 16:24:52 -06:00
ae478e4675 Use qbittorrentapi, refactor qbth 2024-11-05 15:46:06 -06:00
14 changed files with 341 additions and 257 deletions

4
.envrc
View File

@ -1 +1,3 @@
use nix source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
use devenv

9
.gitignore vendored
View File

@ -1 +1,10 @@
.direnv .direnv
# Devenv
.devenv*
devenv.local.nix
# direnv
.direnv
# pre-commit
.pre-commit-config.yaml

View File

@ -1,45 +0,0 @@
#!/usr/bin/env python3
"""add_qbt_trackers.py
Description:
This script fetches torrent tracker URLs from plaintext lists hosted on the web
and adds them to each torrent in a qBittorrent instance.
Usage:
add_qbt_trackers.py (HOSTNAME) (USERNAME) (PASSWORD)
add_qbt_trackers.py -h
Examples:
add_qbt_trackers.py "http://localhost:8080" "admin" "adminadmin"
Options:
-h, --help show this help message and exit
"""
import requests
from docopt import docopt
from qbittorrent import Client
if __name__ == "__main__":
args = docopt(__doc__) # type: ignore
# Initialize client and login
qb = Client(args["HOSTNAME"])
qb.login(username=args["USERNAME"], password=args["PASSWORD"])
live_trackers_list_urls = [
"https://newtrackon.com/api/stable",
"https://trackerslist.com/best.txt",
"https://trackerslist.com/http.txt",
"https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt",
]
combined_trackers_urls = []
for url in live_trackers_list_urls:
response = requests.get(url, timeout=60)
tracker_urls = [x for x in response.text.splitlines() if x != ""]
combined_trackers_urls.extend(tracker_urls)
for torrent in qb.torrents():
qb.add_trackers(torrent.get("hash"), "\n".join(combined_trackers_urls)) # type: ignore

116
devenv.lock Normal file
View File

@ -0,0 +1,116 @@
{
"nodes": {
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1730745597,
"owner": "cachix",
"repo": "devenv",
"rev": "7cfc04e544e67adf803c3634b53a911c670e046e",
"type": "github"
},
"original": {
"dir": "src/modules",
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1716977621,
"owner": "cachix",
"repo": "devenv-nixpkgs",
"rev": "4267e705586473d3e5c8d50299e71503f16a6fb6",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1730741070,
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1730814269,
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "d70155fdc00df4628446352fc58adc640cd705c2",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
}
}
},
"root": "root",
"version": 7
}

34
devenv.nix Normal file
View File

@ -0,0 +1,34 @@
{ pkgs, lib, config, inputs, ... }:
{
# https://devenv.sh/basics/
env.GREET = "devenv";
# https://devenv.sh/packages/
packages = [
pkgs.git
pkgs.python312Packages.beautifulsoup4
pkgs.python312Packages.black
pkgs.python312Packages.bpython
pkgs.python312Packages.docopt
pkgs.python312Packages.isort
pkgs.python312Packages.pandas
pkgs.python312Packages.pytest
pkgs.python312Packages.qbittorrent-api
pkgs.python312Packages.requests
pkgs.python312Packages.resend
pkgs.python312Packages.rich
pkgs.python312Packages.tabulate
pkgs.pyright
pkgs.shellcheck
];
# https://devenv.sh/languages/
# languages.rust.enable = true;
languages.python.enable = true;
enterShell = ''
hello
git --version
'';
}

15
devenv.yaml Normal file
View File

@ -0,0 +1,15 @@
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
inputs:
nixpkgs:
url: github:cachix/devenv-nixpkgs/rolling
# If you're using non-OSS software, you can set allowUnfree to true.
# allowUnfree: true
# If you're willing to use a package that's vulnerable
# permittedInsecurePackages:
# - "openssl-1.1.1w"
# If you have more than one devenv you can merge them
#imports:
# - ./backend

View File

@ -15,9 +15,8 @@ Options:
-h, --help show this help message and exit -h, --help show this help message and exit
""" """
import qbittorrentapi
from docopt import docopt from docopt import docopt
from qbittorrent import Client
from tabulate import tabulate
# convert byte units # convert byte units
@ -43,36 +42,25 @@ def human_bytes(input_bytes: int) -> str:
return "" return ""
def print_table():
qb = Client("http://localhost:8080/")
qb.login()
table = []
headers = ["Name", "Total Size", "Trackers Count", "Ratio", "Uploaded"]
sorted_torrents = sorted(qb.torrents(), key=lambda d: d["ratio"], reverse=True) # type: ignore
for torrent in sorted_torrents:
row = []
row.append(torrent["name"]) # type: ignore
row.append(human_bytes(int(torrent["total_size"]))) # type: ignore
row.append(torrent["trackers_count"]) # type: ignore
row.append(torrent["ratio"]) # type: ignore
row.append(human_bytes(int(torrent["uploaded"]))) # type: ignore
table.append(row)
print(tabulate(table, headers, tablefmt="grid"))
def print_ssv(): def print_ssv():
qb = Client("http://localhost:8080/") with qbittorrentapi.Client(
qb.login() host="localhost", port=8080, username="", password=""
sorted_torrents = sorted(qb.torrents(), key=lambda d: d["ratio"], reverse=True) # type: ignore ) as qbt_client:
print("Name Size Trackers Ratio Uploaded") try:
for torrent in sorted_torrents: qbt_client.auth_log_in()
name = torrent["name"] # type: ignore except qbittorrentapi.LoginFailed as e:
size = human_bytes(int(torrent["total_size"])) # type: ignore print(e)
trackers = torrent["trackers_count"] # type: ignore
ratio = torrent["ratio"] # type: ignore sorted_torrents = sorted(
uploaded = human_bytes(int(torrent["uploaded"])) # type: ignore qbt_client.torrents_info(), key=lambda d: d.ratio, reverse=True
print(f"{name} {size} {trackers} {ratio} {uploaded}") )
for torrent in sorted_torrents:
name = torrent.name
size = human_bytes(torrent.total_size)
trackers = torrent.trackers_count
ratio = torrent.ratio
uploaded = human_bytes(torrent.uploaded)
print(f"{name} {size} {trackers} {ratio} {uploaded}")
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -18,8 +18,8 @@ Options:
-h, --help show this help message and exit -h, --help show this help message and exit
""" """
import qbittorrentapi
from docopt import docopt from docopt import docopt
from qbittorrent import Client
# convert byte units # convert byte units
@ -48,21 +48,26 @@ def human_bytes(bites: int) -> str:
if __name__ == "__main__": if __name__ == "__main__":
args = docopt(__doc__) # type: ignore args = docopt(__doc__) # type: ignore
# Initialize client and login
qb = Client(args["HOSTNAME"])
qb.login(username=args["USERNAME"], password=args["PASSWORD"])
# get total_completed_bytes
completed_torrent_sizes = [] completed_torrent_sizes = []
for torrent in qb.torrents(): total_added_bytes = int()
if torrent["completion_on"] != 0: # type: ignore
completed_torrent_sizes.append(torrent["total_size"]) # type: ignore with qbittorrentapi.Client(
host=args["HOSTNAME"], username=args["USERNAME"], password=args["PASSWORD"]
) as qbt_client:
try:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
print(e)
for torrent in qbt_client.torrents_info():
if torrent.completion_on != 0:
completed_torrent_sizes.append(torrent.total_size)
total_added_bytes = sum(
[torrent.total_size for torrent in qbt_client.torrents_info()]
)
total_completed_bytes = sum(completed_torrent_sizes) total_completed_bytes = sum(completed_torrent_sizes)
# get total_added_bytes
total_added_bytes = sum([torrent["total_size"] for torrent in qb.torrents()]) # type: ignore
# print the results
print(f"\nTotal completed size: {human_bytes(total_completed_bytes)}") print(f"\nTotal completed size: {human_bytes(total_completed_bytes)}")
print(f"Total added size: {human_bytes(total_added_bytes)}\n") print(f"Total added size: {human_bytes(total_added_bytes)}\n")

124
qbth.py
View File

@ -17,15 +17,25 @@ Options:
import json import json
import os import os
import subprocess import subprocess
from shutil import which
import qbittorrentapi
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from docopt import docopt from docopt import docopt
from qbittorrent import Client
args = docopt(__doc__) args = docopt(__doc__)
qb = Client(args["HOSTNAME"]) conn_info = dict(
qb.login(username=args["USERNAME"], password=args["PASSWORD"]) host=args["HOSTNAME"],
username=args["USERNAME"],
password=args["PASSWORD"],
)
try:
with qbittorrentapi.Client(**conn_info) as qbt_client:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
print(e)
def add_torrents(urls: list[str]): def add_torrents(urls: list[str]):
@ -35,9 +45,16 @@ def add_torrents(urls: list[str]):
Params: Params:
urls: list of strings that are URLs. urls: list of strings that are URLs.
""" """
for url in urls: with qbittorrentapi.Client(**conn_info) as qbt_client:
qb.download_from_link(url, category="distro") for url in urls:
print(f"Added {os.path.basename(url)}") response = requests.get(url)
if response.status_code == 200:
if qbt_client.torrents_add(url, category="distro") != "Ok.":
raise Exception("Failed to add torrent: " + os.path.basename(url))
else:
print(f"Added {os.path.basename(url)}")
else:
print(f"{response.status_code}: {url}")
def add_torrents_from_html(webpage_url: str, torrent_substring: str): def add_torrents_from_html(webpage_url: str, torrent_substring: str):
@ -52,11 +69,21 @@ def add_torrents_from_html(webpage_url: str, torrent_substring: str):
""" """
reqs = requests.get(webpage_url, timeout=60) reqs = requests.get(webpage_url, timeout=60)
soup = BeautifulSoup(reqs.text, "html.parser") soup = BeautifulSoup(reqs.text, "html.parser")
for link in soup.find_all("a"): with qbittorrentapi.Client(**conn_info) as qbt_client:
if torrent_substring in link.get("href"): for link in soup.find_all("a"):
url = f"{webpage_url}/{link.get('href')}" if torrent_substring in link.get("href"):
qb.download_from_link(url, category="distro") url = f"{webpage_url}/{link.get('href')}"
print(f"Added {link.get('href')}") response = requests.get(url)
if response.status_code == 200:
if qbt_client.torrents_add(url, category="distro") != "Ok.":
raise Exception(
"Failed to add torrent: " + os.path.basename(url)
)
else:
print(f"Added {os.path.basename(url)}")
else:
print(f"{response.status_code}: {url}")
def remove_torrents(distro_substring: str): def remove_torrents(distro_substring: str):
@ -69,10 +96,13 @@ def remove_torrents(distro_substring: str):
distro_substring: a string that is a substring of the distro distro_substring: a string that is a substring of the distro
torrent's file name. torrent's file name.
""" """
for torrent in qb.torrents(): with qbittorrentapi.Client(**conn_info) as qbt_client:
if distro_substring in torrent.get("name"): # type: ignore for torrent in qbt_client.torrents_info():
qb.delete_permanently(torrent.get("hash")) # type: ignore if distro_substring in torrent.name:
print(f"Removed {torrent.get('name')}") # type: ignore qbt_client.torrents_delete(
torrent_hashes=torrent.hash, delete_files=True
)
print(f"Removed {torrent.name}")
def add_almalinux(rel_ver: str): def add_almalinux(rel_ver: str):
@ -142,8 +172,7 @@ def add_devuan(rel_ver: str):
relver: the Devuan release version. relver: the Devuan release version.
""" """
url = f"https://files.devuan.org/devuan_{rel_ver}.torrent" url = f"https://files.devuan.org/devuan_{rel_ver}.torrent"
qb.download_from_link(url, category="distro") add_torrents([url])
print(f"Added {os.path.basename(url)}")
def remove_devuan(rel_ver: str): def remove_devuan(rel_ver: str):
@ -175,11 +204,13 @@ def remove_fedora(rel_ver: str):
Params: Params:
relver: the Fedora release version. relver: the Fedora release version.
""" """
torrents = qb.torrents() with qbittorrentapi.Client(**conn_info) as qbt_client:
for torrent in torrents: for torrent in qbt_client.torrents_info():
if torrent.get("name").startswith("Fedora") and torrent.get("name").endswith(rel_ver): # type: ignore if torrent.name.startswith("Fedora") and torrent.name.endswith(rel_ver):
qb.delete_permanently(torrent.get("hash")) # type: ignore qbt_client.torrents_delete(
print(f"Removed {torrent.get('name')}") # type: ignore torrent_hashes=torrent.hash, delete_files=True
)
print(f"Removed {torrent.name}")
def add_freebsd(rel_ver: str): def add_freebsd(rel_ver: str):
@ -194,10 +225,13 @@ def add_freebsd(rel_ver: str):
reqs = requests.get(url, timeout=60) reqs = requests.get(url, timeout=60)
data = reqs.text.split("\n") data = reqs.text.split("\n")
for line in data: with qbittorrentapi.Client(**conn_info) as qbt_client:
if line.startswith("magnet:"): for line in data:
qb.download_from_link(line, category="distro") if line.startswith("magnet:"):
print(f"Added {line.split('=')[2]}") if qbt_client.torrents_add(line) != "Ok.":
raise Exception("Failed to add torrent: " + line.split("=")[2])
print(f"Added {line.split('=')[2]}")
def remove_freebsd(rel_ver: str): def remove_freebsd(rel_ver: str):
@ -266,9 +300,25 @@ def add_nixos():
url = "https://api.github.com/repos/AnimMouse/NixOS-ISO-Torrents/releases/latest" url = "https://api.github.com/repos/AnimMouse/NixOS-ISO-Torrents/releases/latest"
reqs = requests.get(url, timeout=60) reqs = requests.get(url, timeout=60)
json_data = json.loads(reqs.text) json_data = json.loads(reqs.text)
for item in json_data["assets"]:
qb.download_from_link(item["browser_download_url"], category="distro") with qbittorrentapi.Client(**conn_info) as qbt_client:
print(f"Added {os.path.basename(item['browser_download_url'])}") for item in json_data["assets"]:
response = requests.get(item["browser_download_url"])
if response.status_code == 200:
if (
qbt_client.torrents_add(
item["browser_download_url"], category="distro"
)
!= "Ok."
):
raise Exception(
"Failed to add torrent: "
+ os.path.basename(item["browser_download_url"])
)
else:
print(f"Added {os.path.basename(item['browser_download_url'])}")
else:
print(f"{response.status_code}: {item['browser_download_url']}")
def remove_nixos(): def remove_nixos():
@ -289,8 +339,16 @@ def add_qubes(rel_ver: str):
relver: the QubesOS release version. relver: the QubesOS release version.
""" """
url = f"https://mirrors.edge.kernel.org/qubes/iso/Qubes-R{rel_ver}-x86_64.torrent" url = f"https://mirrors.edge.kernel.org/qubes/iso/Qubes-R{rel_ver}-x86_64.torrent"
qb.download_from_link(url, category="distro")
print(f"Added {os.path.basename(url)}") response = requests.get(url)
if response.status_code == 200:
with qbittorrentapi.Client(**conn_info) as qbt_client:
if qbt_client.torrents_add(url, category="distro") != "Ok.":
raise Exception("Failed to add torrent: " + os.path.basename(url))
else:
print(f"Added {os.path.basename(url)}")
else:
print(f"{response.status_code}: {url}")
def remove_qubes(rel_ver: str): def remove_qubes(rel_ver: str):
@ -356,6 +414,10 @@ def remove_tails(rel_ver: str):
if __name__ == "__main__": if __name__ == "__main__":
# Check if gum is installed.
if which("gum") is None:
exit("Please install gum first. https://github.com/charmbracelet/gum")
# Run the gum program in a subprocess to allow easy selecting of distro # Run the gum program in a subprocess to allow easy selecting of distro
# torrents. # torrents.
distro_selection = subprocess.run( distro_selection = subprocess.run(

View File

@ -39,9 +39,9 @@ Options:
import json import json
import qbittorrentapi
import requests import requests
from docopt import docopt from docopt import docopt
from qbittorrent import Client
def get_torrent_health_data() -> list[dict]: def get_torrent_health_data() -> list[dict]:
@ -62,6 +62,8 @@ def convert_size_to_bytes(size: str) -> int:
Example: 42G --> 45097156608 bytes Example: 42G --> 45097156608 bytes
""" """
total_bytes = int()
if size.endswith("T"): if size.endswith("T"):
total_bytes = int(size.split("T")[0]) * (1024**4) total_bytes = int(size.split("T")[0]) * (1024**4)
@ -157,8 +159,14 @@ if __name__ == "__main__":
dry_run = args["--dry-run"] dry_run = args["--dry-run"]
# Initialize client and login # Initialize client and login
qb = Client(hostname) qbt_client = qbittorrentapi.Client(
qb.login(username=username, password=password) host=hostname, username=username, password=password
)
try:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
print(e)
# Fill the knapsack # Fill the knapsack
knapsack = fill_knapsack(max_seeders, knapsack_size, smaller) knapsack = fill_knapsack(max_seeders, knapsack_size, smaller)
@ -183,13 +191,15 @@ if __name__ == "__main__":
for torrent in knapsack: for torrent in knapsack:
if "gen.lib.rus.ec" in torrent["link"]: if "gen.lib.rus.ec" in torrent["link"]:
new_torrent = torrent["link"].replace("gen.lib.rus.ec", "libgen.is") new_torrent = torrent["link"].replace("gen.lib.rus.ec", "libgen.is")
qb.download_from_link(new_torrent, category="scihub") qbt_client.torrents_add(new_torrent, category="scihub")
if "libgen.rs" in torrent["link"]: if "libgen.rs" in torrent["link"]:
new_torrent = torrent["link"].replace("libgen.rs", "libgen.is") new_torrent = torrent["link"].replace("libgen.rs", "libgen.is")
qb.download_from_link(new_torrent, category="scihub") qbt_client.torrents_add(new_torrent, category="scihub")
# print(f"Added {torrent['name']}") # print(f"Added {torrent['name']}")
qbt_client.auth_log_out()
print("----------------") print("----------------")
print(f"Count: {len(knapsack)} torrents") print(f"Count: {len(knapsack)} torrents")
print(f"Total combined size: {get_knapsack_weight(knapsack)}") print(f"Total combined size: {get_knapsack_weight(knapsack)}")

View File

@ -1,63 +0,0 @@
#!/usr/bin/env python3
"""seed_armbian_torrents.py
Description:
Armbian torrents seed script
This script will download Armbian torrent files and add them to a qBittorrent
instance. It's intended to be run under /etc/cron.weekly or used in a systemd
timer.
This is a Python implementation of https://docs.armbian.com/Community_Torrent/
for qBittorrent.
Usage:
seed_armbian_torrents.py (HOSTNAME) (USERNAME) (PASSWORD)
seed_armbian_torrents.py -h
Examples:
seed_armbian_torrents.py "http://localhost:8080" "admin" "adminadmin"
seed_armbian_torrents.py "https://cat.seedhost.eu/lol/qbittorrent" "lol" "pw"
Options:
-h, --help show this help message and exit.
"""
import os
from io import BytesIO
from tempfile import TemporaryDirectory
from zipfile import ZipFile
import requests
from docopt import docopt
from qbittorrent import Client
if __name__ == "__main__":
args = docopt(__doc__)
# Initialize client and login
qb = Client(args["HOSTNAME"])
qb.login(username=args["USERNAME"], password=args["PASSWORD"])
with TemporaryDirectory() as tmp_dir:
req = requests.get(
"https://dl.armbian.com/torrent/all-torrents.zip",
stream=True,
timeout=60,
)
with ZipFile(BytesIO(req.content)) as zip_file:
zip_file.extractall(tmp_dir)
for torrent in qb.torrents():
if "Armbian" in torrent.get("name"): # type: ignore
qb.delete_permanently(torrent.get("hash")) # type: ignore
print(f"Removed {torrent.get('name')}") # type: ignore
torrent_files = os.listdir(tmp_dir)
for torrent_file in torrent_files:
with open(os.path.join(tmp_dir, torrent_file), "rb") as tf:
qb.download_from_file(tf, category="distro")
print(
f"Added {os.path.basename(os.path.join(tmp_dir, torrent_file))}"
)

View File

@ -1,44 +0,0 @@
with import <nixpkgs> { };
let
python-qbittorrent = pkgs.python312Packages.buildPythonPackage rec {
name = "python-qbittorrent-${version}";
version = "0.4.3";
src = pkgs.fetchurl {
url = "https://files.pythonhosted.org/packages/86/25/a5ad35ad229c8016a8c98327495e649cb795be2fda63f8cace6c9a739af7/python-qbittorrent-${version}.tar.gz";
sha256 = "4e22cf89890628b054a60aa4bd1161a68c2b0fad48ef0886fa4d325e69d3828a";
};
meta = {
homepage = "https://github.com/v1k45/python-qBittorrent";
description = "Python wrapper for qBittorrent Web API (for versions above v3.1.x)";
license = lib.licenses.mit;
maintainers = with maintainers; [ v1k45 ];
};
nativeBuildInputs = with pkgs.python312Packages; [
pip
requests
];
};
in
mkShell {
buildInputs = with pkgs; [
python312Packages.beautifulsoup4
python312Packages.black
python312Packages.bpython
python312Packages.docopt
python312Packages.isort
python312Packages.pandas
python312Packages.pytest
python312Packages.requests
python312Packages.resend
python312Packages.rich
python312Packages.tabulate
pyright
python-qbittorrent
shellcheck
];
}

View File

@ -28,8 +28,8 @@ import subprocess
import tempfile import tempfile
from pathlib import Path from pathlib import Path
import qbittorrentapi
from docopt import docopt from docopt import docopt
from qbittorrent import Client
from rich.console import Console from rich.console import Console
from rich.text import Text from rich.text import Text
@ -53,11 +53,18 @@ if __name__ == "__main__":
) )
torrent_infohashes = [] torrent_infohashes = []
for item in auth_data["instances"]: for item in auth_data["instances"]:
qb = Client(item["hostname"]) with qbittorrentapi.Client(
qb.login(username=item["username"], password=item["password"]) host=item["hostname"],
username=item["username"],
password=item["password"],
) as qbt_client:
try:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
print(e)
for torrent in qb.torrents(): for torrent in qbt_client.torrents_info():
torrent_infohashes.append(torrent.get("hash")) # type: ignore torrent_infohashes.append(torrent.hash)
# Format the infohashes to have a \n at the end # Format the infohashes to have a \n at the end
console.log("Formatting infohashes to have a newline at the end.") console.log("Formatting infohashes to have a newline at the end.")
@ -97,28 +104,16 @@ if __name__ == "__main__":
] ]
) )
# Ensure {tracker_domain}:6969/announce is added to each torrent's
# tracker list.
if tracker_domain:
console.log(
f"Ensuring {tracker_domain}:6969/announce is added to each torrent's tracker list."
)
for item in auth_data["instances"]:
qb = Client(item["hostname"])
qb.login(username=item["username"], password=item["password"])
for torrent in qb.torrents():
qb.add_trackers(
torrent.get("hash"), # type: ignore
f"http://{tracker_domain}:6969/announce\nudp://{tracker_domain}:6969/announce",
)
# Reannounce all torrents in each qBittorrent instance to their trackers # Reannounce all torrents in each qBittorrent instance to their trackers
console.log("Reannouncing all torrents to their trackers.") console.log("Reannouncing all torrents to their trackers.")
for item in auth_data["instances"]: for item in auth_data["instances"]:
qb = Client(item["hostname"]) with qbittorrentapi.Client(
qb.login(username=item["username"], password=item["password"]) host=item["hostname"],
torrent_infohashes = [torrent.get("hash") for torrent in qb.torrents()] # type: ignore username=item["username"],
qb.reannounce(torrent_infohashes) password=item["password"],
) as qbt_client:
for torrent in qbt_client.torrents_info():
torrent.reannounce(torrent.hash)
console.log("Done!") console.log("Done!")