
    :j                      v    d Z ddlZddlmZ ddlmZmZmZmZ ddl	m
Z
mZ e G d d             Z G d	 d
      Zy)a  
GitHub Credentials Manager

This module manages GitHub session tokens and API tokens with load balancing.
It provides thread-safe access to multiple credentials for improved concurrency.

Key Features:
- Load balanced credential distribution
- Support for both session tokens and API tokens
- Thread-safe credential access
- Usage statistics and monitoring
- Automatic fallback between credential types
    N)	dataclass)DictListOptionalTuple   )BalancerStrategyc                       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<   d	Zee	   ed
<   d	Z
ee	   ed<   edefd       Zedefd       Zedefd       Zy	)CredentialStatszCredential usage statisticstotal_requestssession_requeststoken_requestssessions_counttokens_countsession_percentagetoken_percentageNsession_statstoken_statsreturnc                      | j                   dkD  S )zCheck if sessions are availabler   )r   selfs    7/root/.openclaw/workspace/harvester/tools/credential.pyhas_sessionszCredentialStats.has_sessions&   s     ""Q&&    c                      | j                   dkD  S )zCheck if tokens are availabler   )r   r   s    r   
has_tokenszCredentialStats.has_tokens+   s       1$$r   c                 4    | j                   | j                  z   S )zTotal number of credentials)r   r   r   s    r   total_credentialsz!CredentialStats.total_credentials0   s     ""T%6%666r   )__name__
__module____qualname____doc__int__annotations__floatr   r   r   r   propertyboolr   r   r     r   r   r   r      s    %$(M8D>("&K$&'d ' ' %D % % 73 7 7r   r   c                      e Zd ZdZddee   dee   defdZdee   fdZdee   fdZ	dd	e
deeef   fd
Zdeeef   fdZde
fdZde
fdZde
fdZdee   ddfdZdee   ddfdZddZdefdZdefdZdefdZy)Credentialsz.GitHub credentials manager with load balancingsessionstokensstrategyc                    |s|st        d      |r|j                         ng | _        |r|j                         ng | _        |dk(  rt        j
                  nt        j                  }| j                  rt        | j                  |      nd| _        | j                  rt        | j                  |      nd| _	        t        j                         | _        d| _        d| _        d| _        y)zInitialize credentials manager

        Args:
            sessions: List of GitHub session tokens
            tokens: List of GitHub API tokens
            strategy: Load balancing strategy ("round_robin" or "random")
        z.At least one session or token must be providedround_robinNr   )
ValueErrorcopyr-   r.   r
   ROUND_ROBINRANDOMr	   session_balancertoken_balancer	threadingLocklockr   r   r   )r   r-   r.   r/   strategy_enums        r   __init__zCredentials.__init__9   s     MNN+3'-fkkm2 19M0I,,x KO-- F]aFJkkht{{MBW[NN$	 !r   r   c                     | j                   sy| j                  5  | xj                  dz  c_        | xj                  dz  c_        | j                   j	                         cddd       S # 1 sw Y   yxY w)z{Get next session token

        Returns:
            Optional[str]: Session token or None if no sessions available
        Nr   )r6   r:   r   r   getr   s    r   get_sessionzCredentials.get_sessionS   s`     $$YY 	/1$!!Q&!((,,.	/ 	/ 	/   AA((A1c                     | j                   sy| j                  5  | xj                  dz  c_        | xj                  dz  c_        | j                   j	                         cddd       S # 1 sw Y   yxY w)zqGet next API token

        Returns:
            Optional[str]: API token or None if no tokens available
        Nr   )r7   r:   r   r   r>   r   s    r   	get_tokenzCredentials.get_tokena   s`     ""YY 	-1$1$&&**,	- 	- 	-r@   prefer_tokenc                     |r"| j                   r| j                         }|r|dfS | j                  r| j                         }|r|dfS |s"| j                   r| j                         }|r|dfS t	        d      )a#  Get next credential with type preference

        Args:
            prefer_token: Whether to prefer API tokens over sessions

        Returns:
            Tuple[str, str]: (credential_value, credential_type)

        Raises:
            RuntimeError: If no credentials are available
        tokensessionzNo credentials available)r7   rB   r6   r?   RuntimeError)r   rC   rE   rF   s       r   get_credentialzCredentials.get_credentialo   s}     D//NN$Eg~%  &&(G	)) 3 3NN$Eg~%566r   c                 &    | j                  d      S )zGet any available credential

        Returns:
            Tuple[str, str]: (credential_value, credential_type)

        Raises:
            RuntimeError: If no credentials are available
        T)rC   )rH   r   s    r   get_anyzCredentials.get_any   s     """55r   c                 ,    t        | j                        S )zkCheck if sessions are available

        Returns:
            bool: True if sessions are available
        )r)   r-   r   s    r   r   zCredentials.has_sessions   s     DMM""r   c                 ,    t        | j                        S )zgCheck if tokens are available

        Returns:
            bool: True if tokens are available
        )r)   r.   r   s    r   r   zCredentials.has_tokens   s     DKK  r   c                 F    | j                         xs | j                         S )zyCheck if any credentials are available

        Returns:
            bool: True if any credentials are available
        )r   r   r   s    r   has_credentialszCredentials.has_credentials   s       "7doo&77r   Nc                    | j                   5  |r|j                         ng | _        | j                  r| j                  r&| j                  j	                  | j                         nU| j
                  r| j
                  j                  nt        j                  }t        | j                  |      | _        nd| _        ddd       y# 1 sw Y   yxY w)zcUpdate session tokens list

        Args:
            sessions: New list of session tokens
        N)
r:   r3   r-   r6   update_itemsr7   r/   r
   r4   r	   )r   r-   r/   s      r   update_sessionszCredentials.update_sessions   s     YY 		-/7HMMORDM}}(())66t}}E?C?R?Rt22;;X`XlXlH,4T]]H,MD)(,%		- 		- 		-   B-CCc                    | j                   5  |r|j                         ng | _        | j                  r| j                  r&| j                  j	                  | j                         nU| j
                  r| j
                  j                  nt        j                  }t        | j                  |      | _        nd| _        ddd       y# 1 sw Y   yxY w)zYUpdate API tokens list

        Args:
            tokens: New list of API tokens
        N)
r:   r3   r.   r7   rP   r6   r/   r
   r4   r	   )r   r.   r/   s      r   update_tokenszCredentials.update_tokens   s     YY 		++1&++-rDK{{&&''44T[[AAEAVAVt44==\d\p\pH*24;;*ID'&*#		+ 		+ 		+rR   c                    | j                   5  d| _        d| _        d| _        | j                  r| j                  j                          | j                  r| j                  j                          ddd       y# 1 sw Y   yxY w)zReset usage statisticsr   N)r:   r   r   r   r6   resetr7   r   s    r   reset_statszCredentials.reset_stats   sl    YY 	,"#D$%D!"#D$$%%++-""##))+	, 	, 	,s   A"A88Bc                 N   | j                   5  | j                  dkD  rMt        | j                  | j                  z  dz  d      }t        | j                  | j                  z  dz  d      }nd}d}t        | j                  | j                  | j                  t        | j                        t        | j                        ||| j                  r| j                  j                         nd| j                  r| j                  j                         nd	      cddd       S # 1 sw Y   yxY w)zkGet usage statistics

        Returns:
            CredentialStats: Comprehensive usage statistics
        r   d      g        N)	r   r   r   r   r   r   r   r   r   )r:   r   roundr   r   r   lenr-   r.   r6   	get_statsr7   )r   r   r   s      r   r]   zCredentials.get_stats   s     YY 	""Q&%*D,A,ADDWDW,W[^+^`a%b"#($*=*=@S@S*SWZ)Z\]#^ %("#& "#22!%!6!6#22"4==1 -#5!1CGCXCXd33==?^b?C?R?RD//99;X\
	 	 	s   DDD$c                 z    dt        | j                         dt        | j                         d| j                   dS )zWString representation

        Returns:
            str: String representation
        Credentials(sessions=	, tokens=z, requests=))r\   r-   r.   r   r   s    r   __str__zCredentials.__str__   s=     's4=='9&:)CDTCUU`aeatat`uuvwwr   c                 <    d| j                    d| j                   dS )zbDetailed string representation

        Returns:
            str: Detailed representation
        r_   r`   ra   )r-   r.   r   s    r   __repr__zCredentials.__repr__   s!     't}}oYt{{m1MMr   )r1   )T)r   N)r!   r"   r#   r$   r   strr<   r   r?   rB   r)   r   rH   rJ   r   r   rN   rQ   rT   rW   r   r]   rb   rd   r*   r   r   r,   r,   6   s    8 c  DI    4/Xc] /-8C= -74 75c? 7:	6sCx 	6#d #!D !8 8-S	 -d -"+DI +$ +"	,? 6x xN# Nr   r,   )r$   r8   dataclassesr   typingr   r   r   r   balancerr	   r
   r   r,   r*   r   r   <module>ri      sB     ! . . ( 7 7 7:ON ONr   