First commit
This commit is contained in:
+165
@@ -0,0 +1,165 @@
|
|||||||
|
# Custom
|
||||||
|
*.cookies
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||||
|
.pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# UNIT3D Seedbox Manager
|
||||||
|
|
||||||
|
For when you have a non-static IP on your seedbox and this is a script that can automagically manage it for you.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
seedbox.py tracker username [ip] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
> It is up to **you** as user to fill in the `tracker.py` file with all your own trackers. There are two trackers in the file as an example.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
You will need a `Netscape HTTP Cookie File` with the cookie `remember_web_*` from the UNIT3D tracker of your choice. Basically, login and then save the cookies to a file called `unit3d.cookies` and place it in the script folder or use the `--cookie-file` option with a custom file.
|
||||||
|
|
||||||
|
## All options
|
||||||
|
|
||||||
|
- `--help`, `--print | --no-print`, `--seedbox-name`, `--delete | --no-delete`, `--cookie-file`
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
python ./seedbox.py TRACKER USERNAME 1.1.1.2 --no-delete --seedbox-name SeedExample1 --print
|
||||||
|
|
||||||
|
| Name IP ID
|
||||||
|
| -----------------------------------------------------
|
||||||
|
| MainBox 192.168.12.234 1448
|
||||||
|
| SeedExample 1.1.1.1 1455
|
||||||
|
|
||||||
|
Successfully added Seedbox "SeedExample1" (1.1.1.2) to TRACKER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Help
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
usage: seedbox.py tracker username [ip] [options]
|
||||||
|
|
||||||
|
Automagically add or remove seedbox entries on any UNIT3D
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
tracker Tracker name or abbreviation.
|
||||||
|
username username
|
||||||
|
ip IP of the seedbox
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--print, --no-print Prints list of seedboxes (default: False)
|
||||||
|
--seedbox-name SEEDBOX_NAME
|
||||||
|
Name of the seedbox (default: PikminBox)
|
||||||
|
--delete, --no-delete
|
||||||
|
Deletes all old seedbox entries (default: False)
|
||||||
|
--cookie-file COOKIE_FILE
|
||||||
|
Cookies to be used when making requests (default: ./unit3d.cookies)
|
||||||
|
|
||||||
|
For bugs/errors, please DM me on FnP or make an issue on GitHub
|
||||||
|
```
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 1. Update qBittorrent port
|
||||||
|
python3 /pia/scripts/qbitport.py "$1"
|
||||||
|
|
||||||
|
# 2. Get WireGuard IP
|
||||||
|
ip_adress=$(wg show | grep 'endpoint: ' | awk -F ':' '{print $2}' | xargs)
|
||||||
|
|
||||||
|
# 3. Update Unit3D seedboxes
|
||||||
|
trackers=("fnp" "sp" "rs" "ulcx" "dps" "lum")
|
||||||
|
|
||||||
|
for tracker in "${trackers[@]}"; do
|
||||||
|
python3 /pia/scripts/seedbox.py "$tracker" swedish_wiking "$ip_adress" --delete --seedbox-name MainFrame
|
||||||
|
done
|
||||||
|
|
||||||
|
# 4. Update MaM seedbox
|
||||||
|
python3 /pia/scripts/mam_seedbox.py
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# mam_seedbox.py
|
||||||
|
|
||||||
|
import json
|
||||||
|
import urllib.error
|
||||||
|
import urllib.request
|
||||||
|
from http.cookies import SimpleCookie
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
__location__ = Path(__file__).parent.resolve()
|
||||||
|
cookie_file = __location__.joinpath("mam_id")
|
||||||
|
api_url = "https://t.myanonamouse.net/json/dynamicSeedbox.php"
|
||||||
|
|
||||||
|
|
||||||
|
def save_cookie(headers):
|
||||||
|
set_cookie_header = headers.get("Set-Cookie")
|
||||||
|
if set_cookie_header:
|
||||||
|
cookie = SimpleCookie(set_cookie_header)
|
||||||
|
if "mam_id" in cookie:
|
||||||
|
cookie_file.write_text(cookie["mam_id"].value)
|
||||||
|
|
||||||
|
|
||||||
|
def load_cookie() -> str:
|
||||||
|
if not cookie_file.exists():
|
||||||
|
print("Warning: mam_id file not found. Proceeding without it...", flush=True)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
mam_id = cookie_file.read_text().strip()
|
||||||
|
return f"mam_id={mam_id}"
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Updating MaM Dynamic Seedbox IP...", flush=True)
|
||||||
|
|
||||||
|
req = urllib.request.Request(api_url)
|
||||||
|
cookie_val = load_cookie()
|
||||||
|
if cookie_val:
|
||||||
|
req.add_header("Cookie", cookie_val)
|
||||||
|
|
||||||
|
status_code = None
|
||||||
|
data = {}
|
||||||
|
headers = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req) as response:
|
||||||
|
status_code = response.status
|
||||||
|
data = json.loads(response.read().decode("utf-8"))
|
||||||
|
headers = response.headers
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
status_code = e.code
|
||||||
|
try:
|
||||||
|
data = json.loads(e.read().decode("utf-8"))
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
data = {"msg": "Unknown server error"}
|
||||||
|
except urllib.error.URLError as e:
|
||||||
|
print(f"Failed to connect to MaM: {e.reason}", flush=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
msg = data.get("msg", "No message provided")
|
||||||
|
|
||||||
|
match status_code:
|
||||||
|
case 200:
|
||||||
|
print(f"Successfully updated MaM seedbox: {msg}", flush=True)
|
||||||
|
save_cookie(headers)
|
||||||
|
case 429:
|
||||||
|
print(f"Failed to update MaM seedbox (Rate Limited): {msg}", flush=True)
|
||||||
|
case 403:
|
||||||
|
print(f"Failed to update MaM seedbox (Forbidden): {msg}", flush=True)
|
||||||
|
case _:
|
||||||
|
print(f"Something went VERY wrong... HTTP {status_code}: {msg}", flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
# qbitport.py
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import urllib.error
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
prog="qBittorrent Port Manager",
|
||||||
|
description="Update your qBittorrent port",
|
||||||
|
usage=f"{Path(__file__).name} port [options]",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument("port", type=str, help="Forwarding Port")
|
||||||
|
parser.add_argument(
|
||||||
|
"--host",
|
||||||
|
type=str,
|
||||||
|
default="localhost",
|
||||||
|
help="IP/hostname of qBittorrent instance (default: %(default)s)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--host-port",
|
||||||
|
type=int,
|
||||||
|
default=8080,
|
||||||
|
help="qBittorrent port (default: %(default)s)",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def ping_until_connected(url, max_retries=12):
|
||||||
|
req = urllib.request.Request(url, method="HEAD")
|
||||||
|
retries = 0
|
||||||
|
while retries < max_retries:
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req, timeout=5) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
return True
|
||||||
|
except (urllib.error.URLError, TimeoutError):
|
||||||
|
print(
|
||||||
|
f"{url} is unreachable, trying again in 5 sec... ({retries + 1}/{max_retries})",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
time.sleep(5)
|
||||||
|
retries += 1
|
||||||
|
|
||||||
|
print("Error: Could not connect to qBittorrent after maximum retries.", flush=True)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
base_url = f"http://{args.host}:{args.host_port}"
|
||||||
|
print("Establishing connection with qBittorrent...", flush=True)
|
||||||
|
ping_until_connected(base_url)
|
||||||
|
print("Connection established", flush=True)
|
||||||
|
|
||||||
|
print(f"Setting qBittorrent port settings ({args.port})...", flush=True)
|
||||||
|
|
||||||
|
prefs_data = urllib.parse.urlencode(
|
||||||
|
{"json": json.dumps({"listen_port": int(args.port)})}
|
||||||
|
).encode("utf-8")
|
||||||
|
prefs_req = urllib.request.Request(
|
||||||
|
f"{base_url}/api/v2/app/setPreferences", data=prefs_data
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(prefs_req, timeout=10) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
print("Port has been set!", flush=True)
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
print(
|
||||||
|
f"HTTP Error {e.code}: Failed to set port. (Is auth bypass enabled in qBittorrent?)",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
# seedbox.py
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from trackers import trackers
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
prog="Unit3D seedbox manager",
|
||||||
|
description="Automagically add or remove seedbox entries on any Unit3D",
|
||||||
|
usage=f"{Path(__file__).name} tracker username [ip] [options] ",
|
||||||
|
epilog="For bugs/errors, please DM me on FnP or make an issue on GitHub",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument("tracker", type=str, help="Tracker")
|
||||||
|
parser.add_argument("username", type=str, help="Username")
|
||||||
|
parser.add_argument("ip", nargs="?", type=str, help="IP of the seedbox")
|
||||||
|
parser.add_argument(
|
||||||
|
"--print",
|
||||||
|
default=False,
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
help="Prints list of seedboxes",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--seedbox-name",
|
||||||
|
type=str,
|
||||||
|
default="PikminBox",
|
||||||
|
help="Name of the seedbox (default: %(default)s)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--delete",
|
||||||
|
default=False,
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
help="Deletes all old seedbox entries",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--cookie-file",
|
||||||
|
type=Path,
|
||||||
|
default=Path(__file__).parent.joinpath("unit3d.cookies"),
|
||||||
|
help="Cookies to be used",
|
||||||
|
)
|
||||||
|
parsed_args = parser.parse_args()
|
||||||
|
|
||||||
|
COOKIE_HEADER = ""
|
||||||
|
|
||||||
|
|
||||||
|
def generateHeaders(host: str) -> dict:
|
||||||
|
headers = {
|
||||||
|
"Host": host,
|
||||||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0",
|
||||||
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||||
|
"Accept-Language": "en-US,en;q=0.5",
|
||||||
|
"Origin": f"https://{host}",
|
||||||
|
"DNT": "1",
|
||||||
|
"Sec-GPC": "1",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Upgrade-Insecure-Requests": "1",
|
||||||
|
}
|
||||||
|
if COOKIE_HEADER:
|
||||||
|
headers["Cookie"] = COOKIE_HEADER
|
||||||
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
def parseTracker(tracker: str) -> dict:
|
||||||
|
for t in trackers:
|
||||||
|
if tracker.lower() in [x.lower() for x in t.values()]:
|
||||||
|
return t
|
||||||
|
print(f'No tracker in database matched "{tracker}"')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def parseCookieFile(file: Path, domain: str) -> None:
|
||||||
|
global COOKIE_HEADER
|
||||||
|
with open(file, "r") as f:
|
||||||
|
for line in f:
|
||||||
|
if not re.match(r"^\#", line) and not re.match(r"^\s*$", line):
|
||||||
|
lineFields = line.strip().split("\t")
|
||||||
|
if domain in lineFields[0]:
|
||||||
|
COOKIE_HEADER = f"{lineFields[5]}={lineFields[6]}"
|
||||||
|
return
|
||||||
|
print(f"No remember_web_* cookie was found in {file}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def getSeedboxes(domain: str) -> tuple[list[dict], str]:
|
||||||
|
try:
|
||||||
|
req = urllib.request.Request(
|
||||||
|
f"https://{domain}/users/{parsed_args.username}/seedboxes",
|
||||||
|
headers=generateHeaders(domain),
|
||||||
|
)
|
||||||
|
with urllib.request.urlopen(req) as resp:
|
||||||
|
html = resp.read().decode("utf-8")
|
||||||
|
|
||||||
|
token_match = re.search(
|
||||||
|
r'<meta\s+name="csrf-token"\s+content="([^"]+)"', html, re.IGNORECASE
|
||||||
|
)
|
||||||
|
if not token_match:
|
||||||
|
raise Exception("Could not find CSRF token on the page.")
|
||||||
|
add_token = token_match.group(1)
|
||||||
|
|
||||||
|
pattern = re.compile(
|
||||||
|
r'<td>\s*(.*?)\s*</td>\s*<td>\s*(.*?)\s*</td>.*?action="[^"]+/seedboxes/(\d+)".*?name="_token"\s+value="([^"]+)"',
|
||||||
|
re.DOTALL | re.IGNORECASE,
|
||||||
|
)
|
||||||
|
|
||||||
|
seedboxes = [
|
||||||
|
{
|
||||||
|
"name": m.group(1).strip(),
|
||||||
|
"ip": m.group(2).strip(),
|
||||||
|
"id": m.group(3),
|
||||||
|
"token": m.group(4),
|
||||||
|
}
|
||||||
|
for m in pattern.finditer(html)
|
||||||
|
]
|
||||||
|
|
||||||
|
return seedboxes, add_token
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error while getting seedboxes: {e}", flush=True)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def addSeedbox(domain: str, token: str) -> bool:
|
||||||
|
try:
|
||||||
|
data = urllib.parse.urlencode(
|
||||||
|
{
|
||||||
|
"_token": token,
|
||||||
|
"name": parsed_args.seedbox_name,
|
||||||
|
"ip": parsed_args.ip,
|
||||||
|
}
|
||||||
|
).encode("utf-8")
|
||||||
|
|
||||||
|
req = urllib.request.Request(
|
||||||
|
f"https://{domain}/users/{parsed_args.username}/seedboxes",
|
||||||
|
data=data,
|
||||||
|
headers=generateHeaders(domain),
|
||||||
|
)
|
||||||
|
with urllib.request.urlopen(req) as resp:
|
||||||
|
html = resp.read().decode("utf-8")
|
||||||
|
|
||||||
|
error_match = re.search(
|
||||||
|
r'<div[^>]*id="ERROR_COPY"[^>]*>(.*?)</div>',
|
||||||
|
html,
|
||||||
|
re.DOTALL | re.IGNORECASE,
|
||||||
|
)
|
||||||
|
if error_match:
|
||||||
|
clean_error = re.sub(r"<[^>]+>", "", error_match.group(1))
|
||||||
|
error_msg = " ".join(
|
||||||
|
[x.strip() for x in clean_error.split("\n") if x.strip()]
|
||||||
|
)
|
||||||
|
raise Exception(error_msg)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to add seedbox", flush=True)
|
||||||
|
print(f"Error: {e}", flush=True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tracker = parseTracker(parsed_args.tracker)
|
||||||
|
domain = tracker["domain"]
|
||||||
|
parseCookieFile(parsed_args.cookie_file, domain)
|
||||||
|
|
||||||
|
seedboxes, add_token = getSeedboxes(domain)
|
||||||
|
|
||||||
|
if parsed_args.print:
|
||||||
|
print(f"Tracker: {tracker['name']}")
|
||||||
|
print(f"\n| {'Name':<25}{'IP':<20}{'ID':<5}")
|
||||||
|
print("| " + "-" * 53)
|
||||||
|
for sbox in seedboxes:
|
||||||
|
print(f"| {sbox['name']:<25}{sbox['ip']:<20}{sbox['id']:<5}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
if parsed_args.delete:
|
||||||
|
for sbox in seedboxes:
|
||||||
|
print(f'Deleting Seedbox: "{sbox["name"]}" ({sbox["ip"]})', flush=True)
|
||||||
|
data = urllib.parse.urlencode(
|
||||||
|
{"_token": sbox["token"], "_method": "DELETE"}
|
||||||
|
).encode("utf-8")
|
||||||
|
req = urllib.request.Request(
|
||||||
|
f"https://{domain}/users/{parsed_args.username}/seedboxes/{sbox['id']}",
|
||||||
|
data=data,
|
||||||
|
headers=generateHeaders(domain),
|
||||||
|
)
|
||||||
|
urllib.request.urlopen(req)
|
||||||
|
|
||||||
|
if parsed_args.ip:
|
||||||
|
if addSeedbox(domain, add_token):
|
||||||
|
print(
|
||||||
|
f"Successfully added Seedbox \"{parsed_args.seedbox_name}\" ({parsed_args.ip}) to {tracker['name']}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
# trackers.py
|
||||||
|
|
||||||
|
|
||||||
|
trackers = [
|
||||||
|
{"name": "FearNoPeer", "abbr": "FNP", "domain": "fearnopeer.com"},
|
||||||
|
{"name": "SeedPool", "abbr": "SP", "domain": "seedpool.org"},
|
||||||
|
{"name": "Rastastugan", "abbr": "RS", "domain": "rastastugan.org"},
|
||||||
|
{"name": "ULCX", "abbr": "ULCX", "domain": "upload.cx"},
|
||||||
|
{"name": "Darkpeers", "abbr": "DPS", "domain": "darkpeers.org"},
|
||||||
|
{"name": "Luminarr", "abbr": "LUM", "domain": "luminarr.me"},
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user