Ë
    o›Xj?  ã                  ó¨   — d dl mZ d dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d d	lmZ d
gZdddddœ	 	 	 	 	 	 	 dd„Z G d„ d«      Zy)é    )ÚannotationsN)ÚPath)ÚRequest)Úservice_account)ÚCredentials)ÚInstalledAppFlow)Úbuild)ÚMediaFileUploadz*https://www.googleapis.com/auth/drive.fileF©Úoauth_client_secretsÚoauth_token_fileÚservice_account_fileÚuse_shared_drivec                ó   — d}|r‹|j                  «       r{t        j                  t        |«      t        «      }|�r6|j
                  �r)|j                  �r|j                  t        «       «       |j                  |j                  «       d¬«       ná| r†| j                  «       rvt        j                  t        | «      t        «      }|j                  d¬«      }|r˜|j                  j                  dd¬«       |j                  |j                  «       d¬«       nY|rL|j                  «       r<|st!        d«      ‚t"        j                  j%                  t        |«      t        ¬	«      }nt'        d
«      ‚t)        dd|d¬«      S )zPPrefer OAuth (personal My Drive). Service account only works with Shared Drives.Nzutf-8)Úencodingr   )ÚportT)ÚparentsÚexist_okzÁGoogle service accounts cannot upload to normal My Drive folders (no storage quota). Use OAuth once (see docs/SETUP.md) or put the folder in a Shared Drive and set GOOGLE_USE_SHARED_DRIVE=true.)ÚscopeszcNo Google credentials found. Add config/google_oauth_client.json and run: python bin/google_auth.pyÚdriveÚv3F)ÚcredentialsÚcache_discovery)Úexistsr   Úfrom_authorized_user_fileÚstrÚSCOPESÚexpiredÚrefresh_tokenÚrefreshr   Ú
write_textÚto_jsonr   Úfrom_client_secrets_fileÚrun_local_serverÚparentÚmkdirÚRuntimeErrorr   Úfrom_service_account_fileÚFileNotFoundErrorr	   )r   r   r   r   ÚcredsÚflows         ú5/var/www/html/content_generation/src/storage/drive.pyÚbuild_drive_servicer-      sM  € ð €EáÐ,×3Ñ3Ô5Ü×5Ñ5´cÐ:JÓ6KÌVÓTˆÚ�U—]“] u×':Ó':Ø�M‰Mœ'›)Ô$Ø×'Ñ'¨¯©«À'Ð'ÕJÙ	Ð"6×"=Ñ"=Ô"?Ü×8Ñ8¼Ð=QÓ9RÔTZÓ[ˆØ×%Ñ%¨1Ð%Ó-ˆÙØ×#Ñ#×)Ñ)°$ÀÐ)ÔFØ×'Ñ'¨¯©«À'Ð'ÕJÙ	Ð"6×"=Ñ"=Ô"?ÙÜðQóð ô
  ×+Ñ+×EÑEÜÐ$Ó%¬fð Fó 
‰ô  ð1ó
ð 	
ô
 �˜$¨EÀ5ÔIÐIó    c                  óx   — e Zd Zdddddœ	 	 	 	 	 	 	 	 	 dd„Zddd„Zddd„Zddd„Zdd„Z	 	 	 	 	 	 	 	 dd	„Zdd
„Z	y)ÚDriveUploaderNFr   c               óz   — |st        d«      ‚t        ||||¬«      | _        || _        |r
ddi| _        y i | _        y )NzGOOGLE_DRIVE_FOLDER_ID is emptyr   ÚsupportsAllDrivesT)Ú
ValueErrorr-   ÚserviceÚparent_folder_idÚ_drive_params)Úselfr5   r   r   r   r   s         r,   Ú__init__zDriveUploader.__init__9   sM   € ñ  ÜÐ>Ó?Ð?Ü*Ø!5Ø-Ø!5Ø-ô	
ˆŒð !1ˆÔÙ<LÐ1°4Ð8ˆÕÐRTˆÕr.   c                óÄ   — |xs | j                   }|d|gdœ} | j                  j                  «       j                  d|ddœ| j                  ¤Žj                  «       }|d   S )Nz"application/vnd.google-apps.folder)ÚnameÚmimeTyper   zid, webViewLink)ÚbodyÚfieldsÚid© )r5   r4   ÚfilesÚcreater6   Úexecute)r7   r:   Ú	parent_idr%   ÚmetaÚfolders         r,   Úcreate_folderzDriveUploader.create_folderM   sv   € ØÒ3˜d×3Ñ3ˆàØ<Ø�xñ
ˆðˆD�L‰L×ÑÓ ß‰VðOØÐ&7ñOØ;?×;MÑ;MñOç‰W‹Yð 	ð
 �d‰|Ðr.   c                ó(  — |xs | j                   }|j                  dd«      }d|› d|› d�} | j                  j                  «       j                  d|dddd	œ| j
                  ¤Žj                  «       }|j                  d
«      xs g }|r|d   d   S dS )z?Return folder id if a child folder with this exact name exists.Ú'z\'zname = 'z' and 'zT' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = falser   zfiles(id, name)é   )ÚqÚspacesr=   ÚpageSizer@   r   r>   Nr?   )r5   Úreplacer4   r@   Úlistr6   rB   Úget)r7   r:   rC   r%   ÚsaferJ   Úrespr@   s           r,   Úfind_folderzDriveUploader.find_folder[   s·   € àÒ3˜d×3Ñ3ˆà�|‰|˜C Ó'ˆà�t�f˜G F 8ð ,Vð Wð 	
ð
ˆD�L‰L×ÑÓ ß‰TðàØØ(Øñð ×$Ñ$ñ÷ ‰W‹Yð 	ð —‘˜Ó!Ò' RˆÙ!&ˆu�Q‰x˜‰~Ð0¨DÐ0r.   c                óR   — | j                  ||«      }|r|S | j                  ||«      S ©N)rR   rF   )r7   r:   rC   Úexistings       r,   Úget_or_create_folderz"DriveUploader.get_or_create_folderr   s/   € Ø×#Ñ# D¨)Ó4ˆÙØˆOØ×!Ñ! $¨	Ó2Ð2r.   c                ó*  — t        j                  t        |«      «      \  }}|xs d}t        t        |«      |d¬«      }|j                  |gdœ} | j
                  j                  «       j                  d||ddœ| j                  ¤Žj                  «       S )Nzapplication/octet-streamT)ÚmimetypeÚ	resumable)r:   r   zid, name, webViewLink)r<   Ú
media_bodyr=   r?   )
Ú	mimetypesÚ
guess_typer   r
   r:   r4   r@   rA   r6   rB   )r7   Ú
local_pathrC   ÚmimeÚ_ÚmediarD   s          r,   Úupload_filezDriveUploader.upload_filex   s�   € Ü×&Ñ&¤s¨:£Ó7‰ˆˆaØÒ1Ð1ˆÜ¤ J£¸$È$ÔOˆØ"Ÿ™°Y°KÑ@ˆðˆD�L‰L×ÑÓ ß‰VðgØ¨%Ð8OñgØSW×SeÑSeñgç‰W‹Yð	
r.   c               óR  — | j                  || j                  «      }| j                  ||«      }d|i}g }t        |j	                  d«      «      D ]Ã  }|j                  «       sŒ|j                  dv rŒ#d|j                  v r|j                  dk(  rŒAd|j                  v rŒP|j                  |«      }	t        |	j                  «      dk7  rt        |	j                  «      nd}
| j                  |
||«      }|j                  | j                  ||«      «       ŒÅ d|› �}d|› �}|||||||d	œS )
a)  Upload preserving structure under: parent / YYYY-MM-DD / batch_HHMMSS / ...

        Example:
          Content Root/
            2026-07-16/
              batch_093933/
                idea-01_topic/
                  linkedin.txt
                  hero.png
                manifest.json
        Ú Ú*>   ú
frames.txtÚframesz.pngÚ_video_workÚ.z'https://drive.google.com/drive/folders/)Ú	folder_idÚ
folder_urlÚdate_folderÚdate_folder_idÚdate_folder_urlÚbatch_folderr@   )rV   r5   rF   ÚsortedÚrglobÚis_filer:   ÚpartsÚsuffixÚrelative_tor   r%   Ú_ensure_nested_folderÚappendra   )r7   Ú	local_dirrk   rn   Údate_idÚbatch_idÚfolder_cacheÚuploadedÚpathÚrelÚ
parent_relÚparent_drive_idÚlinkÚ	date_links                 r,   Úupload_treezDriveUploader.upload_treeƒ   s/  € ð$ ×+Ñ+¨K¸×9NÑ9NÓOˆØ×%Ñ% l°GÓ<ˆð )+¨H ~ˆØˆä˜9Ÿ?™?¨3Ó/Ö0ˆDØ—<‘<”>ØØ�y‰y˜NÑ*ØØ˜4Ÿ:™:Ñ%¨$¯+©+¸Ò*?ØØ §
¡
Ñ*Øà×"Ñ" 9Ó-ˆCÜ,/°·
±
«O¸sÒ,Bœ˜SŸZ™ZœÈˆJØ"×8Ñ8¸À\ÐS[Ó\ˆOØ�O‰O˜D×,Ñ,¨T°?ÓCÕDð 1ð 9¸¸
ÐCˆØ=¸g¸YÐGˆ	à!ØØ&Ø%Ø(Ø(Øñ
ð 	
r.   c                ó¸   — |s|S ||v r||   S t        |«      j                  }d}|}|D ]+  }|r|› d|› �n|}||vr| j                  ||«      ||<   ||   }Œ- ||   S )Nrc   Ú/)r   rr   rF   )r7   Úrel_dirÚcacheÚroot_idrr   ÚcurrentrC   Úparts           r,   ru   z#DriveUploader._ensure_nested_folder·   s†   € ÙØˆNØ�eÑØ˜‘>Ð!ä�W“×#Ñ#ˆØˆØˆ	ÛˆDÙ-4˜˜	  4 &Ñ)¸$ˆGØ˜eÑ#à!%×!3Ñ!3°D¸)Ó!D��g‘Ø˜g™‰Ið ð �W‰~Ðr.   )
r5   r   r   úPath | Noner   rŠ   r   rŠ   r   ÚboolrT   )r:   r   rC   ú
str | NoneÚreturnr   )r:   r   rC   rŒ   r�   rŒ   )r]   r   rC   r   r�   Údict)rw   r   rk   r   rn   r   r�   rŽ   )r…   r   r†   zdict[str, str]r‡   r   r�   r   )
Ú__name__Ú
__module__Ú__qualname__r8   rF   rR   rV   ra   r‚   ru   r?   r.   r,   r0   r0   8   s�   „ ð
 -1Ø(,Ø,0Ø!&ñUàðUð *ð	Uð
 &ðUð *ðUð óUô(ô1ô.3ó	
ð2
àð2
ð ð	2
ð
 ð2
ð 
ó2
ôhr.   r0   )r   rŠ   r   rŠ   r   rŠ   r   r‹   )Ú
__future__r   r[   Úpathlibr   Úgoogle.auth.transport.requestsr   Úgoogle.oauth2r   Úgoogle.oauth2.credentialsr   Úgoogle_auth_oauthlib.flowr   Úgoogleapiclient.discoveryr	   Úgoogleapiclient.httpr
   r   r-   r0   r?   r.   r,   Ú<module>rš      ss   ðÝ "ã Ý å 2Ý )Ý 1Ý 6Ý +Ý 0à
6Ð	7€ð
 )-Ø$(Ø(,Ø"ñ%Jà%ð%Jð "ð%Jð &ð	%Jð
 ó%J÷PNò Nr.   