o
    i	m                     @   s>  d dl Z d dlmZ d dlmZmZmZ d dlmZm	Z	m
Z
mZmZmZmZmZmZ d dlmZmZmZmZmZmZmZmZmZmZmZmZ dedB fddZdedB fd	d
Z G dd dej!Z"G dd dej!Z#G dd dej!Z$G dd dej!Z%G dd dej!Z&G dd dej!Z'G dd deZ(de(fddZ)dS )    N)override)IOComfyExtensionInput)	ImageEditRequestImageGenerationRequestImageGenerationResponseInputUrlObjectVideoEditRequestVideoExtensionRequestVideoGenerationRequestVideoGenerationResponseVideoStatusResponse)ApiEndpointdownload_url_to_image_tensordownload_url_to_video_outputget_fs_object_sizeget_number_of_imagespoll_opsync_optensor_to_base64_stringupload_images_to_comfyapiupload_video_to_comfyapivalidate_stringvalidate_video_durationreturnc                 C   s"   | j r| j jd ur| j jd S d S )Nl    d(	 )usagecost_in_usd_ticks)response r   8/mnt/c/Users/fbmor/ComfyUI/comfy_api_nodes/nodes_grok.py_extract_grok_price    s   r!   c                 C   s   t | }|d ur|d S d S )NgzG?)r!   )r   pricer   r   r    _extract_grok_video_price&   s   r#   c                   @   sH   e Zd Zedd Ze	ddededededed	ed
ejfddZ	dS )GrokImageNodec                 C   s   t jddddt jjdg ddt jjdd	d
dt jjdg ddt jjddddddt jjdt jjdddddt jjd	ddt jjdddgd	dgt j	 gt j
jt j
jt j
jgd	t jt jddgdddd	S ) Nr$   z
Grok Imageapi node/image/Grokz1Generate images using Grok based on a text promptmodelgrok-imagine-image-prozgrok-imagine-imagezgrok-imagine-image-betaoptionspromptT*The text prompt used to generate the image	multilinetooltipaspect_ratio)1:12:33:23:44:39:1616:99:19.519.5:99:2020:91:22:1number_of_images   
   zNumber of images to generatedefaultminmaxstepr/   display_modeseedr   `Seed to determine if node should re-run; actual results are nondeterministic regardless of seed.rB   rC   rD   rE   rF   control_after_generater/   
resolution1K2K)r*   optionalwidgetsz
                (
                  $rate := $contains(widgets.model, "pro") ? 0.07 : 0.02;
                  {"type":"usd","usd": $rate * widgets.number_of_images}
                )
                
depends_onexpr	node_iddisplay_namecategorydescriptioninputsoutputshiddenis_api_nodeprice_badge)r   SchemaCombor   StringIntNumberDisplaynumberImageOutputHiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgePriceBadgeDependsclsr   r   r    define_schema/   sf   	3zGrokImageNode.define_schemarM   r&   r+   r0   r>   rG   rL   r   c                    s   t |ddd t| tdddt|||||| dttdI d H }t|jdkr7t	
t|jd	 jI d H S t	
td
d dd |jD D I d H S )NTr?   strip_whitespace
min_lengthz /proxy/xai/v1/images/generationsPOSTpathmethod)r&   r+   r0   nrG   rL   dataresponse_modelprice_extractorr   c                       g | ]	}t |I d H qS Nr   .0ir   r   r    
<listcomp>       z)GrokImageNode.execute.<locals>.<listcomp>c                 S      g | ]
}|j rt|j qS r   urlstrr   dr   r   r    r          )r   r   r   r   lowerr   r!   lenry   r   
NodeOutputr   r   torchcat)rn   r&   r+   r0   r>   rG   rL   r   r   r   r    execute|   s.   

zGrokImageNode.executeN)rM   )
__name__
__module____qualname__classmethodro   r   intr   r   r   r   r   r   r    r$   -   s(    
Lr$   c                   @   sN   e Zd Zedd Ze	ddedejdededed	ed
ede	j
fddZdS )GrokImageEditNodec                 C   s   t jddddt jjdg ddt jjdd	d
t jjddddt jjdddgdt jjddddddt jjdt jjdddddt jjdddt jjdg ddddgt j	 gt j
jt j
jt j
jgdt jt jddgd d!d"d#	S )$Nr   zGrok Image Editr%   z/Modify an existing image based on a text promptr&   r'   r)   imageimages)rW   r+   Tr,   r-   rL   rM   rN   r>   r?   r@   z#Number of edited images to generaterA   rG   r   rH   rI   rJ   r0   )autor1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   zCOnly allowed when multiple images are connected to the image input.)r*   rO   r/   rP   z
                (
                  $rate := $contains(widgets.model, "pro") ? 0.07 : 0.02;
                  {"type":"usd","usd": 0.002 + $rate * widgets.number_of_images}
                )
                rR   rU   )r   r_   r`   r   re   ra   rb   rc   rd   rf   rg   rh   ri   rj   rk   rl   rm   r   r   r    ro      sl   	7zGrokImageEditNode.define_schemar   r&   r   r+   rL   r>   rG   r0   r   c           	         s   t |ddd |dkrt|dkrtdn
t|dkr!td|dkr/t|dkr/td	t| td
ddt|dd |D || |||dkrJd n|dttdI d H }t	|j
dkrjtt|j
d jI d H S ttdd dd |j
D D I d H S )NTr?   rp   r(   z*The pro model supports only 1 input image.   z)A maximum of 3 input images is supported.r   zZCustom aspect ratio is only allowed when multiple images are connected to the image input.z/proxy/xai/v1/images/editsrs   rt   c                 S   s    g | ]}t d t| dqS )data:image/png;base64,r   )r	   r   r   r   r   r    r     s     z-GrokImageEditNode.execute.<locals>.<listcomp>)r&   r   r+   rL   rw   rG   r0   rx   r   c                    r|   r}   r~   r   r   r   r    r     r   c                 S   r   r   r   r   r   r   r    r     r   )r   r   
ValueErrorr   r   r   r   r   r!   r   ry   r   r   r   r   r   r   )	rn   r&   r   r+   rL   r>   rG   r0   r   r   r   r    r      sD   
	zGrokImageEditNode.executeN)r   )r   r   r   r   ro   r   r   re   r   r   r   r   r   r   r   r    r      s,    
P		r   c                   @   sR   e Zd Zedd Ze	ddededededed	ed
ejdB de	j
fddZdS )GrokVideoNodec                 C   s   t jddddt jjdddgdt jjd	d
ddt jjdddgddt jjdg dddt jjddddddt jjdt jjdddddt jjd
ddt j	jd d
d!gt j
 gt jjt jjt jjgd
t jt jddgd gd"d#d$d%	S )&Nr   z
Grok Videoapi node/video/Grokz(Generate video from a prompt or an imager&   grok-imagine-videogrok-imagine-video-betar)   r+   T&Text description of the desired video.r-   rL   480p720p#The resolution of the output video.r*   r/   r0   )r   r7   r5   r3   r1   r2   r4   r6   %The aspect ratio of the output video.duration   r?      ,The duration of the output video in seconds.rA   rG   r   rH   rI   rJ   r   )rO   )rQ   rZ   a  
                (
                  $rate := widgets.resolution = "720p" ? 0.07 : 0.05;
                  $base := $rate * widgets.duration;
                  {"type":"usd","usd": inputs.image.connected ? $base + 0.002 : $base}
                )
                rR   rU   )r   r_   r`   r   ra   rb   rc   sliderrd   re   Videorf   rg   rh   ri   rj   rk   rl   rm   r   r   r    ro      sl   	(zGrokVideoNode.define_schemaNr&   r+   rL   r0   r   rG   r   r   c                    s   |dkrd}d }|d ur!t |dkrtdtdt| d}t|ddd t| td	d
dt||||||dkr;d n||dtdI d H }	t	| td|	j
 ddd ttdI d H }
tt|
jjI d H S )Nr   r   r?   z"Only one input image is supported.r   r   Trp    /proxy/xai/v1/videos/generationsrs   rt   r   )r&   r   r+   rL   r   r0   rG   ry   rz   /proxy/xai/v1/videos/ru   c                 S      | j d ur| j S dS Ncompletestatusrr   r   r    <lambda>      z'GrokVideoNode.execute.<locals>.<lambda>status_extractorrz   r{   )r   r   r	   r   r   r   r   r   r   r   
request_idr   r!   r   r   r   videor   )rn   r&   r+   rL   r0   r   rG   r   	image_urlinitial_responser   r   r   r    r   c  s>   
	zGrokVideoNode.executer}   )r   r   r   r   ro   r   r   r   re   r   r   r   r   r   r   r    r     s,    
B		r   c                   @   s>   e Zd Zedd Zedededejdede	j
f
dd	Zd
S )GrokVideoEditNodec                 C   s   t jddddt jjdddgdt jjd	d
ddt jjdddt jjdddddt jjd
ddgt j	 gt j
jt j
jt j
jgd
t jddd	S )Nr   zGrok Video Editr   z.Edit an existing video based on a text prompt.r&   r   r   r)   r+   Tr   r-   r   z=Maximum supported duration is 8.7 seconds and 50MB file size.r/   rG   r   rH   r?   rI   rJ   zM{"type":"usd","usd": 0.06, "format": {"suffix": "/sec", "approximate": true}})rT   rU   )r   r_   r`   r   ra   r   rb   rc   rd   rf   rg   rh   ri   rj   rk   rm   r   r   r    ro     sD   zGrokVideoEditNode.define_schemar&   r+   r   rG   r   c           	   	      s   t |ddd t|ddd | }t|}|dkr(td|d d d	d
t| tdddt|tt	| |I d H d||dt
dI d H }t| td|j ddd ttdI d H }tt|jjI d H S )NTr?   rp   gffffff!@min_durationmax_duration   Video size (   .1fMB) exceeds 50MB limit.z/proxy/xai/v1/videos/editsrs   rt   r   )r&   r   r+   rG   r   r   r   c                 S   r   r   r   r   r   r   r    r     r   z+GrokVideoEditNode.execute.<locals>.<lambda>r   )r   r   get_stream_sourcer   r   r   r   r
   r	   r   r   r   r   r   r!   r   r   r   r   r   )	rn   r&   r+   r   rG   video_stream
video_sizer   r   r   r   r    r     s4   
zGrokVideoEditNode.executeN)r   r   r   r   ro   r   r   r   r   r   r   r   r   r   r   r    r     s    
(r   c                	   @   s8   e Zd Zedd Zededededej	fddZ
d	S )
GrokVideoReferenceNodec                 C   s  t jddddt jjddddt jjd	t jd
t jjdt jjt jdddddddt j	jdddgddt j	jdg dddt j
jddddddt jjd ggd!dt j
jd"d#d#d$dt jjdd%d&gt j gt jjt jjt jjgdt jt jd'd(gd)gd*d+d,d-	S ).Nr   zGrok Reference-to-Videor   zJGenerate video guided by reference images as style and content references.r+   Tr   r-   r&   r   reference_imagesr   
reference_r?      )prefixrC   rD   z7Up to 7 reference images to guide the video generation.)templater/   rL   r   r   r   r   r0   )r7   r5   r3   r1   r2   r4   r6   r   r   r      r@   r   rA   z&The model to use for video generation.rG   r   rH   rI   rJ   model.durationzmodel.resolutionzmodel.reference_images)rQ   input_groupsa  
                (
                  $res := $lookup(widgets, "model.resolution");
                  $dur := $lookup(widgets, "model.duration");
                  $refs := inputGroups["model.reference_images"];
                  $rate := $res = "720p" ? 0.07 : 0.05;
                  $price := ($rate * $dur + 0.002 * $refs) * 1.43;
                  {"type":"usd","usd": $price}
                )
                rR   rU   )r   r_   ra   r   DynamicComboOptionAutogrowTemplatePrefixre   r`   rb   rc   r   rd   r   rf   rg   rh   ri   rj   rk   rl   rm   r   r   r    ro     s   

$(;z$GrokVideoReferenceNode.define_schemar+   r&   rG   r   c                    s   t |ddd t| t|d  ddddI d H }t| td	d
dt|d dd |D ||d |d |d |dtdI d H }t| td|j	 ddd t
tdI d H }tt|jjI d H S )NTr?   rp   r   z	image/pngzUploading base imagesr   )	mime_type
wait_label
max_imagesr   rs   rt   r&   c                 S   s   g | ]}t |d qS )r   )r	   r   r   r   r    r   N  s    z2GrokVideoReferenceNode.execute.<locals>.<listcomp>rL   r   r0   )r&   r   r+   rL   r   r0   rG   r   r   r   c                 S   r   r   r   r   r   r   r    r   Z  r   z0GrokVideoReferenceNode.execute.<locals>.<lambda>r   )r   r   listvaluesr   r   r   r   r   r   r   r#   r   r   r   r   r   )rn   r+   r&   rG   ref_image_urlsr   r   r   r   r    r   :  s>   
	zGrokVideoReferenceNode.executeN)r   r   r   r   ro   r   dictr   r   r   r   r   r   r   r    r     s    
[r   c                   @   s>   e Zd Zedd Zededejdede	de
jf
dd	Zd
S )GrokVideoExtendNodec                 C   s   t jddddt jjddddt jjd	d
dt jjdt jdt jjddddddt jj	dggddt jjdddddt jj
dddgt j gt jjt jjt jjgdt jt jdgdddd 	S )!Nr   zGrok Video Extendr   zMExtend an existing video with a seamless continuation based on a text prompt.r+   Tz9Text description of what should happen next in the video.r-   r   z1Source video to extend. MP4 format, 2-15 seconds.r   r&   r   r      r   r@   r?   z#Length of the extension in seconds.rA   z%The model to use for video extension.r   rG   r   rH   rI   rJ   r   rP   a;  
                (
                  $dur := $lookup(widgets, "model.duration");
                  {
                    "type": "range_usd",
                    "min_usd": (0.02 + 0.05 * $dur) * 1.43,
                    "max_usd": (0.15 + 0.05 * $dur) * 1.43
                  }
                )
                rR   rU   )r   r_   ra   r   r   r   r   rb   rc   r   rd   rf   rg   rh   ri   rj   rk   rl   rm   r   r   r    ro   c  sh   (z!GrokVideoExtendNode.define_schemar+   r   r&   rG   r   c              	      s   t |ddd t|ddd t| }|dkr&td|d	 d	 d
dt| tdddt|tt	| |I d H d|d dt
dI d H }t| td|j ddd ttdI d H }tt|jjI d H S )NTr?   rp   r   r   r   r   r   r   r   r   z/proxy/xai/v1/videos/extensionsrs   rt   r   r   )r+   r   r   r   r   r   c                 S   r   r   r   r   r   r   r    r     r   z-GrokVideoExtendNode.execute.<locals>.<lambda>r   )r   r   r   r   r   r   r   r   r	   r   r   r   r   r   r#   r   r   r   r   r   )rn   r+   r   r&   rG   r   r   r   r   r   r    r     s0   

zGrokVideoExtendNode.executeN)r   r   r   r   ro   r   r   r   r   r   r   r   r   r   r   r   r    r   a  s    
Er   c                   @   s(   e Zd Zedeeej  fddZdS )GrokExtensionr   c                    s   t tttttgS r}   )r$   r   r   r   r   r   )selfr   r   r    get_node_list  s   zGrokExtension.get_node_listN)	r   r   r   r   r   typer   	ComfyNoder   r   r   r   r    r     s    r   c                      s   t  S r}   )r   r   r   r   r    comfy_entrypoint  s   r   )*r   typing_extensionsr   comfy_api.latestr   r   r   comfy_api_nodes.apis.grokr   r   r   r	   r
   r   r   r   r   comfy_api_nodes.utilr   r   r   r   r   r   r   r   r   r   r   r   floatr!   r#   r   r$   r   r   r   r   r   r   r   r   r   r   r    <module>   s"    ,8q pN i