diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 4a65906f..18330a0e 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -1544,10 +1544,10 @@
The name of the S3 bucket to store backups.
@@ -2521,7 +2521,7 @@ $(document).ready(function() { }); $("#test_s3_connection").click(function() { - var s3_bucket = $("#s3_bucket").val(); + var s3_bucket = $("#s3_bucket_name").val(); var s3_region = $("#s3_region").val(); var s3_access_key = $("#s3_access_key").val(); var s3_secret_key = $("#s3_secret_key").val(); diff --git a/plexpy/s3_uploader.py b/plexpy/s3_uploader.py index ba75163e..1a56bec8 100644 --- a/plexpy/s3_uploader.py +++ b/plexpy/s3_uploader.py @@ -74,13 +74,21 @@ def get_s3_client(): region = plexpy.CONFIG.S3_REGION if plexpy.CONFIG.S3_REGION else None try: + # Create a custom config that disables checksum algorithms for compatibility with Backblaze B2 + # and other S3-compatible services that don't support newer AWS features + s3_config = boto3.session.Config( + signature_version='s3v4', + s3={'payload_signing_enabled': False} + ) + s3_client = session.client( service_name='s3', aws_access_key_id=access_key, aws_secret_access_key=secret_key, endpoint_url=endpoint_url, region_name=region, - use_ssl=bool(plexpy.CONFIG.S3_SECURE) + use_ssl=True, #bool(plexpy.CONFIG.S3_SECURE) + config=s3_config ) return s3_client except Exception as e: @@ -133,7 +141,8 @@ def upload_file_to_s3(file_path, object_name=None): except NoCredentialsError: logger.error("Tautulli S3 Uploader :: Credentials not available for S3 upload") return False - except EndpointConnectionError: + except EndpointConnectionError as e: + logger.error(f"Tautulli S3 Uploader :: Could not connect to S3 endpoint: {e}") logger.error(f"Tautulli S3 Uploader :: Could not connect to S3 endpoint: {plexpy.CONFIG.S3_ENDPOINT}") return False except ClientError as e: diff --git a/plexpy/webserve.py b/plexpy/webserve.py index d57a3857..0b4d3b19 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -173,7 +173,7 @@ class WebInterface(object): try: # Create S3 client s3_config = { - 'region_name': s3_region if s3_region else 'us-east-1' + 'region_name': s3_region if s3_region else 'us-east-1', } # Add custom endpoint URL if provided @@ -3337,7 +3337,31 @@ class WebInterface(object): # If we change the authentication settings, make sure we refresh the users lists. if kwargs.pop('auth_changed', None): refresh_users = True - + + # Handle S3 backup parameter mappings + s3_field_maps = { + 's3_bucket': 'S3_BUCKET_NAME', + 's3_region': 'S3_REGION', + 's3_access_key': 'S3_ACCESS_KEY', + 's3_secret_key': 'S3_SECRET_KEY', + 's3_endpoint': 'S3_ENDPOINT', + 's3_prefix': 'S3_PREFIX', + 's3_secure': 'S3_SECURE' + } + + for form_key, config_key in s3_field_maps.items(): + if form_key in kwargs: + # Ensure string values for endpoints to prevent list nesting + if isinstance(kwargs[form_key], list) or (form_key == 's3_endpoint' and kwargs[form_key]): + kwargs[form_key] = str(kwargs[form_key]) + # Remove any nested list formatting + if form_key == 's3_endpoint': + kwargs[form_key] = kwargs[form_key].replace('[', '').replace(']', '').replace("'", "") + if ',' in kwargs[form_key]: + kwargs[form_key] = kwargs[form_key].split(',')[0].strip() + + kwargs[config_key] = kwargs.pop(form_key) + all_settings = config.SETTINGS + config.CHECKED_SETTINGS kwargs = {k: v for k, v in kwargs.items() if k.upper() in all_settings}