From 1bfd2d7a210022fa1afc086fb00a52964bc1c873 Mon Sep 17 00:00:00 2001 From: Sam Chau Date: Sat, 30 Nov 2024 03:57:40 +1030 Subject: [PATCH] feat: add required versions for sonarr / radarr --- backend/app/__init__.py | 6 +++ backend/app/arr/__init__.py | 7 ++- backend/app/arr/status/ping.py | 44 ++++++++++++++++--- .../src/components/settings/arrs/ArrModal.jsx | 26 ++++++++--- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/backend/app/__init__.py b/backend/app/__init__.py index 3cd32fe..6c4cd91 100644 --- a/backend/app/__init__.py +++ b/backend/app/__init__.py @@ -9,6 +9,7 @@ from .arr import bp as arr_bp from .data import bp as data_bp from .settings_utils import create_empty_settings_if_not_exists, load_settings from .db import init_db +import logging REGEX_DIR = os.path.join('data', 'db', 'regex_patterns') FORMAT_DIR = os.path.join('data', 'db', 'custom_formats') @@ -20,6 +21,11 @@ def create_app(): app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) + # Set up logging + logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') + # Initialize directories and create empty settings file if it doesn't exist initialize_directories() create_empty_settings_if_not_exists() diff --git a/backend/app/arr/__init__.py b/backend/app/arr/__init__.py index fdbea2a..64c9868 100644 --- a/backend/app/arr/__init__.py +++ b/backend/app/arr/__init__.py @@ -6,7 +6,7 @@ from .manager import (save_arr_config, get_all_arr_configs, get_arr_config, update_arr_config, delete_arr_config) logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +logger.setLevel(logging.ERROR) bp = Blueprint('arr', __name__, url_prefix='/arr') @@ -16,7 +16,6 @@ bp = Blueprint('arr', __name__, url_prefix='/arr') def ping(): if request.method == 'OPTIONS': return jsonify({}), 200 - data = request.get_json() url = data.get('url') api_key = data.get('apiKey') @@ -28,9 +27,9 @@ def ping(): 'error': 'URL, API key, and type are required' }), 400 - logger.debug(f"Attempting to ping URL: {url} of type: {arr_type}") + logger.error(f"Attempting to ping URL: {url} of type: {arr_type}") success, message = ping_service(url, api_key, arr_type) - logger.debug(f"Ping result - Success: {success}, Message: {message}") + logger.error(f"Ping result - Success: {success}, Message: {message}") return jsonify({ 'success': success, diff --git a/backend/app/arr/status/ping.py b/backend/app/arr/status/ping.py index bda0496..a2d1495 100644 --- a/backend/app/arr/status/ping.py +++ b/backend/app/arr/status/ping.py @@ -5,35 +5,69 @@ import logging logger = logging.getLogger(__name__) +REQUIRED_VERSIONS = {'radarr': '5.10.4', 'sonarr': '4.0.10'} + + +def check_version_compatibility(installed_version, required_version): + """ + Check if installed version meets minimum required version for Radarr/Sonarr. + """ + installed_parts = [int(x) for x in installed_version.split('.')] + required_parts = [int(x) for x in required_version.split('.')] + + # Only compare the parts we care about (first 3 numbers for Radarr/Sonarr) + for installed, required in zip(installed_parts[:3], required_parts[:3]): + if installed < required: + return False + if installed > required: + return True + return True + def ping_service(url, api_key, arr_type): """ - Ping an Arr service and verify its type + Ping an Arr service and verify its type and version """ try: - # Clean up URL base_url = url.rstrip('/') headers = {'X-Api-Key': api_key} - # First check if service is responsive + logger.warning(f"Attempting to connect to {base_url} for {arr_type}") + response = requests.get(f"{base_url}/api/v3/system/status", headers=headers, timeout=10) + logger.warning(f"Response status: {response.status_code}") + logger.warning(f"Response content: {response.text}") + if response.status_code != 200: return False, f"Service returned status code: {response.status_code}" data = response.json() + logger.warning(f"Parsed response data: {data}") - # Verify the application type + # First check app type app_name = data.get('appName', '').lower() + version = data.get('version') + logger.warning(f"Found app: {app_name} version: {version}") + + # Check app type if arr_type == 'radarr' and app_name != 'radarr': return False, f"Expected Radarr but found {app_name}" elif arr_type == 'sonarr' and app_name != 'sonarr': return False, f"Expected Sonarr but found {app_name}" - return True, "Connection successful and application type verified" + # Check version + if not version: + return False, "Could not determine application version" + + required_version = REQUIRED_VERSIONS.get(arr_type) + if not check_version_compatibility(version, required_version): + return False, f"{app_name.title()} version {version} is not supported. Minimum required version is {required_version}" + + return True, "Connection successful and application type and version verified" except requests.exceptions.Timeout: return False, "Connection timed out" diff --git a/frontend/src/components/settings/arrs/ArrModal.jsx b/frontend/src/components/settings/arrs/ArrModal.jsx index 38952dc..0b7d86f 100644 --- a/frontend/src/components/settings/arrs/ArrModal.jsx +++ b/frontend/src/components/settings/arrs/ArrModal.jsx @@ -37,7 +37,7 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => { } else { setFormData({ name: '', - type: '', + type: 'radarr', // Keep the default value tags: [], profilarrServer: '', arrServer: '', @@ -89,12 +89,19 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => { const result = await pingService( formData.arrServer, formData.apiKey, - formData.type // Add type + formData.type ); if (result.success) { Alert.success('Connection successful!'); } else { - Alert.error(`Connection failed: ${result.message}`); + // Check if the error is version related + if (result.message.includes('version')) { + Alert.error( + `Unsupported ${formData.type} version. ${result.message}` + ); + } else { + Alert.error(`Connection failed: ${result.message}`); + } } } catch (error) { Alert.error('An error occurred while testing the connection.'); @@ -123,9 +130,16 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => { ); if (!testResult.success) { - Alert.error( - `Connection test failed: ${testResult.message}` - ); + // Check if the error is version related + if (testResult.message.includes('version')) { + Alert.error( + `Unsupported ${formData.type} version. ${testResult.message}` + ); + } else { + Alert.error( + `Connection test failed: ${testResult.message}` + ); + } setSaveConfirm(false); return; }