§
    E«jˆQ  ã                   óš  — d Z ddlZddlZddlmZ ddlmZmZm	Z	 ddl
mZ ddlZddlZddlZddlmZ ddlZddlZddlmZmZmZ ddlmZ ddlZdd	lmZmZmZmZm Z m!Z!m"Z"m#Z# 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-d.œ¥Z$ ej%        e&¦  «        Z'd/Z( G d0„ d1¦  «        Z) e)¦   «         Z* G d2„ d3e+¦  «        Z,d4ej-        j.        d5e/fd6„Z0d4ej-        j.        d7e1d5e/fd8„Z2d4ej-        j.        d5e/fd9„Z3d4ej-        j.        d5e/fd:„Z4d;e!d5ej5        dz  fd<„Z6d=e7d5e/fd>„Z8d?e#d5dfd@„Z9 G dA„ dB¦  «        Z:dS )CzCommunication with APIs.é    N)Úurljoin)ÚConnectionErrorÚ	HTTPErrorÚReadTimeout)ÚRemoteDisconnected)Údefaultdict)ÚTimerÚsecondsÚsec_str)Úcast)ÚUserProfileTypeÚREQUESTS_PAYLOAD_TYPEÚGameTypeÚPublicDataTypeÚ
OnlineTypeÚChallengeTypeÚTOKEN_TESTS_TYPEÚBackoffDetailsÚprofilez/api/accountÚplayingz/api/account/playingÚstreamz/api/bot/game/stream/{}Ústream_eventz/api/stream/eventÚmovez/api/bot/game/{}/move/{}Útakebackz/api/bot/game/{}/takeback/{}Úchatz/api/bot/game/{}/chatÚabortz/api/bot/game/{}/abortÚacceptz/api/challenge/{}/acceptÚdeclinez/api/challenge/{}/declineÚupgradez/api/bot/account/upgradeÚresignz/api/bot/game/{}/resignÚexportz/game/export/{}Úonline_botsz/api/bot/onlineÚ	challengez/api/challenge/{}Úcancelz/api/challenge/{}/cancelÚstatusz/api/users/statusz/api/user/{}z/api/token/test)Úpublic_dataÚ
token_testéŒ   c                   ó   — e Zd ZdZdd„ZdS )ÚStopzClass to stop the bot.ÚreturnNc                 ó0   — d| _         d| _        d| _        dS )zInitialize the Stop class.FTN)Ú
terminatedÚ
force_quitÚrestart©Úselfs    ú&/app/lichess-bot-master/lib/lichess.pyÚ__init__zStop.__init__3   s   € àˆŒØˆŒØˆŒˆˆó    ©r+   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r3   © r4   r2   r*   r*   0   s.   € € € € € Ø Ð ðð ð ð ð ð r4   r*   c                   ó:   ‡ — e Zd ZdZdedej        ddfˆ fd„Zˆ xZS )ÚRateLimitedErrorz<Exception raised when we are rate limited (status code 429).ÚmessageÚtimeoutr+   Nc                 óX   •— t          ¦   «                              |¦  «         || _        dS )zLCreate a rate-limited error with the time left until the rate limit expires.N)Úsuperr3   r>   )r1   r=   r>   Ú	__class__s      €r2   r3   zRateLimitedError.__init__@   s&   ø€ å‰Œ×Ò˜Ñ!Ô!Ð!ØˆŒˆˆr4   )	r6   r7   r8   r9   ÚstrÚdatetimeÚ	timedeltar3   Ú__classcell__)rA   s   @r2   r<   r<   =   s[   ø€ € € € € ØFÐFð ð ¨hÔ.@ð ÀTð ð ð ð ð ð ð ð ð ð r4   r<   Úresponser+   c                 ó   — | j         dk    S )zFCheck if the status code is 429, which means that we are rate limited.é­  )Ústatus_code©rF   s    r2   Úis_new_rate_limitrK   F   s   € àÔ 3Ò&Ð&r4   Úrate_limit_status_codec                 óà   — | j         |k    rdS 	 |                      ¦   «         }d|v o-|                     di ¦  «                             dd¦  «        dk    S # t          j        j        $ r Y dS w xY w)zRCheck if response to challenge is a rate limit, either of the bot or the opponent.FÚerrorÚ	ratelimitÚkeyÚ úbot.vsBot.day)rI   ÚjsonÚgetÚrequestsÚ
exceptionsÚJSONDecodeError)rF   rL   Úbodys      r2   Úis_daily_game_rate_limitrY   J   s‚   € àÔÐ5Ò5Ð5ØˆuðØ�}Š}‰ŒˆØ˜$ˆÐ^ 4§8¢8¨K¸Ñ#<Ô#<×#@Ò#@ÀÈÑ#KÔ#KÈÒ#^Ð^øÝÔÔ.ð ð ð Øˆuˆuðøøøs   �AA ÁA-Á,A-c                 ó"   — t          | d¦  «        S )zNCheck if response to a challenge is 400, which means opponent is rate limited.i�  ©rY   rJ   s    r2   Úis_opponent_rate_limitr\   V   ó   € å# H¨cÑ2Ô2Ð2r4   c                 ó"   — t          | d¦  «        S )zMCheck if response to a challenge is 429, which means the bot is rate limited.rH   r[   rJ   s    r2   Úis_bot_rate_limitr_   [   r]   r4   Úchallenge_responsec                 ó®   — |                       di ¦  «        }|                      dd¦  «        }|dk    r"t          t          |d         ¦  «        ¦  «        S dS )z_Return the timeout in a challenge response if the bot or the opponent cannot play another game.rO   rP   rQ   rR   r
   N)rT   r
   Úfloat)r`   Ú
rate_limitrP   s      r2   Úget_challenge_timeoutrd   `   sU   € à#×'Ò'¨°RÑ8Ô8€JØ
�.Š.˜ Ñ
#Ô
#€CØ
ˆoÒÐÝ•u˜Z¨	Ô2Ñ3Ô3Ñ4Ô4Ð4Øˆ4r4   Ú	exceptionc                 óv   — t          | t          ¦  «        r| j        dur| j        j        dk     pt          j        S )z/If `is_final` returns True then we won't retry.Niô  )Ú
isinstancer   rF   rI   Ústopr.   )re   s    r2   Úis_finalri   i   s=   € å�y¥)Ñ,Ô,Ðx°Ô1CÈ4Ð1OÐxÐT]ÔTfÔTrÐuxÒTxð ÝŒð r4   Údetailsc                 óÞ   — | d         }| d         }d|v rd|d<   t                                 dj        d	i | ¤Ž¦  «         t                                dt          j        ¦   «         › �¦  «         dS )
z;Log exceptions inside functions with the backoff decorator.ÚargsÚkwargsr'   z<token redacted>ÚdatazrBacking off {wait:0.1f} seconds after {tries} tries calling function {target} with args {args} and kwargs {kwargs}zException: Nr:   )ÚloggerÚdebugÚformatÚ	tracebackÚ
format_exc)rj   rl   rm   s      r2   Úbackoff_handlerrt   o   s–   € à�6Œ?€DØ�XÔ€FØ�tÐÐØ+ˆˆv‰Ý
‡L‚Lð Yð RÜRXðdð dØ[bðdð dñ eô eð eå
‡L‚LÐ7�yÔ3Ñ5Ô5Ð7Ð7Ñ8Ô8Ð8Ð8Ð8r4   c                   óê  — e Zd ZdZdedededededdfd	„Z ej        ej	        e
eeefd
deeej        ej        ¬¦  «        ddddœdededeeef         dz  dededej        fd„¦   «         Zddœdededeeef         dz  deez  eeee         f         z  fd„Zddœdededeeef         dz  dee         fd„Zddœdededeeef         dz  defd„Z ej        ej	        e
eeefd
deeej        ej        ¬¦  «        ddddddœdededeeeef         z  dz  deeef         dz  deeef         dz  dedz  dedee z  dz  fd „¦   «         Z!dedefd!„Z"d"ej#        j        defd#„Z$d$ed%e%j&        ddfd&„Z'd$edefd'„Z(d$ede%j&        fd(„Z)dKd)„Z*d*ed+e+j,        j-        ddfd,„Z.d*ed-edefd.„Z/d*ed/ed0eddfd1„Z0d*eddfd2„Z1dej#        j        fd3„Z2d*edej#        j        fd4„Z3d5eddfd6„Z4dLd5ed8eddfd9„Z5defd:„Z6dee         dz  fd;„Z7d*eddfd<„Z8d=eddfd>„Z9d*edefd?„Z:dee         fd@„Z;d=ededefdA„Z<d5eddfdB„Z=dMdddCœdDedeeeez  f         dz  dedEede>f
dF„Z?dGedefdH„Z@dIedefdJ„ZAdS )NÚLichesszBCommunication with lichess.org (and chessdb.cn for getting moves).ÚtokenÚurlÚversionÚlogging_levelÚmax_retriesr+   Nc                 óz  — || _         dd|› �i| _        || _        t          j        ¦   «         | _        | j        j                             | j        ¦  «         t          j        ¦   «         | _        |  	                    d¦  «         || _
        || _        t          t          ¦  «        | _        t          t           |                      d|¬¦  «        ¦  «        }|                     |¦  «        }|st'          d¦  «        ‚|                     dd¦  «        }d	|                     d
¦  «        vrt'          d|› d�¦  «        ‚dS )a   
        Communication with lichess.org (and chessdb.cn for getting moves).

        :param token: The bot's token.
        :param url: The base url (lichess.org).
        :param version: The lichess-bot version running.
        :param logging_level: The logging level (logging.INFO or logging.DEBUG).
        :param max_retries: The maximum amount of retries for online moves (e.g. chessdb's opening book).
        ÚAuthorizationzBearer ú?r'   ©rn   z™There was an error in retrieving information about the bot's token. Please check that it was copied correctly into your configuration file and try again.ÚscopesrQ   zbot:playú,z€Please use an API access token for your bot that has the scope "Play games with the bot API (bot:play)". The current token has: ú.N)ry   ÚheaderÚbaseUrlrU   ÚSessionÚsessionÚheadersÚupdateÚother_sessionÚset_user_agentrz   r{   r   r	   Úrate_limit_timersr   r   Úapi_postrT   ÚRuntimeErrorÚsplit)	r1   rw   rx   ry   rz   r{   Útoken_responseÚ
token_infor€   s	            r2   r3   zLichess.__init__~   sT  € ð ˆŒàÐ. uÐ.Ð.ð
ˆŒð ˆŒÝÔ'Ñ)Ô)ˆŒØŒÔ×#Ò# D¤KÑ0Ô0Ð0Ý%Ô-Ñ/Ô/ˆÔØ×Ò˜CÑ Ô Ð Ø*ˆÔØ&ˆÔÝ:EÅeÑ:LÔ:LˆÔõ Õ.°·²¸lÐQV°Ñ0WÔ0WÑXÔXˆØ#×'Ò'¨Ñ.Ô.ˆ
àð 	1Ýð  0ñ 1ô 1ð 1ð —’ ¨"Ñ-Ô-ˆØ˜VŸ\š\¨#Ñ.Ô.Ð.Ð.Ýð  Cà9?ð Cð  Cð  Cñ Dô Dð Dð /Ð.r4   é<   çš™™™™™¹?)Úmax_timeÚintervalÚgiveupÚ
on_backoffÚbackoff_log_levelÚgiveup_log_levelFé   )Úparamsr   r>   Úendpoint_nameÚtemplate_argsrš   r   r>   c                ó¬  — t          j        d¦  «                             | j        ¦  «         |                      |¦  «        }t          | j         |j        |Ž ¦  «        }| j         	                    ||||¬¦  «        }t          |¦  «        r-t          |dk    rdnd¦  «        }	|                      ||	¦  «         |                     ¦   «          d|_        |S )aÝ  
        Send a GET to lichess.org.

        :param endpoint_name: The name of the endpoint.
        :param template_args: The values that go in the url (e.g. the challenge id if `endpoint_name` is `accept`).
        :param params: Parameters sent to lichess.org.
        :param stream: Whether the data returned from lichess.org should be streamed.
        :param timeout: The amount of time in seconds to wait for a response.
        :return: lichess.org's response.
        Úbackoff)rš   r>   r   r   é   r‘   zutf-8)ÚloggingÚ	getLoggerÚsetLevelrz   Úget_path_templater   r„   rq   r†   rT   rK   r
   Úset_rate_limit_delayÚraise_for_statusÚencoding)
r1   r›   rš   r   r>   rœ   Úpath_templaterx   rF   Údelays
             r2   Úapi_getzLichess.api_get¤   sÔ   € õ* 	Ô˜)Ñ$Ô$×-Ò-¨dÔ.@ÑAÔAÐAØ×.Ò.¨}Ñ=Ô=ˆÝ�d”lÐ$8 MÔ$8¸-Ð$HÑIÔIˆØ”<×#Ò# C°ÀÐPVÐ#ÑWÔWˆå˜XÑ&Ô&ð 	<Ý °&Ò!8Ð!8˜A˜A¸bÑAÔAˆEØ×%Ò% m°UÑ;Ô;Ð;à×!Ò!Ñ#Ô#Ð#Ø#ˆÔØˆr4   ©rš   c                óP   —  | j         |g|¢R d|iŽ}|                     ¦   «         }|S )ad  
        Send a GET to the lichess.org endpoints that return a JSON.

        :param endpoint_name: The name of the endpoint.
        :param template_args: The values that go in the url (e.g. the challenge id if `endpoint_name` is `accept`).
        :param params: Parameters sent to lichess.org.
        :return: lichess.org's response in a dict.
        rš   ©r©   rS   ©r1   r›   rš   rœ   rF   Újson_responses         r2   Úapi_get_jsonzLichess.api_get_jsonÆ   s<   € ð  �4”< ÐM°ÐMÐMÐMÀfÐMÐMˆØV^×VcÒVcÑVeÔVeˆØÐr4   c                óP   —  | j         |g|¢R d|iŽ}|                     ¦   «         }|S )a}  
        Send a GET to the lichess.org endpoints that return a list containing JSON.

        :param endpoint_name: The name of the endpoint.
        :param template_args: The values that go in the url (e.g. the challenge id if `endpoint_name` is `accept`).
        :param params: Parameters sent to lichess.org.
        :return: lichess.org's response in a list of dicts.
        rš   r¬   r­   s         r2   Úapi_get_listzLichess.api_get_listÕ   s8   € ð  �4”< ÐM°ÐMÐMÐMÀfÐMÐMˆØ/7¯}ª}©¬ˆØÐr4   c                ó2   —  | j         |g|¢R d|iŽ}|j        S )ae  
        Send a GET to lichess.org that returns plain text (UTF-8).

        :param endpoint_name: The name of the endpoint.
        :param template_args: The values that go in the url (e.g. the challenge id if `endpoint_name` is `accept`).
        :param params: Parameters sent to lichess.org.
        :return: The text of lichess.org's response.
        rš   )r©   Útext)r1   r›   rš   rœ   rF   s        r2   Úapi_get_rawzLichess.api_get_rawã   s-   € ð  �4”< ÐM°ÐMÐMÐMÀfÐMÐMˆØŒ}Ðr4   T)rn   r‡   rš   Úpayloadr¥   rn   r‡   rµ   r¥   c                óð  — t          j        d¦  «                             | j        ¦  «         |                      |¦  «        }t          | j         |j        |Ž ¦  «        }	| j         	                    |	||||d¬¦  «        }
|dk    r|  
                    |
¦  «        S t          |
¦  «        r#|                      |t          d¦  «        ¦  «         |r|
                     ¦   «          |
                     ¦   «         }|S )aD  
        Send a POST to lichess.org.

        :param endpoint_name: The name of the endpoint.
        :param template_args: The values that go in the url (e.g. the challenge id if `endpoint_name` is `accept`).
        :param data: Data sent to lichess.org.
        :param headers: The headers for the request.
        :param params: Parameters sent to lichess.org.
        :param payload: Payload sent to lichess.org.
        :param raise_for_status: Whether to raise an exception if the response contains an error code.
        :return: lichess.org's response in a dict.
        rž   r™   )rn   r‡   rš   rS   r>   r#   r‘   )r    r¡   r¢   rz   r£   r   r„   rq   r†   ÚpostÚhandle_challengerK   r¤   r
   r¥   rS   )r1   r›   rn   r‡   rš   rµ   r¥   rœ   r§   rx   rF   r®   s               r2   rŒ   zLichess.api_postð   sò   € õ8 	Ô˜)Ñ$Ô$×-Ò-¨dÔ.@ÑAÔAÐAØ×.Ò.¨}Ñ=Ô=ˆÝ�d”lÐ$8 MÔ$8¸-Ð$HÑIÔIˆØ”<×$Ò$ S¨t¸WÈVÐZaÐklÐ$ÑmÔmˆà˜KÒ'Ð'Ø×(Ò(¨Ñ2Ô2Ð2å˜XÑ&Ô&ð 	BØ×%Ò% mµW¸R±[´[ÑAÔAÐAàð 	(Ø×%Ò%Ñ'Ô'Ð'àAIÇÂÁÄˆØÐr4   c                 óº   — t           |         }|                      |¦  «        r8|                      |¦  «        }t          |› dt	          |¦  «        › d�|¦  «        ‚|S )zÛ
        Get the path template given the endpoint name. Will raise an exception if the path template is rate limited.

        :param endpoint_name: The name of the endpoint.
        :return: The path template.
        z  is rate-limited. Will retry in z	 seconds.)Ú	ENDPOINTSÚis_rate_limitedÚrate_limit_time_leftr<   r   )r1   r›   r§   Ú	time_lefts       r2   r£   zLichess.get_path_template  sr   € õ " -Ô0ˆØ×Ò Ñ.Ô.ð 	lØ×1Ò1°-Ñ@Ô@ˆIÝ"Ø Ð_Ð_Å'È)ÑBTÔBTÐ_Ð_Ð_Ðajñlô lð làÐr4   rF   c                 ó$  — t          |¦  «        }t          |¦  «        }|                     ¦   «         }|s|rYt          t          j        t          |¦  «        ¦  «        }|r!|                      t          d         |¦  «         ||d<   ||d<   ||d<   |S )zMHandle the response to a challenge and, if necessary, the daily game timeout.r#   Úbot_is_rate_limitedÚopponent_is_rate_limitedÚrate_limit_timeout)	r_   r\   rS   r   rC   rD   rd   r¤   rº   )r1   rF   r¿   rÀ   r`   r¨   s         r2   r¸   zLichess.handle_challenge+  s¦   € å/°Ñ9Ô9ÐÝ#9¸(Ñ#CÔ#CÐ Ø,4¯MªM©O¬OÐØð 	=Ð":ð 	=Ý�Ô+Õ-BÐCUÑ-VÔ-VÑWÔWˆEØ"ð IØ×)Ò)­)°KÔ*@À%ÑHÔHÐHØ8KÐÐ4Ñ5Ø=UÐÐ9Ñ:Ø7<ÐÐ3Ñ4à!Ð!r4   r§   Ú
delay_timec                 ó�   — t                                d|› dt          |¦  «        › d�¦  «         t          |¦  «        | j        |<   dS )z»
        Set a delay to a path template if it was rate limited.

        :param path_template: The path template.
        :param delay_time: How long we won't call this endpoint.
        z	Endpoint z is rate limited. Waiting z seconds until next request.N)ro   Úwarningr   r	   r‹   )r1   r§   rÂ   s      r2   r¤   zLichess.set_rate_limit_delay:  sN   € õ 	�ŠÐ} =Ð}Ð}ÍGÐT^ÑL_ÔL_Ð}Ð}Ð}Ñ~Ô~Ð~Ý05°jÑ0AÔ0AˆÔ˜}Ñ-Ð-Ð-r4   c                 óB   — | j         |                              ¦   «          S )z)Check if a path template is rate limited.)r‹   Ú
is_expired©r1   r§   s     r2   r»   zLichess.is_rate_limitedD  s   € àÔ)¨-Ô8×CÒCÑEÔEÐEÐEr4   c                 ó@   — | j         |                              ¦   «         S )zBHow much time is left until we can use the path template normally.)r‹   Útime_until_expirationrÇ   s     r2   r¼   zLichess.rate_limit_time_leftH  s   € àÔ% mÔ4×JÒJÑLÔLÐLr4   c                 ó0   — |                       d¦  «         dS )z%Upgrade the account to a BOT account.r   N©rŒ   r0   s    r2   Úupgrade_to_bot_accountzLichess.upgrade_to_bot_accountL  s   € à�Š�iÑ Ô Ð Ð Ð r4   Úgame_idr   c           	      ó¨   — |                       d|t          |j        ¦  «        dt          |j        ¦  «                             ¦   «         i¬¦  «         dS )zr
        Make a move.

        :param game_id: The id of the game.
        :param move: The move to make.
        r   ÚofferingDrawrª   N)rŒ   rB   r   Údraw_offeredÚlower)r1   rÍ   r   s      r2   Ú	make_movezLichess.make_moveP  s[   € ð 	�Š�f˜g¥s¨4¬9¡~¤~Ø,­c°$Ô2CÑ.DÔ.D×.JÒ.JÑ.LÔ.LÐMð 	ñ 	Oô 	Oð 	Oð 	Oð 	Or4   r   c                 óÎ   — 	 |                       d||rdnd¦  «         |rt                               d¦  «         nt                               d¦  «         |S # t          $ r Y dS w xY w)z+Answer an opponent's move takeback request.r   ÚyesÚnoz!Opponent took back previous move.z%Refused opponent's take back request.F)rŒ   ro   ÚinfoÚ	Exception)r1   rÍ   r   s      r2   Úaccept_takebackzLichess.accept_takebackZ  s   € ð	Ø�MŠM˜* g¸Ð/H¨u¨uÀDÑIÔIÐIØð EÝ—’Ð?Ñ@Ô@Ð@Ð@å—’ÐCÑDÔDÐDØˆMøÝð 	ð 	ð 	Ø�5�5ð	øøøs   ‚AA Á
A$Á#A$Úroomr³   c                 ó  — t          |¦  «        t          k    rPt                               dt          |¦  «        › dt          › d�¦  «         t                               d|› �¦  «         ||dœ}|                      d||¬¦  «         dS )	zÀ
        Send a message to the chat.

        :param game_id: The id of the game.
        :param room: The room (either chat or spectator room).
        :param text: The text to send.
        zThis chat message is z1 characters, which is longer than the maximum of z. It will not be sent.z	Message: )rÙ   r³   r   r   N)ÚlenÚMAX_CHAT_MESSAGE_LENro   rÄ   rŒ   )r1   rÍ   rÙ   r³   rn   s        r2   r   zLichess.chatf  s¤   € õ ˆt‰9Œ9Õ+Ò+Ð+Ý�NŠNð _µ3°t±9´9ð _ð _Ý2Fð_ð _ð _ñ `ô `ð `å�NŠNÐ- tÐ-Ð-Ñ.Ô.Ð.à dÐ+Ð+ˆØ�Š�f˜g¨DˆÑ1Ô1Ð1Ð1Ð1r4   c                 ó2   — |                       d|¦  «         dS )zAborts a game.r   NrË   ©r1   rÍ   s     r2   r   zLichess.abortv  s   € à�Š�g˜wÑ'Ô'Ð'Ð'Ð'r4   c                 ó2   — |                       ddd¬¦  «        S )z7Get a stream of the events (e.g. challenge, gameStart).r   Té   ©r   r>   ©r©   r0   s    r2   Úget_event_streamzLichess.get_event_streamz  s   € à�|Š|˜N°4Àˆ|ÑDÔDÐDr4   c                 ó4   — |                       d|dd¬¦  «        S )z?Get  stream of the in-game events (e.g. moves by the opponent).r   Trà   rá   râ   rÞ   s     r2   Úget_game_streamzLichess.get_game_stream~  s   € à�|Š|˜H g°dÀBˆ|ÑGÔGÐGr4   Úchallenge_idc                 ó2   — |                       d|¦  «         dS )zAccept a challenge.r   NrË   ©r1   ræ   s     r2   Úaccept_challengezLichess.accept_challenge‚  s   € à�Š�h Ñ-Ô-Ð-Ð-Ð-r4   ÚgenericÚreasonc                 ó¨   — t          j        t          ¦  «        5  |                      d|d|› �ddid¬¦  «         ddd¦  «         dS # 1 swxY w Y   dS )zDecline a challenge.r   zreason=zContent-Typez!application/x-www-form-urlencodedF)rn   r‡   r¥   N)Ú
contextlibÚsuppressr×   rŒ   )r1   ræ   rë   s      r2   Údecline_challengezLichess.decline_challenge†  s­   € åÔ ¥Ñ+Ô+ð 	2ð 	2Ø�MŠM˜) \Ø1¨Ð1Ð1Ø#1Ð3VÐ"WØ+0ð ñ 2ô 2ð 2ð	2ð 	2ð 	2ñ 	2ô 	2ð 	2ð 	2ð 	2ð 	2ð 	2ð 	2ð 	2øøøð 	2ð 	2ð 	2ð 	2ð 	2ð 	2s   š AÁAÁAc                 óŒ   — t          t          |                      d¦  «        ¦  «        }|                      |d         ¦  «         |S )z&Get the bot's profile (e.g. username).r   Úusername)r   r   r¯   rŠ   )r1   r   s     r2   Úget_profilezLichess.get_profileŽ  s=   € å•¨×(9Ò(9¸)Ñ(DÔ(DÑEÔEˆØ×Ò˜G JÔ/Ñ0Ô0Ð0Øˆr4   c                 ó  — t          j        t          ¦  «        5  t          t          t
          t          t                   f         |                      d¦  «        ¦  «        }|d         cddd¦  «         S # 1 swxY w Y   dS )zw
        Get the bot's ongoing games.

        If an error occurs when retrieving the games, None is returned.
        r   Ú
nowPlayingN)	rí   rî   r×   r   ÚdictrB   Úlistr   r¯   )r1   rF   s     r2   Úget_ongoing_gameszLichess.get_ongoing_games”  s©   € õ Ô ¥Ñ+Ô+ð 	*ð 	*Ý�D¥¥d­8¤nÐ!4Ô5°t×7HÒ7HÈÑ7SÔ7SÑTÔTˆHØ˜LÔ)ð	*ð 	*ð 	*ð 	*ñ 	*ô 	*ð 	*ð 	*ð 	*ð 	*ð 	*ð 	*øøøð 	*ð 	*ð 	*ð 	*ð ˆts   šAA4Á4A8Á;A8c                 ó2   — |                       d|¦  «         dS )zResign a game.r    NrË   rÞ   s     r2   r    zLichess.resignŸ  s   € à�Š�h Ñ(Ô(Ð(Ð(Ð(r4   rñ   c                 óœ   — | j                              dd| j        › d|› �i¦  «         | j        j                             | j         ¦  «         dS )z6Set the user agent for communication with lichess.org.z
User-Agentzlichess-bot/z user:N)rƒ   rˆ   ry   r†   r‡   )r1   rñ   s     r2   rŠ   zLichess.set_user_agent£  sQ   € àŒ×Ò˜LÐ*W¸¼Ð*WÐ*WÈXÐ*WÐ*WÐXÑYÔYÐYØŒÔ×#Ò# D¤KÑ0Ô0Ð0Ð0Ð0r4   c                 óR   — 	 |                       d|¦  «        S # t          $ r Y dS w xY w)z6Get the PGN (Portable Game Notation) record of a game.r!   rQ   )r´   r×   rÞ   s     r2   Úget_game_pgnzLichess.get_game_pgn¨  s?   € ð	Ø×#Ò# H¨gÑ6Ô6Ð6øÝð 	ð 	ð 	Ø�2�2ð	øøøs   ‚ ˜
&¥&c                 ó
  — 	 |                       d¦  «        }t          t          t          |                     d¦  «        ¦  «        ¦  «        }t          t          t          j        |¦  «        ¦  «        S # t          $ r g cY S w xY w)z#Get a list of bots that are online.r"   ú
)	r´   rö   ÚfilterÚboolrŽ   ÚmaprS   Úloadsr×   )r1   Úonline_bots_strr"   s      r2   Úget_online_botszLichess.get_online_bots¯  s}   € ð	Ø"×.Ò.¨}Ñ=Ô=ˆOÝ�v¥d¨O×,AÒ,AÀ$Ñ,GÔ,GÑHÔHÑIÔIˆKÝ��DœJ¨Ñ4Ô4Ñ5Ô5Ð5øÝð 	ð 	ð 	ØˆIˆIˆIð	øøøs   ‚A0A3 Á3BÂBc           	      óZ   — t          t          |                      d||d¬¦  «        ¦  «        S )zCreate a challenge.r#   F)rµ   r¥   )r   r   rŒ   )r1   rñ   rµ   s      r2   r#   zLichess.challenge¸  s1   € å•MØ—M’M +¨xÀÐ[`�MÑaÔañcô cð 	cr4   c                 ó6   — |                       d|d¬¦  «         dS )zCancel a challenge.r$   F)r¥   NrË   rè   s     r2   r$   zLichess.cancel½  s    € à�Š�h ¸uˆÑEÔEÐEÐEÐEr4   )r   ÚauthenticatedÚpathr  c                ó  ‡ ‡‡‡‡— t          j        t           j        t          t          t
          t          fd‰ j        dt          t          t          j        t          j        ¬¦	  «	        dt          fˆˆˆˆ ˆfd„¦   «         } |¦   «         S )zBGet an external move from online sources (chessdb or lichess.org).r‘   r’   )r“   Ú	max_triesr”   r•   r–   r—   r˜   r+   c                  ó~   •— ‰r‰j         n‰j        } |                      ‰d‰‰¬¦  «                             ¦   «         }|S )Nr™   )r>   rš   r   )r†   r‰   rT   rS   )r†   r®   r  rš   r  r1   r   s     €€€€€r2   Úonline_book_getz0Lichess.online_book_get.<locals>.online_book_getÄ  sD   ø€ ð '4ÐK�d”l�l¸Ô9KˆGØ(/¯ª°DÀ!ÈFÐ[a¨Ñ(bÔ(b×(gÒ(gÑ(iÔ(iˆMØ Ð r4   )rž   Úon_exceptionÚconstantr   ÚRequestsConnectionErrorr   r   r{   ri   rt   r    ÚDEBUGr   )r1   r  rš   r   r  r  s   ````` r2   r  zLichess.online_book_getÁ  s    øøøøø€ õ 
Ô	�gÔ.Ý1Õ3JÍIÕWbÐcØ')Ø(,Ô(8Ø'*Ý%-Ý)8Ý07´Ý/6¬}ð
>ñ 
>ô 
>ð	!¥ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ð 	!ñ
>ô 
>ð	!ð ˆÑ Ô Ð r4   Úuser_idc                 óˆ   — |                       dd|i¬¦  «        }t          |o|d                              d¦  «        ¦  «        S )z5Check if lichess.org thinks the bot is online or not.r%   Úidsrª   r   Úonline)r±   rÿ   rT   )r1   r  Úusers      r2   Ú	is_onlinezLichess.is_onlineÓ  sB   € à× Ò  °5¸'Ð2BÐ ÑCÔCˆÝ�DÐ2˜T !œWŸ[š[¨Ñ2Ô2Ñ3Ô3Ð3r4   Ú	user_namec                 óT   — t          t          |                      d|¦  «        ¦  «        S )zGet the public data of a bot.r&   )r   r   r¯   )r1   r  s     r2   Úget_public_datazLichess.get_public_dataØ  s"   € å•N D×$5Ò$5°mÀYÑ$OÔ$OÑPÔPÐPr4   r5   )rê   )N)Br6   r7   r8   r9   rB   Úintr3   rž   r  r  r   r  r   r   ri   rt   r    r  rõ   rÿ   rU   ÚResponser©   r   r   rö   r   r¯   r±   r´   r   r   r   rŒ   r£   Úmodelsr¸   rC   rD   r¤   r»   r¼   rÌ   ÚchessÚengineÚ
PlayResultrÒ   rØ   r   r   rã   rå   ré   rï   rò   r÷   r    rŠ   rû   r  r#   r$   r   r  r  r  r:   r4   r2   rv   rv   {   s$  € € € € € ØLÐLð$D˜cð $D¨ð $D°cð $DÈ#ð $DÐ\_ð $DÐdhð $Dð $Dð $Dð $DðL €WÔ˜'Ô*Ø-Ð/FÈ	ÐS^Ð_Ø#%Ø#&Ø!)Ø%4Ø,3¬MØ+2¬=ð:ñ :ô :ð 15Ø$°Qðð ð  Sð ¸#ð Ø˜S #˜Xœ¨Ñ-ðàðà/2ðà;CÔ;Lðð ð ñ:ô :ðð6 6:ðð ð ¨#ð ¸sð Ø! # s (œ^¨dÑ2ðà(¨?Ñ:¸TÀ#ÀtÈHÄ~ÐBUÔ=VÑVðð ð ð ð  6:ðð ð ¨#ð ¸sð Ø! # s (œ^¨dÑ2ðØ>BÀ?Ô>Sðð ð ð ð 59ðð ð ¨ð ¸cð Ø   c œN¨TÑ1ðØ=@ðð ð ð ð €WÔ˜'Ô*Ø-Ð/FÈ	ÐS^Ð_Ø#%Ø#&Ø!)Ø%4Ø,3¬MØ+2¬=ð:ñ :ô :ð 6:Ø26Ø15Ø9=Ø*.ð#ð #ð #Ø #ð#à!$ð#ð ˜T # s (œ^Ñ+¨dÑ2ð#ð ˜s C˜xœ.¨4Ñ/ð	#ð
 ˜c 3˜hœ¨$Ñ.ð#ð 0°$Ñ6ð#ð $(ð#ð 4AÐCSÑ3SÐVZÑ3Zð#ð #ð #ñ:ô :ð#ðJ¨sð °sð ð ð ð ð"¨¬Ô)Að "Àmð "ð "ð "ð "ðB°#ð BÀ8ÔCUð BÐZ^ð Bð Bð Bð BðF¨Sð F°Tð Fð Fð Fð FðM°#ð M¸(Ô:Lð Mð Mð Mð Mð!ð !ð !ð !ðO ð O¨E¬LÔ,Cð OÈð Oð Oð Oð Oð
 sð 
°Dð 
¸Tð 
ð 
ð 
ð 
ð2˜Cð 2 sð 2°#ð 2¸$ð 2ð 2ð 2ð 2ð (˜Sð ( Tð (ð (ð (ð (ðE (¤/Ô":ð Eð Eð Eð EðH sð H¨x¬Ô/Gð Hð Hð Hð Hð.¨Sð .°Tð .ð .ð .ð .ð2ð 2¨cð 2¸3ð 2Ètð 2ð 2ð 2ð 2ð˜_ð ð ð ð ð	 4¨¤>°DÑ#8ð 	ð 	ð 	ð 	ð)˜cð ) dð )ð )ð )ð )ð1 sð 1¨tð 1ð 1ð 1ð 1ð
 Cð ¨Cð ð ð ð ð  oÔ!6ð ð ð ð ðc #ð cÐ0Eð cÈ-ð cð cð cð cð
F 3ð F¨4ð Fð Fð Fð Fð!Ø',ÀEð!ð !ð ! Cð !°°c¸3À¹9°nÔ1EÈÑ1Lð !Ø $ð!Ø=Að!ØNXð!ð !ð !ð !ð$4 ð 4¨ð 4ð 4ð 4ð 4ð
Q¨ð Q°ð Qð Qð Qð Qð Qð Qr4   rv   );r9   rS   rU   Úurllib.parser   Úrequests.exceptionsr   r  r   r   Úhttp.clientr   rž   r    rr   Úcollectionsr   rC   rí   Ú	lib.timerr	   r
   r   Útypingr   Úchess.enginer  Úlib.lichess_typesr   r   r   r   r   r   r   r   rº   r¡   r6   ro   rÜ   r*   rh   r�   r<   r  r  rÿ   rK   r  rY   r\   r_   rD   rd   r×   ri   rt   rv   r:   r4   r2   ú<module>r'     s!  ðØ Ð Ø €€€Ø €€€Ø  Ð  Ð  Ð  Ð  Ð  Ø bÐ bÐ bÐ bÐ bÐ bÐ bÐ bÐ bÐ bØ *Ð *Ð *Ð *Ð *Ð *Ø €€€Ø €€€Ø Ð Ð Ð Ø #Ð #Ð #Ð #Ð #Ð #Ø €€€Ø Ð Ð Ð Ø -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð ðHð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð Hð HðØˆ~ðàÐ%ðð Ð'ðð Ð'ð	ð
 Ð&ðð Ð.ðð Ð#ðð Ð%ðð Ð(ðð Ð*ðð Ð)ðð Ð'ðð Ððð Ð$ðð Ð$ðð  Ð(ð!ð" Ð!ð#ð$ "Ø#ð'ð ð €	ð. 
ˆÔ	˜8Ñ	$Ô	$€àÐ ðð ð ð ð ñ ô ð ð €t�v„v€ðð ð ð ð �|ñ ô ð ð' ¤Ô 8ð '¸Tð 'ð 'ð 'ð 'ð	 x¤Ô'?ð 	ÐY\ð 	Ðaeð 	ð 	ð 	ð 	ð3 X¤_Ô%=ð 3À$ð 3ð 3ð 3ð 3ð
3 ¤Ô 8ð 3¸Tð 3ð 3ð 3ð 3ð
¨mð ÀÔ@RÐUYÑ@Yð ð ð ð ð ˜	ð   dð  ð  ð  ð  ð9˜^ð 9°ð 9ð 9ð 9ð 9ð_Qð _Qð _Qð _Qð _Qñ _Qô _Qð _Qð _Qð _Qr4   