3
™b`Öe  ã               @   sl  d dl mZ d dlZd dlZd dlZd dlZddlmZ ddlm	Z	m
Z
mZmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZ G dd	„ d	eƒZG d
d„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZ G dd„ deƒZ!G dd„ de!ƒZ"G dd„ de!ƒZ#G dd„ de!ƒZ$G dd„ de!ƒZ%G d d!„ d!eƒZ&G d"d#„ d#eƒZ'dS )$é    )Úunicode_literalsNé   )ÚInfoExtractoré   )Úcompat_kwargsÚcompat_parse_qsÚ
compat_strÚcompat_urllib_parse_urlencodeÚcompat_urllib_parse_urlparse)Ú
clean_htmlÚExtractorErrorÚint_or_noneÚ
orderedSetÚparse_durationÚparse_iso8601Útry_getÚunified_timestampÚupdate_url_queryÚurl_or_noneÚurljoinc               @   sP   e Zd ZdZdZdZdZdZdZdZ	dd	„ Z
d
d„ Zdd„ Zdd„ Zdd„ ZdS )ÚTwitchBaseIEz&https?://(?:(?:www|go|m)\.)?twitch\.tvzhttps://api.twitch.tvzhttps://usher.ttvnw.netzhttps://www.twitch.tv/loginz https://passport.twitch.tv/loginZkimne78kx3ncx6brgo4mv6wki5h1koÚtwitchc             C   s>   t |tƒsd S |jdƒ}|r:td| j||jdƒf dd�‚d S )NÚerrorz%s returned error: %s - %sÚmessageT)Úexpected)Ú
isinstanceÚdictÚgetr   ÚIE_NAME)ÚselfÚresponser   © r!   úGC:\Users\Broad\Desktop\All-Down\binaries\youtube_dl\extractor\twitch.pyÚ_handle_error*   s    

zTwitchBaseIE._handle_errorc             O   sR   |j di ƒjƒ }| j|d< ||d< | jd| j|f |f|žt|ƒŽ}| j|ƒ |S )NÚheadersz	Client-IDz%s/%s)r   ÚcopyÚ
_CLIENT_IDÚ_download_jsonÚ	_API_BASEr   r#   )r   ÚpathÚitem_idÚargsÚkwargsr$   r    r!   r!   r"   Ú	_call_api3   s    

zTwitchBaseIE._call_apic             C   s   | j ƒ  d S )N)Ú_login)r   r!   r!   r"   Ú_real_initialize=   s    zTwitchBaseIE._real_initializec                s¬   ˆj ƒ \}}|d krd S dd„ ‰ ‡ ‡fdd„}ˆjˆjd dƒ\}}d|krVˆ t|ƒƒ |||d||ˆjdœƒ\}}|szd S tjd	|ƒd k	r¨ˆjd
ƒ}|||d|ddœƒ d S )Nc             S   s   t d|  dd�‚d S )Nz Unable to login. Twitch said: %sT)r   )r   )r   r!   r!   r"   ÚfailE   s    z!TwitchBaseIE._login.<locals>.failc                sÆ   ˆj | ƒ}|j|ƒ |jƒ }ˆjd| dˆjdd�}t||ƒ}||ddœ}ˆj|d |tj|ƒj	ƒ |dd�}|j
d	ƒpz|j
d
ƒ}	|	rˆˆ |	ƒ d|j
ddƒkrœdS t||j
dƒp°|d ƒ}
ˆj|
d d|d�S )Nz&<form[^>]+action=(["\'])(?P<url>.+?)\1zpost urlÚurl)ÚdefaultÚgroupztext/plain;charset=UTF-8)ÚRefererÚOriginzContent-Typei�  )Údatar$   Úexpected_statusÚerror_descriptionÚ
error_codezAuthenticated successfullyr   Ú ÚredirectZredirect_pathzDownloading login redirect page)r$   )NN)Ú_hidden_inputsÚupdateÚgeturlÚ_search_regexÚ_LOGIN_POST_URLr   r'   ÚjsonÚdumpsÚencoder   Ú_download_webpage_handle)ÚpageÚurlhÚnoter6   ÚformÚpage_urlÚpost_urlr$   r    r   Úredirect_url)r0   r   r!   r"   Ú
login_stepI   s0    



z'TwitchBaseIE._login.<locals>.login_stepzDownloading login pageZblacklist_messagez
Logging in)ÚusernameÚpasswordÚ	client_idz$(?i)<form[^>]+id="two-factor-submit"ztwo-factor authentication tokenzSubmitting TFA tokenÚtrue)Zauthy_tokenZremember_2fa)Ú_get_login_inforD   Ú_LOGIN_FORM_URLr   r&   ÚreÚsearchÚ_get_tfa_info)r   rM   rN   rL   Ú
login_pageÚhandleZredirect_pageZ	tfa_tokenr!   )r0   r   r"   r.   @   s*    !
zTwitchBaseIE._loginc             C   sl   yt dd„ |D ƒƒ}d|d< W n> tk
r\   x(|D ] }d|d kr4|jdddœƒ q4W Y nX | j|ƒ d S )	Nc             s   s   | ]}|d  dkr|V  qdS )Ú	format_idÚSourceNr!   )Ú.0Úfr!   r!   r"   ú	<genexpr>†   s    z.TwitchBaseIE._prefer_source.<locals>.<genexpr>é
   Úqualityz	/chunked/r1   rY   )r^   Úformat_note)ÚnextÚStopIterationr=   Ú_sort_formats)r   ÚformatsÚsourcer[   r!   r!   r"   Ú_prefer_source„   s    
zTwitchBaseIE._prefer_sourceN)Ú__name__Ú
__module__Ú__qualname__Ú_VALID_URL_BASEr(   Ú_USHER_BASErR   r@   r&   Ú_NETRC_MACHINEr#   r-   r/   r.   re   r!   r!   r!   r"   r       s   	
Dr   c               @   s,   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	S )
ÚTwitchItemBaseIEc             C   s"   | j | jd||f |d| j ƒƒS )Nzkraken/videos/%s%szDownloading %s info JSON)Ú_extract_infor-   Ú
_ITEM_TYPE)r   Úitemr*   r!   r!   r"   Ú_download_info“   s    zTwitchItemBaseIE._download_infoc             C   s2  | j | j|ƒ}| jd| j|f |d| j ƒ}g }|d }t|jƒ ƒ}xÖtt|jƒ Ž dd�D ]¾\}}g }	xdt|ƒD ]X\}
}||
 }|d ||dkr”dndd	œ}t	j
d
|ƒ}|r¾t|jdƒƒ|d< |	j|ƒ qpW | j|	ƒ t|ƒ}d|d |f |d< d|d |f |d< |	|d< |j|ƒ qZW | j||d |d ƒS )Nzapi/videos/%s%szDownloading %s playlist JSONÚchunksr   )Ústartr1   Úliver   )r1   rX   r^   z^(?P<height>\d+)[Pp]Úheightz%s_%dÚidz
%s part %dÚtitlerc   )rp   Ú_ITEM_SHORTCUTr-   rn   ÚlistÚkeysÚ	enumerateÚzipÚvaluesrS   rT   Úintr3   Úappendrb   r   Úplaylist_result)r   r*   Úinfor    Úentriesrq   Ú	qualitiesÚnumÚfragmentrc   Zfmt_numZfragment_fmtrX   ÚfmtÚmÚentryr!   r!   r"   Ú_extract_media˜   s2    
zTwitchItemBaseIE._extract_mediac             C   s˜   |j dƒ}|dkrd}n|dkr&d}nd }|d |j dƒp<d|j d	ƒt|j d
ƒƒ|j dƒ|j di ƒj dƒ|j di ƒj dƒt|j dƒƒt|j dƒƒ|dœ
S )NÚstatusÚ	recordingTÚrecordedFÚ_idrv   zUntitled BroadcastÚdescriptionÚlengthÚpreviewÚchannelÚdisplay_nameÚnameZrecorded_atÚviews)
ru   rv   r�   ÚdurationÚ	thumbnailÚuploaderÚuploader_idÚ	timestampÚ
view_countÚis_live)r   r   r   )r   r€   r‰   rš   r!   r!   r"   rm   µ   s     
zTwitchItemBaseIE._extract_infoc             C   s   | j | j|ƒƒS )N)rˆ   Ú	_match_id)r   r1   r!   r!   r"   Ú_real_extractÊ   s    zTwitchItemBaseIE._real_extractN)rf   rg   rh   rp   rˆ   rm   rœ   r!   r!   r!   r"   rl   ’   s   rl   c               @   s6   e Zd ZdZdej ZdZdZddddœd	d
dœZ	dS )ÚTwitchVideoIEztwitch:videoz%s/[^/]+/b/(?P<id>\d+)ÚvideoÚaz*http://www.twitch.tv/riotgames/b/577357806Z
a577357806z0Worlds Semifinals - Star Horn Royal Club vs. OMG)ru   rv   é   zHTTP Error 404: Not Found)r1   Ú	info_dictÚplaylist_mincountÚskipN)
rf   rg   rh   r   r   ri   Ú
_VALID_URLrn   rw   Ú_TESTr!   r!   r!   r"   r�   Î   s   
r�   c               @   s@   e Zd ZdZdej ZdZdZddddœd	d
dœdddœgZ	dS )ÚTwitchChapterIEztwitch:chapterz%s/[^/]+/c/(?P<id>\d+)ÚchapterÚcz-http://www.twitch.tv/acracingleague/c/5285812Zc5285812z,ACRL Off Season - Sports Cars @ Nordschleife)ru   rv   é   zHTTP Error 404: Not Found)r1   r¡   r¢   r£   z,http://www.twitch.tv/tsm_theoddone/c/2349361T)r1   Úonly_matchingN)
rf   rg   rh   r   r   ri   r¤   rn   rw   Ú_TESTSr!   r!   r!   r"   r¦   ß   s   
r¦   c               @   sœ   e Zd ZdZdZdZdZddddd	d
ddddeddœddidœddddd	dddddedœ
ddiddœddd œd!dd œd"dd œd#dd œd$dd œgZd%d&„ Z	d'S )(ÚTwitchVodIEz
twitch:voda(  (?x)
                    https?://
                        (?:
                            (?:(?:www|go|m)\.)?twitch\.tv/(?:[^/]+/v(?:ideo)?|videos)/|
                            player\.twitch\.tv/\?.*?\bvideo=v?
                        )
                        (?P<id>\d+)
                    ÚvodÚvz0http://www.twitch.tv/riotgames/v/6528877?t=5m10sZv6528877Úmp4zLCK Summer Split - Week 6 Day 1zre:^https?://.*\.jpg$i8C  i=_ŠUZ20150624z
Riot GamesZ	riotgamesi6  )ru   Úextrv   r•   r”   r˜   Úupload_dater–   r—   r™   Ú
start_timeÚskip_downloadT)r1   r¡   Úparamsz(http://www.twitch.tv/belkao_o/v/11230755Z	v11230755zUntitled Broadcastif  i”ÊÐUÚ20150816ZBelkAO_oZbelkao_o)
ru   r°   rv   r•   r”   r˜   r±   r–   r—   r™   zHTTP Error 404: Not Found)r1   r¡   r´   r£   z/http://player.twitch.tv/?t=5m10s&video=v6528877)r1   rª   z$https://www.twitch.tv/videos/6528877z+https://m.twitch.tv/beagsandjam/v/247478721z2https://www.twitch.tv/northernlion/video/291940395z)https://player.twitch.tv/?video=480452374c             C   sà   | j |ƒ}| j| j|ƒ}| jd| |d| j ƒ}| jd| j|tddddd|d |d dœƒf |d	d
d�}| j|ƒ ||d< t	|ƒ}t
|jƒ}d|krªt|d d ƒ|d< |jdƒd k	rÜdtd| d| jiƒddœgi|d< |S )Nzapi/vods/%s/access_tokenzDownloading %s access tokenz%s/vod/%s.m3u8?%srP   Ú	twitchwebÚtokenÚsig)Úallow_sourceÚallow_audio_onlyÚallow_spectreÚplayerÚplaylist_include_framerateZnauthZnauthsigr¯   Úm3u8_native)Úentry_protocolrc   Útr   r²   r˜   Zrechatz+https://api.twitch.tv/v5/videos/%s/commentsrO   rA   )r1   r°   Ú	subtitles)r›   rp   rw   r-   rn   Ú_extract_m3u8_formatsrj   r	   re   r
   r   Úqueryr   r   r   r&   )r   r1   r*   r€   Úaccess_tokenrc   Ú
parsed_urlrÃ   r!   r!   r"   rœ   8  s<    



zTwitchVodIE._real_extractN)
rf   rg   rh   r   r¤   rn   rw   r}   r«   rœ   r!   r!   r!   r"   r¬   ó   sR   

r¬   c               @   s4   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚTwitchPlaylistBaseIEz-kraken/channels/%s/videos/?offset=%d&limit=%déd   c                s  ˆ j d| |dƒ}|jdƒp$|jdƒ}g }d}ˆ j}d}d }x°tjdƒD ]¢}	ˆ j ˆ j|||f |dˆ j|pl|	f ƒ}
ˆ j|
ƒ}|s„P t|
jd	ƒƒ}| rÂ|rÂt	|ƒ|krÂˆ j
d
|ƒ d}|}d}qH|j|ƒ |sà|rât	|ƒ|krâP ||7 }qHW ˆ j‡ fdd„t|ƒD ƒ||ƒS )Nzkraken/channels/%szDownloading channel info JSONr‘   r’   r   Fr   zDownloading %s JSON page %sZ_totalzITwitch pagination is broken on twitch side, requesting all videos at onceTz(all at once)c                s   g | ]}ˆ j |ƒ‘qS r!   )Ú_make_url_result)rZ   r‡   )r   r!   r"   ú
<listcomp>Ž  s    z:TwitchPlaylistBaseIE._extract_playlist.<locals>.<listcomp>)r-   r   Ú_PAGE_LIMITÚ	itertoolsÚcountÚ_PLAYLIST_PATHÚ_PLAYLIST_TYPEÚ_extract_playlist_pager   ÚlenÚreport_warningÚextendr   r   )r   Ú
channel_idr€   Úchannel_namer�   ÚoffsetÚlimitZbroken_paging_detectedZcounter_overrideÚcounterr    Úpage_entriesÚtotalr!   )r   r"   Ú_extract_playlisth  sD    

z&TwitchPlaylistBaseIE._extract_playlistc             C   sB   y"dt j|ƒ }| j|t jƒ |d�S  tk
r<   | j|ƒS X d S )Nzv%s)Úvideo_id)r¬   r›   Ú
url_resultÚie_keyÚAssertionError)r   r1   rÛ   r!   r!   r"   rÈ   ‘  s
    z%TwitchPlaylistBaseIE._make_url_resultc             C   s    |j dƒ}|rdd„ |D ƒS g S )NÚvideosc             S   s   g | ]}|d  ‘qS )r1   r!   )rZ   rž   r!   r!   r"   rÉ   š  s    z?TwitchPlaylistBaseIE._extract_playlist_page.<locals>.<listcomp>)r   )r   r    rß   r!   r!   r"   rÏ   ˜  s    
z+TwitchPlaylistBaseIE._extract_playlist_pagec             C   s   | j | j|ƒƒS )N)rÚ   r›   )r   r1   r!   r!   r"   rœ   œ  s    z"TwitchPlaylistBaseIE._real_extractN)	rf   rg   rh   rÍ   rÊ   rÚ   rÈ   rÏ   rœ   r!   r!   r!   r"   rÆ   d  s   )rÆ   c               @   s:   e Zd ZdZdej ZdZddddœdd	œd
ddœgZdS )ÚTwitchProfileIEztwitch:profilez$%s/(?P<id>[^/]+)/profile/?(?:\#.*)?$Úprofilez&http://www.twitch.tv/vanillatv/profileZ	vanillatvZ	VanillaTV)ru   rv   iœ  )r1   r¡   r¢   z$http://m.twitch.tv/vanillatv/profileT)r1   rª   N)	rf   rg   rh   r   r   ri   r¤   rÎ   r«   r!   r!   r!   r"   rà      s   
rà   c               @   s    e Zd Zdej Zejd ZdS )ÚTwitchVideosBaseIEz%s/(?P<id>[^/]+)/videosz&broadcast_type=N)rf   rg   rh   r   ri   Ú_VALID_URL_VIDEOS_BASErÆ   rÍ   r!   r!   r!   r"   râ   ²  s   
râ   c               @   sD   e Zd ZdZdej Zejd ZdZddddœd	d
œdddœgZ	dS )ÚTwitchAllVideosIEztwitch:videos:allz%s/allzarchive,upload,highlightz
all videosz)https://www.twitch.tv/spamfish/videos/allÚspamfishÚSpamfish)ru   rv   ie  )r1   r¡   r¢   z'https://m.twitch.tv/spamfish/videos/allT)r1   rª   N)
rf   rg   rh   r   râ   rã   r¤   rÍ   rÎ   r«   r!   r!   r!   r"   rä   ·  s   

rä   c               @   sD   e Zd ZdZdej Zejd ZdZddddœd	d
œdddœgZ	dS )ÚTwitchUploadsIEztwitch:videos:uploadsz
%s/uploadsZuploadÚuploadsz-https://www.twitch.tv/spamfish/videos/uploadsrå   ræ   )ru   rv   r   )r1   r¡   r¢   z+https://m.twitch.tv/spamfish/videos/uploadsT)r1   rª   N)
rf   rg   rh   r   râ   rã   r¤   rÍ   rÎ   r«   r!   r!   r!   r"   rç   Ê  s   

rç   c               @   sD   e Zd ZdZdej Zejd ZdZddddœd	d
œdddœgZ	dS )ÚTwitchPastBroadcastsIEztwitch:videos:past-broadcastsz%s/past-broadcastsÚarchivezpast broadcastsz5https://www.twitch.tv/spamfish/videos/past-broadcastsrå   ræ   )ru   rv   r   )r1   r¡   r¢   z3https://m.twitch.tv/spamfish/videos/past-broadcastsT)r1   rª   N)
rf   rg   rh   r   râ   rã   r¤   rÍ   rÎ   r«   r!   r!   r!   r"   ré   Ý  s   

ré   c               @   sD   e Zd ZdZdej Zejd ZdZddddœd	d
œdddœgZ	dS )ÚTwitchHighlightsIEztwitch:videos:highlightsz%s/highlightsZ	highlightZ
highlightsz0https://www.twitch.tv/spamfish/videos/highlightsrå   ræ   )ru   rv   i%  )r1   r¡   r¢   z.https://m.twitch.tv/spamfish/videos/highlightsT)r1   rª   N)
rf   rg   rh   r   râ   rã   r¤   rÍ   rÎ   r«   r!   r!   r!   r"   rë   ð  s   

rë   c                   sz   e Zd ZdZdZddddddd	d
dddedœdd	idœdd	dœdd	dœdd	dœdd	dœgZe‡ fdd„ƒZdd„ Z	‡  Z
S )ÚTwitchStreamIEztwitch:streama  (?x)
                    https?://
                        (?:
                            (?:(?:www|go|m)\.)?twitch\.tv/|
                            player\.twitch\.tv/\?.*?\bchannel=
                        )
                        (?P<id>[^/#?]+)
                    zhttp://www.twitch.tv/shroomztvZ12772022048Z	shroomztvr¯   z;re:^ShroomzTV [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$zGH1Z1 - lonewolfing with ShroomzTV | A3 Battle Royale later - @ShroomzTVTieæÀTZ20150122Z	ShroomzTV)ru   Ú
display_idr°   rv   r�   rš   r˜   r±   r–   r—   r™   r³   )r1   r¡   r´   z+http://www.twitch.tv/miracle_doto#profile-0)r1   rª   z)https://player.twitch.tv/?channel=lotsofszhttps://go.twitch.tv/foodzhttps://m.twitch.tv/foodc                s<   t ‡ fdd„ttttttttt	f	D ƒƒr,dS t
t| ƒjˆ ƒS )Nc             3   s   | ]}|j ˆ ƒV  qd S )N)Úsuitable)rZ   Úie)r1   r!   r"   r\   2  s    z*TwitchStreamIE.suitable.<locals>.<genexpr>F)Úanyr�   r¦   r¬   rà   rä   rç   ré   rë   ÚTwitchClipsIEÚsuperrì   rî   )Úclsr1   )Ú	__class__)r1   r"   rî   /  s    zTwitchStreamIE.suitablec             C   s’  | j |ƒ}| jd|jƒ  |dƒjdƒ}|s:td| dd�‚|jdi ƒjdƒpR|jƒ }| jd	| |d
ƒ}dddtjddƒddd|d jdƒ|d jdƒdœ	}| jd| j	|t
|ƒf |dƒ}| j|ƒ |jdƒ}t|jdƒƒ}|d }	| j|	jdƒpø|	jdƒƒ}
|	jdƒ}g }xV|d jƒ D ]F\}}tjd|ƒ}|�s6�q|j|t|jdƒƒt|jdƒƒdœƒ �qW t|d ƒ||
|||	jdƒ|	jdƒ|||dd œS )!Nz!kraken/streams/%s?stream_type=allzDownloading stream JSONÚstreamz%s is offlineT)r   r�   r’   zapi/channels/%s/access_tokenz Downloading channel access tokenrP   i@B i€–˜ r¶   Ú4r¸   zutf-8r·   )	r¹   rº   r»   Úpr¼   r½   Zsegment_preferencer¸   r·   z%s/api/channel/hls/%s.m3u8?%sr¯   ZviewersÚ
created_atr‘   r‰   r�   z$(?P<width>\d+)x(?P<height>\d+)\.jpg$Úwidthrt   )r1   rù   rt   rŒ   )ru   rí   rv   r�   Ú
thumbnailsr–   r—   r˜   r™   rc   rš   )r›   r-   Úlowerr   r   ÚrandomÚrandintrC   rÂ   rj   r	   re   r   Ú_live_titleÚitemsrS   rT   r~   r}   r3   r   )r   r1   rÓ   rõ   rÄ   rÃ   rc   r™   r˜   r�   rv   r�   rú   Úthumbnail_keyÚthumbnail_urlr†   r!   r!   r"   rœ   >  sb    






zTwitchStreamIE._real_extract)rf   rg   rh   r   r¤   r}   r«   Úclassmethodrî   rœ   Ú__classcell__r!   r!   )rô   r"   rì     s2   

rì   c               @   sV   e Zd ZdZdZddddddd	d
ddddœ	dœdddœdddœdddœgZdd„ ZdS )rñ   ztwitch:clipszqhttps?://(?:clips\.twitch\.tv/(?:embed\?.*?\bclip=|(?:[^/]+/)*)|(?:www\.)?twitch\.tv/[^/]+/clip/)(?P<id>[^/?#&]+)z0https://clips.twitch.tv/FaintLightGullWholeWheatZ 761769e1eafce0ffebfb4089cb3847cdZ42850523r¯   z'EA Play 2016 Live from the Novo Theatrezre:^https?://.*\.jpgiáÕ]WZ20160612ZEAZstereotype_Z43566419)	ru   r°   rv   r•   r˜   r±   Úcreatorr–   r—   )r1   Úmd5r¡   z;https://clips.twitch.tv/rflegendary/UninterestedBeeDAESuppyT)r1   rª   zDhttps://www.twitch.tv/sergeynixon/clip/StormyThankfulSproutFutureManzEhttps://clips.twitch.tv/embed?clip=InquisitiveBreakableYogurtJebaitedc             C   sž  | j |ƒ}| jd|tjdd| iƒjƒ d| jid�d d }|sLtdd	d
�‚g }xb|jdg ƒD ]R}t|t	ƒsnq^t
|jdƒƒ}|s‚q^|j||jdƒt|jdƒƒt|jdƒƒdœƒ q^W | j|ƒ g }xfd"D ]^}|j|ƒ}	|	sÜqÈ||	dœ}
tjd|	ƒ}|�r|
jt|jdƒƒt|jdƒƒdœƒ |j|
ƒ qÈW |jdƒ�p8||jdƒ�pF||t|jdƒƒt|jdƒƒt|jdƒƒ|t|dd„ tƒt|dd„ tƒt|d d„ tƒd!œ
S )#Nzhttps://gql.twitch.tv/gqlrÃ   a�  {
  clip(slug: "%s") {
    broadcaster {
      displayName
    }
    createdAt
    curator {
      displayName
      id
    }
    durationSeconds
    id
    tiny: thumbnailURL(width: 86, height: 45)
    small: thumbnailURL(width: 260, height: 147)
    medium: thumbnailURL(width: 480, height: 272)
    title
    videoQualities {
      frameRate
      quality
      sourceURL
    }
    viewCount
  }
}z	Client-ID)r6   r$   r6   Úclipz This clip is no longer availableT)r   ZvideoQualitiesÚ	sourceURLr^   Ú	frameRate)r1   rX   rt   ÚfpsÚtinyÚsmallÚmedium)ru   r1   z-(\d+)x(\d+)\.r   r   )rt   rù   ru   rv   ZdurationSecondsÚ	viewCountÚ	createdAtc             S   s   | d d S )NZbroadcasterÚdisplayNamer!   )Úxr!   r!   r"   Ú<lambda>ï  s    z-TwitchClipsIE._real_extract.<locals>.<lambda>c             S   s   | d d S )NÚcuratorr  r!   )r  r!   r!   r"   r  ð  s    c             S   s   | d d S )Nr  ru   r!   )r  r!   r!   r"   r  ñ  s    )
ru   rv   rc   r”   r“   r˜   rú   r  r–   r—   )r
  r  r  )r›   r'   rA   rB   rC   r&   r   r   r   r   r   r~   r   rb   rS   rT   r=   r}   r3   r   r   r   )r   r1   rÛ   r  rc   Úoptionrd   rú   Úthumbnail_idr  ÚthumbÚmobjr!   r!   r"   rœ   ¢  s\    






zTwitchClipsIE._real_extractN)rf   rg   rh   r   r¤   r«   rœ   r!   r!   r!   r"   rñ   „  s(   

rñ   )(Ú
__future__r   rË   rS   rü   rA   Úcommonr   Úcompatr   r   r   r	   r
   Úutilsr   r   r   r   r   r   r   r   r   r   r   r   rl   r�   r¦   r¬   rÆ   rà   râ   rä   rç   ré   rë   rì   rñ   r!   r!   r!   r"   Ú<module>   s,   4r<q< 