"""MinIO/S3 storage client for audio and video files.""" import logging import boto3 from botocore.exceptions import ClientError logger = logging.getLogger(__name__) class StorageClient: """S3-compatible storage client for MinIO.""" def __init__(self, endpoint: str, access_key: str, secret_key: str, secure: bool = False): self.client = boto3.client( "s3", endpoint_url=f"{'https' if secure else 'http'}://{endpoint}", aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name="us-east-1", ) self.endpoint = endpoint def ensure_bucket(self, bucket: str) -> None: """Create bucket if it doesn't exist.""" try: self.client.head_bucket(Bucket=bucket) except ClientError: try: self.client.create_bucket(Bucket=bucket) logger.info(f"Created bucket: {bucket}") except ClientError as e: logger.error(f"Failed to create bucket {bucket}: {e}") def upload_file(self, bucket: str, object_key: str, file_path: str, content_type: str = "audio/mpeg") -> int: """Upload a file to storage and return file size in bytes.""" import os self.client.upload_file( file_path, bucket, object_key, ExtraArgs={"ContentType": content_type}, ) return os.path.getsize(file_path) def get_presigned_url(self, bucket: str, object_key: str, expires: int = 3600) -> str: """Generate a presigned URL for file access.""" return self.client.generate_presigned_url( "get_object", Params={"Bucket": bucket, "Key": object_key}, ExpiresIn=expires, ) def is_connected(self) -> bool: """Check if storage is accessible.""" try: self.client.list_buckets() return True except Exception: return False