Compare commits

..

2 Commits

Author SHA1 Message Date
c9068a8b50 update 2025-09-15 12:30:48 -04:00
13a0344db0 jellyfin-monitor: cleanup 2025-09-15 12:30:28 -04:00
2 changed files with 27 additions and 46 deletions

30
flake.lock generated
View File

@@ -191,11 +191,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1756679287, "lastModified": 1757808926,
"narHash": "sha256-Xd1vOeY9ccDf5VtVK12yM0FS6qqvfUop8UQlxEB+gTQ=", "narHash": "sha256-K6PEI5PYY94TVMH0mX3MbZNYFme7oNRKml/85BpRRAo=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "07fc025fe10487dd80f2ec694f1cd790e752d0e8", "rev": "f21d9167782c086a33ad53e2311854a8f13c281e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -238,11 +238,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1757618398, "lastModified": 1757930910,
"narHash": "sha256-BlGooRYcF96P356VQZi7SkGEW0Lo8TzxeYZt5CNmLew=", "narHash": "sha256-8qZoSCgID5bE7xVBzF7gsZc4ekUF0KbjRExpqEm7otE=",
"owner": "ggml-org", "owner": "ggml-org",
"repo": "llama.cpp", "repo": "llama.cpp",
"rev": "0e6ff0046f4a2983b2c77950aa75960fe4b4f0e2", "rev": "28c39da7c645185ade5436767929d7ec33006033",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -275,11 +275,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1757103352, "lastModified": 1757943327,
"narHash": "sha256-PtT7ix43ss8PONJ1VJw3f6t2yAoGH+q462Sn8lrmWmk=", "narHash": "sha256-w6cDExPBqbq7fTLo4dZ1ozDGeq3yV6dSN4n/sAaS6OM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "11b2a10c7be726321bb854403fdeec391e798bf0", "rev": "67a709cfe5d0643dafd798b0b613ed579de8be05",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -291,11 +291,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1757545623, "lastModified": 1757810152,
"narHash": "sha256-mCxPABZ6jRjUQx3bPP4vjA68ETbPLNz9V2pk9tO7pRQ=", "narHash": "sha256-Vp9K5ol6h0J90jG7Rm4RWZsCB3x7v5VPx588TQ1dkfs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8cd5ce828d5d1d16feff37340171a98fc3bf6526", "rev": "9a094440e02a699be5c57453a092a8baf569bdad",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -403,11 +403,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1757552363, "lastModified": 1757898151,
"narHash": "sha256-4dtGagSfwMabRi59g7E8T6FcdghNizLbR4PwU1g8lDI=", "narHash": "sha256-FmI8VUvFKkZrQkJ/oqx0F0CnvXdv2O3nlPhVBtCGqWo=",
"owner": "nix-community", "owner": "nix-community",
"repo": "srvos", "repo": "srvos",
"rev": "ec58f16bdb57cf3a17bba79f687945dca1703c64", "rev": "bffcdb335e9dae8d2242ec0bfe4bab4484870c65",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -42,7 +42,7 @@ class JellyfinQBittorrentMonitor:
self.restore_normal_limits() self.restore_normal_limits()
sys.exit(0) sys.exit(0)
def check_jellyfin_sessions(self): def check_jellyfin_sessions(self) -> list[str]:
"""Check if anyone is actively streaming from Jellyfin""" """Check if anyone is actively streaming from Jellyfin"""
try: try:
headers = {} headers = {}
@@ -95,32 +95,15 @@ class JellyfinQBittorrentMonitor:
logger.error(f"SpeedLimitsMode endpoint failed: {e}") logger.error(f"SpeedLimitsMode endpoint failed: {e}")
except Exception as e: except Exception as e:
logger.error(f"Failed to parse speedLimitsMode response: {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
)
if response.status_code == 200:
data = response.json()
if "use_alt_speed_limits" in data:
return data["use_alt_speed_limits"]
except Exception as e:
logger.error(f"Transfer info fallback failed: {e}")
logger.warning(
"Could not determine qBittorrent alternate limits status, using tracked state"
)
return self.throttle_active return self.throttle_active
def toggle_qbittorrent_limits(self, enable_throttle): def use_alt_limits(self, enable: bool) -> None:
"""Toggle qBittorrent alternate speed limits""" """Toggle qBittorrent alternate speed limits"""
action = "enabled" if enable else "disabled"
try: try:
current_throttle = self.check_qbittorrent_alternate_limits() current_throttle = self.check_qbittorrent_alternate_limits()
if current_throttle == enable_throttle: if current_throttle == enable:
action = "enabled" if enable_throttle else "disabled"
logger.info( logger.info(
f"Alternate speed limits already {action}, no action needed" f"Alternate speed limits already {action}, no action needed"
) )
@@ -132,31 +115,29 @@ class JellyfinQBittorrentMonitor:
) )
response.raise_for_status() response.raise_for_status()
self.throttle_active = enable_throttle self.throttle_active = enable
# Verify the change took effect # Verify the change took effect
new_state = self.check_qbittorrent_alternate_limits() new_state = self.check_qbittorrent_alternate_limits()
if new_state == enable_throttle: if new_state == enable:
action = "enabled" if enable_throttle else "disabled" logger.info(f"Activated {action} alternate speed limits")
logger.info(f"✓ Successfully {action} alternate speed limits")
else: else:
logger.warning( logger.warning(
f"Toggle may have failed: expected {enable_throttle}, got {new_state}" f"Toggle may have failed: expected {enable}, got {new_state}"
) )
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
action = "enable" if enable_throttle else "disable"
logger.error(f"Failed to {action} alternate speed limits: {e}") logger.error(f"Failed to {action} alternate speed limits: {e}")
except Exception as e: except Exception as e:
logger.error(f"Failed to toggle qBittorrent limits: {e}") logger.error(f"Failed to toggle qBittorrent limits: {e}")
def restore_normal_limits(self): def restore_normal_limits(self) -> None:
"""Ensure normal speed limits are restored on shutdown""" """Ensure normal speed limits are restored on shutdown"""
if self.throttle_active: if self.throttle_active:
logger.info("Restoring normal speed limits before shutdown...") logger.info("Restoring normal speed limits before shutdown...")
self.toggle_qbittorrent_limits(False) self.use_alt_limits(False)
def should_change_state(self, new_streaming_state): def should_change_state(self, new_streaming_state: bool) -> bool:
"""Apply hysteresis to prevent rapid state changes""" """Apply hysteresis to prevent rapid state changes"""
now = time.time() now = time.time()
@@ -218,7 +199,7 @@ class JellyfinQBittorrentMonitor:
# Apply hysteresis and change state if needed # Apply hysteresis and change state if needed
if self.should_change_state(streaming_active): if self.should_change_state(streaming_active):
self.last_streaming_state = streaming_active self.last_streaming_state = streaming_active
self.toggle_qbittorrent_limits(streaming_active) self.use_alt_limits(streaming_active)
self.last_active_streams = active_streams self.last_active_streams = active_streams
time.sleep(self.check_interval) time.sleep(self.check_interval)