#!/usr/bin/env python3 import os import time import logging from transmission_rpc import Client from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') logger = logging.getLogger() PORT_FILE = os.getenv('PORT_FILE', '/watch/forwarded_port') TRANSMISSION_HOST = os.getenv('TRANSMISSION_HOST', 'gluetun') TRANSMISSION_PORT = os.getenv('TRANSMISSION_PORT', 9091) class PortFileHandler(FileSystemEventHandler): def __init__(self): self.last_port = None self.transmission_client = Client(host=TRANSMISSION_HOST, port=TRANSMISSION_PORT) self.check_port_file() # Initial check def on_modified(self, event): if not event.is_directory and event.src_path == PORT_FILE: self.check_port_file() def check_port_file(self): try: if not os.path.exists(PORT_FILE): logger.info(f"Port file not found: {PORT_FILE}") return with open(PORT_FILE, 'r') as f: port = f.read().strip() if port != self.last_port and port.isdigit(): self.last_port = port logger.info(f"Port forwarding changed to: {port}") self.update_transmission(port) except Exception as e: logger.error(f"Error checking port file: {e}") def update_transmission(self, port): max_attempts = 5 attempt = 1 delay = 5 # seconds between retry attempts while attempt <= max_attempts: logger.info(f"Attempt {attempt}/{max_attempts}: Setting Transmission peer_port to {port}") try: self.transmission_client.set_session(peer_port=int(port)) logger.info(f"Successfully updated Transmission peer_port to {port}") logger.info(f"Testing Transmission peer port...") if self.transmission_client.port_test(): logger.info("Transmission peer port is open") else: logger.warning("Transmission peer port does not appear to be open") return except Exception as e: logger.warning(f"Attempt {attempt}/{max_attempts} failed: {e}") if attempt < max_attempts: logger.info(f"Retrying in {delay} seconds...") time.sleep(delay) attempt += 1 logger.error(f"Failed to update Transmission peer_port after {max_attempts} attempts") if __name__ == "__main__": path = os.path.dirname(PORT_FILE) logger.info(f"Starting port-watcher monitoring {PORT_FILE}") event_handler = PortFileHandler() observer = Observer() observer.schedule(event_handler, path, recursive=False) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()