Files
Huntarr-Sonarr/main.py
Admin9705 4d388e7f95 update
2025-04-09 19:18:54 -04:00

187 lines
7.0 KiB
Python

#!/usr/bin/env python3
"""
Huntarr [Sonarr Edition] - Python Version
Main entry point for the application
"""
import time
import sys
import os
import socket
import signal
import importlib
from utils.logger import logger
from config import HUNT_MODE, SLEEP_DURATION, MINIMUM_DOWNLOAD_QUEUE_SIZE, ENABLE_WEB_UI, log_configuration, refresh_settings
from missing import process_missing_episodes
from upgrade import process_cutoff_upgrades
from state import check_state_reset, calculate_reset_time
from api import get_download_queue_size
# Flag to indicate if cycle should restart
restart_cycle = False
def signal_handler(signum, frame):
"""Handle signals from the web UI for cycle restart"""
global restart_cycle
if signum == signal.SIGUSR1:
logger.info("Received restart signal from web UI. Restarting cycle...")
restart_cycle = True
# Register signal handler for SIGUSR1
signal.signal(signal.SIGUSR1, signal_handler)
def get_ip_address():
"""Get the host's IP address from API_URL for display"""
try:
from urllib.parse import urlparse
from config import API_URL
# Extract the hostname/IP from the API_URL
parsed_url = urlparse(API_URL)
hostname = parsed_url.netloc
# Remove port if present
if ':' in hostname:
hostname = hostname.split(':')[0]
return hostname
except Exception as e:
# Fallback to the current method if there's an issue
try:
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
return ip
except:
return "YOUR_SERVER_IP"
def force_reload_config():
"""Force reload of config module to ensure all settings are freshly loaded"""
try:
# Force reload the config module
import config
importlib.reload(config)
# Call the refresh function to ensure settings are updated
config.refresh_settings()
# Log the reloaded settings for verification
logger.info("Settings reloaded from JSON file after restart signal")
config.log_configuration(logger)
return True
except Exception as e:
logger.error(f"Error reloading config: {e}")
return False
def main_loop() -> None:
"""Main processing loop for Huntarr-Sonarr"""
global restart_cycle
# Log welcome message for web interface
logger.info("=== Huntarr [Sonarr Edition] Starting ===")
# Log web UI information if enabled
if ENABLE_WEB_UI:
server_ip = get_ip_address()
logger.info(f"Web interface available at http://{server_ip}:8988")
logger.info("GitHub: https://github.com/plexguide/huntarr-sonarr")
while True:
# Set restart_cycle flag to False at the beginning of each cycle
restart_cycle = False
# Refresh settings from the settings manager before each cycle
refresh_settings()
# Check if state files need to be reset
check_state_reset()
logger.info(f"=== Starting Huntarr-Sonarr cycle ===")
# Track if any processing was done in this cycle
processing_done = False
# Check if we should ignore the download queue size or if we are below the minimum queue size
download_queue_size = get_download_queue_size()
if MINIMUM_DOWNLOAD_QUEUE_SIZE < 0 or (MINIMUM_DOWNLOAD_QUEUE_SIZE >= 0 and download_queue_size <= MINIMUM_DOWNLOAD_QUEUE_SIZE):
# Process shows/episodes based on HUNT_MODE
if HUNT_MODE in ["missing", "both"]:
if process_missing_episodes():
processing_done = True
# Check if restart signal received
if restart_cycle:
logger.info("Restarting cycle due to settings change...")
# Force reload all configuration before restarting
force_reload_config()
continue
if HUNT_MODE in ["upgrade", "both"]:
# Get the latest HUNT_UPGRADE_EPISODES value directly from config
from config import HUNT_UPGRADE_EPISODES
logger.info(f"Starting upgrade process with HUNT_UPGRADE_EPISODES={HUNT_UPGRADE_EPISODES}")
if process_cutoff_upgrades():
processing_done = True
# Check if restart signal received
if restart_cycle:
logger.info("Restarting cycle due to settings change...")
# Force reload all configuration before restarting
force_reload_config()
continue
else:
logger.info(f"Download queue size ({download_queue_size}) is above the minimum threshold ({MINIMUM_DOWNLOAD_QUEUE_SIZE}). Skipped processing.")
# Calculate time until the next reset
calculate_reset_time()
# Refresh settings before sleep to get the latest sleep_duration
refresh_settings()
# Import it directly from the settings manager to ensure latest value
from config import SLEEP_DURATION as CURRENT_SLEEP_DURATION
# Sleep at the end of the cycle only
logger.info(f"Cycle complete. Sleeping {CURRENT_SLEEP_DURATION}s before next cycle...")
logger.info("⭐ Tool Great? Donate @ https://donate.plex.one for Daughter's College Fund!")
# Log web UI information if enabled
if ENABLE_WEB_UI:
server_ip = get_ip_address()
logger.info(f"Web interface available at http://{server_ip}:8988")
# Sleep with progress updates for the web interface
sleep_start = time.time()
sleep_end = sleep_start + CURRENT_SLEEP_DURATION
while time.time() < sleep_end and not restart_cycle:
# Sleep in smaller chunks for more responsive shutdown and restart
time.sleep(min(5, sleep_end - time.time()))
# Every minute, log the remaining sleep time for web interface visibility
if int((time.time() - sleep_start) % 60) == 0 and time.time() < sleep_end - 10:
remaining = int(sleep_end - time.time())
logger.debug(f"Sleeping... {remaining}s remaining until next cycle")
# Check if restart signal received
if restart_cycle:
logger.info("Sleep interrupted due to settings change. Restarting cycle immediately...")
# Force reload all configuration before restarting
force_reload_config()
break
if __name__ == "__main__":
# Log configuration settings
log_configuration(logger)
try:
main_loop()
except KeyboardInterrupt:
logger.info("Huntarr-Sonarr stopped by user.")
sys.exit(0)
except Exception as e:
logger.exception(f"Unexpected error: {e}")
sys.exit(1)