jellyfin-qbittorrent-monitor: only count external networks

This commit is contained in:
Simon Gardling 2025-10-21 23:39:44 -04:00
parent fb98627a58
commit f58fd08e43
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D

View File

@ -6,6 +6,7 @@ import logging
import sys import sys
import signal import signal
import json import json
import ipaddress
logging.basicConfig( logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
@ -36,6 +37,25 @@ class JellyfinQBittorrentMonitor:
self.streaming_stop_delay = 60 self.streaming_stop_delay = 60
self.last_state_change = 0 self.last_state_change = 0
# Local network ranges (RFC 1918 private networks + localhost)
self.local_networks = [
ipaddress.ip_network("10.0.0.0/8"),
ipaddress.ip_network("172.16.0.0/12"),
ipaddress.ip_network("192.168.0.0/16"),
ipaddress.ip_network("127.0.0.0/8"),
ipaddress.ip_network("::1/128"), # IPv6 localhost
ipaddress.ip_network("fe80::/10"), # IPv6 link-local
]
def is_local_ip(self, ip_address: str) -> bool:
"""Check if an IP address is from a local network"""
try:
ip = ipaddress.ip_address(ip_address)
return any(ip in network for network in self.local_networks)
except ValueError:
logger.warning(f"Invalid IP address format: {ip_address}")
return True # Treat invalid IPs as local for safety
def signal_handler(self, signum, frame): def signal_handler(self, signum, frame):
logger.info("Received shutdown signal, cleaning up...") logger.info("Received shutdown signal, cleaning up...")
self.running = False self.running = False
@ -43,7 +63,7 @@ class JellyfinQBittorrentMonitor:
sys.exit(0) sys.exit(0)
def check_jellyfin_sessions(self) -> list[str]: def check_jellyfin_sessions(self) -> list[str]:
"""Check if anyone is actively streaming from Jellyfin""" """Check if anyone is actively streaming from Jellyfin (external networks only)"""
try: try:
headers = {} headers = {}
if self.jellyfin_api_key: if self.jellyfin_api_key:
@ -55,19 +75,26 @@ class JellyfinQBittorrentMonitor:
response.raise_for_status() response.raise_for_status()
sessions = response.json() sessions = response.json()
# Count active streaming sessions (video only) # Count active streaming sessions (video only, external networks only)
active_streams = [] active_streams = []
for session in sessions: for session in sessions:
if ( if (
"NowPlayingItem" in session "NowPlayingItem" in session
and session.get("PlayState", {}).get("IsPaused", True) == False and session.get("PlayState", {}).get("IsPaused", True) == False
): ):
# Check if session is from external network
remote_endpoint = session.get("RemoteEndPoint", "")
if remote_endpoint and self.is_local_ip(remote_endpoint):
logger.debug(f"Skipping local session from {remote_endpoint}")
continue
item = session["NowPlayingItem"] item = session["NowPlayingItem"]
# Only count video streams (Movies, Episodes, etc.) # Only count video streams (Movies, Episodes, etc.)
item_type = item.get("Type", "").lower() item_type = item.get("Type", "").lower()
if item_type in ["movie", "episode", "video"]: if item_type in ["movie", "episode", "video"]:
user = session.get("UserName", "Unknown") user = session.get("UserName", "Unknown")
active_streams.append(f"{user}: {item.get('Name', 'Unknown')}") client_info = f" (from {remote_endpoint})" if remote_endpoint else ""
active_streams.append(f"{user}: {item.get('Name', 'Unknown')}{client_info}")
return active_streams return active_streams