Ë
    "õj„8  ã            	       ó   — d Z ddlZddlZddlZddlZddlZddlZddlmZmZm	Z	 ddl
mZ  eej                  d«      rej                  j                  d¬«        eej                  d«      rej                  j                  d¬«       ddlZddlmZmZmZ  ej*                  ej,                  d	d
 ej.                  ej                  «      g¬«        ej0                  e«      Z ed«      ZdZd„ Zdee   dee    dedee   fd„Z!dedefd„Z"dede fd„Z#de dedz  fd„Z$dededee   fd„Z%dee   de fd„Z&d„ Z'd„ Z(d „ Z)ed!k(  r e)«        yy)"u§  
EPG Bot â€” Main orchestrator.

Fetches the complete daily EPG at midnight (or on startup) and saves it to epg_daily.json.
Then, runs a local loop every 60 seconds to extract currently airing programs
and saves them to epg.json in real-time.

Usage:
    python epg_bot.py              # Run continuously (updates epg.json every 1 min)
    python epg_bot.py --once       # Single scrape + generate epg.json once, then exit
é    N)ÚdateÚdatetimeÚ	timedelta)ÚZoneInfoÚreconfigureúutf-8©Úencoding©Ú
RaiScraperÚMediasetScraperÚ
SkyScraperz'%(asctime)s [%(levelname)s] %(message)sz%Y-%m-%d %H:%M:%S)ÚlevelÚformatÚdatefmtÚhandlerszEurope/Romezepg_daily.jsonc                  ó<   — t        «       t        «       t        «       gS )zInitialize all scrapers.r   © ó    ú@C:\Users\Claud\Documents\Epg General Channel - Simple\epg_bot.pyÚcreate_scrapersr   /   s   € ô 	‹ÜÓÜ‹ðð r   ÚentriesÚexpected_channelsÚtarget_dateÚreturnc                 ó   — |D �ci c]  }|g “Œ }}| D ]5  }|j                  d«      }||v r||   j                  |«       Œ-|sŒ0|g||<   Œ7 t        |j                  |j                  |j
                  dddt        ¬«      }|t        d¬«      z   }g }	|j                  «       D �]œ  \  }}
|
s6|	j                  dd||j                  «       |j                  «       dd	d
œ«       Œ?g }|
D ];  }	 t        j                  |j                  dd«      «      }|j                  ||f«       Œ= |j                  d„ ¬«       |}|D ]¬  \  }}||t        d¬«      z   kD  r5|	j                  dd||j                  «       |j                  «       dd	d
œ«       |	j                  |«       |j                  d«      }|r#	 t        j                  |«      }t        ||«      }Œ”t        ||t        d¬«      z   «      }Œ® ||t        d¬«      z
  k  s�Œ[|	j                  dd||j                  «       |t        d¬«      z   j                  «       dd	d
œ«       �ŒŸ |	S c c}w # t        $ r Y �Œpw xY w# t        $ r t        ||t        d¬«      z   «      }Y �ŒDw xY w)zGFill schedule gaps with a default 'Nessun Programma Disponibile' event.Úchannelr   )Útzinfoé   )ÚdayszNessun Programma DisponibileÚ z9Nessuna programmazione disponibile per l'intera giornata.ÚIntrattenimento)ÚtitleÚimager   ÚstartÚendÚdescriptionÚcategoryr%   c                 ó   — | d   S )Nr   r   )Úxs    r   Ú<lambda>zfill_epg_gaps.<locals>.<lambda>^   s   €  q¨¢tr   ©Úkeyé   )Úminutesz;Nessuna programmazione disponibile in questa fascia oraria.r&   ©Úhoursé   )ÚgetÚappendr   ÚyearÚmonthÚdayÚROME_TZr   ÚitemsÚ	isoformatÚfromisoformatÚ	ExceptionÚsortÚmax)r   r   r   ÚchÚchannel_programsÚprogr   Ústart_of_dayÚ
end_of_dayÚfilled_entriesÚprogsÚvalid_progsÚpÚdtÚcurrent_timeÚ
prog_startÚend_strÚprog_ends                     r   Úfill_epg_gapsrM   8   s´  € á):Ó;Ñ): 2˜˜B™Ð):ÐÐ;ãˆØ—(‘(˜9Ó%ˆØÐ&Ñ&Ø˜WÑ%×,Ñ,¨TÕ2ÚØ)-¨Ð˜WÒ%ð ô ˜K×,Ñ,¨k×.?Ñ.?ÀÇÁÐRSÐUVÐXYÔbiÔj€LØ¤	¨qÔ 1Ñ1€Jà€Nà*×0Ñ0×2‰ˆ�ÙØ×!Ñ!Ø7ØØ"Ø%×/Ñ/Ó1Ø!×+Ñ+Ó-ØZØ-ñ#ô ð ð ˆÛˆAðÜ×+Ñ+¨A¯E©E°'¸2Ó,>Ó?�Ø×"Ñ" B¨ 7Õ+ð ð 	×Ñ™^ÐÔ,ð $ˆã +ÑˆJ˜à˜L¬9¸QÔ+?Ñ?Ò?Ø×%Ñ%Ø;ØØ&Ø)×3Ñ3Ó5Ø%×/Ñ/Ó1Ø#`Ø 1ñ'ô ð ×!Ñ! $Ô'ð —h‘h˜u“oˆGÙðVÜ'×5Ñ5°gÓ>�Hä#& |°XÓ#>‘Lô  # <°¼iÈaÔ>PÑ1PÓQ‘ð3 !,ð8 ˜*¤y¸Ô';Ñ;Ô;Ø×!Ñ!Ø7ØØ"Ø%×/Ñ/Ó1Ø$¤y°qÔ'9Ñ9×DÑDÓFØ\Ø-ñ#ö ðq 3ðD Ðùòa <øôB ò Úðûô< !ò VÜ#& |°ZÄ)ÐRSÔBTÑ5TÓ#U“LðVús)   …
IÃ'8IÆ*!IÉ	IÉIÉ"I=É<I=c           	      ó°  — |j                  d«      g g g dœ}i }| D ]ê  }|j                  «       }	 t        j                  d› «       t        j                  d|j	                  «       › d�«       |j                  |«      }|D �cg c]  }|j                  «       ‘Œ }}t        |j                  «       j                  «       «      }	t        ||	|«      }|||<   t        |«      ||<   t        j                  d|› dt        |«      › d�«       Œì t        j                  d› «       t        j                  d«       d
}|j                  «       D ]4  \  }}t        j                  d|j	                  «       › d|› d�«       ||z  }Œ6 t        j                  d|› d�«       |S c c}w # t        $ r0}
t        j                  d|› d	|
› �«       g ||<   d
||<   Y d}
~
�Œµd}
~
ww xY w)zg
    Fetch EPG data from all providers for the target date
    and return grouped structured dict.
    ú%Y-%m-%d)r   ÚraiÚmediasetÚskyz2==================================================zScraping EPG da ú...Ú[z
] Totale: z programmi recuperatiz&] ERRORE CRITICO DURANTE LO SCRAPING: r   Nu$   ðŸ“Š Riepilogo Scraping Giornaliero:z  ú: z
 programmiz
  TOTALE: )ÚstrftimeÚget_provider_nameÚloggerÚinfoÚupperÚfetch_all_channelsÚto_dictÚlistÚget_channelsÚvaluesrM   Úlenr<   Úerrorr9   )Úscrapersr   Ú
daily_dataÚstatsÚscraperÚproviderr   ÚentryÚprovider_entriesr   ÚeÚtotalÚcounts                r   Úfetch_daily_epg_from_webrl   �   sÑ  € ð ×$Ñ$ ZÓ0ØØØñ	€Jð €EãˆØ×,Ñ,Ó.ˆð	 Ü�K‰K˜6˜(Ô$Ü�K‰KÐ*¨8¯>©>Ó+;Ð*<¸CÐ@ÔAØ×0Ñ0°Ó=ˆGñ >EÓE¹W°E §¡¥¸WÐÐEô !% W×%9Ñ%9Ó%;×%BÑ%BÓ%DÓ EÐÜ,Ð-=Ð?PÐR]Ó^Ðà#3ˆJ�xÑ Ü!Ð"2Ó3ˆE�(‰OÜ�K‰K˜!˜H˜: Z´Ð4DÓ0EÐ/FÐF[Ð\Õ]ð! ô. ‡K�K�6�(ÔÜ
‡K�KÐ6Ô7Ø€EØ Ÿ;™;ž=‰ˆ�%Ü�‰�b˜Ÿ™Ó)Ð*¨"¨U¨G°:Ð>Ô?Ø�‰‰ð )ô ‡K�K�*˜U˜G :Ð.Ô/àÐùò/  Føô ò 	 Ü�L‰L˜1˜X˜JÐ&LÈQÈCÐPÔQØ#%ˆJ�xÑ ØˆE�(�Oûð	 ús+   ¯AFÂFÂA.FÆFÆ	GÆ%%GÇGÚdataÚoutput_filec                 ó¬   — t        |dd¬«      5 }t        j                  | |dd¬«       ddd«       t        j	                  d|› �«       y# 1 sw Y   Œ"xY w)	z%Save daily EPG database to JSON file.Úwr   r	   Fé   ©Úensure_asciiÚindentNu#   ðŸ’¾ Guida giornaliera salvata in: )ÚopenÚjsonÚdumprX   rY   ©rm   rn   Úfs      r   Úsave_daily_epgrz   ¼   sD   € ä	ˆk˜3¨Õ	1°QÜ�	‰	�$˜¨°aÕ8÷ 
2ä
‡K�KÐ5°k°]ÐCÕD÷ 
2Ð	1ús   �A
Á
AÚ
input_filec                 ó  — t         j                  j                  | «      sy	 t        | dd¬«      5 }t	        j
                  |«      cddd«       S # 1 sw Y   yxY w# t        $ r%}t        j                  d| › d|› �«       Y d}~yd}~ww xY w)z4Load daily EPG database from JSON file if it exists.NÚrr   r	   u   âš ï¸�  Impossibile caricare rU   )	ÚosÚpathÚexistsru   rv   Úloadr<   rX   Úwarning)r{   ry   ri   s      r   Úload_daily_epgrƒ   Ã   sk   € ä�7‰7�>‰>˜*Ô%ØðÜ�*˜c¨GÕ4¸Ü—9‘9˜Q“<÷ 5×4Ò4ûäò Ü�‰Ð6°z°lÀ"ÀQÀCÐHÔIÜûðús4   ¢A °AÁ	A ÁAÁA ÁA Á	B	Á$BÂB	rc   rI   c                 óì  — i }dD ]Z  }| j                  |g «      }|D ]A  }|j                  d«      }|sŒ||vrg ||<   ||   j                  |j                  «       «       ŒC Œ\ g }|j                  «       D �]É  \  }}|j	                  d„ ¬«       t        t        |«      «      D ]�  }	||	   }|j                  d«      rŒ|	dz   t        |«      k  r||	dz      j                  dd«      |d<   ŒG	 t        j                  |d   «      }
|
t        d	¬
«      z   }|j                  «       |d<   Œƒ |D �]  }|j                  dd«      }|j                  dd«      }|r|sŒ-	 t        j                  |«      }
t        j                  |«      }|
|cxk  r|k  r°n n­|j                  dd«      }|r*d|v r&d|j                  «       vrd|j                  «       vrd}|sY|j                  dd«      }|j                  «       j                  dd«      j                  dd«      }d|v rd}n|dk(  rd}d|› d�|d<   |j                  |«        �ŒÇ�Œ �ŒÌ |j	                  d„ ¬«       |S # t        $ r Y �ŒÀw xY w# t        $ r Y �ŒJw xY w)zZ
    Extract currently airing program for each channel from the daily guide database.
    )rP   rQ   rR   r   c                 ó&   — | j                  dd«      S )Nr%   r!   ©r3   ©rG   s    r   r+   z&get_current_programs.<locals>.<lambda>å   s   €  §¡ w°Ô!3r   r,   r&   r   r%   r!   rq   r0   r$   zguidatv.sky.itÚchecksumÚmd5Ú Ú_Ú+ÚplusÚsky_sport_25Ú	sky_sportÚ
sky_tv8_hdÚtv8z3https://addictedbytheproject.nl/epg_general/assets/z.pngc                 ó&   — | j                  dd«      S )Nr   r!   r†   r‡   s    r   r+   z&get_current_programs.<locals>.<lambda>  s   € ¨¯©¨i¸Ô(<r   )r3   r4   Úcopyr9   r=   Úranger`   r   r;   r   r:   r<   ÚlowerÚreplace)rc   rI   r@   rf   ÚprogramsrA   r   Úcurrent_programsrE   ÚiÚstart_dtÚend_dtÚ	start_strrK   ÚimgÚchanÚfmts                    r   Úget_current_programsr    Ï   s–  € ð Ðó /ˆØ—>‘> (¨BÓ/ˆÛˆDØ—h‘h˜yÓ)ˆGÙØØÐ.Ñ.Ø,.Ð  Ñ)à˜WÑ%×,Ñ,¨T¯Y©Y«[Õ9ñ ð /ð Ðà*×0Ñ0×2‰ˆ�à�
‰
Ñ3ˆ
Ô4ô ”s˜5“zÖ"ˆAØ˜‘8ˆDØ—8‘8˜E•?Ø�q‘5œ3˜u›:Ò%Ø"'¨¨A©¡,×"2Ñ"2°7¸BÓ"?�D˜’KðÜ#+×#9Ñ#9¸$¸w¹-Ó#H˜Ø!)¬I¸AÔ,>Ñ!>˜Ø&,×&6Ñ&6Ó&8˜˜Ušð #ô ˆDØŸ™ ¨"Ó-ˆIØ—h‘h˜u bÓ)ˆGÙ¡GØðÜ#×1Ñ1°)Ó<�Ü!×/Ñ/°Ó8�ð ˜|Ô4¨fÕ4àŸ(™( 7¨BÓ/�CÙÐ/°3Ñ6¸:ÈSÏYÉYË[Ñ;XÐ]bÐjm×jsÑjsÓjuÑ]uØ ˜ñ Ø#Ÿx™x¨	°2Ó6˜Ø"Ÿj™j›l×2Ñ2°3¸Ó<×DÑDÀSÈ&ÓQ˜à)¨SÑ0Ø"-™CØ  LÒ0Ø"'˜Cà*]Ð^aÐ]bÐbfÐ(g˜˜W™à$×+Ñ+¨DÔ1Úùò= ð) 3ðn ×ÑÑ<ÐÔ=ØÐøôQ %ò ÚðûôF ò Úðús%   Ã*:IÅC"I&É	I#É"I#É&	I3É2I3c                 óÆ   — t        |dd¬«      5 }t        j                  | |dd¬«       ddd«       t        j	                  d|› d	t        | «      › d
�«       y# 1 sw Y   Œ/xY w)z3Save active EPG list to real-time output JSON file.rp   r   r	   Frq   rr   Nu    ðŸ’¾ EPG in onda aggiornato in: z (z canali attivi))ru   rv   rw   rX   rY   r`   rx   s      r   Úsave_current_epgr¢     sP   € ä	ˆk˜3¨Õ	1°QÜ�	‰	�$˜¨°aÕ8÷ 
2ä
‡K�KÐ2°;°-¸rÄ#ÀdÃ)ÀÈOÐ\Õ]÷ 
2Ð	1ús   �AÁA c                 ó   — t        j                  t        «      }|j                  «       }t        j                  d|j                  d«      › �«       t        j                  d|j                  d«      › �«       t        | |«      }t        |t        «       t        ||«      }t        |t        j                  «       t        j                  d«       y)zRExecute a single network scrape, then write daily and current EPG files, and exit.u$   ðŸš€ Avvio raccolta EPG singola â€” z%d/%m/%Y %H:%M:%Su   ðŸ“… Data target: z%d/%m/%Yu*   âœ… Ciclo singolo completato con successo!N)r   Únowr8   r   rX   rY   rV   rl   rz   ÚDAILY_EPG_FILEr    r¢   ÚconfigÚOUTPUT_FILE)rb   r¤   Útodayrc   r˜   s        r   Úrun_oncer©   %  s™   € ä
�,‰,”wÓ
€CØ�H‰H‹J€Eä
‡K�KÐ6°s·|±|ÐDWÓ7XÐ6YÐZÔ[Ü
‡K�KÐ$ U§^¡^°JÓ%?Ð$@ÐAÔBä)¨(°EÓ:€JÜ�:œ~Ô.ä+¨J¸Ó<ÐÜÐ%¤v×'9Ñ'9Ô:ä
‡K�KÐ<Õ>r   c                 óf  — t         j                  d«       d}	 	 t        j                  t        «      }|j                  d«      }|�|j                  d«      |k7  r“t         j                  d|› d�«       t        t        «      }|�|j                  d«      |k7  r@t         j                  d«       t        | |j                  «       «      }t        |t        «       nt         j                  d	«       t        ||«      }t        |t        j                  «       t         j                  d«       	 t'        j(                  d«       �Œ'# t         $ r t         j                  d
«       Y yt"        $ r$}t         j%                  d|› �d¬«       Y d}~Œtd}~ww xY w# t         $ r t         j                  d
«       Y yw xY w)zPRun EPG bot continuously with daily network scraping and minutely local updates.uC   ðŸ”„ ModalitÃ  continua â€” Aggiornamento real-time ogni 60 secondiNTrO   r   u+   ðŸ“… Verifica EPG giornaliero per la data: rS   u=   ðŸ“‚ File locale assente o scaduto. Avvio scraping di rete...uR   ðŸ“‚ EPG giornaliero valido caricato con successo da file locale! (0 chiamate API)u"   â�¹ï¸�  Bot arrestato dall'utente.u!   â�Œ Errore nel ciclo principale: )Úexc_infouG   â�³ In attesa del prossimo minuto per aggiornare i programmi in onda...é<   )rX   rY   r   r¤   r8   rV   r3   rƒ   r¥   rl   r   rz   r    r¢   r¦   r§   ÚKeyboardInterruptr<   ra   ÚtimeÚsleep)rb   rc   r¤   Ú	today_strr˜   ri   s         r   Úrun_continuousr±   6  sl  € ä
‡K�KÐUÔVà€Jà
ð	QÜ—,‘,œwÓ'ˆCØŸ™ ZÓ0ˆIð Ð! Z§^¡^°FÓ%;¸yÒ%HÜ—‘ÐIÈ)ÈÐTWÐXÔYô ,¬NÓ;�
àÐ%¨¯©¸Ó)?À9Ò)LÜ—K‘KÐ _Ô`Ü!9¸(ÀCÇHÁHÃJÓ!O�JÜ" :¬~Õ>ä—K‘KÐ tÔuô  4°JÀÓDÐÜÐ-¬v×/AÑ/AÔBô 	�‰Ð]Ô^ð	Ü�J‰J�rŒNñA øô. !ò 	Ü�K‰KÐ<Ô=ÙÜò 	QÜ�L‰LÐ<¸Q¸CÐ@È4ˆL×PÑPûð	Qûô !ò 	Ü�K‰KÐ<Ô=Ùð	ús0   šC9E  Ä)F Å FÅ FÅ(FÆFÆF0Æ/F0c                  ó  — t        j                  d¬«      } | j                  ddd¬«       | j                  dt        d dt        j
                  › d	�¬
«       | j                  «       }|j                  r|j                  t        _        t        j                  d«       t        j                  d«       t        j                  d«       t        j                  d«       t        «       }|j                  rt        |«       y t        |«       y )Nu?   EPG Bot Italia â€” Rai, Mediaset, Sky (Real-time & Daily modes))r'   z--onceÚ
store_truez.Esegui una singola raccolta completa e termina)ÚactionÚhelpz--outputz(File di output in tempo reale (default: Ú))ÚtypeÚdefaultrµ   z<============================================================u#     ðŸ“º EPG Bot Italia â€” Real-timeu"     Canali: Rai â€¢ Mediaset â€¢ Sky)ÚargparseÚArgumentParserÚadd_argumentÚstrr¦   r§   Ú
parse_argsÚoutputrX   rY   r   Úoncer©   r±   )ÚparserÚargsrb   s      r   ÚmainrÂ   b  sØ   € Ü×$Ñ$ØUô€Fð ×ÑØØØ=ð ô ð
 ×ÑØÜØØ7¼×8JÑ8JÐ7KÈ1ÐMð	 ô ð ×ÑÓ€Dà‡{‚{Ø!Ÿ[™[ŒÔä
‡K�K�ÔÜ
‡K�KÐ5Ô6Ü
‡K�KÐ4Ô5Ü
‡K�K�ÔäÓ €Hà‡y‚yÜ�Õä�xÕ r   Ú__main__)*Ú__doc__r¹   rv   Úloggingr~   Úsysr®   r   r   r   Úzoneinfor   ÚhasattrÚstdoutr   Ústderrr¦   rb   r   r   r   ÚbasicConfigÚINFOÚStreamHandlerÚ	getLoggerÚ__name__rX   r8   r¥   r   r]   Údictr¼   rM   rl   rz   rƒ   r    r¢   r©   r±   rÂ   r   r   r   Ú<module>rÑ      s²  ðñ
ó Û Û Û 	Û 
Û ß .Ñ .Ý ñ ˆ3�:‰:�}Ô%Ø‡J�J×Ñ GÐÔ,Ù
ˆ3�:‰:�}Ô%Ø‡J�J×Ñ GÐÔ,ã ß <Ñ <ð
 €× Ñ Ø
�,‰,Ø4Øàˆ×Ñ˜cŸj™jÓ)ðõ	ð 
ˆ×	Ñ	˜8Ó	$€á
�=Ó
!€Ø!€òðR˜4 ™:ð R¸$¸s¹)ð RÐRVð RÐ[_Ð`dÑ[eó Rðj,°Dð ,¸Tó ,ð^E˜ð E¨Có Eð	˜sð 	 t¨d¡{ó 	ðL Tð L¸ð LÀdÈ4Ájó Lð^^˜4 ™:ð ^°Có ^ò?ò")òX!ðB ˆzÒÙ…Fð r   