o
    g;4                     @   s   d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
 ddlmZ ddlZddlZddlmZ ddlmZmZmZ G d	d
 d
Zdd ZedkrfdZdZdZeedZeeeZdS dS )z+Module for interacting with S3 bucket files    N)datetime)BytesIO)IOList)urlparse)ClientError)backoff_hdlrfailure_hdlrsuccess_hdlrc                	   @   sJ  e Zd ZdZd-deddfddZejeje	de
eed		d.d
ededefddZdedefddZejeje	de
eed		d/d
ededefddZejeje	de
eed	d0ddZejeje	de
eed	d.ded
efddZ	d1dededeeef fdd Zded!edee fd"d#Zd2d%ed&ed'efd(d)Zd*efd+d,ZdS )3S3BucketStoragezb
    Class to handle operations related to an S3 bucket, such as uploading and getting files.
    xcap-bucketbucket_namereturnNc                 C   s   t d| _|| _dS )z
        Initializes the S3BucketStorage class with the specified bucket name.

        Args:
            bucket_name (str): The name of the S3 bucket.
        s3N)boto3client	s3_clientr   )selfr    r   ,/var/www/html/XCapMarket/utils/s3_storage.py__init__   s   
zS3BucketStorage.__init__   )	max_tries
on_backoff
on_success	on_giveups3_file_pathsource_file_paths3_filec              
   C   s<  d|v rt j|}n|}zf|s;|r;|r;t|d}| j|| j| | | j|| _W d   n1 s5w   Y  n+|rR|rR| jj	|| j|d}| | j|| _n|rbt j
|sbtd| dtdd| d| d	| j d
W S  ty } ztdt d|| j| td| d| j d| |d}~ww )a(  
        Uploads a file to the specified location in the S3 bucket with retry logic.

        Args:
            s3_file_path (str): The path to upload the file to in the S3 bucket.
            source_file_path (str): The path of the file to upload from the local system.
            max_retries (int): Maximum number of retries if upload fails (default is 5).
            retry_delay (int): Delay between retries in seconds (default is 2).

        Returns:
            str: A message indicating the success or failure of the upload operation.
        /rbN)BodyBucketKeyzFile z( does not exist or file is not provided.z4Enter source file path or base64 encode binary file.z uploaded to  in z bucket.z>Error %s:
 Failed uploading file %s to S3 bucket %s. 
Error %s%Y/%m/%d %H:%M:%SzFailed uploading z to z	 bucket: )ospathbasenameopenr   upload_fileobjr   create_object_bucket_urls3_file_location
put_objectexists
ValueErrorloggingerrorr   nowstrftime)r   r   r   r   	file_namesource_fileresponsever   r   r   upload_file_to_s3_bucket"   sT   
z(S3BucketStorage.upload_file_to_s3_bucket
object_keyc                 C   s   d| d| S )zCreate the object URL for S3zhttps://z.s3.amazonaws.com/r   )r   r   r9   r   r   r   r+   i   s   z(S3BucketStorage.create_object_bucket_url   max_retriesretry_delayc              
   C   s   zE| drt|}|j| _|jd}| jj| j|d}|d d dkr;|d  }|s8t	d| d	| j |W S t	d
| j d|  t	yk } zt
dt d|| j| t	d| d| |d}~ww )a  
        Retrieves a file from the specified location in the S3 bucket with retry logic.

        Args:
            s3_file_path (str): The path of the file to retrieve from the S3 bucket.
            max_retries (int): Maximum number of retries if retrieval fails (default is 5).
            retry_delay (int): Delay between retries in seconds (default is 2).

        Returns:
            bytes: The content of the retrieved file as binary data.
        s3://r   r"   r#   ResponseMetadataHTTPStatusCode   r!   zFile content is empty at r$   zError getting object from z. File not found at zCError %s Error: Empty file content %s from S3 bucket %s. 
Error: %sr%   zFailed getting z: N)
startswithr   netlocr   r'   lstripr   
get_objectreadr/   r0   r1   r   r2   r3   )r   r   r;   r<   
parsed_urir6   file_contentr7   r   r   r   get_file_from_s3_bucketm   s:   
z'S3BucketStorage.get_file_from_s3_bucketc           	   
   C   s   zDg }| j j| jd}|dg D ]}|d }d|v r0|dd dd }||v r0|| qt|dkrBtd| j d	| |W S  tyn } zt	d
t
 d| j|| td| j d| d| |d}~ww )a  
        Search for files containing the specified keyword in the S3 bucket with retry logic.

        Args:
            keyword (str): The keyword to search for in file names.
            max_retries (int): Maximum number of retries if retrieval fails (default is 5).
            retry_delay (int): Delay between retries in seconds (default is 2).

        Returns:
            list: A list of file paths in the bucket that contain the keyword.
        )r"   Contentsr#   .r   r   zNo files in S3 bucket z has keyword zLError %s: Error searching files in S3 bucket %s with keyword '%s'. 
Error:%sr%   z#Error searching files in S3 bucket z with keyword 'z': N)r   list_objects_v2r   getsplitappendlenr/   r0   r1   r   r2   r3   )	r   keywordr;   matching_filesr6   objfile_keyr4   r7   r   r   r   search_files_in_bucket   s<   
z&S3BucketStorage.search_files_in_bucketsource_folderc              
   C   s   z0|s|}t |D ]}t jt j||r)t j||}|| }| j||d}q
d| dW S  tyM } ztd|  tdd| i|d}~ww )a  
        Bulk File Upload method to perform upload and download operations with the S3 bucket.

        Args:
            source_folder (str): The path of the local folder containing files to upload.
            s3_file_path (str): The path of folder to upload files to in the S3 bucket.

        Returns:
            bytes: The content of the retrieved file from the S3 bucket.
        )r   r   zFiles uploaded to z successfully.zError: messageN)r&   listdirr'   isfilejoinr8   r/   print)r   rW   r   filer   r6   r7   r   r   r   bulk_file_upload   s"   z S3BucketStorage.bulk_file_upload  s3_key
expires_inc              
   C   sl   ddl }z||\}}| jjd| j|d|pdd|d}||fW S  ty5 } ztd| |d}~ww )	a  
        Generates a signed URL for an S3 object.

        Args:
            s3_key (str): The S3 object key
            expires_in (int): URL expiration time in seconds (default: 1 hour)

        Returns:
            tuple[str, str]: A tuple containing (signed_url, mime_type)
        r   NrE   zinline; filename=document.pdfzapplication/pdf)r"   r#   ResponseContentDispositionResponseContentType)ClientMethodParams	ExpiresInzError generating signed URL: )	mimetypes
guess_typer   generate_presigned_urlr   r   r/   )r   r`   ra   rg   	mime_type_
signed_urler   r   r   generate_signed_url  s"   
z#S3BucketStorage.generate_signed_urlfolder_namec                 C   sF   | j j||d}g }|dg D ]}|d |krq||d  q|S )zList all the files in an S3 folder.

        Args:
            bucket_name: Name of the S3 bucket
            folder_name: Path to the folder in the bucket

        Returns:
            List of file paths
        )r"   PrefixrJ   r#   )r   rM   rN   rP   )r   r   ro   r6   filesrT   r   r   r   list_files_in_folder*  s   z$S3BucketStorage.list_files_in_folder 
project_idteam_idnested_pathc                 C   s   | d| d}|r| | d}t jd }| ||}g }|D ].}d| d| }	t j|}
t j|
d }| jj||d}|d }||
|	||d q |S )zGet the files in a folderr   xcap_s3_storager=      r>   ContentLength)r4   file_url	file_type	file_size)	r&   environrr   r'   r(   splitextr   head_objectrP   )r   rt   ru   rv   ro   r   rq   file_detailsrU   rz   r4   r{   r6   r|   r   r   r   get_files_in_folderA  s(   
	z#S3BucketStorage.get_files_in_folder	file_pathc                 C   s   | j j| j|d dS )zDelete the file from S3r>   T)r   delete_objectr   )r   r   r   r   r   delete_file_from_s3^  s   z#S3BucketStorage.delete_file_from_s3)r   )NN)Nr   r:   )r   )r_   )rs   )__name__
__module____qualname____doc__strr   backoffon_exceptionexpor   r   r
   r	   r8   r+   intrI   rV   r^   tuplern   r   rr   r   r   r   r   r   r   r      s    
	?	7)!

%r   c                   C   s
   t jd S )zGet the default bucket namerw   )r&   r}   r   r   r   r   get_default_bucket_named  s   
r   __main__zxcap-storage-devzimages/zgeneric/images/unity/)r   )r   base64r0   r&   timer   ior   typingr   r   urllib.parser   r   r   botocore.exceptionsr   utils.backoff_handlersr   r	   r
   r   r   r   BUCKET_NAMESOURCE_FOLDERS3_FILE_PATHs3_storage_objr^   r6   r   r   r   r   <module>   s0      S
