
    -މj
h                    4   S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSK	r
SSKJrJrJr  SSKJr  SSKJr  SSKJrJrJr  SSKJrJr  SS	KJr  \" \5      R9                  5       R:                  r\S
-  r\S-  S-  r \RB                  " 5       r"SSSS.r#S*S jr$S+S jr%S,S jr&S-S jr'S.S jr(S/S jr)S0S jr*S1S jr+S2S jr,S3S jr-S4S jr.S5S jr/S6S jr0S7S jr1S8S jr2S9S  jr3S:S! jr4S;S" jr5S<S# jr6S=S$ jr7S>S% jr8S?S& jr9S+S' jr:S@S( jr;\<S):X  a  \;" 5         gg)AuU   Stáhne veřejné stránky CK Fischer, uloží hotely, termíny letů a historii cen.    )annotationsN)datetime	timedeltatimezone)Path)Any)parse_qs	urlencodeurlparse)connectinit_db)send_eventszconfig.jsondatazsnapshot.json)zRhodos DiagorasRHO)	HeraklionHER)AraxosGPA)Rhodosu   Krétau
   Peloponésc                     [         R                  " [        R                  5      R	                  5       R                  SS9R                  5       $ )Nr   )microsecond)r   nowr   utc
astimezonereplace	isoformat     /var/www/vacation/scrape.pynow_isor    !   s5    <<%002::q:ISSUUr   c                 P    [         R                  " [        R                  SS95      $ )Nutf-8encoding)jsonloadsCONFIG_PATH	read_textr   r   r   load_configr)   %   s    ::k++W+=>>r   c                n    1 SknU R                  5        VVs0 s H  u  p#X!;  d  M  X#_M     snn$ s  snnf )N>   email
user_agentaccess_token)items)cfgskipkvs       r   public_filtersr3   )   s/    2D YY[:[TQAMDAD[:::s   11c                P   [         R                  R                  U UR                  SS5      R	                  S5      =(       d    SSS.S9n[         R                  R                  U[        SS9 nUR                  5       R	                  S	S
5      sS S S 5        $ ! , (       d  f       g = f)NasciiignoreVacationOverview/1.0zcs-CZ,cs;q=0.9,en;q=0.8)
User-AgentAccept-Languageheaders<   contexttimeoutr"   r   )urllibrequestRequestencodedecodeurlopenCTXreadurlr,   reqresps       r   fetchrL   .   s    
..
 
 $++GX>EEgNhRh8
 ! C 
		S"		=yy{!!'95 
>	=	=s   - B
B%c                z   [         R                  R                  U UR                  SS5      R	                  S5      =(       d    SSSS.S9n[         R                  R                  U[        SS	9 n[        R                  " UR                  5       R	                  S
S5      5      sS S S 5        $ ! , (       d  f       g = f)Nr5   r6   r7   zapplication/jsonzcs-CZ,cs;q=0.9)r8   Acceptr9   r:   r<   r=   r"   r   )
r@   rA   rB   rC   rD   rE   rF   r%   r&   rG   rH   s       r   
fetch_jsonrO   :   s    
..
 
 $++GX>EEgNhRh(/
 ! C 
		S"		=zz$))+,,Wi@A 
>	=	=s   .4B,,
B:c                    [         R                  " S[         R                  " U5       S3U [         R                  5      nU(       d  g [        R
                  " UR                  S5      5      $ )Nz<div data-component-name="z3">\s*<script type="application/json">(.*?)</script>   )researchescapeSr%   r&   group)htmlnamems      r   component_jsonrZ   G   sO    
		%biio%66ij
	A
 ::aggaj!!r   c                Z   U (       d  g[         R                  " SSU [         R                  S9n [         R                  " SSU [         R                  S9n [         R                  " SSU [         R                  S9n [         R                  " SSU [         R                  S9n [         R                  " S	SU 5      n [        R                  " U 5      n U R                  S
S5      R                  SS5      n [         R                  " SSU 5      n [         R                  " SSU 5      n U R                  5       $ )N z	<br\s*/?>
)flagsz</p>z</li>z	<li[^>]*>   • z<[^>]+>     z[ \t]+z\n{3,}

)rR   subIhtmlmodunescaper   strip)texts    r   
strip_htmlrj   R   s    66,d"$$7D66'4RTT2D66(D$bdd3D66,BDD9D66*b$'DD!D<<$,,T26D66)S$'D66)VT*D::<r   c                :   U (       d  g [         R                  " SU R                  SS5      [         R                  5      nU(       a*  [	        UR                  S5      R                  SS5      5      $ [         R                  " SU [         R                  5      (       a  gg )	Nz([\d]+(?:[.,]\d+)?)\s*kmra   r\   rQ   ,.z	^\s*0\s*mg        )rR   rS   r   re   floatrV   )rawrY   s     r   km_valuerp   a   sj    
		-s{{3/CRTTJAQWWQZ''S122	yysBDD))r   c                    0 nU =(       d    /  HP  nUR                  S5      =(       d    SR                  5       nU(       d  M4  [        UR                  S5      5      X'   MR     U$ )Ntitler\   description)getrh   rj   )detail_descriptionsoutitemrr   s       r   section_maprx   l   sW    C#)r)'"(b//1 78
	 *
 Jr   c                   ^ U R                  5        H<  u  p#UR                  5       m[        U4S jU 5       5      (       d  M1  U(       d  M:  Us  $    g)Nc              3  H   >#    U  H  oR                  5       T;   v   M     g 7f)Nlower).0nkls     r   	<genexpr>pick_section.<locals>.<genexpr>y   s     01wwyBs   "r\   )r.   r|   any)sectionsneedleskeyvalr   s       @r   pick_sectionr   v   s@    NN$YY[0000SSJ % r   c                f    U R                  5       nSU;   d  SU;   a  gSU;   d  SU;   a  gSU;   a  gg	)
Nzultra all inclusiveuallzUltra all inclusiveall inclusiveallinclusivezAll inclusive	polopenze	Polopenzer\   r{   )ri   ts     r   infer_meals_typer   ~   s>    

A!Vq[$!~2ar   c                B   U(       a  X#4$ [         R                  U 5      nU(       a
  US   US   4$ SR                  UR                  5       5      n[        R
                  " SU[        R                  5      nU(       a!  UR                  S5      R                  5       U4$ X4$ )Nr   rQ   ra   uY   letišt[eě]\s+([A-ZÁÉÍÓÚÝČĎĚŇŘŠŤŽ][A-Za-zÁÉÍÓÚÝČĎĚŇŘŠŤŽ\-]+))	DEST_AIRPORTSrt   joinvaluesrR   rS   re   rV   rh   )destinationr   hintiatamappedblobrY   s          r   infer_airportr      s    z{+Fay&)##88HOO%&D
		nptvxvzvz{Awwqz!4''r   c                	   [        U S5      nU(       d  [        S5      eUS   nUS   S   nUS   nUS   n[        US   S	   5      nUR                  S
5      =(       d    /  Vs0 s H  oS   US   _M     n	n/ n
UR                  S5      =(       d    /  H{  nUR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      nU(       d  MM  U
R	                  XR                  S5      =(       d    US   S.5        M}     [        USS5      n[        US5      n[        US5      nX4 Vs/ s H  nU(       d  M  UPM     nn[        US   R                  S5      5      =(       d    [        USS5      nUS   S   n[        UXqR                  SS5      UR                  SS5      5      u  nnU	R                  S5      =(       d    SnU(       dY  [        USS5      n[        R                  " SU[        R                  5      nU(       a  UR                  S 5      R                  5       n[        U5      =(       dK    [        U5      =(       d9    [        S!R                  S" UR                  S#5      =(       d    /  5       5      5      n[        US$5      nUR                  S%5      S&   R                  S'5      R                  5       n0 S(US)   _S*[!        US+   5      R"                  R%                  S,5      R                  S,5      S-   _SUS   R                  5       _S+US+   _S.UR                  S/5      _SU_S0US   S(   _S1US1   S   _S2US2   S   _S3US4   S5   S6   _S7US4   S5   S8   _S9U_SU_S:U_S;['        U5      _S<U	R                  S=5      =(       d    S_S>U	R                  S?5      =(       d    S_U	UR                  S#5      =(       d    /  Vs/ s H  nUS@   PM
     snUUUSAR                  U5      UU
(       a  U
S&   S+   OSU
S SB UUSC   R                  SD5      USC   R                  SE5      USC   R                  SF5      UR                  SG5      UR                  SH5      SI.E$ s  snf s  snf s  snf )JNabnbHotelDetailu1   Na stránce chybí JSON hotelu (abnbHotelDetail).hotelDetailInfodataNewhotelhotelLocationhotelSdors   detailDescriptions	distancesrX   valueimagesmediumlargesmall)rI   altStravau   Stravováníu	   Poznámkau   ZvláštnostimainDescriptionzInformace o hoteluPolohar   airport_hintr\   airport_iatau'   Vzdálenost od nejbližšího letištěu   Vzdálenostu    letišt[eě][^:]*:\s*([^\n•]+)rQ   ra   c              3  D   #    U  H  oR                  S S5      v   M     g7f)ri   r\   N)rt   )r}   bs     r   r   parse_hotel.<locals>.<genexpr>   s     O-Mqvr""-Ms    mainPropertiesWebr]   r   r_   id
identifierslugrI   /official_starsstardestination_idareacountrylathotelPingpslatitudelng	longitudeairport_nameairport_distanceairport_distance_kmbeach_distanceu   Vzdálenost k plážicenter_distanceu   Centrum městari   rc      identifiersgiata
dataSource	bedBankIDfilterParametersBasetourTip)r   benefitssummarymeals
meals_type
conditionsr   	image_urlr   websiter   data_sourceprovider_idfilter_basetour_tip)rZ   
ValueErrorrx   rt   appendr   rj   r   rR   rS   re   rV   rh   r   r   splitr   pathrstriprp   )rW   cfg_itemr   infor   locsdor   dr   r   imgrI   r   notesspecspconditions_partsr   	dest_namer   r   r   loc_blobrY   r   r   r   s                               r   parse_hotelr      s   $ 12DLMM!"DOG$E

 C
j/C5/0DEFH15+1F1L"1LN1L16AgJ&1LINFxx!'R'gghG3777#3Gswww7G3MM#ggm.D.TVUV (
 8^<E;/E?3E$)>7>aQ>7}-112CDE &JG M"6*I!.8\\."=x||N\^?_"L, !}}%NOUSU-BII98RTTJ wwqz//1!%( ,<W,E IYOTXX6F-G-M2-MOOJJ 8U+GmmD!!$**6288:G!d< !e%**11#6<<SA"E! 	V""$! 	tE{	!
 	$((6*! 	y! 	#m,T2! 	FF#! 	3y>&)! 	tJ&z2! 	tJ&{3! 	! 	! 	,! 	x(89!  	)--(?@FB!!" 	9==)9:@b#!$ )-2B)C)Ir)IK)I1QvY)IK kk"23)/VAYu%R"+}%))'2]+//=]+//<xx 67HHY'A! !E O 8T Ls   #Q2<Q7Q7Q<c                (   [        U S5      nU(       d  / $ UR                  S5      =(       d    0 R                  S5      =(       d    / n/ nUS   nUS   nUS   R                  5       nUS   n	U GH  n
U
R                  S5      =(       d    0 nU
R                  S	5      =(       d    S
R                  5       nU
R                  S5      =(       d    S
S S nU
R                  S5      =(       d    0 R                  S5      nU
R                  S5      =(       d    S
n[	        U5      n[        UR                  SS/5      S   =(       d    S5      nUR                  S5      =(       d    S
/S   S S nU(       d  U(       a	  U(       a  S
nUU	:w  a  UR                  5       U:w  a  GM.  U(       a
  X:  d  X:  a  GMB  UR                  S5      (       a  UR                  S5      S:w  a  GMp  UR                  [        UR                  SS/5      S   =(       d    S5      =(       d    S UR                  S5      UR                  S5      =(       d    SU=(       d    US   U=(       d    U	UUUU
R                  S5      =(       d    0 R                  S5      UUS.5        GM"     U$ )NappTourListtourListResulttours	date_fromdate_todeparture_airportdeparture_airport_idlocationdepartureLocationr\   departureDate
   nightsCountfromsearchFilterTOr   RDr   u   ŘeckoDr   adultPriceFromamount)r   r   r   r   r   departure_datereturn_datenights
price_fromsearch_filter
source_url)rZ   rt   r|   rh   r	   intr   )rW   r  r/   r   r   rv   r   r   wanted_airport	wanted_idtourr   depdep_dater  filtqs
airport_idrets                      r   parse_flightsr     s2   $.D	XX&'-2227;ArE
CK I)nG,-335N*+Ihhz"(bxx+,299;HH_-3Sb9((=)/R44V<xx'-2d^qc*1-23
vvd|#tQ',xFC"syy{n'D8/83E779#'')"4"@

"%bffS1#&6q&9&>Q"?"G4"ww}5779-9%(%DC0C,D(2(?i"*" #xx(89?RDDXN!%(	
) F Jr   c                    [        U R                  S5      =(       d    S5      nUR                  S5      =(       d    S/S   $ )Nr   r\   DPRr   )r	   rt   )r   r  s     r   _dprr    s4    	%))M*0b	1BFF5M!bT1%%r   c                    U S   S   S   S   S   nUR                  S5      U:X  a  gUR                  S	5      =(       d    S
R	                  5       nUS:H  =(       d    UR                  S5      S:H  $ ! [         [        [        4 a     gf = f)Nflight	departuresegmentsr   airportFfromIdTr   r\   	pardubicefromIATAPED)KeyError
IndexError	TypeErrorrt   r|   )r	  r  r  rX   s       r   _is_pardubicer     s    x.-j9!<YG {{8
*KK%2,,.D;B'++j"9U"BB j), s   A1 1B	B	c                V    U =(       d    SR                  5       nSU;   =(       d    US;   $ )Nr\   r   >   aiuair{   )mealr   s     r   _is_all_inclusiver%  '  s)    	Aa51#55r   c                	   [         R                  " US   S5      R                  5       n[         R                  " US   S5      R                  5       nUS   nUR                  S5      =(       d    S/nUR                  SS5      n0 nUnX::  Ga  U GH  n	U[	        U	S	9-   n
0 S
U S   _SU S   _SU S   _SU S   _SS_SU_SUR                  5       _SU
R                  5       _SUR                  5        SU
R                  5        3_SS_SUR                  SS5      _SS_SS_S U R                  S!5      =(       d    S"_S#S$_S%U	_S&S'_S(S)0En[        U 5      nU(       a  XS*'   S+[        U5      -   n [        XS,   5      nUR                  S15      =(       d    /  GH  nUR                  S25      =(       d    0 n[        UU5      (       d  M1  UR                  S35      =(       d    0 /nUS   =(       d    0 R                  S45      =(       d    S"n[        U5      (       d  M  UR                  S55      =(       d    0 R                  S65      =(       d    UR                  5       nUR                  S55      =(       d    0 R                  S75      =(       d    U
R                  5       nUUS   :  d	  UUS   :  a  GM  UUS   :  a  GM%  UR                  S85      =(       d    0 R                  S95      nUc  GMT   US:   S;   S<   S   S=   S6   nUS   =(       d    0 R                  S?5      =(       d    S"nUUUR                  S@5      =(       d    U	UU4nUUUR                  S@5      =(       d    U	UR                  SA5      =(       d    U	S-   UU R                  SB5      UUUUR                  S85      =(       d    0 R                  SC5      SDUR                  SE5      =(       d    U SF   -   UR                  S55      UR                  S85      UR                  S:5      UUSG.SH.nUR                  U5      nUb  UUSI   :  d  GM  UUU'   GM     [        R                  " U5        GM     U[	        SS	9-  nX::  a  GM  [%        UR'                  5       SJ SK9$ ! [         a6  n[        S-U S.U	 S/U 35        [        R                  " U5         S0nAGM+  S0nAff = f! [        [         ["        4 a	    US>   n GNf = f)LuY   Termíny konkrétního hotelu z veřejného search API Fischeru (cena celkem za 2 osoby).r   z%Y-%m-%dr   r   r     term_delay_secgQ?)daysDSr   GIATAr   HIDr   r   r   TTrQ   r   DDr   DF|ERMr   AC1adults   KC1IC1PIDr   r\   DIAINNsortbyPrice	sortorder0r  z5https://www.fischer.cz/api/searchapi/getsearchresult?r,   u       termín z / zn: Nr   r	  roomsr$  dater   topricetotalr  r  r  r  r   rX   r   	daysCountr   
adultPricezhttps://www.fischer.cz	detailUrlrI   )r@  rB  r  roomr$  )r   r  r  r)  r   arrival_airportr$  rG  price_totalprice_per_personbooking_urlro   rI  c                    U S   U S   4$ )NrI  r   r   )os    r   <lambda>%search_hotel_offers.<locals>.<lambda>  s    =1A1EUCV0Wr   )r   )r   strptimer@  rt   r   r   r  r
   rO   	Exceptionprinttimesleepr   r%  r  r  r  sortedr   )r   r/   r   r   r  nights_optionsdelayfounddayr  r  paramsdprrI   r   excrw   r	  r?  r$  r
  backrB  originrG  r   offerprevs                               r   search_hotel_offersra  ,  s   !!#k"2J?DDFII
;@@BG+,JWWX&-1#NGG$d+E!E
C
.$F	v..CeM*w uT{ U+,	
 a j cmmo cmmo )3==?*;< q swwx+ q q uyy/52 d  f!" '#$ S%F( u+C #uIIV\L]]C!#<'89
 )/R/xx'-2$T:66)1bTaB++F39r(..xx'-2226:Mcmmo(.B33D9LS]]_[))S3y>-A#i.('*0b55g>=6!(^K8DQG	RSYZF aB++F39rD$((="9"CVT4P&)#'"hh}5? HH[1Afqj)/',yy'@  #()-'):)@b(E(El(S#;txx?T?dX]^cXd#e $ 0!%'!2"&((8"4 $ $( yy~<54+>#>!&E#J[ 0\ JJu] %^ 	ya  a .b %,,.&WXXi  SEVHCu=>

5!. !*i8 6 !45F6s*   .Q?+S?
R?	*R::R?S S c                0   U R                  S0 UE[        R                  " US   SS9[        R                  " US   SS9[        R                  " US   SS9[        R                  " US   UR                  S5      UR                  S	5      S
.SS9US.E5        g )Na  
        INSERT INTO hotels (
            id, slug, name, url, official_stars, destination, destination_id, area, country,
            lat, lng, airport_name, airport_iata, airport_distance, airport_distance_km,
            beach_distance, center_distance, distances_json, benefits_json, summary, meals,
            meals_type, conditions, image_url, images_json, website, giata, data_source,
            provider_id, extra_json, updated_at
        ) VALUES (
            :id, :slug, :name, :url, :official_stars, :destination, :destination_id, :area, :country,
            :lat, :lng, :airport_name, :airport_iata, :airport_distance, :airport_distance_km,
            :beach_distance, :center_distance, :distances_json, :benefits_json, :summary, :meals,
            :meals_type, :conditions, :image_url, :images_json, :website, :giata, :data_source,
            :provider_id, :extra_json, :updated_at
        )
        ON CONFLICT(id) DO UPDATE SET
            slug=excluded.slug, name=excluded.name, url=excluded.url,
            official_stars=excluded.official_stars, destination=excluded.destination,
            destination_id=excluded.destination_id, area=excluded.area, country=excluded.country,
            lat=excluded.lat, lng=excluded.lng, airport_name=excluded.airport_name,
            airport_iata=excluded.airport_iata, airport_distance=excluded.airport_distance,
            airport_distance_km=excluded.airport_distance_km, beach_distance=excluded.beach_distance,
            center_distance=excluded.center_distance, distances_json=excluded.distances_json,
            benefits_json=excluded.benefits_json, summary=excluded.summary, meals=excluded.meals,
            meals_type=excluded.meals_type, conditions=excluded.conditions, image_url=excluded.image_url,
            images_json=excluded.images_json, website=excluded.website, giata=excluded.giata,
            data_source=excluded.data_source, provider_id=excluded.provider_id,
            extra_json=excluded.extra_json, updated_at=excluded.updated_at
        r   Fensure_asciir   r   r   r   r   )r   r   r   )distances_jsonbenefits_jsonimages_json
extra_json
updated_at)executer%   dumpsrt   )connr   ri  s      r   upsert_hotelrm    s    LL	8	
	
"jj{);%P!ZZj(9N::eHoEJ** %j 1#(99]#; %		* 5
 # %	
;,r   c                    U R                  SUS   US   US   US   US   US   US   US	   US
   US   US   UU45        g )Nav  
        INSERT INTO flights (
            destination_id, destination, country, departure_airport, departure_airport_id,
            departure_date, return_date, nights, price_from, currency, search_filter,
            source_url, scrape_id, scraped_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'CZK', ?, ?, ?, ?)
        ON CONFLICT(destination_id, departure_airport_id, departure_date, return_date, nights)
        DO UPDATE SET
            price_from=excluded.price_from, search_filter=excluded.search_filter,
            source_url=excluded.source_url, scrape_id=excluded.scrape_id, scraped_at=excluded.scraped_at
        r   r   r   r   r   r   r  r  r  r  r  )rj  )rl  r  	scrape_id
scraped_ats       r   upsert_flightrq    s|    LL
	 #$=!9&')*#$=!8< ?#< 	
r   c           	     `    SR                  SU S   U S   [        U S   5      U S   U S   /5      $ )Nr0  r   r   r  r  r$  rG  )r   str)r_  s    r   make_offer_keyrt    sF    88"#- h &M&M	
	 	r   c                   [        U5      nU R                  SUUUS   US   US   UR                  S5      US   US   US   US	   US
   US   US   [        R                  " UR                  S5      SS9UU45        U SU 3nU R                  SU45      R                  5       nUb  [        US   5      [        US
   5      :w  a2  U R                  SUUUS   US   US   US   US   US	   US
   UU45        U$ )Na  
        INSERT INTO offers (
            hotel_id, offer_key, departure_date, return_date, nights, days, departure_airport,
            arrival_airport, meal, room, price_total, price_per_person, currency, scope,
            booking_url, raw_json, scrape_id, scraped_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'CZK', 'hotel', ?, ?, ?, ?)
        ON CONFLICT(hotel_id, offer_key) DO UPDATE SET
            days=excluded.days, price_total=excluded.price_total,
            price_per_person=excluded.price_per_person, booking_url=excluded.booking_url,
            scrape_id=excluded.scrape_id, scraped_at=excluded.scraped_at, raw_json=excluded.raw_json
        r   r  r  r)  r   rH  r$  rG  rI  rJ  rK  ro   Frc  :zJSELECT price FROM price_history WHERE offer_key=? ORDER BY id DESC LIMIT 1rB  a#  
            INSERT INTO price_history (
                hotel_id, offer_key, departure_date, return_date, nights, departure_airport,
                meal, room, price, currency, scope, scrape_id, scraped_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'CZK', 'hotel', ?, ?)
            )rt  rj  rt   r%   rk  fetchonern   )rl  hotel_idr_  ro  rp  	offer_keyhist_keylasts           r   record_hotel_offerr|    s\   u%ILL
	 "#- (OIIf%&#$&M&M- $%- JJuyy'e<!	
> 1YK(H<<T	 hj 	 |uT']+uU=5I/JJ &'m$h)*ffm$	
* r   c           	        U R                  S5       Vs/ s H  n[        U5      PM     nnU R                  S5       Vs/ s H  n[        U5      PM     nnU R                  S5       Vs/ s H  n[        U5      PM     nnU R                  S5       Vs/ s H  n[        U5      PM     nnU R                  S5      R                  5       nU GH  n[        R                  " US   =(       d    S5      US'   [        R                  " US	   =(       d    S
5      US'   [        R                  " US   =(       d    S
5      US'   [        R                  " US   =(       d    S5      nUR                  S5      =(       d    0 US'   UR                  SS 5        UR                  S	S 5        UR                  SS 5        UR                  SS 5        U V	s/ s HF  n	U	S   US   :X  d5  U	S   (       d  M  U	S   R                  S5      S   US   =(       d    S;   d  MD  U	PMH     sn	US'   U V
s/ s H)  oS   US   :X  d  M  U
R                  S5      S:X  d  M'  U
PM+     sn
US'   U Vs/ s H)  oS   US   :X  d  M  UR                  S5      S:X  d  M'  UPM+     snS S US'   GM     [        5       [        [        R                  " [        R                  SS95      5      U(       a  [        U5      OS UUS.$ s  snf s  snf s  snf s  snf s  sn	f s  sn
f s  snf ) Nz/SELECT * FROM hotels ORDER BY destination, namez:SELECT * FROM flights ORDER BY departure_date, destinationz,SELECT * FROM offers ORDER BY departure_datezHSELECT * FROM price_history ORDER BY scraped_at DESC, id DESC LIMIT 2000z.SELECT * FROM scrapes ORDER BY id DESC LIMIT 1re  z{}r   rf  z[]r   rg  r   rh  r   r   r   ra   r   r\   flightsrx  r   scoper   offers(   historyr"   r#   )generated_atfilterslast_scrapehotelsr~  )rj  dictrw  r%   r&   rt   popr   r    r3   r'   r(   )rl  rr  r~  r  r  r{  hextrafrM  xs               r   build_snapshotr  %  s   #||,]^_^!d1g^F_ $-i jk j1tAw jGk#||,Z[\[!d1g[F\ V

A 	Q
   <<HIRRTDA&6$7$?4@+

1_#5#=>*jj=!1!9T:(

1\?2d3		*-3*	%	ot$	mT"	lD! 
!"a(8&99-   &'}%5%;%;C%@%C-HXH^\^%_ 
) #)c&QjMQtW,Dqw[bIbq&c(#*e7a
mqw.F155QX>]dKd7efigij)# (  	!$**[-B-BG-B-T"UV%)tDzt = `k\$
 desL   K'K,(K1K6K;&%K;K;L 2L 	L L,LLc                    [        5       n [        5       n[        5       nUR                  SUS45      nUR                  nSnSn/ n/ nU S    GH4  n	U	S   n
[        SU
 3SS9   [        XS	   5      n[        X5      n[        XU5        US
-  n[        SUS    SUS    SUS    S35        UR                  SUS   45       Vs0 s H  nUS   [        U5      _M     nn[        X5      n[        5       nU H  n[        U5      nUR                  U5        UR                  U5      nUc  UR                  SUS   US.5        O@US   b:  [!        US   5      [!        US   5      :w  a  UR                  SUS   UUS   S.5        [#        XS   UXB5        US
-  nM     U(       aD  UR                  SR%                  SR'                  S[)        U5      -  5      5      US   /UQ75        OUR                  SUS   45        U(       a=  US   n[        S[)        U5       SUS   S S US!    S"US#    S$US%    S&US'    S(35        O[        S)5        UR+                  5         [.        R0                  " U R                  S,S-5      5        GM7     UR                  S.[        5       XVS/R'                  U5      U45        UR+                  5         [3        U5      n[4        R6                  R9                  SSS09  [4        R;                  [<        R>                  " US1S2S39S4S59  URA                  5          [C        X5        [        S8U S9U S:[)        U5       S;[4         35        g s  snf ! [,         a/  nUR                  U
 S*U 35        [        S+U 35         S nAGN3S nAff = f! [,         a,  n[        S6U 35        UR                  S7U 35         S nANS nAff = f)<Nz5INSERT INTO scrapes (started_at, notes) VALUES (?, ?)uA   hotely + konkrétní termíny z Pardubic (all inclusive, 2 osoby)r   r  rI   zHotel: T)flushr,   rQ   u     → rX   z (r   u   , letiště r   )zLSELECT offer_key, price_total FROM offers WHERE hotel_id=? AND scope='hotel'r   ry  new)typer   r_  rI  rB  )r  r   r_  	old_pricezODELETE FROM offers WHERE hotel_id=? AND scope='hotel' AND offer_key NOT IN ({})rl   ?z5DELETE FROM offers WHERE hotel_id=? AND scope='hotel'u    termín(ů) z Pardubic, od z.0fu    Kč (r   u    → r  z, r  u	    nocí / r)  u    dní)u4     → v okně není all inclusive termín z Pardubicz: z	  CHYBA: request_delay_secg      ?zOUPDATE scrapes SET finished_at=?, hotels_ok=?, flights_ok=?, notes=? WHERE id=?z; )parentsexist_okFr4  )rd  indentr"   r#   u   E-mail se nepodařilo odeslat: zemail: zHotovo: u
    hotelů, u    termínů, u    změn → )"r)   r   r    rj  	lastrowidrR  rL   r   rm  r  ra  setrt  addrt   r   rn   r|  formatr   lencommitrQ  rS  rT  r  SNAPSHOT_PATHparentmkdir
write_textr%   rk  closer   )r/   rl  startedcurro  	hotels_ok	offers_okr   eventsrw   rI   rW   r   rowpreviousr  	seen_keysr_  r   oldcheapestr\  snapshots                          r   runr  M  s   
-C9DiG
,,?	UVC IIIEFH5kuoT*6	%,/0D+Eg.NIF5=/E-,@+AeTfNgMhhijk  <<b4[NC K $s)+   )4FI$U+c"ll3';MM55=SX"YZ'3c->P8QUZ[`an[oUp8pMM$+%*6]%*),]);	 #4teYPQ	!  " ells9~!56 4[-9-	 TW\]aWbVde!!9S[M)Eh}F]^aEb c !1235-9P8QQS)*)HV4D3EVM LMKKM 	

377.45u x 	LLY	I$))E*:IF 	KKMd#Htd;TZZuQOZabJJL&C 
 
HYKz)LV[YfXg
hiGZ  	%LLC53%)IcU#$$	%$  &/u56wse_%%&sD   #A MME>M$N M
N#$NN
O"OO__main__)returnrs  )r  r  )r/   r  r  r  )rI   rs  r,   rs  r  rs  )rI   rs  r,   rs  r  r   )rW   rs  rX   rs  r  z
Any | None)ri   
str | Noner  rs  )ro   r  r  zfloat | None)ru   
list[dict]r  dict[str, str])r   r  r   rs  r  rs  )ri   rs  r  rs  )
r   rs  r   r  r   rs  r   rs  r  ztuple[str, str])rW   rs  r   r  r  r  )rW   rs  r  rs  r/   r  r  r  )r   r  r  rs  )r	  r  r  r  r  bool)r$  rs  r  r  )r   r  r/   r  r  r  )r   r  ri  rs  r  None)r  r  ro  r  rp  rs  r  r  )r_  r  r  rs  )
rx  r  r_  r  ro  r  rp  rs  r  rs  )r  r  )=__doc__
__future__r   rW   rf   r%   rR   sslrS  urllib.requestr@   r   r   r   pathlibr   typingr   urllib.parser	   r
   r   dbr   r   notifyr   __file__resolver  ROOTr'   r  create_default_contextrF   r   r    r)   r3   rL   rO   rZ   rj   rp   rx   r   r   r   r   r  r  r   r%  ra  rm  rq  rt  r|  r  r  __name__r   r   r   <module>r     s    [ "   	 
   2 2   6 6  H~&&]"v/	  " )"#V?;
	6
B"
M`.b&
C6
[Y|-`>
<~%P[j| zE r   