mirror of
https://codeberg.org/hyperreal/admin-scripts
synced 2024-11-25 09:03:41 +01:00
Compare commits
No commits in common. "af5873f37a8a63ae957a93d9c5e7f0696e853945" and "7e09519e626e058abe5eab9447df74d6ee60ee76" have entirely different histories.
af5873f37a
...
7e09519e62
4
.envrc
4
.envrc
@ -1,3 +1 @@
|
|||||||
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
|
use nix
|
||||||
|
|
||||||
use devenv
|
|
||||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,10 +1 @@
|
|||||||
.direnv
|
.direnv
|
||||||
# Devenv
|
|
||||||
.devenv*
|
|
||||||
devenv.local.nix
|
|
||||||
|
|
||||||
# direnv
|
|
||||||
.direnv
|
|
||||||
|
|
||||||
# pre-commit
|
|
||||||
.pre-commit-config.yaml
|
|
||||||
|
45
add_qbt_trackers.py
Executable file
45
add_qbt_trackers.py
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/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
116
devenv.lock
@ -1,116 +0,0 @@
|
|||||||
{
|
|
||||||
"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
34
devenv.nix
@ -1,34 +0,0 @@
|
|||||||
{ 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
15
devenv.yaml
@ -1,15 +0,0 @@
|
|||||||
# 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
|
|
@ -15,8 +15,9 @@ 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
|
||||||
@ -42,25 +43,36 @@ def human_bytes(input_bytes: int) -> str:
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def print_ssv():
|
def print_table():
|
||||||
with qbittorrentapi.Client(
|
qb = Client("http://localhost:8080/")
|
||||||
host="localhost", port=8080, username="", password=""
|
qb.login()
|
||||||
) as qbt_client:
|
table = []
|
||||||
try:
|
headers = ["Name", "Total Size", "Trackers Count", "Ratio", "Uploaded"]
|
||||||
qbt_client.auth_log_in()
|
sorted_torrents = sorted(qb.torrents(), key=lambda d: d["ratio"], reverse=True) # type: ignore
|
||||||
except qbittorrentapi.LoginFailed as e:
|
for torrent in sorted_torrents:
|
||||||
print(e)
|
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)
|
||||||
|
|
||||||
sorted_torrents = sorted(
|
print(tabulate(table, headers, tablefmt="grid"))
|
||||||
qbt_client.torrents_info(), key=lambda d: d.ratio, reverse=True
|
|
||||||
)
|
|
||||||
for torrent in sorted_torrents:
|
def print_ssv():
|
||||||
name = torrent.name
|
qb = Client("http://localhost:8080/")
|
||||||
size = human_bytes(torrent.total_size)
|
qb.login()
|
||||||
trackers = torrent.trackers_count
|
sorted_torrents = sorted(qb.torrents(), key=lambda d: d["ratio"], reverse=True) # type: ignore
|
||||||
ratio = torrent.ratio
|
print("Name Size Trackers Ratio Uploaded")
|
||||||
uploaded = human_bytes(torrent.uploaded)
|
for torrent in sorted_torrents:
|
||||||
print(f"{name} {size} {trackers} {ratio} {uploaded}")
|
name = torrent["name"] # type: ignore
|
||||||
|
size = human_bytes(int(torrent["total_size"])) # type: ignore
|
||||||
|
trackers = torrent["trackers_count"] # type: ignore
|
||||||
|
ratio = torrent["ratio"] # type: ignore
|
||||||
|
uploaded = human_bytes(int(torrent["uploaded"])) # type: ignore
|
||||||
|
print(f"{name} {size} {trackers} {ratio} {uploaded}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -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,26 +48,21 @@ 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 = []
|
||||||
total_added_bytes = int()
|
for torrent in qb.torrents():
|
||||||
|
if torrent["completion_on"] != 0: # type: ignore
|
||||||
with qbittorrentapi.Client(
|
completed_torrent_sizes.append(torrent["total_size"]) # type: ignore
|
||||||
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
124
qbth.py
@ -17,25 +17,15 @@ 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__)
|
||||||
conn_info = dict(
|
qb = Client(args["HOSTNAME"])
|
||||||
host=args["HOSTNAME"],
|
qb.login(username=args["USERNAME"], password=args["PASSWORD"])
|
||||||
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]):
|
||||||
@ -45,16 +35,9 @@ def add_torrents(urls: list[str]):
|
|||||||
Params:
|
Params:
|
||||||
urls: list of strings that are URLs.
|
urls: list of strings that are URLs.
|
||||||
"""
|
"""
|
||||||
with qbittorrentapi.Client(**conn_info) as qbt_client:
|
for url in urls:
|
||||||
for url in urls:
|
qb.download_from_link(url, category="distro")
|
||||||
response = requests.get(url)
|
print(f"Added {os.path.basename(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):
|
||||||
@ -69,21 +52,11 @@ 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")
|
||||||
with qbittorrentapi.Client(**conn_info) as qbt_client:
|
for link in soup.find_all("a"):
|
||||||
for link in soup.find_all("a"):
|
if torrent_substring in link.get("href"):
|
||||||
if torrent_substring in link.get("href"):
|
url = f"{webpage_url}/{link.get('href')}"
|
||||||
url = f"{webpage_url}/{link.get('href')}"
|
qb.download_from_link(url, category="distro")
|
||||||
response = requests.get(url)
|
print(f"Added {link.get('href')}")
|
||||||
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):
|
||||||
@ -96,13 +69,10 @@ 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.
|
||||||
"""
|
"""
|
||||||
with qbittorrentapi.Client(**conn_info) as qbt_client:
|
for torrent in qb.torrents():
|
||||||
for torrent in qbt_client.torrents_info():
|
if distro_substring in torrent.get("name"): # type: ignore
|
||||||
if distro_substring in torrent.name:
|
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_almalinux(rel_ver: str):
|
def add_almalinux(rel_ver: str):
|
||||||
@ -172,7 +142,8 @@ 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"
|
||||||
add_torrents([url])
|
qb.download_from_link(url, category="distro")
|
||||||
|
print(f"Added {os.path.basename(url)}")
|
||||||
|
|
||||||
|
|
||||||
def remove_devuan(rel_ver: str):
|
def remove_devuan(rel_ver: str):
|
||||||
@ -204,13 +175,11 @@ def remove_fedora(rel_ver: str):
|
|||||||
Params:
|
Params:
|
||||||
relver: the Fedora release version.
|
relver: the Fedora release version.
|
||||||
"""
|
"""
|
||||||
with qbittorrentapi.Client(**conn_info) as qbt_client:
|
torrents = qb.torrents()
|
||||||
for torrent in qbt_client.torrents_info():
|
for torrent in torrents:
|
||||||
if torrent.name.startswith("Fedora") and torrent.name.endswith(rel_ver):
|
if torrent.get("name").startswith("Fedora") and torrent.get("name").endswith(rel_ver): # type: ignore
|
||||||
qbt_client.torrents_delete(
|
qb.delete_permanently(torrent.get("hash")) # type: ignore
|
||||||
torrent_hashes=torrent.hash, delete_files=True
|
print(f"Removed {torrent.get('name')}") # type: ignore
|
||||||
)
|
|
||||||
print(f"Removed {torrent.name}")
|
|
||||||
|
|
||||||
|
|
||||||
def add_freebsd(rel_ver: str):
|
def add_freebsd(rel_ver: str):
|
||||||
@ -225,13 +194,10 @@ 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")
|
||||||
|
|
||||||
with qbittorrentapi.Client(**conn_info) as qbt_client:
|
for line in data:
|
||||||
for line in data:
|
if line.startswith("magnet:"):
|
||||||
if line.startswith("magnet:"):
|
qb.download_from_link(line, category="distro")
|
||||||
if qbt_client.torrents_add(line) != "Ok.":
|
print(f"Added {line.split('=')[2]}")
|
||||||
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):
|
||||||
@ -300,25 +266,9 @@ 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"]:
|
||||||
with qbittorrentapi.Client(**conn_info) as qbt_client:
|
qb.download_from_link(item["browser_download_url"], category="distro")
|
||||||
for item in json_data["assets"]:
|
print(f"Added {os.path.basename(item['browser_download_url'])}")
|
||||||
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():
|
||||||
@ -339,16 +289,8 @@ 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")
|
||||||
response = requests.get(url)
|
print(f"Added {os.path.basename(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):
|
||||||
@ -414,10 +356,6 @@ 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(
|
||||||
|
@ -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,8 +62,6 @@ 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)
|
||||||
|
|
||||||
@ -159,14 +157,8 @@ if __name__ == "__main__":
|
|||||||
dry_run = args["--dry-run"]
|
dry_run = args["--dry-run"]
|
||||||
|
|
||||||
# Initialize client and login
|
# Initialize client and login
|
||||||
qbt_client = qbittorrentapi.Client(
|
qb = Client(hostname)
|
||||||
host=hostname, username=username, password=password
|
qb.login(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)
|
||||||
@ -191,15 +183,13 @@ 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")
|
||||||
qbt_client.torrents_add(new_torrent, category="scihub")
|
qb.download_from_link(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")
|
||||||
qbt_client.torrents_add(new_torrent, category="scihub")
|
qb.download_from_link(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)}")
|
||||||
|
63
seed_armbian_torrents.py
Executable file
63
seed_armbian_torrents.py
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/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))}"
|
||||||
|
)
|
44
shell.nix
Normal file
44
shell.nix
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
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
|
||||||
|
];
|
||||||
|
}
|
@ -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,18 +53,11 @@ if __name__ == "__main__":
|
|||||||
)
|
)
|
||||||
torrent_infohashes = []
|
torrent_infohashes = []
|
||||||
for item in auth_data["instances"]:
|
for item in auth_data["instances"]:
|
||||||
with qbittorrentapi.Client(
|
qb = Client(item["hostname"])
|
||||||
host=item["hostname"],
|
qb.login(username=item["username"], password=item["password"])
|
||||||
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 qbt_client.torrents_info():
|
for torrent in qb.torrents():
|
||||||
torrent_infohashes.append(torrent.hash)
|
torrent_infohashes.append(torrent.get("hash")) # type: ignore
|
||||||
|
|
||||||
# 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.")
|
||||||
@ -104,16 +97,28 @@ 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"]:
|
||||||
with qbittorrentapi.Client(
|
qb = Client(item["hostname"])
|
||||||
host=item["hostname"],
|
qb.login(username=item["username"], password=item["password"])
|
||||||
username=item["username"],
|
torrent_infohashes = [torrent.get("hash") for torrent in qb.torrents()] # type: ignore
|
||||||
password=item["password"],
|
qb.reannounce(torrent_infohashes)
|
||||||
) as qbt_client:
|
|
||||||
for torrent in qbt_client.torrents_info():
|
|
||||||
torrent.reannounce(torrent.hash)
|
|
||||||
|
|
||||||
console.log("Done!")
|
console.log("Done!")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user