split js
This commit is contained in:
@@ -86,15 +86,6 @@ RTORRENT_CONFIG_FIELDS = [
|
||||
"description": "Maximum simultaneous HTTP connections for tracker and metadata requests.",
|
||||
"recommendation": "Moderate values reduce tracker pressure; increase only if tracker requests queue up.",
|
||||
},
|
||||
{
|
||||
"group": "Network",
|
||||
"key": "network.http.dns_cache_timeout",
|
||||
"label": "HTTP DNS cache timeout",
|
||||
"type": "number",
|
||||
"description": "Seconds rTorrent keeps DNS results for tracker and HTTP requests.",
|
||||
"recommendation": "Use a small positive value, for example 25, when many tracker hostnames are queried repeatedly.",
|
||||
"runtime_note": "Applied through SCGI immediately; new HTTP lookups use the updated timeout.",
|
||||
},
|
||||
{
|
||||
"group": "Network",
|
||||
"key": "network.http.ssl_verify_peer",
|
||||
@@ -171,65 +162,34 @@ RTORRENT_CONFIG_FIELDS = [
|
||||
{
|
||||
"group": "Throttle",
|
||||
"key": "throttle.max_downloads.global",
|
||||
"label": "Global download slots",
|
||||
"label": "Max active downloads",
|
||||
"type": "number",
|
||||
"description": "Global number of peer download slots across all torrents; this is not the active torrent count.",
|
||||
"recommendation": "Raise this on large instances so a few busy torrents do not starve the rest.",
|
||||
"runtime_note": "Applied through SCGI immediately; existing peer scheduling catches up gradually.",
|
||||
"description": "Maximum number of downloading torrents active at once.",
|
||||
"recommendation": "Match disk and network capacity; fewer active downloads often finish faster.",
|
||||
},
|
||||
{
|
||||
"group": "Throttle",
|
||||
"key": "throttle.max_uploads.global",
|
||||
"label": "Global upload slots",
|
||||
"label": "Max active uploads",
|
||||
"type": "number",
|
||||
"description": "Global number of peer upload slots across all torrents; this is not the active torrent count.",
|
||||
"recommendation": "Keep enough slots for many seeds, but stay below socket and file descriptor limits.",
|
||||
"runtime_note": "Applied through SCGI immediately; current peer connections may rebalance over time.",
|
||||
},
|
||||
{
|
||||
"group": "Throttle",
|
||||
"key": "throttle.max_downloads",
|
||||
"label": "Per-torrent download slots",
|
||||
"type": "number",
|
||||
"description": "Maximum peer download slots allowed for a single torrent in the default throttle group.",
|
||||
"recommendation": "Use values like 5-20 to prevent one torrent from consuming all global download slots.",
|
||||
"runtime_note": "Applied through SCGI immediately; it affects new and rebalanced peer slot allocation.",
|
||||
},
|
||||
{
|
||||
"group": "Throttle",
|
||||
"key": "throttle.max_uploads",
|
||||
"label": "Per-torrent upload slots",
|
||||
"type": "number",
|
||||
"description": "Maximum peer upload slots allowed for a single torrent in the default throttle group.",
|
||||
"recommendation": "Use conservative values on very large seedboxes so many seeds can stay reachable.",
|
||||
"runtime_note": "Applied through SCGI immediately; it affects new and rebalanced peer slot allocation.",
|
||||
"description": "Maximum number of uploading torrents active at once.",
|
||||
"recommendation": "Keep enough slots for ratio goals without overloading disks and sockets.",
|
||||
},
|
||||
{
|
||||
"group": "Throttle",
|
||||
"key": "throttle.max_downloads.div",
|
||||
"label": "Download slot divisor",
|
||||
"label": "Max downloads per throttle",
|
||||
"type": "number",
|
||||
"description": "Per-throttle download slot divisor used by rTorrent throttling logic.",
|
||||
"recommendation": "Keep at 1 unless you intentionally use advanced throttle groups.",
|
||||
"runtime_note": "Applied through SCGI immediately for the default throttle scheduler.",
|
||||
"recommendation": "Change only when using named throttle groups or advanced queues.",
|
||||
},
|
||||
{
|
||||
"group": "Throttle",
|
||||
"key": "throttle.max_uploads.div",
|
||||
"label": "Upload slot divisor",
|
||||
"label": "Max uploads per throttle",
|
||||
"type": "number",
|
||||
"description": "Per-throttle upload slot divisor used by rTorrent throttling logic.",
|
||||
"recommendation": "Keep at 1 unless you intentionally use advanced throttle groups.",
|
||||
"runtime_note": "Applied through SCGI immediately for the default throttle scheduler.",
|
||||
},
|
||||
{
|
||||
"group": "Ratio",
|
||||
"key": "ratio.max",
|
||||
"label": "Global ratio max",
|
||||
"type": "number",
|
||||
"description": "Global maximum ratio value used by rTorrent ratio logic where enabled.",
|
||||
"recommendation": "Use -1 for no global cap, or manage per-profile ratio policies from pyTorrent when possible.",
|
||||
"runtime_note": "Applied through SCGI immediately when the rTorrent ratio method is available.",
|
||||
"recommendation": "Change only when using named throttle groups or advanced queues.",
|
||||
},
|
||||
{
|
||||
"group": "DHT / PEX",
|
||||
@@ -450,19 +410,6 @@ def default_download_path(profile: dict) -> str:
|
||||
errors.append(f"{method}: {exc}")
|
||||
raise RuntimeError("Cannot read rTorrent default download directory: " + "; ".join(errors))
|
||||
|
||||
def _rtorrent_set_method(key: str, meta: dict) -> str:
|
||||
# Note: Most runtime values use the conventional <method>.set setter.
|
||||
# Some rTorrent commands, such as protocol.encryption.set, are already
|
||||
# setter commands and must not receive another .set suffix.
|
||||
return str(meta.get("set_method") or (key if key.endswith(".set") else f"{key}.set"))
|
||||
|
||||
|
||||
def _rtorrent_config_line_key(key: str, meta: dict) -> str:
|
||||
# Note: Generated snippets must match rTorrent config syntax and avoid
|
||||
# producing invalid protocol.encryption.set.set lines.
|
||||
return str(meta.get("config_key") or _rtorrent_set_method(key, meta))
|
||||
|
||||
|
||||
def generate_config_text(values: dict) -> str:
|
||||
known = {f["key"]: f for f in RTORRENT_CONFIG_FIELDS}
|
||||
lines = []
|
||||
@@ -473,7 +420,7 @@ def generate_config_text(values: dict) -> str:
|
||||
normalized = _normalize_config_value(meta, value)
|
||||
if meta.get("type") == "text" and any(ch.isspace() for ch in normalized):
|
||||
normalized = '"' + normalized.replace('\\', '\\\\').replace('"', '\\"') + '"'
|
||||
lines.append(f"{_rtorrent_config_line_key(key, meta)} = {normalized}")
|
||||
lines.append(f"{key}.set = {normalized}")
|
||||
return "\n".join(lines) + ("\n" if lines else "")
|
||||
|
||||
|
||||
@@ -559,11 +506,10 @@ def set_config(profile: dict, values: dict, apply_now: bool = True, apply_on_sta
|
||||
value = _normalize_config_value(meta, raw_value)
|
||||
rpc_value = int(value) if meta.get("type") in {"bool", "number"} else value
|
||||
try:
|
||||
method = _rtorrent_set_method(key, meta)
|
||||
try:
|
||||
c.call(method, "", rpc_value)
|
||||
c.call(key + ".set", "", rpc_value)
|
||||
except Exception:
|
||||
c.call(method, rpc_value)
|
||||
c.call(key + ".set", rpc_value)
|
||||
updated.append(key)
|
||||
except Exception as exc:
|
||||
errors.append({"key": key, "error": str(exc)})
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from .client import *
|
||||
from .. import poller_control
|
||||
import shlex
|
||||
|
||||
def scgi_diagnostics(profile: dict) -> dict:
|
||||
c = client_for(profile)
|
||||
@@ -89,12 +90,12 @@ def profile_diagnostics(profile: dict) -> dict:
|
||||
base = paths.get("default_directory") if isinstance(paths.get("default_directory"), str) else ""
|
||||
if base:
|
||||
try:
|
||||
out = _rt_execute(c, "execute.capture", "sh", "-c", 'if test -w "$1"; then printf writable; else printf readonly; fi', "pytorrent-diagnostics-write", base)
|
||||
out = _rt_execute(c, "execute.capture", "sh", "-lc", f"test -w {shlex.quote(base)} && printf writable || printf readonly")
|
||||
write_permissions[base] = str(out or "").strip() or "unknown"
|
||||
except Exception as exc:
|
||||
write_permissions[base] = f"error: {exc}"
|
||||
try:
|
||||
out = _rt_execute(c, "execute.capture", "sh", "-c", "df -Pk \"$1\" 2>/dev/null | awk 'END {print $4}'", "pytorrent-diagnostics-df", base)
|
||||
out = _rt_execute(c, "execute.capture", "sh", "-lc", f"df -Pk {shlex.quote(base)} | tail -1 | awk '{{print $4}}'")
|
||||
kb = int(str(out or "0").strip() or 0)
|
||||
free_disk[base] = {"free_bytes": kb * 1024, "free_h": human_size(kb * 1024)}
|
||||
except Exception as exc:
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from .client import *
|
||||
from .files import set_file_priorities
|
||||
from .system import disk_usage_for_default_path
|
||||
@@ -216,7 +214,6 @@ TORRENT_FIELDS = [
|
||||
]
|
||||
|
||||
TORRENT_OPTIONAL_FIELDS = [
|
||||
"d.timestamp.last_active=",
|
||||
"d.timestamp.finished=",
|
||||
]
|
||||
|
||||
@@ -255,12 +252,7 @@ def normalize_row(row: list) -> dict:
|
||||
directory = str(row[14] or "")
|
||||
base_path = str(row[15] or "")
|
||||
is_multi_file = int(row[22] or 0) if len(row) > 22 else 0
|
||||
# Note: Last activity is optional because older rTorrent builds may not expose this timestamp.
|
||||
last_activity = int(row[23] or 0) if len(row) > 23 else 0
|
||||
if not last_activity and (down_rate > 0 or up_rate > 0):
|
||||
# Note: rTorrent builds without d.timestamp.last_active still expose live rates, so active rows get a safe current timestamp.
|
||||
last_activity = int(time.time())
|
||||
completed_at = int(row[24] or 0) if len(row) > 24 else 0
|
||||
completed_at = int(row[23] or 0) if len(row) > 23 else 0
|
||||
|
||||
# Show the selected download location only. Hide the torrent root
|
||||
# directory for multi-file torrents and the filename for single-file
|
||||
@@ -318,7 +310,6 @@ def normalize_row(row: list) -> dict:
|
||||
"priority": int(row[13] or 0),
|
||||
"path": display_path,
|
||||
"created": int(row[16] or 0),
|
||||
"last_activity": last_activity,
|
||||
"completed_at": completed_at,
|
||||
"label": str(row[17] or ""),
|
||||
"ratio_group": str(row[18] or ""),
|
||||
|
||||
Reference in New Issue
Block a user