fix disabling alternate limits

This commit is contained in:
Simon Gardling 2025-09-12 01:27:17 -04:00
parent 43317044f2
commit 4729bd2cc4
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D

View File

@ -32,8 +32,8 @@ class JellyfinQBittorrentMonitor:
self.session = requests.Session() # Use session for cookies
# Hysteresis settings to prevent rapid switching
self.streaming_start_delay = 10 # seconds to wait before throttling
self.streaming_stop_delay = 60 # seconds to wait before removing throttle
self.streaming_start_delay = 10
self.streaming_stop_delay = 60
self.last_state_change = 0
# Try to authenticate with qBittorrent
@ -50,18 +50,11 @@ class JellyfinQBittorrentMonitor:
logger.info("Attempting to authenticate with qBittorrent...")
try:
# First, try to access a simple endpoint to see if auth is needed
test_response = self.session.get(
f"{self.qbittorrent_url}/api/v2/app/version", timeout=5
)
logger.info(
f"Version endpoint test: HTTP {test_response.status_code}, Response: {test_response.text}"
)
if test_response.status_code == 200:
logger.info(
"qBittorrent accessible without explicit login - subnet whitelist working"
)
logger.info("qBittorrent accessible without explicit login - subnet whitelist working")
return True
except Exception as e:
@ -75,7 +68,6 @@ class JellyfinQBittorrentMonitor:
"Content-Type": "application/x-www-form-urlencoded",
}
logger.info(f"Attempting login to {self.qbittorrent_url}/login")
response = self.session.post(
f"{self.qbittorrent_url}/login",
data=login_data,
@ -83,22 +75,13 @@ class JellyfinQBittorrentMonitor:
timeout=10,
)
logger.info(
f"Login response: HTTP {response.status_code}, Response: '{response.text}'"
)
if response.status_code == 200:
if "Ok." in response.text or response.text.strip() == "Ok.":
logger.info("Successfully authenticated with qBittorrent")
return True
elif "Fails." in response.text:
logger.warning(
"qBittorrent login failed - authentication may be required"
)
else:
logger.info(f"Unexpected login response: '{response.text}'")
if response.status_code == 200 and ("Ok." in response.text or response.text.strip() == "Ok."):
logger.info("Successfully authenticated with qBittorrent")
return True
elif "Fails." in response.text:
logger.warning("qBittorrent login failed - authentication may be required")
else:
logger.warning(f"Login request failed with HTTP {response.status_code}")
logger.warning(f"Login failed: HTTP {response.status_code}")
except Exception as e:
logger.error(f"Could not authenticate with qBittorrent: {e}")
@ -140,97 +123,65 @@ class JellyfinQBittorrentMonitor:
def check_qbittorrent_alternate_limits(self):
"""Check if alternate speed limits are currently enabled"""
# For qBittorrent v5.1.0, use API v2 with GET requests
try:
# Try the transfer info endpoint first (more reliable)
response = self.session.get(
f"{self.qbittorrent_url}/api/v2/transfer/speedLimitsMode", timeout=10
)
if response.status_code == 200:
return response.text.strip() == "1"
else:
logger.warning(f"SpeedLimitsMode endpoint returned HTTP {response.status_code}")
except requests.exceptions.RequestException as e:
logger.error(f"SpeedLimitsMode endpoint failed: {e}")
except Exception as e:
logger.error(f"Failed to parse speedLimitsMode response: {e}")
# Fallback: try transfer info endpoint
try:
response = self.session.get(
f"{self.qbittorrent_url}/api/v2/transfer/info", timeout=10
)
logger.info(f"Transfer info endpoint: HTTP {response.status_code}")
if response.status_code == 200:
data = response.json()
logger.info(f"Transfer info keys: {list(data.keys())}")
# Check for alternative speed limit status in the response
if "use_alt_speed_limits" in data:
is_enabled = data["use_alt_speed_limits"]
logger.info(f"Alternative speed limits enabled: {is_enabled}")
return is_enabled
response.raise_for_status()
except requests.exceptions.RequestException as e:
logger.error(f"Transfer info endpoint failed: {e}")
except json.JSONDecodeError as e:
logger.error(f"Failed to parse transfer info JSON: {e}")
# Fallback: try app preferences endpoint
try:
response = self.session.get(
f"{self.qbittorrent_url}/api/v2/app/preferences", timeout=10
)
logger.info(f"Preferences endpoint: HTTP {response.status_code}")
if response.status_code == 200:
data = response.json()
# Look for alternative speed settings
if "alt_up_limit" in data or "scheduler_enabled" in data:
# Check if alternative speeds are currently active
# This is a bit indirect but should work
logger.info(
"Found preferences data, assuming alt speeds not active by default"
)
return False
return data["use_alt_speed_limits"]
except Exception as e:
logger.error(f"Preferences endpoint failed: {e}")
logger.error(f"Transfer info fallback failed: {e}")
logger.error(
"Failed to check qBittorrent alternate limits status: all endpoints failed"
)
return False
logger.warning("Could not determine qBittorrent alternate limits status, using tracked state")
return self.throttle_active
def toggle_qbittorrent_limits(self, enable_throttle):
"""Toggle qBittorrent alternate speed limits"""
try:
# Check current state
current_throttle = self.check_qbittorrent_alternate_limits()
if current_throttle == enable_throttle:
action = "enabled" if enable_throttle else "disabled"
logger.info(f"Alternate speed limits already {action}, no action needed")
return
if enable_throttle and not current_throttle:
try:
# Use API v2 POST endpoint to toggle alternative speed limits
response = self.session.post(
f"{self.qbittorrent_url}/api/v2/transfer/toggleSpeedLimitsMode",
timeout=10,
)
logger.info(
f"Toggle enable response: HTTP {response.status_code}, {response.text[:100]}"
)
response.raise_for_status()
self.throttle_active = True
logger.info("✓ Enabled alternate speed limits (throttling)")
return
except requests.exceptions.RequestException as e:
logger.error(f"Failed to enable alternate speed limits: {e}")
elif not enable_throttle and current_throttle:
try:
# Use API v2 POST endpoint to toggle alternative speed limits
response = self.session.post(
f"{self.qbittorrent_url}/api/v2/transfer/toggleSpeedLimitsMode",
timeout=10,
)
logger.info(
f"Toggle disable response: HTTP {response.status_code}, {response.text[:100]}"
)
response.raise_for_status()
self.throttle_active = False
logger.info("✓ Disabled alternate speed limits (normal)")
return
except requests.exceptions.RequestException as e:
logger.error(f"Failed to disable alternate speed limits: {e}")
response = self.session.post(
f"{self.qbittorrent_url}/api/v2/transfer/toggleSpeedLimitsMode",
timeout=10,
)
response.raise_for_status()
self.throttle_active = enable_throttle
# Verify the change took effect
new_state = self.check_qbittorrent_alternate_limits()
if new_state == enable_throttle:
action = "enabled" if enable_throttle else "disabled"
logger.info(f"✓ Successfully {action} alternate speed limits")
else:
logger.warning(f"Toggle may have failed: expected {enable_throttle}, got {new_state}")
except requests.exceptions.RequestException as e:
action = "enable" if enable_throttle else "disable"
logger.error(f"Failed to {action} alternate speed limits: {e}")
except Exception as e:
logger.error(f"Failed to toggle qBittorrent limits: {e}")
@ -244,24 +195,28 @@ class JellyfinQBittorrentMonitor:
"""Apply hysteresis to prevent rapid state changes"""
now = time.time()
# If state hasn't changed, no action needed
if new_streaming_state == self.last_streaming_state:
return False
# Calculate time since last state change
time_since_change = now - self.last_state_change
# If we want to start throttling (streaming started)
# Start throttling (streaming started)
if new_streaming_state and not self.last_streaming_state:
if time_since_change >= self.streaming_start_delay:
self.last_state_change = now
return True
else:
remaining = self.streaming_start_delay - time_since_change
logger.info(f"Streaming started - waiting {remaining:.1f}s before enabling throttling")
# If we want to stop throttling (streaming stopped)
# Stop throttling (streaming stopped)
elif not new_streaming_state and self.last_streaming_state:
if time_since_change >= self.streaming_stop_delay:
self.last_state_change = now
return True
else:
remaining = self.streaming_stop_delay - time_since_change
logger.info(f"Streaming stopped - waiting {remaining:.1f}s before disabling throttling")
return False
@ -287,8 +242,8 @@ class JellyfinQBittorrentMonitor:
logger.info(
f"Active streams ({len(active_streams)}): {', '.join(active_streams)}"
)
else:
logger.debug("No active streaming sessions")
elif len(active_streams) == 0 and self.last_streaming_state:
logger.info("No active streaming sessions")
# Apply hysteresis and change state if needed
if self.should_change_state(streaming_active):