
    DinY                    @   d Z ddlmZ ddl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mZmZ ddlZ ej                  e      ZdZdZdZ G d	 d
      Z G d d      Zedk(  r=ddlZ ej0                  ej2                  d       d Z ej6                   e              yy)u4  
Grok Playwright Provider - Image/Video generation via UI automation.

Uses Playwright in headless mode with stealth techniques to bypass Cloudflare.
This is the ONLY viable approach for Grok automation without paying for the API.

Auth: Cookie-based (sso, sso-rw, x-userid JWTs from grok.com).
Flow: Navigate to Imagine → Type prompt → Wait for images → Click "Make video" → Download.

Env vars:
  GROK_SSO_TOKEN       - 'sso' cookie value (JWT)
  GROK_SSO_RW_TOKEN    - 'sso-rw' cookie value (JWT)
  GROK_USER_ID         - 'x-userid' cookie value (UUID)
    )annotationsN)Path)CallableOptionalListzhttps://grok.comi,  x   c                      e Zd ZdZdddZd Z	 	 d	 	 	 	 	 	 	 	 	 ddZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZdddZddZ	d	 Z
d
 Zd Zy)GrokPlaywrightProviderzLGenerates images and videos via Grok's Imagine UI using Playwright headless.c                   |xs t        j                  dd      | _        |xs t        j                  dd      | _        |xs t        j                  dd      | _        || _        t        | j                  | j                  | j                  g      st        j                  d       d | _	        d | _
        d | _        d | _        t        j                  dd      | _        d	| _        y )
NGROK_SSO_TOKEN GROK_SSO_RW_TOKENGROK_USER_IDzGrok credentials not fully set (sso_token/sso_rw_token/user_id). Browser operations will fail until valid credentials are provided.r   T)timeoutfollow_redirectsHhttp://gabslocked:Pryl02123_country-us_streaming-1@geo.iproyal.com:12321)osgetenv	sso_tokensso_rw_tokenuser_idheadlessallloggerwarning_playwright_browser_context_pagehttpxClientclient	proxy_urlselfr   r   r   r   s        K/root/.openclaw/workspace/visionaryfx/providers/grok_playwright_provider.py__init__zGrokPlaywrightProvider.__init__&   s    "Ebii0@"&E(NBII6I2,N?"))NB"? DNND$5$5t||DENNU
  
 ll!

 d    c                   K   | j                   yddlm}  |       j                          d{   | _        | j                  j
                  j                  | j                  g d       d{   | _        | j                  j                  dddd	d
ddddd       d{   | _
        | j                  j                  d| j                  dddddd| j                  dddddd| j                  dddddg       d{    | j                  j                          d{   | _         | j                   j!                  d       d{    t"        j%                  d| j                         y7 B7 7 7 w7 W7 1w)z1Launch Playwright browser if not already running.Nr   )async_playwright)z---disable-blink-features=AutomationControlledz--disable-dev-shm-usagez--no-sandboxz--disable-setuid-sandboxz--disable-infobarsz--window-size=1920,1080)r   argsi  i8  )widthheighteMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36zen-USzAmerica/Sao_Paulozhttp://geo.iproyal.com:12321
gabslockedz Pryl02123_country-us_streaming-1)serverusernamepassword)viewport
user_agentlocaletimezone_idproxyssoz	.grok.com/T)namevaluedomainpathsecurehttpOnlyzsso-rwzx-userida:  
            // Remove webdriver property
            Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
            
            // Mock plugins
            Object.defineProperty(navigator, 'plugins', {
                get: () => [1, 2, 3, 4, 5]
            });
            
            // Mock languages
            Object.defineProperty(navigator, 'languages', {
                get: () => ['en-US', 'en']
            });
            
            // Mock permissions
            const originalQuery = window.navigator.permissions.query;
            window.navigator.permissions.query = (parameters) => (
                parameters.name === 'notifications' ?
                    Promise.resolve({ state: Notification.permission }) :
                    originalQuery(parameters)
            );
        z&Playwright browser ready (headless=%s))r   playwright.async_apir*   startr   chromiumlaunchr   r   new_contextr   add_cookiesr   r   r   new_pageadd_init_scriptr   info)r%   r*   s     r&   _ensure_browserz&GrokPlaywrightProvider._ensure_browser>   s    ::!9!1!3!9!9!;; #..77>>]] ? 

 

 #mm77#t4~+;  dF  G 8 
 
 mm''%  !**%  #% #)
  	 	6  ==1133
 jj(( *  	 	. 	<dmmL] <


	6 4	sj   ,E>E0?E>.E3/3E>"E6#AE> E8!E>"E:#'E>
E<&E>3E>6E>8E>:E><E>Nc                v  K   | j                          d{    | j                  }t        |      }|j                  dd       t        j                  d|dd        |j                  t         dd       d{    |j                  d	       d{    t        j                  d
       d{    |r |d       |j                  d      j                  }|j                  dd       d{    t        j                  d       d{    |j                         j                  d      sd| n|}|j                   j#                  |d       d{    t        j                  d       d{    |r |d       |j                   j%                  d       d{    t        j                  d       t'        j&                         }g }	t'        j&                         |z
  t(        k  rt        j                  d
       d{    t+        t'        j&                         |z
        }
|j-                  d       d{   }|rPt/        |      dk\  rBt1        t2        j5                  |            d| }	t        j                  dt/        |	      |
       no|r/|
dkD  r*t7        ddt+        |
t(        z  dz        z         } ||       |
dz  dk(  rt        j                  d|
       t'        j&                         |z
  t(        k  r|	st9        dt(         d       |r |d!       g }t;        |	      D ]R  \  }}|d"|d#z    d$z  }| j=                  ||       d{    |j?                  |       t        j                  d%|       T |r |d&       |S 7 7 7 7 7 7 7 O7 57 7 7 q7 Zw)'ax  
        Generate images using Grok Imagine UI.

        Args:
            prompt: Text prompt for image generation
            output_dir: Directory to save generated images
            num_images: Number of images to download (max available)
            on_progress: Optional callback for progress updates

        Returns:
            List of paths to saved images
        NTparentsexist_okzGenerating images: %s<   r9   `  r   domcontentloaded      zdiv[contenteditable="true"]'  )forcer   333333?generatezGenerate an image of    )delay      ?
   Enterz'Prompt submitted, waiting for images...a	  
                () => {
                    return Array.from(document.querySelectorAll('img'))
                        .map(img => img.src)
                        .filter(src => src.includes('/generated/') && src.includes('.jpg'));
                }
               zFound %d images after %dsZ   P   r   zWaiting for images... (%ds)z!Image generation timed out after s_   grok_image_   z.pngz	Saved: %sd   ) rI   r   r   mkdirr   rH   goto	GROK_BASEwait_for_load_stateasynciosleeplocatorfirstclicklower
startswithkeyboardtypepresstimeIMAGE_GEN_TIMEOUTintevaluatelenlistdictfromkeysminRuntimeError	enumerate_download_fileappend)r%   prompt
output_dir
num_imageson_progresspage
input_areafull_promptrA   
image_urlselapsedfound_imagesprogresssaved_pathsiurloutput_paths                    r&   generate_imagez%GrokPlaywrightProvider.generate_image   s\    & ""$$$zz*%
5+VCR[9 ii9+Qi777&&'9:::mmAN \\"?@FF
T5999mmC    ?Elln>W>WXb>c-fX6iomm  B 777mmC   O mm!!'***=> 		
iikE!$55--"""$))+-.G "& 0 " L L 1Q 6!$--"=>{
K
7Z'Rw{r2G6G,G",L(M#MNH%|q 97C1 iikE!$554 !BCTBUUVWXXO 
+ 	2FAs$QqSE'>>K%%c;777{+KK[1		2 a 	% 	8: 	:  	8  	+ #> 8s   N9NA$N9;N<N9NN91N2?N91N"2N9N%A
N9N(N96N+7,N9#N.$A&N9
N18N9N4CN9	AN9N7:N9N9N9N9"N9%N9(N9+N9.N91N94N97N9c                r  K   | j                          d{    | j                  }t        |      }||j                  d      }t        |      }|j                  j                  dd       |j                         st        d|       t        j                  d|j                         |j                  t         dd	       d{    |j                  d
       d{    t        j                  d       d{    |r |d       |j!                  d      j"                  }|j%                  t'        |j)                                      d{    t        j                  d       |r |d       d}t+        j*                         }t+        j*                         |z
  dk  rt        j                  d       d{    |j,                  }	t/        j0                  d|	      }
|
r(|
j3                  d      }t        j                  d|       nt+        j*                         |z
  dk  r|st5        d|j,                         t        j                  d       d{    |r |d       |rt        j                  d|dd        	 |j!                  d      j"                  }|j7                          d{    t        j                  d       d{    |j9                  |       d{    t        j                  d       d{    t        j                  d       |r |d       t        j                  d       	 |j!                  d       j"                  }|j7                  d!	       d{    t        j                  d       d{    t        j                  d"       t        j                  d#       	 |j!                  d$      j"                  }|j7                  d%	       d{    t        j                  d       d{    t        j                  d&       |r |d)       t        j                  d*       	 |jC                  d+       d{    t        j                  d,       t        j                  d       d{    |r |d.       t        j                  d/tD        |dd0        t+        j*                         }d}t+        j*                         |z
  tD        k  r"t        j                  d       d{    tG        t+        j*                         |z
        }|jC                  d1       d{   }|r[|D ]  }||v s|}t        j                  d2        n |s|d3   }t        j=                  d4       t        j                  d5||dd6        no|r/|dkD  r*tI        d7d.tG        |tD        z  d8z        z         } ||       |dz  d3k(  rt        j                  d9|       t+        j*                         |z
  tD        k  r"|s"t5        d:tD         d;| d<|j,                         |r |d=       t/        jJ                  d>d?|      }| jM                  ||       d{    t        j                  d@|       |r |dA       |S 7 |7 7 7 7 K7 7 G7 7 7 7 # t:        $ rV}t        j=                  d|       	 |j>                  jA                  |       d{  7   n# t:        $ r Y nw xY wY d}~d}~ww xY w7 7 7 +7 # t:        $ r!}t        j=                  d'|       Y d}~d}~ww xY w# t:        $ r!}t        j=                  d(|       Y d}~Ld}~ww xY w7  # t:        $ r!}t        j=                  d-|       Y d}~.d}~ww xY w7 7 7 q7 Iw)BaX  
        Generate video from image using Grok Imagine I2V.

        Args:
            image_path: Path to source image
            video_prompt: Optional motion prompt
            output_path: Where to save the video
            on_progress: Optional callback for progress updates

        Returns:
            Path to saved video file
        Nz.mp4TrK   zImage not found: zGenerating video from: %sz/imaginerO   rP   rQ   r]   rS   zinput[type="file"]z4Image uploaded, waiting for redirect to post page...r[   rX   rc   z/imagine/post/([a-f0-9-]+)zPost page loaded with token: %sz4Failed to get post token after upload. Current URL: rR      zTyping video prompt: %srN   z|input[placeholder*="customize video"], textarea[placeholder*="customize video"], [role="textbox"][aria-label="Make a video"]rV   rZ   z!Video prompt entered successfullyzCould not type video prompt: %s   z,Opening Video Options menu to select 720p...z"button[aria-label="Video Options"]rT   zVideo Options menu openedzSelecting 720p resolution...zbutton[aria-label="720p"]i  zSelected 720p resolutionz!720p button not found in menu: %sz%Could not open Video Options menu: %s   zClicking 'Make video' button...a  
                () => {
                    // Find button with aria-label="Make video"
                    const btn = document.querySelector('button[aria-label="Make video"]');
                    if (btn) {
                        btn.click();
                        return;
                    }
                    // Fallback: find button containing "Make video" text
                    const btns = document.querySelectorAll('button');
                    for (const b of btns) {
                        if (b.textContent.includes('Make video') || b.textContent.includes('Redo')) {
                            b.click();
                            break;
                        }
                    }
                }
            zClicked 'Make video' buttonz%Could not click Make video button: %s   z8Waiting for video generation (timeout %ds, token: %s)...   a  
                () => {
                    const srcs = [];
                    document.querySelectorAll('video').forEach(v => {
                        if (v.src && v.src.includes('/generated/') && v.src.includes('.mp4')) {
                            srcs.push(v.src);
                        }
                        // Also check source elements
                        v.querySelectorAll('source').forEach(s => {
                            if (s.src && s.src.includes('/generated/') && s.src.includes('.mp4')) {
                                srcs.push(s.src);
                            }
                        });
                    });
                    return srcs;
                }
            z Found video matching post token!r   z-No video matched token, using first availablezVideo ready after %ds: %sr_   ra   F   zStill generating video... (%ds)z!Video generation timed out after zs. Post token: z, Final URL: b   z\?cache=\d+$r   zVideo saved: %srd   )'rI   r   r   with_suffixparentre   existsFileNotFoundErrorr   rH   r:   rf   rg   rh   ri   rj   rk   rl   set_input_filesstrresolvers   r   researchgroupr|   rm   fill	Exceptionr   rp   rq   rv   VIDEO_GEN_TIMEOUTru   r{   subr~   )r%   
image_pathvideo_promptr   r   r   
file_input
post_token
start_waitcurrent_urlmatchprompt_inputevideo_options_btnresolution_btnrA   	video_urlr   
video_srcssrcr   s                        r&   generate_videoz%GrokPlaywrightProvider.generate_video   s    & ""$$$zz*%
$008K;'   =  "#&7
|$DEE/A ii9+X.i>>>&&'9:::mmAN \\"67==
((Z-?-?-A)BCCCJKO 
YY[
iikJ&+--"""((KII;[IE"[[^
=zJ iikJ&+ FtxxjQ 
 mmAO KK1<3DE#||B  %	 
 #((***mmC((("''555mmC(((?@ O 	BC	G $-Q R X X#))%)888--"""KK34 KK67G!%.I!J!P!P$**4*888mmC(((67 O 	56	G-- !   $ KK56 mmAO 	NPacmnpopcqr			iikE!$55--"""$))+-.G  $}} .   J$ % C!S($'	$FG	 ! *1INN#RS7)CR.Qw|r2G6G,G",L(M#MNH%|q =wGY iikE!$55\ 34E3F G)l-zC 
 O FF?B	:	 !!)[999%{3a 	% 	?: 	D # 	 +(5( @!D--,,\:::  " 9" 9( GBAFFG  	GNNBAFF	G&  	GNNBAFF	G 	 #l 	:sJ  ^7ZB1^7Z	^7!Z"^7>Z?A^7ZA+^7?Z! A*^7+2^7Z$)^7.Z3 6Z'7Z3 Z*Z3 ,Z--Z3 	Z0
Z3 #^70] 3\4] \.]  0\! 0\1\! \\! '^7]> ];]> 5^7^+A9^7^.8^7 ^1^7B>^7A^7+^4,'^7^7^7^7^7!^7$^7'Z3 *Z3 -Z3 0Z3 3	\<\[81[42[87\8	\\\\^7\^7] ] \! \! !	]*] ] ]] 	]8]3-^73]88^7;]> >	^(^#^7#^((^7.^71^74^7c                F   K   | j                  ||||       d{   S 7 w)uA   Alias for generate_video — matches GrokVideoProvider interface.N)r   )r%   r   r   r   r   s        r&   rW   zGrokPlaywrightProvider.generate  s$     ((\;P[\\\\s   !!c                  K   dj                  d| j                   d| j                   d| j                   g      }|t         ddd}dd	l}dd	l}|j                         5 }d
dddddd| ddt         dddd|j                  |g}|j                  |dd      }	|	j                  dk7  rn|	j                  r|	j                  j                         nd}
|	j                  r|	j                  j                         nd}t        d|	j                   d|
 d|       |j                         }|st        d      |j!                  |       d	d	d	       y	# 1 sw Y   y	xY ww)z3Download file from URL using authenticated session.z; zsso=zsso-rw=z	x-userid=r9   r.   )CookieRefererz
User-Agentr   Ncurlz-sz-Lz-xr   z-HzCookie: z	Referer: zqUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36z-oTr   )capture_outputr   zNo error messagez	No stdoutzCurl download failed (code z): z | stdout: zDownloaded file is empty)joinr   r   r   rg   
subprocesstempfileNamedTemporaryFiler:   run
returncodestderrdecodestdoutr   readwrite_bytes)r%   r   r   cookie_headerheadersr   r   tmp_filecurl_cmdresult
stderr_msg
stdout_msgtmp_contents                r&   r~   z%GrokPlaywrightProvider._download_file  s    		4>>"#d''()~&#
  $#A B
 	 ((* 	1hd`0	)A.  JhmmH  ^^HT3^OF  A%7=}}V]]113J\
7=}}V]]113+
"=f>O>O=PPST^S__jkujv wxx #--/K :;;##K0+	1 	1 	1s   A!E#C%E	EEEc                  K   | j                   r)| j                   j                          d{    d| _         | j                  r)| j                  j                          d{    d| _        | j                  r)| j                  j                          d{    d| _        | j                  r)| j                  j                          d{    d| _        | j                  j                          y7 7 7 _7 ,w)zClose browser and cleanup.N)r   closer   r   r   stopr"   r%   s    r&   r   zGrokPlaywrightProvider.close  s     ::**""$$$DJ==--%%''' DM==--%%''' DM""'')))#D % ( ( *sE   *C:C24C:!C4"4C:C64C:C8'C:4C:6C:8C:c                   K   | S wN r   s    r&   
__aenter__z!GrokPlaywrightProvider.__aenter__  s     s   c                @   K   | j                          d {    y 7 wr   r   r%   r+   s     r&   	__aexit__z GrokPlaywrightProvider.__aexit__   s     jjls   )r   r   r   Fr   r   r   r   r   r   r   bool)   N)
r   r   r   
str | Pathr   ru   r   Optional[Callable[[int], None]]return
List[Path])r   NN)
r   r   r   r   r   r   r   r   r   r   )r   r   r   r   )__name__
__module____qualname____doc__r'   rI   r   r   rW   r~   r   r   r   r   r(   r&   r
   r
   #   s    Vd0UMv 7;cc c 	c
 5c 
cP "&7;cc c  	c
 5c 
cJ](1T r(   r
   c                  V    e Zd ZdZd
ddZd ZddZ	 	 d	 	 	 	 	 	 	 ddZd Zd Z	d	 Z
y)GrokPlaywrightProviderSyncz/Synchronous wrapper for GrokPlaywrightProvider.c                :    t        ||||      | _        d | _        y )N)r   r   r   r   )r
   	_provider_loopr$   s        r&   r'   z#GrokPlaywrightProviderSync.__init__(  s%    /)R^ho  {C  D
r(   c                    | j                   | j                   j                         r8t        j                         | _         t        j                  | j                          | j                   S r   )r   	is_closedri   new_event_loopset_event_loopr   s    r&   	_get_loopz$GrokPlaywrightProviderSync._get_loop,  sG    ::!5!5!7 //1DJ""4::.zzr(   c                x    | j                         j                   | j                  j                  ||fi |      S r   )r   run_until_completer   r   )r%   r   r   kwargss       r&   r   z)GrokPlaywrightProviderSync.generate_image2  s7    ~~22)DNN))&*GG
 	
r(   Nc                z    | j                         j                   | j                  j                  |||fi |      S r   )r   r   r   r   )r%   r   r   r   r   s        r&   r   z)GrokPlaywrightProviderSync.generate_video7  s<     ~~22)DNN))*lKZSYZ
 	
r(   c                    | j                   ri| j                   j                         sN| j                   j                  | j                  j	                                | j                   j	                          y y y r   )r   r   r   r   r   r   s    r&   r   z GrokPlaywrightProviderSync.closeB  sN    ::djj224JJ))$..*>*>*@AJJ 5:r(   c                    | S r   r   r   s    r&   	__enter__z$GrokPlaywrightProviderSync.__enter__G  s    r(   c                $    | j                          y r   r   r   s     r&   __exit__z#GrokPlaywrightProviderSync.__exit__J  s    

r(   )r   r   r   Tr   )r   r   r   r   r   r   )r   N)r   r   r   r   r   r   r   r   )r   r   r   r   r'   r   r   r   r   r   r   r   r(   r&   r   r   %  sV    9
 "&		
	
 	
  		
 
	

r(   r   __main__z)%(asctime)s - %(levelname)s - %(message)s)levelformatc                 0  K   t        d       t        d       t        d       t        d      4 d {   } t        d       	 | j                  dddd	 
       d {   }t        dt        |       d       |D ]  }t        d|         	 d d d       d {    t        d       t        d       t        d       y 7 7 f# t        $ r,}t        d|        dd l}|j                          Y d }~fd }~ww xY w7 b# 1 d {  7  sw Y   rxY ww)Nz<============================================================z(Grok Playwright Provider Test (Headless)T)r   z
1. Testing image generation...z9a majestic dragon flying over a medieval castle at sunsetz./test_outputr]   c                     t        d|  d      S )Nz   Progress: %)print)ps    r&   <lambda>ztest.<locals>.<lambda>_  s    %-s!0D*E r(   )r   r   r   r   u      ✓ Generated z images:z     - u      ✗ Error: r   z=
============================================================zTest complete)r   r
   r   rw   r   	traceback	print_exc)providerimagesimgr   r  s        r&   testr  R  s    h89h)48 	& 	&H45&'66V.  E	  7    )#f+h?@! +CGC5/*+	& 	&$ 	ooh)	&  &qc*+ ##%%&	& 	& 	& 	&s   2DCDDCC1CDDC?'DC	C<"C72D7C<<D?DDD
DD)r   
__future__r   ri   loggingr   r   rs   pathlibr   typingr   r   r   r    	getLoggerr   r   rg   r   rt   r
   r   sysbasicConfigINFOr  r   r   r(   r&   <module>r     s    #   	 	   + + 			8	$	  ~ ~D& &R zGgll3^_6 GKK? r(   