Ë
    }D™j*%  ã                   ó>  — d 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 ddlmZmZmZ dd	lmZ  ee«      Z e
d
«      dz  ZdZ eh d£«      Zdedefd„Z G d„ d«      Zedk(  r/	 ddlmZ  ed«        edd«      Z  e!e jE                  «       «       yy)zS
Author: Giacomo Battaglia
Copyright: (C) 2025 Kerykeion Project
License: AGPL-3.0
é    )Ú	getLogger)Ú	timedelta)ÚJSONDecodeError)Úgetenv)ÚPath)ÚOptionalÚUnion)ÚRequestÚRequestExceptionÚResponse)ÚCachedSessionÚcacheÚkerykeion_geonames_cacheÚKERYKEION_GEONAMES_CACHE_NAME>   é   é   é   é   é   ÚresponseÚreturnc                 óè   — 	 | j                  «       }d|v rH|d   j                  dd«      }|t        v r+t        j	                  d||d   j                  dd«      «       yy# t
        t        f$ r Y yw xY w)	aÓ  
    Filter function for requests-cache to prevent caching transient error responses.

    GeoNames API returns errors with HTTP 200 status code but with a 'status' key
    in the JSON response. This function checks for transient errors (rate limits,
    timeouts, server overload) and returns False to prevent caching them.

    Args:
        response: The HTTP response to evaluate.

    Returns:
        True if the response should be cached, False otherwise.
    ÚstatusÚvaluer   z9GeoNames transient error (code %d) will not be cached: %sÚmessagezunknown errorFT)ÚjsonÚgetÚTRANSIENT_GEONAMES_ERROR_CODESÚloggerÚdebugÚ
ValueErrorr   )r   ÚdataÚ
error_codes      úd/var/www/html/Astrologybackend/backend/venv/lib/python3.12/site-packages/kerykeion/fetch_geonames.pyÚ_should_cache_geonames_responser%   (   s~   € ðØ�}‰}‹ˆØ�tÑØ˜h™×+Ñ+¨G°QÓ7ˆJØÔ;Ñ;Ü—‘ØOØØ˜‘N×&Ñ& y°/ÓBôð
 ØøÜœÐ(ò áðús   ‚AA ÁA1Á0A1c                   ó&  — e Zd ZU dZeZeed<   	 	 	 ddededede	e
eef      fd„Zede
eef   d	dfd
„«       Zede	e
eef      d	efd„«       Zde
eeef   de
eeef   d	eeef   fd„Zdeded	eeef   fd„Zdeded	eeef   fd„Zd	eeef   fd„Zy)ÚFetchGeonamesaw  
    Class to handle requests to the GeoNames API for location data and timezone information.

    This class provides cached access to the GeoNames API to retrieve location coordinates,
    timezone information, and other geographical data for astrological calculations.

    Args:
        city_name: Name of the city to search for.
        country_code: Two-letter country code (ISO 3166-1 alpha-2).
        username: GeoNames username for API access, defaults to "century.boy".
        cache_expire_after_days: Number of days to cache responses, defaults to 30.
        cache_name: Optional path (directory or filename stem) used by requests-cache.
            Defaults to "cache/kerykeion_geonames_cache" and may also be overridden
            via the environment variable ``KERYKEION_GEONAMES_CACHE_NAME`` or by
            calling :meth:`FetchGeonames.set_default_cache_name`.
    Údefault_cache_nameNÚ	city_nameÚcountry_codeÚusernameÚ
cache_namec                 ó¾   — t        t        | j                  |«      «      dt        |¬«      t        ¬«      | _        || _        || _        || _        d| _	        d| _
        y )NÚsqlite)Údays)r,   ÚbackendÚexpire_afterÚ	filter_fnz"http://api.geonames.org/searchJSONz$http://api.geonames.org/timezoneJSON)r   ÚstrÚ_resolve_cache_namer   r%   Úsessionr+   r)   r*   Úbase_urlÚtimezone_url)Úselfr)   r*   r+   Úcache_expire_after_daysr,   s         r$   Ú__init__zFetchGeonames.__init__[   s[   € ô %Ü˜4×3Ñ3°JÓ?Ó@ØÜ"Ð(?Ô@Ü5ô	
ˆŒð !ˆŒØ"ˆŒØ(ˆÔð =ˆŒØBˆÕó    r   c                 ó$   — t        |«      | _        y)z;Override the default cache name used when none is provided.N)r   r(   )Úclsr,   s     r$   Úset_default_cache_namez$FetchGeonames.set_default_cache_names   s   € ô "& jÓ!1ˆÕr;   c                 ól   — |�t        |«      S t        t        «      }|rt        |«      S | j                  S )zDReturn the resolved cache name applying overrides in priority order.)r   r   ÚGEONAMES_CACHE_ENV_VARr(   )r=   r,   Úenv_overrides      r$   r4   z!FetchGeonames._resolve_cache_namey   s:   € ð Ð!Ü˜
Ó#Ð#äÔ4Ó5ˆÙÜ˜Ó%Ð%à×%Ñ%Ð%r;   ÚlatÚlonc                 ó‚  — i }||| j                   dœ}t        d| j                  |¬«      j                  «       }t        j                  d|j                  «       	 | j                  j                  |«      }|j                  «       }	 |d   |d	<   t        |d«      r|j                   |d<   |S # t        $ r-}t        j                  d| j                  |«       i cY d}~S d}~wt        $ r"}t        j                  d|«       i cY d}~S d}~ww xY w# t        t        f$ r"}t        j                  d
|«       i cY d}~S d}~ww xY w)a  
        Get timezone information for a given latitude and longitude.

        Args:
            lat: Latitude coordinate.
            lon: Longitude coordinate.

        Returns:
            dict: Timezone data including timezone string and cache status.
        )rB   Úlngr+   ÚGET©ÚparamszGeoNames timezone lookup url=%sz*GeoNames timezone network error for %s: %sNz+GeoNames timezone invalid JSON response: %sÚ
timezoneIdÚtimezonestrz3GeoNames timezone payload missing expected keys: %sÚ
from_cacheÚfrom_tz_cache)r+   r
   r7   Úpreparer   r    Úurlr5   Úsendr   r   Úerrorr   ÚKeyErrorÚ	TypeErrorÚhasattrrK   )	r8   rB   rC   Útimezone_datarH   Úprepared_requestr   Úresponse_jsonÚes	            r$   Ú__get_timezonezFetchGeonames.__get_timezone†   s  € ð ˆà S°d·m±mÑDˆä" 5¨$×*;Ñ*;ÀFÔK×SÑSÓUÐÜ�‰Ð6Ð8H×8LÑ8LÔMð		Ø—|‘|×(Ñ(Ð)9Ó:ˆHØ$ŸM™M›OˆMð	Ø+8¸Ñ+FˆM˜-Ñ(ô �8˜\Ô*Ø-5×-@Ñ-@ˆM˜/Ñ*àÐøô#  ò 	Ü�L‰LÐEÀt×GXÑGXÐZ[Ô\Ø�IûÜò 	Ü�L‰LÐFÈÔJØ�Iûð	ûô œ)Ð$ò 	Ü�L‰LÐNÐPQÔRØ�Iûð	úsN   Á+B+ ÂD Â+	D
Â4"CÃD
ÃD
Ã(DÃ?D
ÄD
ÄD>ÄD9Ä3D>Ä9D>c                 óB  — i }||| j                   ddddgdœ}t        d| j                  |¬«      j                  «       }t        j                  d|j                  «       	 | j                  j                  |«      }|j                  «        |j                  «       }t        j                  d	|«       	 |d   d   d   |d<   |d   d   d   |d<   |d   d   d   |d<   |d   d   d   |d<   t#        |d«      r|j$                  |d<   |S # t        $ r-}t        j                  d
| j                  |«       i cY d}~S d}~wt        $ r"}t        j                  d|«       i cY d}~S d}~ww xY w# t        t        t         f$ r"}t        j                  d|«       i cY d}~S d}~ww xY w)a'  
        Get city location data without timezone for a given city and country.

        Args:
            city_name: Name of the city to search for.
            country_code: Two-letter country code.

        Returns:
            dict: City location data excluding timezone information.
        é   ÚSHORTÚAÚP)ÚqÚcountryr+   ÚmaxRowsÚstyleÚfeatureClassrF   rG   zGeoNames search url=%szGeoNames search response: %sz(GeoNames search network error for %s: %sNz)GeoNames search invalid JSON response: %sÚgeonamesr   ÚnamerB   rE   ÚcountryCodez1GeoNames search payload missing expected keys: %srK   Úfrom_country_cache)r+   r
   r6   rM   r   r    rN   r5   rO   Úraise_for_statusr   r   rP   r   rQ   Ú
IndexErrorrR   rS   rK   )	r8   r)   r*   Úcity_data_without_tzrH   rU   r   rV   rW   s	            r$   Ú__get_country_dataz FetchGeonames.__get_country_data°   s¨  € ð  "Ðð Ø#ØŸ™ØØØ  #˜Jñ
ˆô # 5¨$¯-©-ÀÔG×OÑOÓQÐÜ�‰Ð-Ð/?×/CÑ/CÔDð	Ø—|‘|×(Ñ(Ð)9Ó:ˆHØ×%Ñ%Ô'Ø$ŸM™M›OˆMÜ�L‰LÐ7¸ÔGð	Ø+8¸Ñ+DÀQÑ+GÈÑ+OÐ  Ñ(Ø*7¸
Ñ*CÀAÑ*FÀuÑ*MÐ  Ñ'Ø*7¸
Ñ*CÀAÑ*FÀuÑ*MÐ  Ñ'Ø2?À
Ñ2KÈAÑ2NÈ}Ñ2]Ð  Ñ/ô �8˜\Ô*Ø9A×9LÑ9LÐ Ð!5Ñ6à#Ð#øô)  ò 	Ü�L‰LÐCÀTÇ]Á]ÐTUÔVØ�IûÜò 	Ü�L‰LÐDÀaÔHØ�Iûð	ûô œ*¤iÐ0ò 	Ü�L‰LÐLÈaÔPØ�Iûð	úsO   ÁAD Â18E( Ä	E%Ä"D7Ä1E%Ä7E%ÅE ÅE%Å E%Å(FÅ<FÆFÆFc                 ó&   — | j                  ||«      S )N)Ú _FetchGeonames__get_country_data)r8   r)   r*   s      r$   Ú__get_contry_datazFetchGeonames.__get_contry_dataæ   s   € Ø×&Ñ& y°,Ó?Ð?r;   c                 óè   — | j                  | j                  | j                  «      }	 | j                  |d   |d   «      }i |¥|¥S # t        $ r"}t
        j                  d|«       i cY d}~S d}~ww xY w)zù
        Returns all the data necessary for the Kerykeion calculation.

        Returns:
            dict[str, str]: Dictionary containing city name, latitude, longitude,
                country code, timezone, and cache status information.
        rB   rE   z1Unable to fetch timezone details, missing key: %sN)rl   r)   r*   Ú_FetchGeonames__get_timezonerQ   r   rP   )r8   Úcity_data_responseÚtimezone_responserW   s       r$   Úget_serialized_dataz!FetchGeonames.get_serialized_dataé   s€   € ð "×4Ñ4°T·^±^ÀT×EVÑEVÓWÐð	Ø $× 3Ñ 3Ð4FÀuÑ4MÐOaÐbgÑOhÓ iÐð ;Ð#Ð:Ð'9Ð:Ð:øô	 ò 	Ü�L‰LÐLÈaÔPØ�Iûð	ús   ¨A Á	A1ÁA,Á&A1Á,A1)zcentury.boyé   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚDEFAULT_GEONAMES_CACHE_NAMEr(   r   Ú__annotations__r3   r   r	   r:   Úclassmethodr>   r4   ÚfloatÚintÚdictro   rl   Ú_FetchGeonames__get_contry_datarr   © r;   r$   r'   r'   G   sV  … ñð"  ;Ð˜Ó:ð &Ø "Ø15ñCàðCð ðCð ð	Cð ˜U 3¨ 9Ñ-Ñ.óCð0 ð2°°c¸4°iÑ0@ð 2ÀTò 2ó ð2ð
 ð
&¨X°e¸CÀ¸IÑ6FÑ-Gð 
&ÈDò 
&ó ð
&ð( %¨¨U°C¨Ñ"8ð (¸uÀSÈ%ÐQTÀ_Ñ?Uð (ÐZ^Ð_bÐdgÐ_gÑZhó (ðT4$¨Cð 4$¸sð 4$ÀtÈCÐQTÈHÁ~ó 4$ðl@¨3ð @¸cð @ÀdÈ3ÐPSÈ8Ánó @ð; T¨#¨s¨(¡^ô ;r;   r'   Ú__main__)Úsetup_loggingr    ÚMontichiariÚITN)#rw   Úloggingr   Údatetimer   r   r   Úosr   Úpathlibr   Útypingr   r	   Úrequestsr
   r   r   Úrequests_cacher   rt   r   rx   r@   Ú	frozensetr   Úboolr%   r'   Úkerykeion.utilitiesr�   Úconfigure_loggingrc   Úprintrr   r   r;   r$   ú<module>r�      s·   ðñõ Ý Ý  Ý Ý ß "ç 8Ñ 8Ý (ñ 
�8Ó	€ñ # 7›mÐ.HÑHÐ Ø8Ð ñ "+òó"Ð ð¨hð ¸4ó ÷>r;ñ r;ðj ˆzÒØFÝFá�gÔÙ˜]¨DÓ1€HÙ	ˆ(×
&Ñ
&Ó
(Õ)ð r;   