
    	]jA(                         d dl Z 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mZ  e j&                  e      Zd ZddZd Zd ZddZddZddZd Zd Zd Zd Z y)    Nwraps)flag_set)start_job_async_or_sync)	load_func)settings)Q)QuerySet   )WebhookWebhookActionc           
         t         j                  |   }|r|j                  d      rt        d      t        j
                  j                  t        |       t        |      t        d      z  z  t        d      z  t        d      t        t         j
                  j                  | |	      j                  d
d            z  z        j                         S )zReturn all active webhooks for organization or project by action.

    If project is None - function return only organization hooks
    else project is not None - function return project and organization hooks
    Organization hooks are global hooks.
    zorganization-onlyz9There is no project webhooks for organization-only action)organization)projectNT)	is_active)send_for_all_actions)webhook__organizationaction
webhook_id)flatid__in)
r   ACTIONSget
ValueErrorr   objectsfilterr	   values_listdistinct)r   r   r   action_metas       E/root/env/lib/python3.12/site-packages/label_studio/webhooks/utils.pyget_active_webhooksr"      s      ''/K;??#67TUU??!!	|$W$/	1
d
	 4($,,33,_e3frr t s 	
	
 hj    c                 p   d|i}| j                   r|r|j                  |       	 t        j                  d| j                  |       t        j                  | j                  | j                  |t        j                        S # t
        j                  $ r!}t        j                  |d       Y d}~yd}~ww xY w)zRRun one webhook for action.

    This function must not raise any exceptions.
    r   zRun webhook %s for action %s)headersjsontimeoutT)exc_infoN)send_payloadupdateloggingdebugidrequestsposturlr%   r   WEBHOOK_TIMEOUTRequestExceptionerror)webhookr   payloaddataexcs        r!   run_webhook_syncr8   +   s     	&D G
4gjj&I}}KKOO,,	
 	
 $$ cD)s   AB B5B00B5c                     t        | ||      }|rR|rP|j                  d      j                         r0 t        t        j
                  d         |      j                  |d<   |D ]  }t        |||        y)z1
    Run all active webhooks for the action.
    Tr)   r   instanceN)r"   r   existsr   r   WEBHOOK_SERIALIZERSr6   r8   )r   r   r   r5   webhookswhs         r!   emit_webhooks_syncrA   B   sp     #<&AH7xDAHHJOYx'C'CI'NOY`aff	 .VW-.r#   c                    i }|r| j                  d      j                         r|j                  d      }|r |||d         j                  ||d   <   |r2|r0 t	        t
        j                  d         |      j                  |d<   |rId	|v rE|d	   j                         D ]/  \  }} |d   t        ||d
         |d         j                  ||<   1 | D ]  }	t        |	||        y)a!  Process a single batch of instances for webhooks.

    Args:
        webhooks: Active webhooks to send
        project: Project instance (optional)
        action: Action name
        batch: Batch of instances to process
        action_meta: Action metadata from WebhookAction.ACTIONS
    Tr:   
serializermany)r<   rD   keyr   r;   znested-fieldsfieldN)
r   r=   r   r6   r   r   r>   itemsget_nested_fieldr8   )
r?   r   r   batchr    r5   serializer_classrE   valuer@   s
             r!   _process_webhook_batchrL   M   s     Gd3::<&??<8*:EP[\bPc*d*i*iGK&'w!S8+G+G	+R!S]d!e!j!jGI+5)/:@@B 
U2u\2-eU7^D5QW= $ 
  .VW-.r#   c           	         t        | ||      }|j                         syt        j                  |   }|rBt	        |t
              r2t	        |d   t              r|d   j                  j                  |      }t	        |t
        t        f      }|xr t        d      }|r)t        j                  }t	        |t              r|j                         }	t        j                  d|	 d|        t!        d|	|      D ]I  }
||
|
|z    }t        j                  d|
|z  d	z    d
|j                          d       t#        |||||       K yt%        |      }	t        j                  d|	 d|        t!        dt%        |      |      D ]D  }
||
|
|z    }t        j                  d|
|z  d	z    d
t%        |       d       t#        |||||       F yt#        |||||       y)zRun all active webhooks for the action using instances as payload.

    Be sure WebhookAction.ACTIONS contains all required fields.
    Nr   modelr   @fflag_fix_back_plt_843_webhook_memory_improvement_12082025_shortzProcessing webhook for z instances in batches of zProcessing batch r   z with z
 instances)r"   r=   r   r   
isinstancelistintr   r   r
   r   r   WEBHOOK_BATCH_SIZEcountloggerr,   rangerL   len)r   r   r   r<   r?   r    is_batch_collectionuse_batching
batch_sizetotal_countirI   s               r!   emit_webhooks_for_instance_syncr]   i   s   
 #<&AH??''/K Jx.:hqk33Ow'//66h6G %Xh/?@&w84v+wL00
h)"..*KLL2;-?XYcXdef1k:6 V Q^40j11D0EVEKKM?Zdef&x&%UV h-KLL2;-?XYcXdef1c(mZ8 V Q^40j11D0EVCPUJ<Wabc&x&%UV 	x&(KPr#   c                 ^    t        d      rt        t        | ||d       yt        | ||       y)z{Run one webhook for action.

    This function must not raise any exceptions.

    Will run a webhook in an RQ worker.
    8fflag_fix_back_lsdv_4604_excess_sql_queries_in_api_shorthigh
queue_nameN)r   r   r8   )r4   r   r5   s      r!   run_webhookrc      s2     JK	
 	&'2r#   c                     t        d      rt        | ||      }|j                         syt        d      rt        t        | |||d       yt	        | |||       y)zRun all active webhooks for the action using instances as payload.

    Be sure WebhookAction.ACTIONS contains all required fields.

    Will run all selected webhooks in an RQ worker.
    ?fflag_fix_plt_1004_skip_job_for_disabled_webhook_04022026_shortNr_   lowra   )r   r"   r=   r   r]   )r   r   r   r<   r?   s        r!   emit_webhooks_for_instancerg      sW     QR&|WfE JK+\7FHaf	
 	(gvxPr#   c                 b    t        d      rt        t        | |||d       yt        | |||       y)zf
    Run all active webhooks for the action.

    Will run all selected webhooks in an RQ worker.
    r_   rf   ra   N)r   r   rA   )r   r   r   r5   s       r!   emit_webhooksri      s0     JK 2L'6SZglm<&'Br#   c                       fd}|S )a  Decorator emit webhooks for APIView methods: post, put, patch.

    Used for simple Create/Update methods.
    The decorator expects authorized request and response with 'id' key in data.

    Example:
        ```
        @api_webhook(WebhookAction.PROJECT_UPDATED)
        def put(self, request, *args, **kwargs):
            return super(ProjectAPI, self).put(request, *args, **kwargs)
        ```
    c                 2     t                fd       }|S )Nc                 :    
| |g|i |}t         j                  	   }|d   }|d   j                  j                  |j                  j                  d            }|r|g}d }d|v rt        ||d         }t        |j                  j                  |	|       |S )NrD   rN   r-   )r-   project-field)	r   r   r   r   r6   rH   rg   useractive_organization)selfrequestargskwargsresponser    rD   r<   r   r   funcs            r!   wrapz,api_webhook.<locals>.decorator.<locals>.wrap   s    D';D;F;H'//7Kv&D"7+33778==;L;LT;R7SH$:G+-*8[5QR&00	 Or#   r   ru   rv   r   s   ` r!   	decoratorzapi_webhook.<locals>.decorator   s     	t	 
	& r#    r   rx   s   ` r!   api_webhookr{      s    . r#   c                       fd}|S )a  Decorator emit webhooks for APIView delete method.

    The decorator expects authorized request and use get_object() method
    before delete.

    Example:
        ```
        @extend_schema(tags=['Annotations'])
        @api_webhook_for_delete(WebhookAction.ANNOTATIONS_DELETED)
        def delete(self, request, *args, **kwargs):
            return super(AnnotationAPI, self).delete(request, *args, **kwargs)
        ```
    c                 2     t                fd       }|S )Nc                    | j                         }t        j                  
   }|d   }d }d|v rt        ||d         }d|j                  i}|r|g} | |g|i |}	t        |j                  j                  |
|       |	S )NrD   rm   r-   )
get_objectr   r   rH   pkrg   rn   ro   )rp   rq   rr   rs   r<   r    rD   r   objrt   r   ru   s             r!   rv   z7api_webhook_for_delete.<locals>.decorator.<locals>.wrap   s    (H'//7Kv&DG+-*8[5QR%CeD';D;F;H&w||'G'GRXZ]^Or#   r   rw   s   ` r!   rx   z)api_webhook_for_delete.<locals>.decorator   s     	t	 
	" r#   ry   rz   s   ` r!   api_webhook_for_deleter      s    * r#   c                     |dk(  r| S |j                  d      }|D ]8  }t        | t              r| D cg c]  }t        ||       } }-t        | |      } : | S c c}w )z
    Get nested field from list of objects or single instance
    :param value: Single instance or list to look up field
    :param field: Field to lookup
    :return: List or single instance of looked up field
    __self____)splitrP   rQ   getattr)rK   rF   fieldsfldvs        r!   rH   rH     si     
[[F (eT".34WQ_4E4E3'E	(
 L 5s   A)N)!r+   	functoolsr   r.   core.feature_flagsr   
core.redisr   core.utils.commonr   django.confr   django.db.modelsr	   django.db.models.queryr
   modelsr   r   	getLogger__name__rU   r"   r8   rA   rL   r]   rc   rg   ri   r{   r   rH   ry   r#   r!   <module>r      sr       ' . '    + *			8	$4...8)QX3&Q&	C%P$Nr#   