o
    ȳgM                  
   @   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   a/var/www/html/chatdoc2/venv/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'   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 )
Nr9   r#   r:   r-   r;   r,   r<   r&   )r9   r#   r:   r-   r;   r,   r<   r&   )getr   r   r   r   r   Q   s   zCUList.from_data)r   r   r   r   floatr7   r    r:   r	   r-   r6   r;   boolr,   r<   r&   r   dictr   r   r   r   r   r8   D   s   
 r8   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"   r3   r4   initialsr   r   c                 C   s0   | |d d |d d |d d |d d dS )Nuserr"   r3   r4   rB   )r"   r3   r4   rB   r   r   r   r   r   r   h   s   



zMember.from_dataN)
r   r   r   r   r6   r7   r    r   r   r   r   r   r   r   rA   _   s   
 rA   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   )rA   r   ).0member_datar   r   r   
<listcomp>|   s    z"Team.from_data.<locals>.<listcomp>rE   r"   r#   )r"   r#   rE   r   )r   r   rE   r   r   r   r   z   s   zTeam.from_dataN)r   r   r   r   r6   r7   r    r   rA   r   r   r   r   r   r   r   rD   r   s   
 rD   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   )rF   featurevaluer   r   r   
<dictcomp>   s    z#Space.from_data.<locals>.<dictcomp>featuresr"   r#   rJ   )r"   r#   rJ   rK   )items)r   r   
space_datarK   r   r   r   r      s   
zSpace.from_dataN)r   r   r   r   r6   r7   r    r?   r   r   r   r   r   r   r   r   rI      s   
  rI   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   rT   rU   ewarning_strr   r   r   parse_dict_through_component   s   
r\   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   rT   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`   rU   rZ   r   r   r   
load_query   s   rd   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 rV   z. Defaulting to first.r"   N)lenrX   rY   )r   re   r   r   r   fetch_first_id   s
   rh   urlaccess_tokenc                 C   s(   d|i}t j| ||d}|  | S )zFetch data from a URL.Authorizationheadersparams)requestsr=   raise_for_statusra   )ri   rj   r`   rm   responser   r   r   
fetch_data   s   rr   c                 C   s   t  d}t|| }t|dS )zFetch the team id./teamteamsDEFAULT_URLrr   rh   )rj   ri   r   r   r   r   fetch_team_id   s   


rw   r0   c                 C   ,   t  d|  d}t||ddid}t|dS )zFetch the space id./team//spacearchivedfalser`   rL   ru   )r0   rj   ri   r   r   r   r   fetch_space_id      
r~   space_idc                 C   rx   )zFetch the folder id./space//folderr{   r|   r}   foldersru   )r   rj   ri   r   r   r   r   fetch_folder_id   r   r   r9   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   r{   r|   r}   r"   listsru   )r   r9   rj   ri   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.Nrj   r0   r   r9   list_id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   ri   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)	client_idclient_secretr   )rn   rj   zError: ECODE	OAUTH_014z4You already used this code once. Generate a new one.z1Our best guess for the url to get a new code is:
N)rv   ro   postra   printr   r   )r   r   r   r   ri   rn   rq   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.rj   CLICKUP_ACCESS_TOKENr0   r   r9   r   )r   rw   r~   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.rt   FrU   zError parsing a team N)r\   rD   appendrW   rX   rY   )selfr   parsed_teamsteamrZ   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)rk   zContent-Type)
isinstancerj   r    	TypeError)r   rm   r   r   r   get_headersc  s   zClickupAPIWrapper.get_headersc                 C   s   ddiS )Nr{   r|   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.rs   )rm   )rv   ro   r=   r   ra   r   )r   ri   rq   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.
        ry   rz   rl   rq   )rv   r    r0   r   ro   r=   r   r   ri   rn   rq   r   r   r   get_folders~  s   zClickupAPIWrapper.get_foldersTr`   rU   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   include_subtasksrl   )	rd   rv   r0   ro   r=   r   ra   r\   r!   )	r   r`   rU   rn   errorri   rq   r   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   rl   rq   )rv   r9   r   ro   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   /taskrl   rq   )rd   rv   r   ro   r=   r   )r   r`   rn   r   ri   rq   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.
        ry   rz   rl   Tr   )	rv   r0   ro   r=   r   r   ra   r\   rI   )r   ri   rq   r   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   rd   r   r@   keys)r   r`   taskrn   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   rO   rm   rn   ra   rq   )rd   rv   r0   r   ro   put)	r   r`   
query_dictr   ri   rn   rm   payloadrq   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   usersz3All users must be integers, not strings!
"Got user z	 if type r   r   	operationadd)r   remr   zInvalid operation (z). zValid options ['add', 'rem'].r   r   r*   r   rq   )
rd   r   r6   typerv   r   
ValueErrorr0   ro   r   )r   r`   r   r   rC   ri   rm   assigne_payloadrn   r   rq   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   )ra   rm   rn   )rd   r   rv   r0   r_   r!   r   ro   r   ra   r\   )r   r`   r   r   r   ri   rn   r   rm   rq   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   ra   rm   r"   )rd   r9   r   rv   r_   r!   r   ro   r   ra   r\   r8   r   )r   r`   r   r   locationri   r   rm   rq   r   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"   )rd   r   rv   r   ro   r   ra   r   )
r   r`   r   r   r   ri   r   rm   rq   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   	get_teamsr   r   r   r   r   r   r   r   	ModeErrorzGot unexpected mode .)r   r   r   r   r   r   r   r   r   r   r   ra   dumpsrW   r    )r   r   r`   r]   r   r   r   runT  s8   



zClickupAPIWrapper.run)r   )T)+r   r   r   r   rj   r	   r    r7   r0   r   r9   r   r   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   ra   rX   dataclassesr   r   r   typingr   r   r   r   r	   r
   r   r   ro   langchain_core.utilsr   pydanticr   r   r   rv   r   r!   r8   rA   rD   rI   r@   r?   r\   r_   r    rd   r6   rh   rr   rw   r~   r   r   r   r   r   r   r   <module>   sj    (+


 	