o
    ZhM                  
   @   s  d Z ddlZddl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 ddlZddlmZ ddlmZmZmZ dZeG dd	 d	ZeG d
d deZeG dd deZeG dd deZeG dd deZeG dd deZ	d4dedee dede	fddZ dedee defddZ!	d4de"dedeee	 ee" f fddZ#ded e"dee$ fd!d"Z%d5d#e"d$e"dee defd%d&Z&d$e"dee$ fd'd(Z'd)e$d$e"dee$ fd*d+Z(d,e$d$e"dee$ fd-d.Z)d,e$d/e$d$e"dee$ fd0d1Z*G d2d3 d3eZ+dS )6zUtil that calls clickup.    N)asdict	dataclassfields)AnyDictListMappingOptionalTupleTypeUnion)get_from_dict_or_env)	BaseModel
ConfigDictmodel_validatorzhttps://api.clickup.com/api/v2c                   @   s.   e Zd ZdZedeeef dd fddZdS )	ComponentzBase class for all components.datareturnc                 C   s   t  N)NotImplementedErrorclsr    r   \/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/utilities/clickup.py	from_data   s   zComponent.from_dataN)	__name__
__module____qualname____doc__classmethodr   strr   r   r   r   r   r   r      s     r   c                   @   s   e Zd ZU dZeed< eed< eed< eed< eed< eed< eed< eed	< eeee	f  ed
< eeee	f  ed< e
e ed< e
e ed< e
e ed< eed< eed< eed< edeee	f dd fddZdS )TaskzClass for a task.idnametext_contentdescriptionstatus
creator_idcreator_usernamecreator_email	assigneeswatchersprioritydue_date
start_datepointsteam_id
project_idr   r   c                 C   s   |d d u rd n|d d }| di d|d d|d d|d d|d d|d d d|d d d	|d d
 d|d d d|d d|d d|d|d d|d d|d d|d d|d d S )Nr,   r"   r#   r$   r%   r&   r'   Zcreatorr(   usernamer)   emailr*   r+   r-   r.   r/   r0   r1   projectr   r   )r   r   r,   r   r   r   r   -   sD   	
zTask.from_dataN)r   r   r   r   int__annotations__r    r   r   r   r	   r   r   r   r   r   r   r!      s(   
  r!   c                   @   s   e Zd ZU dZeed< eed< dZee ed< dZ	ee
 ed< dZee ed< dZee
 ed< dZee
 ed	< dZee ed
< ededd fddZdS )CUListzComponent class for a list.	folder_idr#   Ncontentr-   due_date_timer,   assigneer&   r   r   c                 C   sD   | |d |d | d| d| d| d| d| dd	S )
Nr8   r#   r9   r-   r:   r,   r;   r&   )r8   r#   r9   r-   r:   r,   r;   r&   )getr   r   r   r   r   Q   s   zCUList.from_data)r   r   r   r   floatr6   r    r9   r	   r-   r5   r:   boolr,   r;   r&   r   dictr   r   r   r   r   r7   D   s   
 r7   c                   @   sH   e Zd ZU dZeed< eed< eed< eed< ededd fdd	Z	d
S )MemberzComponent class for a member.r"   r2   r3   initialsr   r   c                 C   s0   | |d d |d d |d d |d d dS )Nuserr"   r2   r3   rA   )r"   r2   r3   rA   r   r   r   r   r   r   h   s   



zMember.from_dataN)
r   r   r   r   r5   r6   r    r   r   r   r   r   r   r   r@   _   s   
 r@   c                   @   sD   e Zd ZU dZeed< eed< ee ed< e	de
dd fddZd	S )
TeamzComponent class for a team.r"   r#   membersr   r   c                 C   s(   dd |d D }| |d |d |dS )Nc                 S   s   g | ]}t |qS r   )r@   r   ).0Zmember_datar   r   r   
<listcomp>|   s    z"Team.from_data.<locals>.<listcomp>rD   r"   r#   )r"   r#   rD   r   )r   r   rD   r   r   r   r   z   s   zTeam.from_dataN)r   r   r   r   r5   r6   r    r   r@   r   r   r   r   r   r   r   rC   r   s   
 rC   c                   @   sX   e Zd ZU dZeed< eed< eed< eee	f ed< e
deee	f dd fdd	Zd
S )SpacezComponent class for a space.r"   r#   privateenabled_featuresr   r   c                 C   s>   |d d }dd |d   D }| |d |d |d |d	S )
Nspacesr   c                 S   s   i | ]\}}|d  r||qS )enabledr   )rE   featurevaluer   r   r   
<dictcomp>   s    z#Space.from_data.<locals>.<dictcomp>featuresr"   r#   rH   )r"   r#   rH   rI   )items)r   r   Z
space_datarI   r   r   r   r      s   
zSpace.from_dataN)r   r   r   r   r5   r6   r    r>   r   r   r   r   r   r   r   r   rG      s   
  rG   Fr   	componentfault_tolerantr   c              
   C   sf   zt || W S  ty2 } z|r,dt|  dt| d}t| | W  Y d}~S |d}~ww )a  Parse a dictionary by creating
    a component and then turning it back into a dictionary.

    This helps with two things
    1. Extract and format data from a dictionary according to schema
    2. Provide a central place to do this in a fault-tolerant way

    z(Error encountered while trying to parse
: z'
 Falling back to returning input data.N)r   r   	Exceptionr    warningswarn)r   rQ   rR   eZwarning_strr   r   r   parse_dict_through_component   s   
rX   c                 C   s0   i }t |D ]}|j| v r| |j ||j< q|S )a"  Extract elements from a dictionary.

    Args:
        data: The dictionary to extract elements from.
        component: The component to extract elements from.

    Returns:
        A dictionary containing the elements from the input dictionary that are also
        in the component.
    )r   r#   )r   rQ   output	attributer   r   r   +extract_dict_elements_from_component_fields   s   
r[   queryc              
   C   sT   zt | dfW S  t jy) } z|r#ddt| dfW  Y d}~S |d}~ww )aD  Parse a JSON string and return the parsed object.

    If parsing fails, returns an error message.

    :param query: The JSON string to parse.
    :return: A tuple containing the parsed object or None and an error message or None.

    Exceptions:
        json.JSONDecodeError: If the input is not a valid JSON string.
    Nz5Input must be a valid JSON. Got the following error: z". 
"Please reformat and try again.)jsonloadsJSONDecodeErrorr    )r\   rR   rW   r   r   r   
load_query   s   r`   keyc                 C   sX   || v r*t | | dkr*t | | dkr"td| d| |  d | | d d S dS )z%Fetch the first id from a dictionary.r      zFound multiple rS   z. Defaulting to first.r"   N)lenrU   rV   )r   ra   r   r   r   fetch_first_id   s
   rd   urlaccess_tokenc                 C   s(   d|i}t j| ||d}|  | S )zFetch data from a URL.Authorizationheadersparams)requestsr<   raise_for_statusr]   )re   rf   r\   ri   responser   r   r   
fetch_data   s   rn   c                 C   s   t  d}t|| }t|dS )zFetch the team id./teamteamsDEFAULT_URLrn   rd   )rf   re   r   r   r   r   fetch_team_id   s   


rs   r0   c                 C   ,   t  d|  d}t||ddid}t|dS )zFetch the space id./team//spacearchivedfalser\   rJ   rq   )r0   rf   re   r   r   r   r   fetch_space_id      
rz   space_idc                 C   rt   )zFetch the folder id./space//folderrw   rx   ry   foldersrq   )r|   rf   re   r   r   r   r   fetch_folder_id   r{   r   r8   c                 C   sV   |rt  d| d}nt  d|  d}t||ddid}|r&d|v r&|d S t|dS )	zFetch the list id./folder//listr}   rw   rx   ry   r"   listsrq   )r|   r8   rf   re   r   r   r   r   fetch_list_id  s   
r   c                
   @   s  e Zd ZU dZdZee ed< dZee ed< dZ	ee ed< dZ
ee ed< dZee ed< edd	Ze	
d>dededefddZededededee fddZeddededefddZdedeeee f fddZdeeeeef f fddZdefddZdeeef fd d!Zdefd"d#Zd?d%ed&edefd'd(Z defd)d*Z!d%edefd+d,Z"defd-d.Z#d%edefd/d0Z$d%edefd1d2Z%d%edefd3d4Z&d%edefd5d6Z'd%edefd7d8Z(d%edefd9d:Z)d;ed%edefd<d=Z*dS )@ClickupAPIWrapperzWrapper for Clickup API.Nrf   r0   r|   r8   list_idZforbid)extrahttps://google.comoauth_client_idredirect_urir   c                 C   s   d| }| d| S )z"Get the URL to get an access code.z&https://app.clickup.com/api?client_id=z&redirect_uri=r   )r   r   r   re   r   r   r   get_access_code_url!  s   
z%ClickupAPIWrapper.get_access_code_urloauth_client_secretcodec                 C   s|   t  d}|||d}tj||d}| }d|vr:td|  d|v r8|d dkr8t|}tdd	|  d
S |d S )zGet the access token.z/oauth/token)Z	client_idZclient_secretr   )rj   rf   zError: ZECODEZ	OAUTH_014z4You already used this code once. Generate a new one.z1Our best guess for the url to get a new code is:
N)rr   rk   postr]   printr   r   )r   r   r   r   re   rj   rm   r   r   r   r   get_access_token)  s"   

z"ClickupAPIWrapper.get_access_tokenbefore)modevaluesc                 C   sl   t |dd|d< t|d |d< t|d |d |d< t|d |d |d< t|d |d |d |d< |S )z?Validate that api key and python package exists in environment.rf   ZCLICKUP_ACCESS_TOKENr0   r|   r8   r   )r   rs   rz   r   r   )r   r   r   r   r   validate_environmentE  s   z&ClickupAPIWrapper.validate_environment
input_dictc                 C   sn   dg i}|d D ],}zt |tdd}|d | W q ty4 } ztd|  W Y d}~qd}~ww |S )z1Parse appropriate content from the list of teams.rp   FrR   zError parsing a team N)rX   rC   appendrT   rU   rV   )selfr   parsed_teamsZteamrW   r   r   r   attempt_parse_teamsW  s   z%ClickupAPIWrapper.attempt_parse_teamsc                 C   s2   t | jtstd| j dt| jdd}|S )z Get the headers for the request.zAccess Token: z, must be str.zapplication/json)rg   zContent-Type)
isinstancerf   r    	TypeError)r   ri   r   r   r   get_headersc  s   zClickupAPIWrapper.get_headersc                 C   s   ddiS )Nrw   rx   r   )r   r   r   r   get_default_paramsp  s   z$ClickupAPIWrapper.get_default_paramsc                 C   s2   t  d}tj||  d}| }| |}|S )zGet all teams for the user.ro   )ri   )rr   rk   r<   r   r]   r   )r   re   rm   r   r   r   r   r   get_authorized_teamss  s
   

z&ClickupAPIWrapper.get_authorized_teamsc                 C   s<   t  dt| j d }|  }tj||  |d}d|iS )z3
        Get all the folders for the team.
        ru   rv   rh   rm   )rr   r    r0   r   rk   r<   r   r   re   rj   rm   r   r   r   get_folders~  s   zClickupAPIWrapper.get_foldersTr\   rR   c           	      C   sn   t |dd\}}|du rd|iS t d|d  }d| jdd}tj||  |d	}| }t|t|d}|S )
z+
        Retrieve a specific task.
        Tr   NError/task/task_idtruecustom_task_idsr0   Zinclude_subtasksrh   )	r`   rr   r0   rk   r<   r   r]   rX   r!   )	r   r\   rR   rj   errorre   rm   r   Zparsed_taskr   r   r   get_task  s   zClickupAPIWrapper.get_taskc                 C   s6   t  d| j d}|  }tj||  |d}d|iS )z*
        Get all available lists.
        r   r   rh   rm   )rr   r8   r   rk   r<   r   r   r   r   r   	get_lists  s   zClickupAPIWrapper.get_listsc                 C   sX   t |dd\}}|du rd|iS t d|d  d}|  }tj||  |d}d	|iS )
z7
        Query tasks that match certain fields
        Tr   Nr   /list/r   /taskrh   rm   )r`   rr   r   rk   r<   r   )r   r\   rj   r   re   rm   r   r   r   query_tasks  s   zClickupAPIWrapper.query_tasksc                 C   sD   t  d| j d}tj||  |  d}| }t|tdd}|S )z.
        Get all spaces for the team.
        ru   rv   rh   Tr   )	rr   r0   rk   r<   r   r   r]   rX   rG   )r   re   rm   r   Zparsed_spacesr   r   r   
get_spaces  s   zClickupAPIWrapper.get_spacesc                 C   sn   | j |dd}t|dd\}}t|tsd|iS |d |vr-dd|d  d|  diS |d ||d  iS ):
        Update an attribute of a specified task.
        Tr   r   attribute_namezattribute_name = z was not 
found in task keys z.. Please call again with one of the key names.)r   r`   r   r?   keys)r   r\   taskrj   r   r   r   r   get_task_attribute  s   
z$ClickupAPIWrapper.get_task_attributec           	      C   sr   t |dd\}}|du rd|iS t d|d  }d| jdd}|  }|d	 |d
 i}tj||||d}d|iS )r   Tr   Nr   r   r   r   r   r   rM   ri   rj   r]   rm   )r`   rr   r0   r   rk   put)	r   r\   
query_dictr   re   rj   ri   payloadrm   r   r   r   update_task  s   zClickupAPIWrapper.update_taskc                 C   s   t |dd\}}|du rd|iS |d D ]}t|ts)dd| dt| i  S qt d|d	  }|  }|d
 dkrE|d g d}n|d
 dkrSg |d d}ntd|d
  ddd| jdd}d|i}	tj	||||	d}
d|
iS )z>
        Add or remove assignees of a specified task.
        Tr   Nr   Zusersz3All users must be integers, not strings!
"Got user z	 if type r   r   Z	operationadd)r   remr   zInvalid operation (z). zValid options ['add', 'rem'].r   r   r*   r   rm   )
r`   r   r5   typerr   r   
ValueErrorr0   rk   r   )r   r\   r   r   rB   re   ri   Zassigne_payloadrj   r   rm   r   r   r   update_task_assignees  s:   
z'ClickupAPIWrapper.update_task_assigneesc                 C   s|   t |dd\}}|du rd|iS | j}t d| d}d| jd}t|t}|  }tj||||d	}	|		 }
t
|
tddS )
z%
        Creates a new task.
        Tr   Nr   r   r   r   )r   r0   )r]   ri   rj   )r`   r   rr   r0   r[   r!   r   rk   r   r]   rX   )r   r\   r   r   r   re   rj   r   ri   rm   r   r   r   r   create_task  s   
zClickupAPIWrapper.create_taskc                 C   s   t |dd\}}|du rd|iS | jr| jn| j}t d| d}t|t}|  }tj|||d}|	 }	t
|	tdd}
d|
v rF|
d | _|
S )	z%
        Creates a new list.
        Tr   Nr   r   r   r]   ri   r"   )r`   r8   r|   rr   r[   r!   r   rk   r   r]   rX   r7   r   )r   r\   r   r   locationre   r   ri   rm   r   Zparsed_listr   r   r   create_list$  s   

zClickupAPIWrapper.create_listc           
      C   sx   t |dd\}}|du rd|iS | j}t d| d}d|d i}|  }tj|||d}| }	d	|	v r:|	d	 | _|	S )
z'
        Creates a new folder.
        Tr   Nr   r}   r~   r#   r   r"   )r`   r|   rr   r   rk   r   r]   r   )
r   r\   r   r   r|   re   r   ri   rm   r   r   r   r   create_folder<  s   
zClickupAPIWrapper.create_folderr   c                 C   s  |dkr
|  |}nh|dkr| |}n^|dkr|  }nU|dkr'| |}nK|dkr1| |}nA|dkr;| |}n7|dkrD|  }n.|dkrM|  }n%|d	krV|  }n|d
kr`| 	|}n|dkrj| 
|}ndd| di}zt|W S  ty   t| Y S w )zRun the API.r   r   Z	get_teamsr   r   r   r   r   r   r   r   Z	ModeErrorzGot unexpected mode .)r   r   r   r   r   r   r   r   r   r   r   r]   dumpsrT   r    )r   r   r\   rY   r   r   r   runT  s8   



zClickupAPIWrapper.run)r   )T)+r   r   r   r   rf   r	   r    r6   r0   r|   r8   r   r   Zmodel_configr   r   r   r   r   r   r   r?   r   r   r   r   bytesr   r   r   r   r>   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     sd   
 
	
'r   )Fr   ),r   r]   rU   dataclassesr   r   r   typingr   r   r   r   r	   r
   r   r   rk   Zlangchain_core.utilsr   Zpydanticr   r   r   rr   r   r!   r7   r@   rC   rG   r?   r>   rX   r[   r    r`   r5   rd   rn   rs   rz   r   r   r   r   r   r   r   <module>   sj    (+


 	