§
    ¡tjiú  ã                   ó�   — 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Zd dlZd dlm	Z	m
Z
mZmZ d dlmZ d dlmZ  G d„ d¦  «        ZdS )é    N)ÚOptionalÚDictÚListÚAny)Údatetime©ÚSessionc                   ó,  — e Zd Zd„ Zdedee         fd„Zdedefd„Zdefd„Zdede	eef         fd„Z
de	eef         fd	„Zdede	eef         fd
„Zdedefd„Zdededefd„Zddededede	eef         fd„Zddededede	eef         fd„Zdefd„ZdS )ÚTwitchServicec                 ó‚   — d| _         d| _        d| _        d| _        d | _        dd l} |j        | j        d¬¦  «         d S )NÚkimne78kx3ncx6brgo4mv6wki5h1koÚ7nfx52bjgr2kf5ltg6lu7dyu979pciÚmyoxudv1apj1uzgsbd4fsqiott65irz/app/twitch_cacher   T©Úexist_ok)Ú	client_idÚoauth_client_idÚoauth_client_secretÚ	cache_dirÚoauth_tokenÚosÚmakedirs)Úselfr   s     ú#/app/app/services/twitch_service.pyÚ__init__zTwitchService.__init__   sP   € Ø9ˆŒØ?ˆÔØ#CˆÔ Ø,ˆŒØˆÔØˆ	ˆ	ˆ	ØˆŒ�D”N¨TÐ2Ñ2Ô2Ð2Ð2Ð2ó    ÚurlÚreturnc                 ó  — g d¢}|D ]j}t          j        ||¦  «        }|rQt          |                     ¦   «         ¦  «        dk    r|                     d¦  «        n|                     d¦  «        c S Œkt          j        d|¦  «        r|S dS )zExtract VOD ID from Twitch URL)ztwitch\.tv/videos/(\d+)ztwitch\.tv/(\w+)/video/(\d+)z"clips\.twitch\.tv/([a-zA-Z0-9_-]+)é   é   z^\d+$N)ÚreÚsearchÚlenÚgroupsÚgroupÚmatch)r   r   ÚpatternsÚpatternr'   s        r   Úextract_vod_idzTwitchService.extract_vod_id   s¥   € ð
ð 
ð 
ˆð  ð 	Vð 	VˆGÝ”I˜g sÑ+Ô+ˆEØð VÝ),¨U¯\ª\©^¬^Ñ)<Ô)<ÀÒ)AÐ)A�u—{’{ 1‘~”~�~ÀuÇ{Â{ÐSTÁ~Ä~ÐUÐUÐUðVõ Œ8�H˜cÑ"Ô"ð 	ØˆJàˆtr   c              ƒ   óÖ  K  — 	 t          j        ¦   «         4 ƒd{V —†}|                     |¦  «        ƒ d{V —†}|j        dk    rZt          j                             d|j        › d�¦  «         t          j                             ¦   «          	 ddd¦  «        ƒd{V —† dS t          j	        |j
        ¦  «                             d¦  «        }|j                             dd¦  «        }d	|› d
|› �cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t          $ rL}t          j                             d|› d�¦  «         t          j                             ¦   «          Y d}~dS d}~ww xY w)z#Download image and encode as base64NéÈ   z([IMAGE ERROR] Failed to download image: Ú
Ú zutf-8zcontent-typez	image/pngzdata:z;base64,z'[IMAGE ERROR] Error downloading image: )ÚhttpxÚAsyncClientÚgetÚstatus_codeÚsysÚstderrÚwriteÚflushÚbase64Ú	b64encodeÚcontentÚdecodeÚheadersÚ	Exception)r   r   ÚclientÚresponseÚ
image_dataÚcontent_typeÚes          r   Údownload_and_encode_imagez'TwitchService.download_and_encode_image)   sl  è è € ð	ÝÔ(Ñ*Ô*ð Bð Bð Bð Bð Bð Bð B¨fØ!'§¢¨C¡¤Ð0Ð0Ð0Ð0Ð0Ð0�ØÔ'¨3Ò.Ð.Ý”J×$Ò$Ð%hÐPXÔPdÐ%hÐ%hÐ%hÑiÔiÐiÝ”J×$Ò$Ñ&Ô&Ð&ØðBð Bð Bñ Bô Bð Bð Bð Bð Bð Bð Bð Bð Bð Bõ $Ô-¨hÔ.>Ñ?Ô?×FÒFÀwÑOÔO�
à'Ô/×3Ò3°NÀKÑPÔP�ØA˜|ÐAÐA°ZÐAÐAðBð Bð Bð Bñ Bô Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bøøøð Bð Bð Bð Bð Bð Bøõ ð 	ð 	ð 	ÝŒJ×ÒÐLÀqÐLÐLÐLÑMÔMÐMÝŒJ×ÒÑÔÐØ�2�2�2�2�2øøøøð	øøøsI   „D �A.C?ÂD ÂAC?Ã,D Ã?
D	Ä	D ÄD	ÄD Ä
E(ÄAE#Å#E(c              ƒ   ó|  K  — | j         r| j         S 	 t          j        ¦   «         4 ƒd{V —†}|                     d| j        | j        ddœ¬¦  «        ƒ d{V —†}|j        dk    rZt          j         	                    d|j        › d�¦  «         t          j         
                    ¦   «          	 ddd¦  «        ƒd{V —† d	S |                     ¦   «         }|                     d
d	¦  «        | _         t          j         	                    d| j         dd…         › d�¦  «         t          j         
                    ¦   «          | j         cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t          $ rL}t          j         	                    d|› d�¦  «         t          j         
                    ¦   «          Y d}~d	S d}~ww xY w)z)Generate OAuth token for Twitch Helix APINz!https://id.twitch.tv/oauth2/tokenÚclient_credentials)r   Úclient_secretÚ
grant_type)Údatar,   z.[OAUTH ERROR] Failed to generate OAuth token: r-   r.   Úaccess_tokenz[OAUTH] Generated OAuth token: é
   z...
z,[OAUTH ERROR] Error generating OAuth token: )r   r/   r0   Úpostr   r   r2   r3   r4   r5   r6   Újsonr1   r<   )r   r=   r>   rG   rA   s        r   Úget_oauth_tokenzTwitchService.get_oauth_token=   s¢  è è € àÔð 	$ØÔ#Ð#ð	ÝÔ(Ñ*Ô*ð (ð (ð (ð (ð (ð (ð (¨fØ!'§¢Ø7à%)Ô%9Ø)-Ô)AØ&:ðð ð "-ñ "ô "ð ð ð ð ð ð �ð Ô'¨3Ò.Ð.Ý”J×$Ò$Ð%nÐV^ÔVjÐ%nÐ%nÐ%nÑoÔoÐoÝ”J×$Ò$Ñ&Ô&Ð&Øð(ð (ð (ñ (ô (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð  —}’}‘”�Ø#'§8¢8¨N¸BÑ#?Ô#?�Ô Ý”
× Ò Ð!_À4ÔCSÐTWÐUWÐTWÔCXÐ!_Ð!_Ð!_Ñ`Ô`Ð`Ý”
× Ò Ñ"Ô"Ð"ØÔ'ð'(ð (ð (ð (ñ (ô (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (ð (øøøð (ð (ð (ð (ð (ð (øõ( ð 	ð 	ð 	ÝŒJ×ÒÐQÈAÐQÐQÐQÑRÔRÐRÝŒJ×ÒÑÔÐØ�2�2�2�2�2øøøøð	øøøsI   ’E% «A>EÂ)E% Â<BEÄ?E% Å
EÅE% ÅEÅ E% Å%
F;Å/AF6Æ6F;Úbroadcaster_idc              ƒ   óÀ  K  — 	 |                       ¦   «         ƒ d{V —†}|s?t          j                             d¦  «         t          j                             ¦   «          i S t          j        ¦   «         4 ƒd{V —†}|                     dd|i| j        d|› �dœ¬¦  «        ƒ d{V —†}t          j                             d|j	        › d	�¦  «         t          j                             ¦   «          |j	        d
k    r‚t          j                             d|j	        › d	�¦  «         t          j                             d|j
        › d	�¦  «         t          j                             ¦   «          i cddd¦  «        ƒd{V —† S |                     ¦   «         }|                     dg ¦  «        }t          j                             dt          |¦  «        › d	�¦  «         t          j                             ¦   «          i }|D ]k}|                     d¦  «        }	|                     dg ¦  «        }
|
D ];}|                     d¦  «        }|                     dd¦  «        }|r|	› d|› �}|||<   Œ<Œl|cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t          $ rM}t          j                             d|› d	�¦  «         t          j                             ¦   «          i cY d}~S d}~ww xY w)z[Fetch channel badges from Twitch Helix API and return mapping of set_id:version to badge_idNú'[OAUTH ERROR] No OAuth token available
z'https://api.twitch.tv/helix/chat/badgesrM   úBearer ©ú	Client-IDÚAuthorization)Úparamsr;   z)[BADGES] Channel badges response status: r-   r,   z/[BADGES ERROR] Failed to fetch channel badges: ú[BADGES ERROR] Response body: rG   z$[BADGES] Channel badges data count: Úset_idÚversionsÚidÚimage_url_1xr.   ú:z.[BADGES ERROR] Error fetching channel badges: ©rL   r3   r4   r5   r6   r/   r0   r1   r   r2   ÚtextrK   r$   r<   )r   rM   r   r=   r>   rG   Úbadges_dataÚbadge_mappingÚ	badge_setrV   rW   ÚversionÚ
version_idÚ	image_urlÚkeyrA   s                   r   Úget_channel_badgesz TwitchService.get_channel_badges\   sá  è è € ð0	Ø $× 4Ò 4Ñ 6Ô 6Ð6Ð6Ð6Ð6Ð6Ð6ˆKØð Ý”
× Ò Ð!KÑLÔLÐLÝ”
× Ò Ñ"Ô"Ð"Ø�	åÔ(Ñ*Ô*ð %%ð %%ð %%ð %%ð %%ð %%ð %%¨fØ!'§¢Ø>Ø,¨nÐ=à%)Ô%9Ø)@°;Ð)@Ð)@ðð ð ",ñ "ô "ð ð ð ð ð ð �õ ”
× Ò Ð!eÈXÔMaÐ!eÐ!eÐ!eÑfÔfÐfÝ”
× Ò Ñ"Ô"Ð"àÔ'¨3Ò.Ð.Ý”J×$Ò$Ð%oÐW_ÔWkÐ%oÐ%oÐ%oÑpÔpÐpÝ”J×$Ò$Ð%WÀhÄmÐ%WÐ%WÐ%WÑXÔXÐXÝ”J×$Ò$Ñ&Ô&Ð&Øð#%%ð %%ð %%ð %%ñ %%ô %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð&  —}’}‘”�Ø"Ÿhšh v¨rÑ2Ô2�Ý”
× Ò Ð!\ÍÈKÑHXÔHXÐ!\Ð!\Ð!\Ñ]Ô]Ð]Ý”
× Ò Ñ"Ô"Ð"ð !#�Ø!,ð 	;ð 	;�IØ&Ÿ]š]¨8Ñ4Ô4�FØ(Ÿ}š}¨Z¸Ñ<Ô<�HØ#+ð ;ð ;˜Ø%,§[¢[°Ñ%6Ô%6˜
Ø$+§K¢K°ÀÑ$CÔ$C˜	à$ð ;Ø%+Ð":Ð":¨jÐ":Ð":˜CØ1:˜M¨#Ñ.øð;ð %ðK%%ð %%ð %%ð %%ñ %%ô %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%ð %%øøøð %%ð %%ð %%ð %%ð %%ð %%øõL ð 	ð 	ð 	ÝŒJ×ÒÐSÈaÐSÐSÐSÑTÔTÐTÝŒJ×ÒÑÔÐØˆIˆIˆIˆIˆIˆIøøøøð	øøøsW   „AJ ÁJ Á8C,I3Å$J Å7C)I3É J É3
I=É=J Ê I=ÊJ Ê
KÊAKËKËKc              ƒ   óº  K  — 	 |                       ¦   «         ƒ d{V —†}|s?t          j                             d¦  «         t          j                             ¦   «          i S t          j        ¦   «         4 ƒd{V —†}|                     d| j        d|› �dœ¬¦  «        ƒ d{V —†}t          j                             d|j	        › d�¦  «         t          j                             ¦   «          |j	        d	k    r‚t          j                             d
|j	        › d�¦  «         t          j                             d|j
        › d�¦  «         t          j                             ¦   «          i cddd¦  «        ƒd{V —† S |                     ¦   «         }|                     dg ¦  «        }t          j                             dt          |¦  «        › d�¦  «         t          j                             ¦   «          i }|D ]k}|                     d¦  «        }|                     dg ¦  «        }	|	D ];}
|
                     d¦  «        }|
                     dd¦  «        }|r|› d|› �}|||<   Œ<Œl|cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t          $ rM}t          j                             d|› d�¦  «         t          j                             ¦   «          i cY d}~S d}~ww xY w)zZFetch global badges from Twitch Helix API and return mapping of set_id:version to badge_idNrO   z.https://api.twitch.tv/helix/chat/badges/globalrP   rQ   )r;   z([BADGES] Global badges response status: r-   r,   z.[BADGES ERROR] Failed to fetch global badges: rU   rG   z#[BADGES] Global badges data count: rV   rW   rX   rY   r.   rZ   z-[BADGES ERROR] Error fetching global badges: r[   )r   r   r=   r>   rG   r]   r^   r_   rV   rW   r`   ra   rb   rc   rA   s                  r   Úget_global_badgeszTwitchService.get_global_badges�   sÙ  è è € ð/	Ø $× 4Ò 4Ñ 6Ô 6Ð6Ð6Ð6Ð6Ð6Ð6ˆKØð Ý”
× Ò Ð!KÑLÔLÐLÝ”
× Ò Ñ"Ô"Ð"Ø�	åÔ(Ñ*Ô*ð $%ð $%ð $%ð $%ð $%ð $%ð $%¨fØ!'§¢ØEà%)Ô%9Ø)@°;Ð)@Ð)@ðð ð ",ñ "ô "ð ð ð ð ð ð �õ ”
× Ò Ð!dÈHÔL`Ð!dÐ!dÐ!dÑeÔeÐeÝ”
× Ò Ñ"Ô"Ð"àÔ'¨3Ò.Ð.Ý”J×$Ò$Ð%nÐV^ÔVjÐ%nÐ%nÐ%nÑoÔoÐoÝ”J×$Ò$Ð%WÀhÄmÐ%WÐ%WÐ%WÑXÔXÐXÝ”J×$Ò$Ñ&Ô&Ð&Øð!$%ð $%ð $%ð $%ñ $%ô $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð$  —}’}‘”�Ø"Ÿhšh v¨rÑ2Ô2�Ý”
× Ò Ð![ÅsÈ;ÑGWÔGWÐ![Ð![Ð![Ñ\Ô\Ð\Ý”
× Ò Ñ"Ô"Ð"ð !#�Ø!,ð 	;ð 	;�IØ&Ÿ]š]¨8Ñ4Ô4�FØ(Ÿ}š}¨Z¸Ñ<Ô<�HØ#+ð ;ð ;˜Ø%,§[¢[°Ñ%6Ô%6˜
Ø$+§K¢K°ÀÑ$CÔ$C˜	à$ð ;Ø%+Ð":Ð":¨jÐ":Ð":˜CØ1:˜M¨#Ñ.øð;ð %ðI$%ð $%ð $%ð $%ñ $%ô $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%ð $%øøøð $%ð $%ð $%ð $%ð $%ð $%øõJ ð 	ð 	ð 	ÝŒJ×ÒÐRÈQÐRÐRÐRÑSÔSÐSÝŒJ×ÒÑÔÐØˆIˆIˆIˆIˆIˆIøøøøð	øøøsW   „AJ ÁJ Á8C)I0Å!J Å4C)I0ÉJ É0
I:É:J É=I:É>J Ê
KÊAKËKËKc              ƒ   óv  K  — |                       |¦  «        }|st          d¦  «        ‚	 t          j        ¦   «         4 ƒd{V —†}d|z  }|                     dd|id| j        i¬¦  «        ƒ d{V —†}|j        dk    rt          d	|j        › �¦  «        ‚|                     ¦   «         }| 	                    d
i ¦  «         	                    d¦  «        }|st          d¦  «        ‚| 	                    dd¦  «        | 	                    dd¦  «        | 	                    d¦  «        | 	                    dd¦  «        d| 	                    d¦  «        r| 	                    ddg¦  «        d         nd| 	                    di ¦  «         	                    dd¦  «        | 	                    di ¦  «         	                    dd¦  «        | 	                    di ¦  «         	                    dd¦  «        dœ	cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t          $ r$}t          dt          |¦  «        › �¦  «        ‚d}~ww xY w)z-Get stream information using Twitch Helix APIúInvalid Twitch URL or IDNa^  
                {
                    video(id: "%s") {
                        title
                        description
                        createdAt
                        lengthSeconds
                        viewCount
                        thumbnailURLs(width: 640, height: 360)
                        owner {
                            displayName
                        }
                        game {
                            displayName
                            boxArtURL(width: 100, height: 140)
                        }
                    }
                }
                úhttps://gql.twitch.tv/gqlÚqueryrR   ©rK   r;   r,   úTwitch API request failed: rG   ÚvideoúVideo not foundÚtitler.   ÚdescriptionÚ	createdAtÚlengthSecondsr   ÚthumbnailURLsÚownerÚdisplayNameÚgameÚ	boxArtURL)	ro   rp   Ú
created_atÚduration_secondsÚ
view_countÚthumbnail_urlÚstreamerrv   Úgame_box_artzFailed to get stream info: )r*   Ú
ValueErrorr/   r0   rJ   r   r2   ÚRuntimeErrorrK   r1   r<   Ústr)	r   r   Úvod_idr=   rj   r>   rG   Ú
video_datarA   s	            r   Úget_stream_infozTwitchService.get_stream_infoÃ   sø  è è € à×$Ò$ SÑ)Ô)ˆØð 	9ÝÐ7Ñ8Ô8Ð8ð2	GÝÔ(Ñ*Ô*ð /ð /ð /ð /ð /ð /ð /¨fðð$ ñ%�ð( "(§¢Ø/Ø! 5Ð)Ø(¨$¬.Ð9ð "-ñ "ô "ð ð ð ð ð ð �ð Ô'¨3Ò.Ð.Ý&Ð'[ÀXÔEYÐ'[Ð'[Ñ\Ô\Ð\à—}’}‘”�Ø!ŸXšX f¨bÑ1Ô1×5Ò5°gÑ>Ô>�
à!ð :Ý&Ð'8Ñ9Ô9Ð9ð (Ÿ^š^¨G°RÑ8Ô8Ø#-§>¢>°-ÀÑ#DÔ#DØ",§.¢.°Ñ"=Ô"=Ø(2¯ª°ÈÑ(JÔ(JØ"#ØQ[×Q_ÒQ_Ð`oÑQpÔQpÐ%z Z§^¢^°OÀbÀTÑ%JÔ%JÈ1Ô%MÐ%MÐvzØ *§¢¨w¸Ñ ;Ô ;× ?Ò ?ÀÈrÑ RÔ RØ&ŸNšN¨6°2Ñ6Ô6×:Ò:¸=È"ÑMÔMØ$.§N¢N°6¸2Ñ$>Ô$>×$BÒ$BÀ;ÐPRÑ$SÔ$Sð
ð 
ðK/ð /ð /ð /ñ /ô /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /ð /øøøð /ð /ð /ð /ð /ð /øõ` ð 	Gð 	Gð 	GÝÐE½SÀ¹V¼VÐEÐEÑFÔFÐFøøøøð	Gøøøs<   ªH
 ÁF!G7Ç$H
 Ç7
HÈH
 ÈHÈH
 È

H8ÈH3È3H8r�   c              ƒ   ó²  K  — 	 t          j        ¦   «         4 ƒd{V —†}ddddœidd|idœ}|                     d	|d
di¬¦  «        ƒ d{V —†}|j        dk    rt	          d|j        › �¦  «        ‚|                     ¦   «         }|cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t          $ r$}t	          dt          |¦  «        › �¦  «        ‚d}~ww xY w)z:Get video chapters using TwitchDownloader's persistedQueryNÚpersistedQueryÚ@71835d5ef425e154bf282453a926d99b328cdc5e32f36d3a209d0f4778b41203r    )Ú
sha256Hashr`   Ú$VideoPlayer_ChapterSelectButtonVideoÚvideoID)Ú
extensionsÚoperationNameÚ	variablesri   rR   r   rk   r,   z$Twitch chapters API request failed: zFailed to get video chapters: )r/   r0   rJ   r2   r   rK   r<   r€   )r   r�   r=   Úrequest_bodyr>   rG   rA   s          r   Úget_video_chaptersz TwitchService.get_video_chaptersý   sÏ  è è € ð	JÝÔ(Ñ*Ô*ð ð ð ð ð ð ð ¨fð )Ø*lØ'(ð+ð +ð#ð &Là! 6ð"ð ð  �ð "(§¢Ø/Ø%Ø(Ð*JÐKð "-ñ "ô "ð ð ð ð ð ð �ð Ô'¨3Ò.Ð.Ý&Ð'dÈhÔNbÐ'dÐ'dÑeÔeÐeà—}’}‘”�Øð3ð ð ð ñ ô ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð øøøð ð ð ð ð ð øõ4 ð 	Jð 	Jð 	JÝÐHÅÀAÁÄÐHÐHÑIÔIÐIøøøøð	Jøøøs;   „B( �A%BÂB( Â
BÂB( Â"BÂ#B( Â(
CÂ2CÃCÚ	stream_idÚchaptersÚdbc                 óª  — ddl m} |                     |¦  «                             |j        |k    ¦  «                             ¦   «          |D ]¡} |||                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     dd¦  «        |                     d	d¦  «        |                     d
d¦  «        ¬¦  «        }|                     |¦  «         Œ¢|                     ¦   «          t          j
                             dt          |¦  «        › d|› d�¦  «         t          j
                             ¦   «          dS )z,Save chapters to the dedicated chapter tabler!   )ÚChapterÚgameDisplayNamer.   ÚgameIdrp   ÚstartMillisecondsr   ÚlengthMillisecondsÚthumbnailUrl)r�   Úgame_display_nameÚgame_idrp   Ústart_millisecondsÚlength_millisecondsr{   z[CHAPTERS] Saved z! chapters to database for stream r-   N)Úmodels.chapterr“   rj   Úfilterr�   Údeleter1   ÚaddÚcommitr3   r4   r5   r$   r6   )r   r�   r�   r‘   r“   ÚchapterÚ
db_chapters          r   Úsave_chapters_to_dbz!TwitchService.save_chapters_to_db  sL  € à,Ð,Ð,Ð,Ð,Ð,ð 	�Š�ÑÔ× Ò  Ô!2°iÒ!?Ñ@Ô@×GÒGÑIÔIÐIð  ð 
	ð 
	ˆGØ ˜Ø#Ø")§+¢+Ð.?ÀÑ"DÔ"DØŸš H¨bÑ1Ô1Ø#ŸKšK¨°rÑ:Ô:Ø#*§;¢;Ð/BÀAÑ#FÔ#FØ$+§K¢KÐ0DÀaÑ$HÔ$HØ%Ÿkšk¨.¸"Ñ=Ô=ðñ ô ˆJð �FŠF�:ÑÔÐÐà
�	Š	‰ŒˆÝŒ
×ÒÐj­S°©]¬]ÐjÐjÐ]fÐjÐjÐjÑkÔkÐkÝŒ
×ÒÑÔÐÐÐr   TFÚembed_emotesÚinclude_metadatac              ƒ   ót  K  — |                       |¦  «        }|st          d¦  «        ‚d}	 t          j        ¦   «         4 ƒd{V —†}g }d}d}	d}
d}d}d}d}d}i }|                      ¦   «         ƒ d{V —†}|s|	|k     �r,|sd||
d	œd
dddœidœ}nd||dœd
dddœidœ}	 |                     d|d|i¬¦  «        ƒ d{V —†}|j        dk    r#|dk    rt          d|j        › �¦  «        ‚|dz  }Œw|                     ¦   «         }| 	                    di ¦  «         	                    di ¦  «        }|st          d¦  «        ‚|�sª| 	                    di ¦  «         	                    d¦  «        }t          j                             d|› d�¦  «         t          j                             ¦   «          |rÿt          j                             d|› d�¦  «         t          j                             ¦   «          |                      |¦  «        ƒ d{V —†}t          j                             dt          |¦  «        › d�¦  «         t          j                             ¦   «          i |¥|¥}t          j                             d t          |¦  «        › d�¦  «         t          j                             ¦   «          n?t          j                             d!¦  «         t          j                             ¦   «          |}| 	                    d"¦  «        }|�| 	                    d#¦  «        €L|dk    r?t          j                             d$¦  «         t          j                             ¦   «          �nQ|dz  }�Œët!          d|d%z
  ¦  «        }t!          d|d%z
  ¦  «        }| 	                    d#g ¦  «        }| 	                    d&i ¦  «        }|D �]m}| 	                    d'i ¦  «        }| 	                    d(i ¦  «         	                    d)g ¦  «        }d}g }|D ]“}| 	                    d*¦  «        r\|d*         } |  	                    d+d¦  «        }!|                     |!|!d,|!› d-�d.œ¦  «         | 	                    d/¦  «        r||d/         z  }Œs| 	                    d/¦  «        r||d/         z  }Œ”| 	                    d(i ¦  «         	                    d0g ¦  «        }"g }#|"D ]¸}$|$ 	                    d1¦  «        r¡|$ 	                    d1¦  «        }%|$ 	                    d2¦  «        }&|%› d3|&› �}'| 	                    |'d¦  «        }(|(s=d4d5d6d7d5d8d9d:œ})|) 	                    |'d¦  «        }(|(s|%› d;�}*|) 	                    |*d¦  «        }(|(r|#                     |%|&|(d<œ¦  «         Œ¹| 	                    d=d¦  «        }+|                     t%          t'          j        ¦   «         ¦  «        | 	                    d>i ¦  «         	                    d?d@¦  «        ||+| 	                    d(i ¦  «         	                    dAdB¦  «        ||#dCœ¦  «         |+|	k    r|+}	�Œo| 	                    dDdE¦  «        snp|r|dF          	                    dGd¦  «        nd}|snMnB# t*          $ r5},|dk    rt          dHt%          |,¦  «        › �¦  «        ‚|dz  }Y d},~,�Œ#d},~,ww xY w|�°%|	|k     �°,d}-|�r1	 t          j                             dI|› d�¦  «         t          j                             ¦   «          |                      |¦  «        ƒ d{V —†}.t          j                             dJ|. 	                    dK¦  «        › d�¦  «         t          j                             ¦   «          |                      |¦  «        ƒ d{V —†}/t          j                             dL|/                     ¦   «         › d�¦  «         t          j                             ¦   «          g }0|/ 	                    di ¦  «         	                    di ¦  «         	                    dMi ¦  «         	                    d#g ¦  «        }1t          j                             dNt          |1¦  «        › dO�¦  «         t          j                             ¦   «          |1D �]�}2|2 	                    d'i ¦  «        }3|0                     |3 	                    dd¦  «        |3 	                    dPd¦  «        |3 	                    dQd¦  «        |3 	                    dRdS¦  «        |3 	                    dTi ¦  «         	                    dKi ¦  «         	                    d?d¦  «        d|3 	                    dUd¦  «        |3 	                    dTi ¦  «         	                    dKi ¦  «         	                    dd¦  «        |3 	                    dTi ¦  «         	                    dKi ¦  «         	                    d?d¦  «        |3 	                    dTi ¦  «         	                    dKi ¦  «         	                    dVd¦  «        dWœ
¦  «         �Œ�t          j                             dXt          |0¦  «        › dY�¦  «         t          j                             ¦   «          t          |0¦  «        dk    r÷t          j                             dZ¦  «         t          j                             ¦   «          |0                     d[d|. 	                    d\d¦  «        d]z  dS|. 	                    dKd¦  «        ddd|. 	                    dKd¦  «        |. 	                    d^d¦  «        dWœ
¦  «         t          j                             d_|0d         › d�¦  «         t          j                             ¦   «          |. 	                    dKd¦  «        |. 	                    d^d¦  «        |0d`œ}-nX# t*          $ rK},t          j                             da|,› d�¦  «         t          j                             ¦   «          Y d},~,nd},~,ww xY w||-dbœcddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS # t*          $ r$},t          dHt%          |,¦  «        › �¦  «        ‚d},~,ww xY w)czŽDownload chat using Twitch GraphQL API with TwitchDownloader's approach
        Returns dict with 'messages' list and optional 'metadata' dictrh   Úkd1unb4b3q4t58fwlpcbzcbnm76a8fpNr.   r   i?B TÚVideoCommentsByOffsetOrCursor)r‰   ÚcontentOffsetSecondsr…   r    Ú@b70a3591ff0f4e0313d126c6a1502d79a1c02baebb288227c582044aa76adf6a)r`   r‡   )r‹   rŒ   rŠ   )r‰   Úcursorri   rR   rk   r,   rI   rl   rG   rm   rn   rt   rX   z![CHAT] Extracted broadcaster_id: r-   z3[CHAT] Fetching channel badges for broadcaster_id: z[CHAT] Channel badges fetched: z badges
z[CHAT] Total badge mapping: z9[CHAT] No broadcaster_id found, using only global badges
ÚcommentsÚedgesz2[CHAT ERROR] Received too many null comment lists
çš™™™™™¹?ÚpageInfoÚnodeÚmessageÚ	fragmentsÚemoteÚemoteIDz*https://static-cdn.jtvnw.net/emoticons/v2/z/default/dark/1.0)rX   Únamer   r\   Ú
userBadgesÚsetIDr`   rZ   zMhttps://static-cdn.jtvnw.net/badges/v1/5527c58c-fb7d-422d-b71b-f309dcb85cc1/1zMhttps://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-4b17-b3df-f923a41db1d0/1zMhttps://static-cdn.jtvnw.net/badges/v1/b817aba4-fad8-49e2-b88a-7cc744dfa6ec/1zMhttps://static-cdn.jtvnw.net/badges/v1/5d9f2208-5dd8-11e7-8513-2ff4adfae661/1z>https://static-cdn.jtvnw.net/badges/v1/9r7hx2k0608i8x6s8u8g8/1zMhttps://static-cdn.jtvnw.net/badges/v1/d12a2e27-16f6-41d0-ab77-b780518f00a3/1)zbroadcaster:1zmoderator:1zvip:1zsubscriber:0z	founder:1z	premium:1z	partner:1z:1)rV   r`   r   rª   Ú	commenterru   ÚUnknownÚ	userColorz#9146FF)rX   Úusernamer²   Útimestamp_offsetÚcolorÚemotesÚbadgesÚhasNextPageFéÿÿÿÿr¬   zFailed to download chat: z([METADATA] Extracting metadata for URL: z[METADATA] Stream info game: rv   z[METADATA] Chapters data keys: Úmomentsz[METADATA] Found z chapter moments
ÚpositionMillisecondsÚdurationMillisecondsÚ_typeÚGAME_CHANGEÚdetailsÚthumbnailURLrw   )
rX   r–   r—   Útyperp   ÚsubDescriptionr˜   r•   r”   ÚgameBoxArtUrlz[METADATA] Extracted z
 chapters
zF[METADATA] No chapters found, generating bogus chapter with game info
Úbogus_chapter_0ry   iè  r}   z$[METADATA] Generated bogus chapter: )rv   r}   r�   z-[METADATA ERROR] Failed to extract metadata: )ÚmessagesÚmetadata)r*   r~   r/   r0   rf   rJ   r2   r   rK   r1   r3   r4   r5   r6   rd   r$   ÚmaxÚappendr€   ÚuuidÚuuid4r<   rƒ   rŽ   Úkeys)4r   r   r¥   r¦   r�   r   r=   Úconverted_messagesr¬   Úlatest_offsetÚvideo_startÚ	video_endÚ
run_to_endÚerror_countÚ
null_countrM   r^   Úglobal_badge_mappingÚpayloadr>   rG   r‚   Úchannel_badgesÚcomments_dataÚcomments_edgesÚ	page_infoÚedger±   r³   Úmessage_textr¿   Úfragmentr´   Úemote_idr]   rÀ   ÚbadgerV   r`   rc   Ú	badge_urlÚknown_badge_urlsÚbase_keyÚoffsetrA   rÏ   Ústream_infoÚchapters_datar�   Úmoments_edgesÚmoment_edgeÚmoments4                                                       r   Údownload_chatzTwitchService.download_chat5  s`  è è € ð ×$Ò$ SÑ)Ô)ˆØð 	9ÝÐ7Ñ8Ô8Ð8ð 6ˆ	ðJ	EÝÔ(Ñ*Ô*ð Gð Gð Gð Gð Gð Gð G¨fØ%'Ð"Ø�Ø !�Ø�Ø"�	Ø!�
Ø�Ø�
Ø!%�Ø "�Ø-1×-CÒ-CÑ-EÔ-EÐ'EÐ'EÐ'EÐ'EÐ'EÐ'EÐ$à ð q! M°IÒ$=Ñ$=à!ð ð .Mà+1Ø8Cð*ð *ð
 !1Ø/0Ø2tð3"ð 3"ð+ð#ð #˜˜ð  .Mà+1Ø*0ð*ð *ð
 !1Ø/0Ø2tð3"ð 3"ð+ð#ð #˜ðP!Ø)/¯ªØ7Ø!(Ø%0°)Ð$<ð *5ñ *ô *ð $ð $ð $ð $ð $ð $˜ð $Ô/°3Ò6Ð6Ø*¨RÒ/Ð/Ý&2Ð3gÐQYÔQeÐ3gÐ3gÑ&hÔ&hÐ hØ'¨1Ñ,˜KØ$à'Ÿ}š}™œ˜Ø%)§X¢X¨f°bÑ%9Ô%9×%=Ò%=¸gÀrÑ%JÔ%J˜
à)ð BÝ".Ð/@Ñ"AÔ"AÐAð  .ñ EØ-7¯^ª^¸GÀRÑ-HÔ-H×-LÒ-LÈTÑ-RÔ-R˜NÝœJ×,Ò,Ð-cÐQ_Ð-cÐ-cÐ-cÑdÔdÐdÝœJ×,Ò,Ñ.Ô.Ð.Ø-ð EÝ #¤
× 0Ò 0Ð1yÐguÐ1yÐ1yÐ1yÑ zÔ zÐ zÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2Ø7;×7NÒ7NÈ~Ñ7^Ô7^Ð1^Ð1^Ð1^Ð1^Ð1^Ð1^ Ý #¤
× 0Ò 0Ð1qÕSVÐWeÑSfÔSfÐ1qÐ1qÐ1qÑ rÔ rÐ rÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2à0ZÐ3GÐ0ZÈ>Ð0Z Ý #¤
× 0Ò 0Ð1mÕPSÐTaÑPbÔPbÐ1mÐ1mÐ1mÑ nÔ nÐ nÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2Ð 2å #¤
× 0Ò 0Ð1mÑ nÔ nÐ nÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2Ø0D à(2¯ª°zÑ(BÔ(B˜ð )Ð0°M×4EÒ4EÀgÑ4NÔ4NÐ4VØ)¨Bš˜Ý #¤
× 0Ò 0Ð1fÑ gÔ gÐ gÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2Ù %Ø&¨!™O˜JÙ$å%(¨¨J¸Ñ,<Ñ%=Ô%=˜
Ý&)¨!¨[¸3Ñ->Ñ&?Ô&?˜à)6×):Ò):¸7ÀBÑ)GÔ)G˜Ø$1×$5Ò$5°jÀ"Ñ$EÔ$E˜	ð %3ð H7ñ H7˜DØ#'§8¢8¨F°BÑ#7Ô#7˜Dð )-¯ª°¸BÑ(?Ô(?×(CÒ(CÀKÐQSÑ(TÔ(T˜IØ+-˜LØ%'˜Fà,5ð Ið I Ø#+§<¢<°Ñ#8Ô#8ð !IØ,4°WÔ,= EØ/4¯yªy¸ÀBÑ/GÔ/G HØ$*§M¢MØ.6Ø08Ø/wÐ\dÐ/wÐ/wÐ/wð3&ð 3&ñ %'ô %'ð %'ð
 (0§|¢|°FÑ';Ô';ð %IØ(4¸ÀÔ8HÑ(H¨øà'/§|¢|°FÑ';Ô';ð %IØ(4¸ÀÔ8HÑ(H¨øð +/¯(ª(°9¸bÑ*AÔ*A×*EÒ*EÀlÐTVÑ*WÔ*W˜KØ%'˜FØ)4ð +ð + Ø#(§9¢9¨WÑ#5Ô#5ð !+Ø-2¯YªY°wÑ-?Ô-? FØ.3¯iªi¸	Ñ.BÔ.B Gà-3Ð*?Ð*?°gÐ*?Ð*? CØ0=×0AÒ0AÀ#ÀrÑ0JÔ0J Ið ,5ð %[ð >Mð <Kð 6Eð =Lð :IØ9yð :Ið<*ð <*Ð(8ð 5E×4HÒ4HÈÈbÑ4QÔ4Q¨	ð 09ð )[Ø:@°}°}°}¨HØ8H×8LÒ8LÈXÐWYÑ8ZÔ8Z¨Ià'0ð %+Ø(.¯ªØ6<Ø7>Ø3<ð7*ð 7*ñ )+ô )+ð )+øð &*§X¢XÐ.DÀaÑ%HÔ%H˜Fà.×5Ò5Ý&)­$¬*©,¬,Ñ&7Ô&7Ø,0¯HªH°[À"Ñ,EÔ,E×,IÒ,IÈ-ÐYbÑ,cÔ,cØ+7Ø4:Ø)-¯ª°)¸RÑ)@Ô)@×)DÒ)DÀ[ÐR[Ñ)\Ô)\Ø*0Ø*0ð7ð 7ñ ô ð ð  &¨Ò5Ð5Ø06 ùð  )Ÿ}š}¨]¸EÑBÔBð "Ø!àIWÐ!_ °Ô!3×!7Ò!7¸À"Ñ!EÔ!EÐ!EÐ]_˜à%ð "Ø!ð"øõ %ð !ð !ð !Ø&¨Ò+Ð+Ý".Ð/SÍ3ÈqÉ6Ì6Ð/SÐ/SÑ"TÔ"TÐTØ# qÑ(˜Ø ˜˜˜™øøøøð	!øøøð[ !ñ q! M°IÒ$=Ñ$=ðh  �Ø#ñ @+ð?+åœ
×(Ò(Ð)[ÐTWÐ)[Ð)[Ð)[Ñ\Ô\Ð\Ýœ
×(Ò(Ñ*Ô*Ð*Ø,0×,@Ò,@ÀÑ,EÔ,EÐ&EÐ&EÐ&EÐ&EÐ&EÐ&E˜Ýœ
×(Ò(Ð)dÈÏÊÐY_ÑI`ÔI`Ð)dÐ)dÐ)dÑeÔeÐeÝœ
×(Ò(Ñ*Ô*Ð*ð /3×.EÒ.EÀfÑ.MÔ.MÐ(MÐ(MÐ(MÐ(MÐ(MÐ(M˜Ýœ
×(Ò(Ð)cÈ=×K]ÒK]ÑK_ÔK_Ð)cÐ)cÐ)cÑdÔdÐdÝœ
×(Ò(Ñ*Ô*Ð*ð $&˜Ø(5×(9Ò(9¸&À"Ñ(EÔ(E×(IÒ(IÈ'ÐSUÑ(VÔ(V×(ZÒ(ZÐ[dÐfhÑ(iÔ(i×(mÒ(mÐnuÐwyÑ(zÔ(z˜Ýœ
×(Ò(Ð)c½SÀÑ=OÔ=OÐ)cÐ)cÐ)cÑdÔdÐdÝœ
×(Ò(Ñ*Ô*Ð*à+8ð ñ ˜KØ%0§_¢_°V¸RÑ%@Ô%@˜FØ$ŸOšOØ&,§j¢j°°rÑ&:Ô&:Ø5;·Z²ZÐ@VÐXYÑ5ZÔ5ZØ6<·j²jÐAWÐYZÑ6[Ô6[Ø(.¯
ª
°7¸MÑ(JÔ(JØ/5¯zªz¸)ÀRÑ/HÔ/H×/LÒ/LÈVÐUWÑ/XÔ/X×/\Ò/\Ð]jÐlnÑ/oÔ/oØ24Ø06·
²
¸>È2Ñ0NÔ0NØ*0¯*ª*°YÀÑ*CÔ*C×*GÒ*GÈÐPRÑ*SÔ*S×*WÒ*WÐX\Ð^`Ñ*aÔ*aØ39·:²:¸iÈÑ3LÔ3L×3PÒ3PÐQWÐY[Ñ3\Ô3\×3`Ò3`ÐanÐprÑ3sÔ3sØ17·²¸IÀrÑ1JÔ1J×1NÒ1NÈvÐWYÑ1ZÔ1Z×1^Ò1^Ð_jÐlnÑ1oÔ1oð-ð -ñ ô ð ñ õ œ
×(Ò(Ð)[ÅÀXÁÄÐ)[Ð)[Ð)[Ñ\Ô\Ð\Ýœ
×(Ò(Ñ*Ô*Ð*õ ˜x™=œ=¨AÒ-Ð-ÝœJ×,Ò,Ð-vÑwÔwÐwÝœJ×,Ò,Ñ.Ô.Ð.Ø$ŸOšOØ&7Ø56Ø6A·o²oÐFXÐZ[Ñ6\Ô6\Ð_cÑ6cØ(5Ø/:¯ª¸vÀrÑ/JÔ/JØ24Ø02Ø*,Ø3>·?²?À6È2Ñ3NÔ3NØ1<·²ÀÐQSÑ1TÔ1Tð-ð -ñ ô ð õ  œJ×,Ò,Ð-cÐT\Ð]^ÔT_Ð-cÐ-cÐ-cÑdÔdÐdÝœJ×,Ò,Ñ.Ô.Ð.ð %0§O¢O°F¸BÑ$?Ô$?Ø,7¯OªO¸NÈBÑ,OÔ,OØ(0ð$ð $˜˜øõ
 %ð +ð +ð +Ýœ
×(Ò(Ð)^ÐYZÐ)^Ð)^Ð)^Ñ_Ô_Ð_Ýœ
×(Ò(Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*øøøøð+øøøð
 !3Ø (ðð ðIGð Gð Gð Gñ Gô Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gð Gøøøð Gð Gð Gð Gð Gð GøõP ð 	Eð 	Eð 	EÝÐC½3¸q¹6¼6ÐCÐCÑDÔDÐDøøøøð	EøøøsÅ   ¬p	 ÁAo6ÂAYÃ*o6Ã+I+YÍo6ÍYÍo6ÍKYØ8o6Ø9"YÙo6Ù
ZÙ'*ZÚo6ÚZÚo6Ú/Snîo6î
oîAoïo6ïoïo6ï#p	 ï6
p ð p	 ðp ðp	 ð	
p7ðp2ð2p7NÚoutput_pathc              ƒ   ón.  ‡‡U‡V‡W‡X‡Y‡ZK  — |                       |¦  «        }|st          d¦  «        ‚	 t          j        t          j                             |¦  «        d¬¦  «         d‰p|› �}d|› d|› d�}dd	l}|                     d
dd¬¦  «        }|                     |¦  «         | 	                    ¦   «          t          j                             d|› d�¦  «         t          j                             d|› d�¦  «         t          j                             ¦   «          t          j                             |¦  «        ŠXt          j                             t          j                             |¦  «        ¦  «        d         }	dddd‰X› d|	› d�dddddd|g}
t          j        |
t          j        t          j        dd¬¦  «        }dd	l}dd	lŠWdd lm} |                     d!d"dd#|j        v r9|j                             d$¦  «        d                              d#¦  «        d         nd	d¬%¦  «        ŠYd}|j        D �]^}d&|v �rVd'|v �rQ	 |                     ¦   «         }t7          d(„ |D ¦   «         d	¦  «        }|�rÄt9          |                     d'd)¦  «        ¦  «        }|d*k    rTt          j                             d+¦  «         t          j                             ¦   «          |                     ¦   «           �n¤d)}d)}d)}d)}t?          |¦  «        D ]‡\  }}d,|v r3|dk    r||dz
           }|dz   tA          |¦  «        k     r||dz            }Œ<d-|v r"|dz   tA          |¦  «        k     r||dz            }Œbd.|v r!|dz   tA          |¦  «        k     r||dz            }Œˆd/|||||d0œ}d‰› �}‰Y !                    |d1‰W "                    |¦  «        ¦  «         tG          |d2z  ¦  «        d2z  }||k    s|d3k    rO|}t          j                             d4|› d5|› d6|› d7|› d8|› d�¦  «         t          j                             ¦   «          �Œ# tH          $ rL}t          j                             d9|› d�¦  «         t          j                             ¦   «          Y d	}~�ŒVd	}~ww xY w�Œ`| %                    d:¬;¦  «        }	 t          j&        |j'        ¦  «         n#  Y nxY w|dk    r|d<k    rtQ          d=|› �¦  «        ‚|d<k    r=t          j                             d>¦  «         t          j                             ¦   «          dd	l)}dd	l*ŠZdd?l+m,} ‰X› d|	› d@�}| )                    |¦  «        } ˆZfdA„}!|  -                    |!¬B¦  «         | �r,t          j                             dCtA          | ¦  «        › dD�¦  «         t          j                             ¦   «          ˆZfdE„}"d·ˆWˆYˆZfdF„	}# |dG¬H¦  «        5 }$t]          |$ /                    |"| ¦  «        ¦  «        }%d	d	d	¦  «         n# 1 swxY w Y   t          j                             dItA          |%¦  «        › dD�¦  «         t          j                             ¦   «          ‰X› d|	› dJ�}&ta          |&d
¦  «        5 }'|'                     dK¦  «         |'                     dL¦  «         |'                     dM¦  «         |'                     dN¦  «         |%D ]L}(|'                     dO¦  «         |'                     t          j                             |(¦  «        › d�¦  «         ŒM|'                     dP¦  «         d	d	d	¦  «         n# 1 swxY w Y   t          j                             dQtA          |%¦  «        › dR�¦  «         ‰X› d|	› dJ�})‰X› d|	› dS�}*t          j         1                    |)¦  «        r=dd	l2}+|+ 3                    |)|*¦  «         t          j                             dT|*› d�¦  «         ddUl4m5}, ddVl6m7}- ddWl8m9}. 	 t7           |,¦   «         ¦  «        }/|/ :                    |-¦  «         ;                    |-j<        ‰k    ¦  «         =                    ¦   «         }0|0radX|0_>        dY‰› d‰› dS�|0_?        dY‰› d‰› dS�|0_@        d|0_A        |/ B                    ¦   «          t          j                             dZ‰› d[�¦  «         n:# tH          $ r-}t          j                             d\|› d�¦  «         Y d	}~nd	}~ww xY wd]d^d_d`daœ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         t          j                             db¦  «         t          j                             ¦   «          ‰X› dc�}1ta          |1d
¦  «        5 }'|%D ]}(|'                     dd|(› de�¦  «         Œ	 d	d	d	¦  «         n# 1 swxY w Y   ‰X› d|	› df�}2tA          |%¦  «        }3dgddhdidjdk|1dldm|2dng}4t          j        |4t          j        t          j        d¬o¦  «        }5|5j        D �]~}t          j                             dp|› �¦  «         t          j                             ¦   «          dq|v �r6dd	l*ŠZ ‰ZjC        dr|¦  «        }6|6�rtG          |6 D                    d¦  «        ¦  «        }7tG          |6 D                    d¦  «        ¦  «        }8t9          |6 D                    ds¦  «        ¦  «        }9|7d1z  |8dtz  z   |9z   }:du};|;dk    r¢t‹          dv|:|;z  ¦  «        }<tG          |<|3z  ¦  «        }=|;|:z
  }>|>dk    rtG          |>dtz  ¦  «        nd}?|>dk    rtG          |>dtz  ¦  «        nd}@d]dw|<dxz  z   d_d`|=|3dy|?dz›d$|@dz›�d{œd|œ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         �Œ€|5 %                    ¦   «          |5jF        dk    rtQ          d}|5jF        › �¦  «        ‚	 t7           |,¦   «         ¦  «        }/|/ :                    |-¦  «         ;                    |-j<        ‰k    ¦  «         =                    ¦   «         }0|0rhd~|0_>        dY‰› d‰› dS�|0_?        dY‰› d‰› dS�|0_@        d|0_A        |/ B                    ¦   «          t          j                             dZ‰› d�¦  «         |0jG        }An<# tH          $ r/}t          j                             d\|› d�¦  «         du}AY d	}~nd	}~ww xY wd]d€d~d�daœ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         ‰X}B|B› d|	› dJ�}Cdgdk|2dldmdd‚dƒd„d…djd†|B› d|	› d‡�dˆd‰dn|Cg}Dt          j        |Dt          j        t          j        d¬o¦  «        }Edd	l*ŠZd}Fd}Gd}Hd}:|Ej        D �]|}t          j                             dŠ|› �¦  «         t          j                             ¦   «           ‰ZjC        d‹|¦  «        }I|Ir"tG          |I D                    d¦  «        ¦  «        }F ‰ZjC        dŒ|¦  «        }J|Jr"t9          |J D                    d¦  «        ¦  «        }G ‰ZjC        d�|¦  «        }K|Kr"t9          |K D                    d¦  «        ¦  «        }HdŽ|v �r• ‰ZjC        d�|¦  «        }L|L�r�tG          |L D                    d¦  «        ¦  «        }7tG          |L D                    d¦  «        ¦  «        }8t9          |L D                    ds¦  «        ¦  «        }9|7d1z  |8dtz  z   |9z   }:|Adk    r|Andu};|;dk    rýt‹          d�d€|:|;z  d^z  z   ¦  «        }M|;|:z
  }>|>dk    rtG          |>dtz  ¦  «        nd}?|>dk    rtG          |>dtz  ¦  «        nd}@d]|Md~d�|F|Gdk    rt‘          |Gd¦  «        nd|Hdk    rt‘          |Hd¦  «        nd|7dz›d$|8dz›d$tG          |9¦  «        dz›�tG          |;dtz  ¦  «        dz›d$tG          |;dtz  ¦  «        dz›�|?dz›d$|@dz›�d‘œd|œ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         �Œ~|E %                    ¦   «          |EjF        dk    rtQ          d’|EjF        › �¦  «        ‚t          jI        |1¦  «         t          jI        |2¦  «         |%D ]5}(t          j         1                    |(¦  «        rt          jI        |(¦  «         Œ6t          j                             d“¦  «         t          j                             ¦   «          	 t7           |,¦   «         ¦  «        }/|/ :                    |-¦  «         ;                    |-j<        ‰k    ¦  «         =                    ¦   «         }0|0rSdY‰› d‰› dJ�|0_?        dY‰› d‰› dJ�|0_@        |/ B                    ¦   «          t          j                             dZ‰› d”�¦  «         n:# tH          $ r-}t          j                             d•|› d�¦  «         Y d	}~nd	}~ww xY w	 dd–lJmK}N  |N¦   «          n:# tH          $ r-}t          j                             d—|› d�¦  «         Y d	}~nd	}~ww xY wd]d˜d™dšd›dœid|œ}‰Y !                    |d1‰W "                    |¦  «        ¦  «          |#‰X|	|¦  «         	 t7           |,¦   «         ¦  «        }/|/ :                    |-¦  «         ;                    |-j<        ‰k    ¦  «         =                    ¦   «         }0|0r>d�|0_>        |/ B                    ¦   «          t          j                             dZ‰› dž�¦  «         n:# tH          $ r-}t          j                             d\|› d�¦  «         Y d	}~nd	}~ww xY wd]dŸd d¡d›d¢id|œ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         t          j                             d£‰› d�¦  «         t          j                             d¤‰X› d�¦  «         t          j                             ¦   «          dd	lLŠUdd	lM}Odd¥lNmOŠV ˆUˆVˆXˆfd¦„}P|O P                    |P¬§¦  «        }Qd|Q_Q        |Q R                    ¦   «          t          j                             d¨‰› d�¦  «         t          j                             ¦   «          d]d©d d¡daœ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         |C}Rt          j                             dª¦  «         t          j                             ¦   «          |R}t          j         S                    |R¦  «        }SnW‰X› d|	› d�}Tt          j         1                    |T¦  «        stQ          d«¦  «        ‚|T}t          j         S                    |T¦  «        }S	 t7           |,¦   «         ¦  «        }/|/ :                    |-¦  «         ;                    |-j<        ‰k    ¦  «         =                    ¦   «         }0|0rad¬|0_>        d|0_T        d|0_U        d	|0_V        d	|0_W        d	|0_X        |/ B                    ¦   «          t          j                             dZ‰› d­�¦  «         n:# tH          $ r-}t          j                             d\|› d�¦  «         Y d	}~nd	}~ww xY w	 dd–lJmK}N  |N¦   «          n:# tH          $ r-}t          j                             d®|› d�¦  «         Y d	}~nd	}~ww xY wd¯d*|Sd°œ}‰Y !                    |d1‰W "                    |¦  «        ¦  «         t          j                             d±|› d²|S› d³�¦  «         t          j                             ¦   «          ||S|d´œS # t          jY        $ r tQ          dµ¦  «        ‚tH          $ rW}t          j         1                    |¦  «        rt          jI        |¦  «         tQ          d¶tµ          |¦  «        › �¦  «        ‚d	}~ww xY w)¸z2Download video using yt-dlp with progress trackingrh   Tr   zstream_progress:a"  
import sys
import json
import logging
import sys
logger = logging.getLogger(__name__)

import redis
r = redis.Redis(host='redis', port=6379, db=0, decode_responses=True)

def progress_hook(d):
    if d['status'] == 'downloading':
        try:
            downloaded = d.get('downloaded_bytes', 0)
            total = d.get('total_bytes') or d.get('total_bytes_estimate', 0)
            speed = d.get('speed', 0)
            eta = d.get('eta', 0)
            
            progress_data = {
                'status': 'downloading',
                'downloaded_bytes': downloaded,
                'total_bytes': total,
                'percentage': (downloaded / total * 100) if total > 0 else 0,
                'speed': speed,
                'eta': eta
            }
            
            r.setex('zí', 3600, json.dumps(progress_data))
        except Exception as e:
            pass
    elif d['status'] == 'finished':
        progress_data = {
            'status': 'finished',
            'percentage': 100
        }
        r.setex('z8', 3600, json.dumps(progress_data))

# Hook into yt-dlp
r   NÚwz.pyF)ÚmodeÚsuffixrŸ   z"[DOWNLOAD] Starting VOD download: r-   z[DOWNLOAD] Output path: zyt-dlpz-fÚbestz-oú/ú.mp4z--no-playlistz	--newlinez
--progressz--keep-fragmentsz--concurrent-fragmentsÚ8r    )Ústdoutr4   r\   Úbufsizer!   )ÚsettingsÚredisië  ú@rZ   )ÚhostÚportr‘   ÚpasswordÚdecode_responsesz
[download]ú%c              3   ó"   K  — | ]
}d |v ¯|V — ŒdS )r  N© )Ú.0Úps     r   ú	<genexpr>z/TwitchService.download_video.<locals>.<genexpr>³  s&   è è € Ð.LÐ.L°QÀ3È!À8À8¨qÀ8À8À8À8Ð.LÐ.Lr   r.   éd   zK[DOWNLOAD] Download complete at 100%, terminating yt-dlp to skip FixupM3u8
ÚofÚatÚETAÚdownloading)ÚstatusÚ
percentageÚdownloaded_sizeÚ
total_sizeÚspeedÚetaé  rI   éc   z[DOWNLOAD] z% (z / z) - z - ETA z [ERROR] Error parsing progress: i   )Útimeoutiñÿÿÿzyt-dlp failed with code zP[DOWNLOAD] yt-dlp terminated at 100% (expected), continuing with HLS conversion
)ÚThreadPoolExecutorz.mp4.part-Frag*c                 ór   •—  ‰j         d| ¦  «        }|r"t          |                     d¦  «        ¦  «        ndS )Nú	Frag(\d+)r    r   ©r#   Úintr&   ©Úfilenamer'   r"   s     €r   Úextract_fragment_numberz=TwitchService.download_video.<locals>.extract_fragment_numberÿ  s8   ø€ Ø!˜œ	 ,°Ñ9Ô9�Ø.3Ð:•s˜5Ÿ;š; q™>œ>Ñ*Ô*Ð*¸Ð:r   ©rc   z%[RENAME] Starting parallel rename of z fragments
c                 ó  •—  ‰j         d| ¦  «        }|r3|                     d¦  «        }|                      d|z   d|› d�¦  «        }n*|                      dd¦  «                             dd¦  «        }t          j        | |¦  «         |S )Nr  r    z.mp4.part-FragÚ-ú.tsz
.part-Fragrø   )r#   r&   Úreplacer   Úrename)Úfragment_filer'   Úfrag_numÚts_filer"   s       €r   Úrename_fragmentz5TwitchService.download_video.<locals>.rename_fragment	  s–   ø€ à%˜BœI l°MÑBÔB�EØð bØ#(§;¢;¨q¡>¤>˜Ø"/×"7Ò"7Ð8HÈ8Ñ8SÐUfÐYaÐUfÐUfÐUfÑ"gÔ"g˜˜à"/×"7Ò"7¸ÀcÑ"JÔ"J×"RÒ"RÐSYÐ[`Ñ"aÔ"a˜Ý”I˜m¨WÑ5Ô5Ð5Ø"�Nr   c                 ó  •‡— 	 ˆfd„t          j        | ¦  «        D ¦   «         }ˆfd„}|                     |¬¦  «         t          |¦  «        }g }t	          |¦  «        D ]û\  }} ||¦  «        }	t           j                             | |¦  «        }
|rb|dk    r\d||z  dz  z   }t          ||z
  dz  ¦  «        }d|d	d
|dz   ||› d�dœdœ}‰                     |d‰ 	                    |¦  «        ¦  «         t          j        ddddddd|
gdd¬¦  «        }|j        dk    r=t          |j                             ¦   «         ¦  «        }|                     |	|f¦  «         Œü|s!t"          j                             d¦  «         d S t           j                             | ‰› d�¦  «        }t)          |d¦  «        5 }|                     ¦   «         }d d d ¦  «         n# 1 swxY w Y   g }d}|D ]h}|                     d¦  «        r<|t          |¦  «        k     r)||         \  }	}|                     d|› d�¦  «         |dz  }|                     |¦  «         Œit           j                             | ‰› d�¦  «        }t)          |d ¦  «        5 }|                     |¦  «         d d d ¦  «         n# 1 swxY w Y   t"          j                             d!|› d"�¦  «         d S # t0          $ r.}t"          j                             d#|› d�¦  «         Y d }~d S d }~ww xY w)$Nc                 óN   •— g | ]!}|                      d ¦  «        ¯‰|v ¯d|v ¯|‘Œ"S )r"  r!  )Úendswith)r  Úfr�   s     €r   ú
<listcomp>zQTwitchService.download_video.<locals>.generate_optimized_m3u8.<locals>.<listcomp>  sC   ø€ Ð(}Ð(}Ð(}¨qÈ1Ï:Ê:ÐV[ÑK\ÔK\Ð(}ÐajÐnoÐaoÐaoÐtwÐ{|Ðt|Ðt|¨Ðt|Ðt|Ðt|r   c                 ór   •—  ‰j         d| ¦  «        }|r"t          |                     d¦  «        ¦  «        ndS )Nz-(\d+)\.ts$r    r   r  r  s     €r   Úextract_segment_numberz]TwitchService.download_video.<locals>.generate_optimized_m3u8.<locals>.extract_segment_number  s8   ø€ Ø$- B¤I¨n¸hÑ$GÔ$G˜EØ:?Ð#F¥3 u§{¢{°1¡~¤~Ñ#6Ô#6Ð#6ÀQÐFr   r  r   é2   rI   r¯   Ú
processingÚgenerating_optimized_m3u8úGenerating optimized m3u8r    Ús)Úcurrent_segmentÚtotal_segmentsr  ©r  r  ÚstepÚ	step_namerÈ   r  Úffprobez-vÚerrorz-show_entrieszformat=start_timez-ofz"default=noprint_wrappers=1:nokey=1T)Úcapture_outputr\   zI[TWITCH] No segment timestamps found, skipping optimized m3u8 generation
ú.m3u8Úrz#EXTINFz#EXT-X-START-TIME:r-   z_optimized.m3u8ró   z%[TWITCH] Optimized m3u8 created with z #EXT-X-START-TIME tags
z*[TWITCH] Error generating optimized m3u8: )r   ÚlistdirÚsortr$   Ú	enumerateÚpathÚjoinr  ÚsetexÚdumpsÚ
subprocessÚrunÚ
returncodeÚfloatrú   ÚstriprÑ   r3   r4   r5   ÚopenÚ	readlinesÚ
startswithÚ
writelinesr<   )Úhls_dirr�   Úprogress_keyÚsegment_filesr/  r6  Úsegment_timestampsÚidxÚseg_fileÚseg_numÚseg_pathÚoptimize_progressÚeta_secondsÚprogress_dataÚresultÚ
start_timeÚ	m3u8_filer,  ÚlinesÚnew_m3u8Ú	seg_indexÚlineÚoptimized_m3u8rA   rK   r>  r"   s    `                      €€€r   Úgenerate_optimized_m3u8z=TwitchService.download_video.<locals>.generate_optimized_m3u8  s.  øø€ ðN]à(}Ð(}Ð(}Ð(}µB´J¸wÑ4GÔ4GÐ(}Ñ(}Ô(}˜ðGð Gð Gð Gð Gð &×*Ò*Ð/EÐ*ÑFÔFÐFÝ),¨]Ñ);Ô);˜ð .0Ð*Ý-6°}Ñ-EÔ-Eð Qð Q™M˜C Ø&<Ð&<¸XÑ&FÔ&F˜GÝ')¤w§|¢|°G¸XÑ'FÔ'F˜Hð  ,ð W°ÀÒ0BÐ0BØ46¸#ÀÑ:NÐQSÑ:SÑ4TÐ 1Ý.1°>ÀCÑ3GÈ3Ñ2NÑ.OÔ.O à.:Ø2CØ,GØ1Là;>À¹7Ø:HØ2=Ð/@Ð/@Ð/@ð0&ð 0&ð
1"ð 
1" ð !"§¢¨°d¸D¿JºJÀ}Ñ<UÔ<UÑ VÔ VÐ Vå%/¤^Ø!*¨D°'¸?ÐL_Ø!&Ð(LÈhð!Xà/3Ø%)ð	&ñ &ô &˜Fð  &Ô0°AÒ5Ð5Ý-2°6´=×3FÒ3FÑ3HÔ3HÑ-IÔ-I 
Ø 2× 9Ò 9¸7ÀJÐ:OÑ PÔ PÐ Pøà1ð #ÝœJ×,Ò,Ð-yÑzÔzÐzØ"˜Fõ %'¤G§L¢L°¸YÐ:MÐ:MÐ:MÑ$NÔ$N˜	Ý! )¨SÑ1Ô1ð 2°QØ$%§K¢K¡M¤M˜Eð2ð 2ð 2ñ 2ô 2ð 2ð 2ð 2ð 2ð 2ð 2øøøð 2ð 2ð 2ð 2ð $&˜Ø$%˜	à$)ð 2ð 2˜DØ#Ÿš¨yÑ9Ô9ð 3à#,­sÐ3EÑ/FÔ/FÒ#FÐ#FØ:LÈYÔ:WÑ$7 G¨Zà$,§O¢OÐ4WÈÐ4WÐ4WÐ4WÑ$XÔ$XÐ$XØ$-°¡N IØ$ŸOšO¨DÑ1Ô1Ð1Ð1õ *,¬¯ª°gÀ)Ð?\Ð?\Ð?\Ñ)]Ô)]˜Ý! .°#Ñ6Ô6ð 3¸!ØŸLšL¨Ñ2Ô2Ð2ð3ð 3ð 3ñ 3ô 3ð 3ð 3ð 3ð 3ð 3ð 3øøøð 3ð 3ð 3ð 3õ œ
×(Ò(Ð)uÐQZÐ)uÐ)uÐ)uÑvÔvÐvÐvÐvøå$ð ]ð ]ð ]Ýœ
×(Ò(Ð)[ÐVWÐ)[Ð)[Ð)[Ñ\Ô\Ð\Ð\Ð\Ð\Ð\Ð\Ð\øøøøð]øøøsg   „E8K Å>3K Æ1GÇK ÇGÇK ÇGÇB%K É?J!ÊK Ê!J%Ê%K Ê(J%Ê)&K Ë
L	Ë#LÌL	é   )Úmax_workersz&[RENAME] Completed parallel rename of r=  z#EXTM3U
z#EXT-X-VERSION:3
z#EXT-X-TARGETDURATION:10
z#EXT-X-MEDIA-SEQUENCE:0
z#EXTINF:10.0,
z#EXT-X-ENDLIST
z,[PLAYLIST] Created basic m3u8 playlist with z
 segments
z	_10s.m3u8z.[PLAYLIST] Saved original playlist as backup: )Úget_db)ÚStreamr   Ú
segmentingz/uploads/videos/z[STATUS] Stream z0 status set to 'segmenting', using 10s playlist
z/[STATUS ERROR] Failed to update stream status: r1  é   Úconcatenating_segmentszConcatenating segments)r  r  r8  r9  z2[FFMPEG] Re-segmenting video to 2-second segments
z/concat_list.txtzfile 'z'
z_temp.tsÚffmpegÚconcatz-safeÚ0z-iz-cÚcopyz-y)rú   r4   r\   z[FFMPEG CONCAT] ztime=z#time=(\d{2}):(\d{2}):(\d{2}\.\d{2})é   é<   iü  g      ð?é   é   zMerging video segmentsÚ02d)Úfiles_processedÚtotal_filesÚcurrent_operationr  r7  zFFmpeg concat failed with code Úresegmentingz8 status set to 'resegmenting', still using 10s playlist
é   z"Re-segmenting to 2-second segmentsÚhlsz	-hls_timeÚ2z-hls_list_sizez-hls_segment_filenamez_%03d.tsz	-progresszpipe:1z[FFMPEG RESEGMENT] zframe=(\d+)zfps=([\d.]+)zspeed=([\d.]+)xz	out_time=z'out_time=(\d{2}):(\d{2}):(\d{2}\.\d{2})r0  )Úcurrent_frameÚfpsr  Úcurrent_timeÚ
total_timer  z"FFmpeg resegment failed with code z![FFMPEG] Re-segmenting completed
z switched to 2-second playlist
z6[STATUS ERROR] Failed to switch to 2-second playlist: )Úregenerate_master_ffconcatz=[FFCONCAT ERROR] Failed to regenerate after playlist switch: éF   r2  r3  ru  z+Creating HLS playlist with exact timestampsÚthumbnail_generationz& status set to 'thumbnail_generation'
éP   Úgenerating_thumbnailszGenerating thumbnailszPreparing thumbnail generationz;[THUMBNAILS] Auto-starting thumbnail generation for stream z[THUMBNAILS] HLS directory: )Úgenerate_thumbnails_backgroundc                  óô  •— 	 t           j                             d‰› d�¦  «         t           j                             ¦   «           ‰j         ‰‰‰¦  «        ¦  «         t           j                             d‰› d�¦  «         t           j                             ¦   «          d S # t
          $ rL} t           j                             d| › d�¦  «         t           j                             ¦   «          Y d } ~ d S d } ~ ww xY w)Nz2[THUMBNAILS] Starting thumbnail thread for stream r-   z3[THUMBNAILS] Thumbnail thread completed for stream z,[THUMBNAILS ERROR] Thumbnail thread failed: )r3   r4   r5   r6   rG  r<   )rA   Úasynciorƒ  Ú
output_dirr�   s    €€€€r   Úrun_thumbnail_generationz>TwitchService.download_video.<locals>.run_thumbnail_generation¥  s  ø€ ð+Ýœ
×(Ò(Ð)kÐ^gÐ)kÐ)kÐ)kÑlÔlÐlÝœ
×(Ò(Ñ*Ô*Ð*Ø#˜œÐ$BÐ$BÀ9ÈjÑ$YÔ$YÑZÔZÐZÝœ
×(Ò(Ð)lÐ_hÐ)lÐ)lÐ)lÑmÔmÐmÝœ
×(Ò(Ñ*Ô*Ð*Ð*Ð*øÝ$ð +ð +ð +Ýœ
×(Ò(Ð)]ÐXYÐ)]Ð)]Ð)]Ñ^Ô^Ð^Ýœ
×(Ò(Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*øøøøð+øøøs   ƒBB! Â!
C7Â+AC2Ã2C7)Útargetz1[THUMBNAILS] Thumbnail thread started for stream éZ   z/[M3U8] Created playlist with 2-second segments
zDownloaded file not foundÚreadyz status set to 'ready'
z'[FFCONCAT ERROR] Failed to regenerate: Úfinished)r  r  Ú	file_sizezVOD download completed: z (z bytes)
)Ú	file_pathrŒ  r�   zVOD download timed outzFailed to download VOD: ©N)[r*   r~   r   r   rB  ÚdirnameÚtempfileÚNamedTemporaryFiler5   Úcloser3   r4   r6   ÚsplitextÚbasenamerF  ÚPopenÚPIPEÚSTDOUTrý   rK   Úconfigrü   ÚRedisÚ	REDIS_URLÚsplitrú   ÚnextrI  r#  Ú	terminaterA  r$   rD  rE  r  r<   ÚwaitÚunlinkr¶   r   Úglobr"   Úconcurrent.futuresr  r@  ÚlistÚmaprK  ÚexistsÚshutilrm  Úapp.databasere  Úapp.models.streamrf  Úsqlalchemy.ormr	   rj   rž   rX   Úfirstr  Úhls_pathÚhls_urlÚhls_availabler¡   r#   r&   ÚminrH  ry   ÚroundÚremoveÚservices.ffconcat_servicer~  r…  Ú	threadingÚapp.api.streamsrƒ  ÚThreadÚdaemonÚstartÚgetsizeÚthumbnail_progress_generatedÚthumbnail_progress_totalÚthumbnail_progress_messageÚthumbnail_progress_errorÚthumbnail_progress_updated_atÚTimeoutExpiredr€   )[r   r   rñ   r�   r�   rP  Úprogress_scriptr�  Ú	hook_fileÚoutput_nameÚcmdÚprocessrý   rü   Úlast_logged_percentager`  ÚpartsÚpercentage_strr  r  r  Ú
speed_infoÚeta_infoÚiÚpartrY  Úcurrent_milestonerA   Úreturn_coder   r  Úfragment_patternÚfragment_filesr  r(  rb  ÚexecutorÚts_filesr\  r,  r'  Úoriginal_playlistÚbackup_playlistr¥  re  ÚStreamModelr	   r‘   ÚstreamÚconcat_list_pathÚ
temp_videort  Ú
concat_cmdÚconcat_processÚ
time_matchÚhoursÚminutesÚsecondsÚtotal_secondsÚdurationÚprogress_ratiors  Úremaining_secondsÚeta_minutesrX  Úactual_durationrO  rª  Úresegment_cmdÚresegment_processrz  Úcurrent_fpsÚcurrent_speedÚframe_matchÚ	fps_matchÚspeed_matchr'   Úresegment_progressr~  r±  r‡  Úthumbnail_threadÚplaylist_pathrŒ  Úmp4_pathr…  rƒ  rK   r†  r>  r"   s[      `                                                                                 @@@@@@r   Údownload_videozTwitchService.download_videoK  sž  øøøøøøøè è € à×$Ò$ SÑ)Ô)ˆØð 	9ÝÐ7Ñ8Ô8Ð8ðk
	DåŒK�œŸš¨Ñ4Ô4¸tÐDÑDÔDÐDð D¨iÐ.A¸6ÐCÐCˆLð&ð6 #ð7&ð &ðF ðG&ð &ð &ˆOðR ˆOˆOˆOØ ×3Ò3¸ÀUÐSXÐ3ÑYÔYˆIØ�OŠO˜OÑ,Ô,Ð,Ø�OŠOÑÔÐåŒJ×ÒÐIÀ#ÐIÐIÐIÑJÔJÐJÝŒJ×ÒÐG¸ÐGÐGÐGÑHÔHÐHÝŒJ×ÒÑÔÐõ œŸš¨Ñ5Ô5ˆJÝœ'×*Ò*­2¬7×+;Ò+;¸KÑ+HÔ+HÑIÔIÈ!ÔLˆKð Ø�fØ˜Ð7Ð7 kÐ7Ð7Ð7ØØØØ"Ø(¨#Øð
ˆCõ !Ô&ØÝ!”Ý!Ô(ØØðñ ô ˆGð ˆLˆLˆLØˆKˆKˆKØ)Ð)Ð)Ð)Ð)Ð)Ø—’ ¨t¸Ðvyð  ~Fô  ~Pð  wPð  wPÀHÔDV×D\ÒD\Ð]`ÑDaÔDaÐbcÔDd×DjÒDjÐknÑDoÔDoÐpqÔDrÐDrð  VZð  mq�ñ  rô  rˆAà%&Ð"àœð 7+ñ 7+�à 4Ð'Ñ'¨C°4¨K©Kð4+à $§
¢
¡¤˜Ý)-Ð.LÐ.L¸%Ð.LÑ.LÔ.LÈdÑ)SÔ)S˜Ø)ñ -3Ý).¨~×/EÒ/EÀcÈ2Ñ/NÔ/NÑ)OÔ)O˜Jð  *¨SÒ0Ð0Ý #¤
× 0Ò 0ð  2Añ  !Bô  !Bð  !BÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2Ø '× 1Ò 1Ñ 3Ô 3Ð 3Ø %¡ð /1˜OØ)+˜JØ)+˜JØ')˜Hå+4°UÑ+;Ô+;ð 
<ð 
<¡  4à#'¨4 < <Ø'(¨1¢u uØ:?ÀÀAÁ¼,¨Ø'(¨1¡u­s°5©z¬zÒ'9Ð'9Ø5:¸1¸q¹5´\¨
øØ%)¨T \ \°a¸!±e½cÀ%¹j¼jÒ6HÐ6HØ16°q¸1±u´ J JØ%*¨d ] ]°q¸1±u½sÀ5¹z¼zÒ7IÐ7IØ/4°Q¸±U¬| Høð +8Ø.8Ø3BØ.8Ø)3Ø'/ð-ð -˜Mð ,J¸iÐ+IÐ+I˜LØŸGšG L°$¸¿
º
À=Ñ8QÔ8QÑRÔRÐRõ 14°JÀ±OÑ0DÔ0DÀrÑ0IÐ-Ø0Ð3IÒIÐIÈZÐ[]ÒM]ÐM]Ø9JÐ 6Ý #¤
× 0Ò 0ð  2YÐ?Pð  2Yð  2YÐUdð  2Yð  2YÐisð  2Yð  2Yð  zDð  2Yð  2Yð  MUð  2Yð  2Yð  2Yñ  !Zô  !Zð  !ZÝ #¤
× 0Ò 0Ñ 2Ô 2Ð 2ùøÝ$ð +ð +ð +Ýœ
×(Ò(Ð)QÈAÐ)QÐ)QÐ)QÑRÔRÐRÝœ
×(Ò(Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ñ*øøøøð+øøøùð
 "Ÿ,š,¨t˜,Ñ4Ô4ˆKðÝ”	˜)œ.Ñ)Ô)Ð)Ð)øðØ�øøøð ˜aÒÐ K°3Ò$6Ð$6Ý"Ð#K¸kÐ#KÐ#KÑLÔLÐLà˜cÒ!Ð!Ý”
× Ò Ð!uÑvÔvÐvÝ”
× Ò Ñ"Ô"Ð"ð ˆKˆKˆKØˆIˆIˆIØ=Ð=Ð=Ð=Ð=Ð=Ø",ÐKÐK¨{ÐKÐKÐKÐØ!ŸYšYÐ'7Ñ8Ô8ˆNð;ð ;ð ;ð ;ð ;ð ×ÒÐ$;ÐÑ<Ô<Ð<àñ I6å”
× Ò Ð!jÍÈ^ÑI\ÔI\Ð!jÐ!jÐ!jÑkÔkÐkÝ”
× Ò Ñ"Ô"Ð"ð	#ð 	#ð 	#ð 	#ð 	#ðO]ð O]ð O]ð O]ð O]ð O]ð O]ð O]ðb (Ð'°AÐ6Ñ6Ô6ð S¸(Ý# H§L¢L°À.Ñ$QÔ$QÑRÔR�HðSð Sð Sñ Sô Sð Sð Sð Sð Sð Sð Søøøð Sð Sð Sð Sõ ”
× Ò Ð!eÍ#ÈhÉ-Ì-Ð!eÐ!eÐ!eÑfÔfÐfÝ”
× Ò Ñ"Ô"Ð"ð  *Ð>Ð>¨KÐ>Ð>Ð>�	Ý˜) SÑ)Ô)ð 0¨QØ—G’G˜KÑ(Ô(Ð(Ø—G’GÐ0Ñ1Ô1Ð1Ø—G’GÐ8Ñ9Ô9Ð9Ø—G’GÐ7Ñ8Ô8Ð8Ø#+ð Bð B˜ØŸšÐ 2Ñ3Ô3Ð3ØŸš¥2¤7×#3Ò#3°GÑ#<Ô#<Ð @Ð @Ð @ÑAÔAÐAÐAØ—G’GÐ.Ñ/Ô/Ð/ð0ð 0ð 0ñ 0ô 0ð 0ð 0ð 0ð 0ð 0ð 0øøøð 0ð 0ð 0ð 0õ ”
× Ò Ð!jÕPSÐT\ÑP]ÔP]Ð!jÐ!jÐ!jÑkÔkÐkð (2Ð$FÐ$F°KÐ$FÐ$FÐ$FÐ!Ø%/Ð"HÐ"H°+Ð"HÐ"HÐ"H�Ý”7—>’>Ð"3Ñ4Ô4ð kØ!�M�M�MØ—K’KÐ 1°?ÑCÔCÐCÝ”J×$Ò$Ð%iÐVeÐ%iÐ%iÐ%iÑjÔjÐjð 0Ð/Ð/Ð/Ð/Ð/ØCÐCÐCÐCÐCÐCØ2Ð2Ð2Ð2Ð2Ð2ð^Ý˜f˜f™hœh™œ�BØŸXšX kÑ2Ô2×9Ò9¸+¼.ÈIÒ:UÑVÔV×\Ò\Ñ^Ô^�FØð zØ(4˜œØ*]¸YÐ*]Ð*]ÈÐ*]Ð*]Ð*]˜œØ)\¸IÐ)\Ð)\È	Ð)\Ð)\Ð)\˜œØ/3˜Ô,ØŸ	š	™œ˜Ýœ
×(Ò(Ð)x¸IÐ)xÐ)xÐ)xÑyÔyÐyøøÝ ð ^ð ^ð ^Ý”J×$Ò$Ð%\ÐWXÐ%\Ð%\Ð%\Ñ]Ô]Ð]Ð]Ð]Ð]Ð]Ð]øøøøð^øøøð +Ø"$Ø4Ø!9ð	!ð !�ð —’˜ d¨D¯JªJ°}Ñ,EÔ,EÑFÔFÐFõ ”
× Ò Ð!WÑXÔXÐXÝ”
× Ò Ñ"Ô"Ð"ð '1Ð#BÐ#BÐ#BÐ ÝÐ*¨CÑ0Ô0ð 7°AØ#+ð 7ð 7˜ØŸšÐ 5¨Ð 5Ð 5Ð 5Ñ6Ô6Ð6Ð6ð7ð7ð 7ð 7ñ 7ô 7ð 7ð 7ð 7ð 7ð 7ð 7øøøð 7ð 7ð 7ð 7ð
 !+ÐBÐB¨[ÐBÐBÐB�
Ý! (™mœm�ð Ø˜(Ø˜SØÐ*Ø˜&ØØð�
õ ",Ô!1ØÝ%œ?Ý%Ô,Øð	"ñ "ô "�ð +Ô1ð #Wñ #W�DÝ”J×$Ò$Ð%>¸Ð%>Ð%>Ñ?Ô?Ð?Ý”J×$Ò$Ñ&Ô&Ð&ð  $�‘Ø!˜	˜	˜	Ø%. R¤YÐ/UÐW[Ñ%\Ô%\˜
Ø%ñ WÝ$'¨
×(8Ò(8¸Ñ(;Ô(;Ñ$<Ô$<˜EÝ&)¨*×*:Ò*:¸1Ñ*=Ô*=Ñ&>Ô&>˜GÝ&+¨J×,<Ò,<¸QÑ,?Ô,?Ñ&@Ô&@˜GØ,1°D©L¸7ÀR¹<Ñ,GÈ'Ñ,Q˜Mð (,˜HØ'¨!š|˜|Ý14°S¸-È(Ñ:RÑ1SÔ1S Ý25°nÀ{Ñ6RÑ2SÔ2S Ø4<¸}Ñ4LÐ 1ØM^ÐabÒMbÐMb­cÐ2CÀbÑ2HÑ.IÔ.IÐ.IÐhi ØM^ÐabÒMbÐMb­cÐ2CÀbÑ2HÑ.IÔ.IÐ.IÐhi ð /;Ø24¸ÈÑ8JÑ2KØ,DØ1Ià;JØ7BØ=UØ2=Ð/UÐ/UÐ/UÀKÐ/UÐ/UÐ/Uð	0&ð 0&ð1"ð 1" ð !"§¢¨°d¸D¿JºJÀ}Ñ<UÔ<UÑ VÔ VÐ Vùà×#Ò#Ñ%Ô%Ð%à!Ô,°Ò1Ð1Ý&Ð'dÈÔIbÐ'dÐ'dÑeÔeÐeð+Ý˜f˜f™hœh™œ�BØŸXšX kÑ2Ô2×9Ò9¸+¼.ÈIÒ:UÑVÔV×\Ò\Ñ^Ô^�FØð 	BØ(6˜œà*]¸YÐ*]Ð*]ÈÐ*]Ð*]Ð*]˜œØ)\¸IÐ)\Ð)\È	Ð)\Ð)\Ð)\˜œØ/3˜Ô,ØŸ	š	™œ˜Ýœ
×(Ò(ð  *A¸Ið  *Að  *Að  *Añ  Bô  Bð  Bà*0Ô*A˜øøÝ ð +ð +ð +Ý”J×$Ò$Ð%\ÐWXÐ%\Ð%\Ð%\Ñ]Ô]Ð]Ø&*�O�O�O�O�O�Oøøøøð+øøøð
 +Ø"$Ø*Ø!Eð	!ð !�ð —’˜ d¨D¯JªJ°}Ñ,EÔ,EÑFÔFÐFð %�Ø%Ð:Ð:¨Ð:Ð:Ð:�ð Ø˜*Ø˜&Ø˜%Ø Ø$ cØ+°Ð-OÐ-O¸+Ð-OÐ-OÐ-OØ ØØð!�õ %/Ô$4Ø!Ý%œ?Ý%Ô,Øð	%ñ %ô %Ð!ð �	�	�	Ø !�Ø�Ø !�Ø !�à-Ô4ð 2Wñ 2W�DÝ”J×$Ò$Ð%A¸4Ð%AÐ%AÑBÔBÐBÝ”J×$Ò$Ñ&Ô&Ð&ð #, "¤)¨N¸DÑ"AÔ"A�KØ"ð BÝ(+¨K×,=Ò,=¸aÑ,@Ô,@Ñ(AÔ(A˜ð !* ¤	¨/¸4Ñ @Ô @�IØ ð @Ý&+¨I¯OªO¸AÑ,>Ô,>Ñ&?Ô&?˜ð #, "¤)Ð,>ÀÑ"EÔ"E�KØ"ð DÝ(-¨k×.?Ò.?ÀÑ.BÔ.BÑ(CÔ(C˜ð # dÐ*Ñ*Ø ) ¤	Ð*TÐVZÑ [Ô [˜Ø ñ WÝ$'¨¯ª°A©¬Ñ$7Ô$7˜EÝ&)¨%¯+ª+°a©.¬.Ñ&9Ô&9˜GÝ&+¨E¯KªK¸©N¬NÑ&;Ô&;˜GØ,1°D©L¸7ÀR¹<Ñ,GÈ'Ñ,Q˜Mð ;JÈAÒ:MÐ:M  ÐSW˜HØ'¨!š|˜|Ý58¸¸RÀ=ÐS[ÑC[Ð^`ÑC`Ñ=aÑ5bÔ5bÐ 2Ø4<¸}Ñ4LÐ 1ØM^ÐabÒMbÐMb­cÐ2CÀbÑ2HÑ.IÔ.IÐ.IÐhi ØM^ÐabÒMbÐMb­cÐ2CÀbÑ2HÑ.IÔ.IÐ.IÐhi ð /;Ø2DØ,:Ø1Uà9FØHSÐVWÊÈ­u°[À!Ñ/DÔ/DÐ/DÐ]^ØLYÐ\]ÒL]ÐL]µ°}ÀaÑ1HÔ1HÐ1HÐcdØ;@Ð8gÐ8gÐ8gÀwÐ8gÐ8gÐ8gÕUXÐY`ÑUaÔUaÐ8gÐ8gÐ8gÝ9<¸XÈ¹^Ñ9LÔ9LÐ6kÐ6kÐ6kÕSVÐW_ÐbdÑWdÑSeÔSeÐ6kÐ6kÐ6kØ2=Ð/UÐ/UÐ/UÀKÐ/UÐ/UÐ/Uð0&ð 0&ð1"ð 1" ð !"§¢¨°d¸D¿JºJÀ}Ñ<UÔ<UÑ VÔ VÐ Vùà!×&Ò&Ñ(Ô(Ð(à$Ô/°1Ò4Ð4Ý&Ð'jÐL]ÔLhÐ'jÐ'jÑkÔkÐkõ ”	Ð*Ñ+Ô+Ð+Ý”	˜*Ñ%Ô%Ð%Ø'ð +ð +�GÝ”w—~’~ gÑ.Ô.ð +Ýœ	 'Ñ*Ô*Ð*øå”
× Ò Ð!FÑGÔGÐGÝ”
× Ò Ñ"Ô"Ð"ð	eÝ˜f˜f™hœh™œ�BØŸXšX kÑ2Ô2×9Ò9¸+¼.ÈIÒ:UÑVÔV×\Ò\Ñ^Ô^�FØð iØ*Y¸YÐ*YÐ*YÈÐ*YÐ*YÐ*Y˜œØ)X¸IÐ)XÐ)XÈ	Ð)XÐ)XÐ)X˜œØŸ	š	™œ˜Ýœ
×(Ò(Ð)g¸IÐ)gÐ)gÐ)gÑhÔhÐhøøÝ ð eð eð eÝ”J×$Ò$Ð%cÐ^_Ð%cÐ%cÐ%cÑdÔdÐdÐdÐdÐdÐdÐdøøøøðeøøøðlØVÐVÐVÐVÐVÐVØ.Ð.Ñ0Ô0Ð0Ð0øÝ ð lð lð lÝ”J×$Ò$Ð%jÐefÐ%jÐ%jÐ%jÑkÔkÐkÐkÐkÐkÐkÐkøøøøðløøøð
 +Ø"$Ø7Ø!<à+Ð-Zð ð!ð !�ð —’˜ d¨D¯JªJ°}Ñ,EÔ,EÑFÔFÐFð (Ð'¨
°KÀÑNÔNÐNð^Ý˜f˜f™hœh™œ�BØŸXšX kÑ2Ô2×9Ò9¸+¼.ÈIÒ:UÑVÔV×\Ò\Ñ^Ô^�FØð pØ(>˜œØŸ	š	™œ˜Ýœ
×(Ò(Ð)n¸IÐ)nÐ)nÐ)nÑoÔoÐoøøÝ ð ^ð ^ð ^Ý”J×$Ò$Ð%\ÐWXÐ%\Ð%\Ð%\Ñ]Ô]Ð]Ð]Ð]Ð]Ð]Ð]øøøøð^øøøð +Ø"$Ø3Ø!8à+Ð-Mð ð!ð !�ð —’˜ d¨D¯JªJ°}Ñ,EÔ,EÑFÔFÐFõ ”
× Ò Ð!lÐ_hÐ!lÐ!lÐ!lÑmÔmÐmÝ”
× Ò Ð!NÀ
Ð!NÐ!NÐ!NÑOÔOÐOÝ”
× Ò Ñ"Ô"Ð"Ø���Ø Ð Ð Ð ØJÐJÐJÐJÐJÐJð	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð 	+ð $-×#3Ò#3Ð;SÐ#3Ñ#TÔ#TÐ Ø*.Ð Ô'Ø ×&Ò&Ñ(Ô(Ð(Ý”
× Ò Ð!bÐU^Ð!bÐ!bÐ!bÑcÔcÐcÝ”
× Ò Ñ"Ô"Ð"ð +Ø"$Ø3Ø!8ð	!ð !�ð —’˜ d¨D¯JªJ°}Ñ,EÔ,EÑFÔFÐFð !)�Ý”
× Ò Ð!TÑUÔUÐUÝ”
× Ò Ñ"Ô"Ð"ð ,�ÝœGŸOšO¨MÑ:Ô:�	�	ð )Ð<Ð<¨;Ð<Ð<Ð<�Ý”w—~’~ hÑ/Ô/ð DÝ&Ð'BÑCÔCÐCØ&�ÝœGŸOšO¨HÑ5Ô5�	ðZÝ˜&˜&™(œ(‘^”^�ØŸš +Ñ.Ô.×5Ò5°k´nÈ	Ò6QÑRÔR×XÒXÑZÔZ�Øð ]Ø$+�F”MØ:;�FÔ7Ø67�FÔ3Ø8<�FÔ5Ø6:�FÔ3Ø;?�FÔ8Ø—I’I‘K”K�KÝ”J×$Ò$Ð%[¸	Ð%[Ð%[Ð%[Ñ\Ô\Ð\øøÝð Zð Zð ZÝ”
× Ò Ð!XÐSTÐ!XÐ!XÐ!XÑYÔYÐYÐYÐYÐYÐYÐYøøøøðZøøøðRØRÐRÐRÐRÐRÐRØ*Ð*Ñ,Ô,Ð,Ð,øÝð Rð Rð RÝ”
× Ò Ð!PÈ1Ð!PÐ!PÐ!PÑQÔQÐQÐQÐQÐQÐQÐQøøøøðRøøøð %Ø!Ø&ðð ˆMð
 �GŠG�L $¨¯
ª
°=Ñ(AÔ(AÑBÔBÐBåŒJ×ÒÐ[¸Ð[Ð[ÀyÐ[Ð[Ð[Ñ\Ô\Ð\ÝŒJ×ÒÑÔÐð )Ø&Ø ðð ð øõ Ô(ð 	9ð 	9ð 	9ÝÐ7Ñ8Ô8Ð8Ýð 	Dð 	Dð 	DåŒw�~Š~˜kÑ*Ô*ð 'Ý”	˜+Ñ&Ô&Ð&ÝÐB½#¸a¹&¼&ÐBÐBÑCÔCÐCøøøøð		Døøøsm  ±HAZ6 É B+P7Ë+AZ6 Ë.EP7Ð5AZ6 Ð7
RÑARÒAZ6 ÒRÒAZ6 Ò)S ÓAZ6 ÓSÓDAZ6 ×$X×?AZ6 ØXØAZ6 ØXØA)AZ6 Ù<B9]Ü5AZ6 Ý]ÝAZ6 Ý]Ý	B1AZ6 ß;B=b9 â8AZ6 â9
c0ã#c+ã&AZ6 ã+c0ã0BAZ6 å6f"æAZ6 æ"f&æ&AZ6 æ)f&æ*HAZ6 î;Cr  ñ?AZ6 ò 
r9ò
%r4ò/AZ6 ò4r9ò9O'AZ6 ÁB!B/AE ÁEAZ6 ÁE
AFÁE#AFÁE>AZ6 ÁFAFÁFAZ6 ÁFAF ÁFAZ6 ÁF
AGÁF'#AGÁG
AZ6 ÁGAGÁGAAZ6 ÁHBAJ4 ÁJ3AZ6 ÁJ4
AK+ÁJ>#AK&ÁK!AZ6 ÁK&AK+ÁK+HAZ6 ÁS8B=AV6 ÁV5AZ6 ÁV6
AW-ÁW #AW(ÁW#AZ6 ÁW(AW-ÁW-AZ6 ÁW1AX ÁXAZ6 ÁX
AX9ÁX#AX4ÁX/AZ6 ÁX4AX9ÁX9A<AZ6 ÁZ6'A\4Á[AA\/Á\/A\4c                 óø   — ddl }|j                             | j        |› d�¦  «        |j                             | j        |› d�¦  «        g}|D ],}|j                             |¦  «        r |j        |¦  «         Œ-dS )z'Clean up cache files for a specific VODr   Nz
_chat.jsonrø   )r   rB  rC  r   r¤  r¯  )r   r�   r   Úfiles_to_remover�  s        r   Úcleanup_cachezTwitchService.cleanup_cacheþ  s�   € àˆ	ˆ	ˆ	àŒG�LŠL˜œ¨FÐ)>Ð)>Ð)>Ñ?Ô?ØŒG�LŠL˜œ¨F¨¨¨Ñ9Ô9ð
ˆð
 )ð 	%ð 	%ˆIØŒw�~Š~˜iÑ(Ô(ð %Ø�”	˜)Ñ$Ô$Ð$øð	%ð 	%r   )TFrŽ  )Ú__name__Ú
__module__Ú__qualname__r   r€   r   r*   rB   rL   r   rd   rf   r   rƒ   ÚdictrŽ   r¢  r	   r¤   Úboolrð   rì  rï  r  r   r   r   r      s  € € € € € ð3ð 3ð 3ð #ð ¨(°3¬-ð ð ð ð ð$°3ð ¸3ð ð ð ð ð( sð ð ð ð ð>2°sð 2¸tÀCÈÀH¼~ð 2ð 2ð 2ð 2ðh1¨¨c°3¨h¬ð 1ð 1ð 1ð 1ðf8G¨ð 8G°°c¸3°h´ð 8Gð 8Gð 8Gð 8GðtJ¨sð J°tð Jð Jð Jð Jð@¨Sð ¸Dð Àgð ð ð ð ð0TEð TE sð TE¸$ð TEÐY]ð TEÐjnÐorÐtwÐowÔjxð TEð TEð TEð TEðlq
Dð q
D¨ð q
D¸#ð q
DÈ#ð q
DÐY]Ð^aÐcfÐ^fÔYgð q
Dð q
Dð q
Dð q
Dðf
% Cð 
%ð 
%ð 
%ð 
%ð 
%ð 
%r   r   )r"   rÒ   r/   r…  r7   rF  r   r3   Útypingr   r   r   r   r   r¨  r	   r   r  r   r   ú<module>rö     sÔ   ðØ 	€	€	€	Ø €€€Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø 	€	€	€	Ø 
€
€
€
Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø Ð Ð Ð Ð Ð Ø "Ð "Ð "Ð "Ð "Ð "ð{%ð {%ð {%ð {%ð {%ñ {%ô {%ð {%ð {%ð {%r   