o
    i>                     @   sX  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 ddl	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mZmZmZmZmZmZmZmZ ddlm Z m!Z! G dd	 d	eZ"G d
d de"Z#dd 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 )    N   )InfoExtractor   )	HTTPError)ExtractorErrorUserNotLivebase_url
clean_htmldict_getfloat_or_noneint_or_nonejoin_nonemptymake_archive_idparse_durationparse_iso8601parse_qs	qualitiesstr_or_nonetry_getunified_timestampupdate_url_queryurl_or_noneurljoin)traverse_objvaluec                   @   s   e Zd ZdZdZdZdZdZdZddd	d
ddddddddZ	e
dd Zdd Zdd Zd&ddZd&ddZdd Zd d! Zd'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/logintwitch@016e1e4ccee0eb4698eb3bf1a04dc1c077fb746c78c82bac9a8f0289658fbd1a@67004f7881e65c297936f32c75246470629557a393788fb5a69d6d9a25a8fd5f@90c33f5e6465122fba8f9371e2a97076f9ed06c6fed3788d002ab9eba8f91d88@1844261bb449fa51e6167040311da4a7a5f1c34fe71c71a3e0c4f551bc30c698@5247910a19b1cd2b760939bf4cba4dcbd3d13bdf8c266decd16956f6ef814077@b57f9b910f8cd1a4659d894fe7550ccc81ec9052c01e438b290fd66a040b9b93@e1edae8122517d013405f237ffcc124515dc6ded82480a88daef69c83b53ac01@9515480dee68a77e667cb19de634739d33f243572b007e98e67184b1a5d8369f@45111672eea2e507f8ba44d101a61862f9c56b11dee09a15634cb75cb9b9084d@71835d5ef425e154bf282453a926d99b328cdc5e32f36d3a209d0f4778b41203@07e99e4d56c5a7c67117a154777b0baf85a5ffefa393b213f4bc712ccaf85dd6)CollectionSideBarFilterableVideoTower_VideosClipsCards__UserShareClipRenderStatusChannelCollectionsContentStreamMetadataComscoreStreamingQueryVideoPreviewOverlayVideoMetadata$VideoPlayer_ChapterSelectButtonVideo"VideoPlayer_VODSeekbarPreviewVideoc                 C   s   | j ddgdddd S )N	client_idue6666qo983tsx6so1t0vnawi233waTwitchT)ie_key	casesenser   )_configuration_arg)self r:   K/home/ubuntu/.local/lib/python3.10/site-packages/yt_dlp/extractor/twitch.py
_CLIENT_ID9   s
   
zTwitchBaseIE._CLIENT_IDc                    s   dd   fdd} jd d\}}d|v r t| |||d||jd\}}|s1d S td	|d urJd
}|||d|dd d S d S )Nc                 S   s   t d|  dd)NzUnable to login. Twitch said: Texpected)r   )messager:   r:   r;   fail?   s   
z)TwitchBaseIE._perform_login.<locals>.failc                    s    | }|| |j}jd| djdd}t||}|ddd}j|d |t|	 |dd	}t
|d
}	|	r> |	 d|ddv rHdS t||dpR|d }
j|
d d|dS )Nz&<form[^>]+action=(["\'])(?P<url>.+?)\1zpost urlurl)defaultgroupzhttps://www.twitch.tvtext/plain;charset=UTF-8)RefererOriginContent-Typei  )dataheadersexpected_status)errorerror_description
error_codezAuthenticated successfullyr?    )NNredirectredirect_pathzDownloading login redirect page)rI   )_hidden_inputsupdaterA   _search_regex_LOGIN_POST_URLr   _download_jsonjsondumpsencoder
   get_download_webpage_handle)pageurlhnoterH   formpage_urlpost_urlrI   responserK   redirect_urlr@   r9   r:   r;   
login_stepC   s:   



z/TwitchBaseIE._perform_login.<locals>.login_stepzDownloading login pageblacklist_messagez
Logging in)usernamepasswordr3   z$(?i)<form[^>]+id="two-factor-submit"ztwo-factor authentication tokenzSubmitting TFA tokentrue)authy_tokenremember_2fa)rZ   _LOGIN_FORM_URLr	   r<   research_get_tfa_info)r9   rf   rg   rd   
login_pagehandleredirect_page	tfa_tokenr:   rc   r;   _perform_login>   s.   !
zTwitchBaseIE._perform_loginc              	   C   s\   zt dd |D }d|d< W d S  ty-   |D ]}d|d v r)|ddd qY d S w )	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/rA   ru   )rz   format_note)nextStopIterationrR   )r9   formatssourcerw   r:   r:   r;   _prefer_source~   s   zTwitchBaseIE._prefer_sourceTc                 C   sN   d| j d}| dd}|rd|j |d< | jd||t| ||dS )	NrD   )rG   z	Client-IDhttps://gql.twitch.tv
auth-tokenzOAuth Authorizationzhttps://gql.twitch.tv/gql)rH   rI   fatal)r<   _get_cookiesrY   r   rU   rV   rW   rX   )r9   video_idopsr]   r   rI   gql_authr:   r:   r;   _download_base_gql   s   zTwitchBaseIE._download_base_gqlc                 C   s4   |D ]}dd| j |d  di|d< q| |||S )NpersistedQueryr   operationName)version
sha256Hash
extensions)_OPERATION_HASHESr   )r9   r   r   r]   r   opr:   r:   r;   _download_gql   s   
zTwitchBaseIE._download_gqlc                 C   s:   | d}dd|||f i}|  ||d| dd | S )NPlaybackAccessTokenquerya?  {
              %s(
                %s: "%s",
                params: {
                  platform: "web",
                  playerBackend: "mediaplayer",
                  playerType: "site"
                }
              )
              {
                value
                signature
              }
            }Downloading z access token GraphQLrH   )r   )r9   r   
token_kind
param_namemethodr   r:   r:   r;   _download_access_token   s   

z#TwitchBaseIE._download_access_tokenc                 C   s$   |rt dd|ddd|igS d S )Nz\d+x\d+(\.\w+)($|(?=[?#]))z0x0\g<1>r   rA   
preferencerA   )rl   sub)r9   	thumbnailr:   r:   r;   _get_thumbnails   s   zTwitchBaseIE._get_thumbnailsFc                 C   s|  z$| j | j d| d| d|ddddtddddd	d||d

d}W nf ty } zZt|jtrA|jjdksA|jj	
ddkrB t|jj	 tjhdthfpRi }|ddv rud}	| ddrmtd|	 dd| d|	  tdd|dd }
rt|
dd d }~ww |D ].}|dr|d dr|di dd dgi |r|di d!d"d#gi d|d$< q|S )%N/z.m3u8mp4rh   i@B i web	twitchwebzav1,h265,h264)
allow_sourceallow_audio_onlyallow_spectrepplatformplayersupported_codecsplaylist_include_frameratesigtokenr   i  zcontent-typezapplication/jsonr   rM   )vod_manifest_restrictedunauthorized_entitlementsz&access to this subscriber-only contentr   r   zYour account does not have Tr=   z,You must be logged into an account that has rK   z: )	from_dictdelimvcodecav01downloader_optionsffmpeg_args_outz-fffmpeg_argsz-live_start_index0is_from_start)_extract_m3u8_formats_USHER_BASErandomrandintr   
isinstancecauser   statusra   
get_headerr   readrV   loadsdictrY   r   raise_login_requiredr   
startswith
setdefaultrR   )r9   pathr   r   	signaturelive_from_startr~   e
error_info
common_msg	error_msgfmtr:   r:   r;   _extract_twitch_m3u8_formats   sP   


"z)TwitchBaseIE._extract_twitch_m3u8_formatsN)T)F)__name__
__module____qualname___VALID_URL_BASE	_API_BASEr   rk   rT   _NETRC_MACHINEr   propertyr<   rs   r   r   r   r   r   r   r:   r:   r:   r;   r   "   s8    
@


r   c                   @   s  e Zd ZdZdZddddddd	d
ddedddddg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"d'd(ddd)ddd*d+dd,ddd,d-d.dd-d)d/dgdded0ddidd1d'd(d2d3dd)ddd*d+dd,ddd,d-d.dd-d)d/dgddeeed4d3dd5d6d7d8d9dd:d;ddd<d=dd;ddgdded0ddid>gd?d@dd"gZdAdB ZdCdD ZdEdF Z	dGdH Z
dIdJ ZdKdL ZdMS )NTwitchVodIEz
twitch:vodal  (?x)
                    https?://
                        (?:
                            (?:(?:www|go|m)\.)?twitch\.tv/(?:[^/]+/v(?:ideo)?|videos)/|
                            player\.twitch\.tv/\?.*?\bvideo=v?|
                            www\.twitch\.tv/[^/]+/schedule\?vodID=
                        )
                        (?P<id>\d+)
                    z0http://www.twitch.tv/riotgames/v/6528877?t=5m10sv6528877r   zLCK Summer Split - Week 6 Day 1zre:^https?://.*\.jpg$i8C  iV_U20150624z
Riot Games	riotgamesi6  r   zLeague of Legends
start_timeend_timetitlewas_live)idextr   r   duration	timestampupload_dateuploaderuploader_id
view_countr   chapterslive_statusskip_downloadTrA   	info_dictparamsz(http://www.twitch.tv/belkao_o/v/11230755	v11230755Untitled Broadcastif  iU20150816BelkAO_obelkao_o)
r   r   r   r   r   r   r   r   r   r   zHTTP Error 404: Not FoundrA   r   r   skipz/http://player.twitch.tv/?t=5m10s&video=v6528877rA   only_matchingz$https://www.twitch.tv/videos/6528877z+https://m.twitch.tv/beagsandjam/v/247478721z2https://www.twitch.tv/northernlion/video/291940395z)https://player.twitch.tv/?video=480452374z&https://www.twitch.tv/videos/635475444
v635475444i{-  i;^20200529i=  iR  zLegends of RuneterraArt)r   r   r   r   r   r   r   r   r   r   r   r   Storyboardssb0mhtml)r   rt   r   r   r   r   r   r   r   r   r   r   r   columnsrows)formatr   )r]   rA   r   r   zVOD with single chapterz'https://www.twitch.tv/videos/1536751224v1536751224z8Porter Robinson Star Guardian Stream Tour with LilyPichui   iS(b20220719z;Unable to download JSON metadata: HTTP Error 403: Forbidden)r]   rA   r   r   expected_warningsz8https://www.twitch.tv/tangotek/schedule?vodID=1822395420c              	   C   s   |  |dd|dddd|dddd|ddgd	}t|d
dd}|d u r1td| dddt|d|d< t|ddddthfdd|d< |S )Nr0   rN   )channelLoginvideoIDr   	variablesr1   F)includePrivater  r2   z#Downloading stream metadata GraphQL).rH   video)get_allzVideo  does not existTr=   ).rH   r  momentsedges.noder
  .rH   r  seekPreviewsURL
storyboard)r   r   r   r   )r9   item_idrH   r  r:   r:   r;   _download_info  s8   
zTwitchVodIE._download_infoc           
      C   s   | d}|dkrd}n	|dkrd}nd }d}t|}g }| d}t|trF| D ]\}}	t|	}	|	s6q+||vr;q+||	||d q+|d	 | d
pOd| dt| d|| di  d| di  dt| dt| d|ddS )Nr   	recordingTrecordedF)smallmediumlargepreviewr   _idr   r   descriptionlengthchanneldisplay_namenamerecorded_atviews)r   r   r  r   
thumbnailsr   r   r   r   is_liver   )	rY   r   r   r   itemsr   appendr   r   )
r9   infor   r   
_QUALITIESquality_keyr  r  thumbnail_idthumbnail_urlr:   r:   r;   _extract_info  sB   



zTwitchVodIE._extract_infoc                 c   s    | dst|d}|rd|iV  d S |d D ]4}t| dd}t| dd}t| d}|d u s9|d u rC| d| | q||| |d	V  qd S )
Nr
  )gamedisplayNamer   positionMillisecondsi  durationMillisecondsr  z2Important chapter information missing for chapter r   )rY   r   r   r   report_warning)r9   r#  r  r)  momentr   r   r  r:   r:   r;   _extract_chapters  s$   



zTwitchVodIE._extract_chaptersc                 C   s   | dp|}|d dkrd| }t| d}d }|r/td|r-| ddk}d }nd}|| d	p6d
| dt| d| |t|dd tt|dd tt| dt| dt	| 
|||ddS )Nr   r   vpreviewThumbnailURLz/404_processing_[^.?#]+\.pngbroadcastTypeARCHIVEFr   r   r  lengthSecondsc                 S      | d d S )Nownerr*  r:   xr:   r:   r;   <lambda>      z/TwitchVodIE._extract_info_gql.<locals>.<lambda>c                 S   r5  )Nr6  loginr:   r7  r:   r:   r;   r9    r:  publishedAt	viewCountT)r   r   r  r   r  r   r   r   r   r   r   r   )rY   r   rl   findallr   r   r   strr   listr/  )r9   r#  r  vod_idr   r   r:   r:   r;   _extract_info_gql  s.   
zTwitchVodIE._extract_info_gqlc           	      #   s    |r|sd S | j ||dddpg }|jdd dd t| t|D ]R\}}t|d}|d	}|r7|s8q#|t| d
| dddddt |d t|dt|d|| t|dt|d fdd|D dV  q#d S )Nz$Downloading storyboard metadata JSONFr   c                 S   s   t | dpdS )Nwidthr   )r   rY   r7  r:   r:   r;   r9  !  s    z1TwitchVodIE._extract_storyboard.<locals>.<lambda>T)keyreversecountimagessbr  r   noner   rD  heightr   colsc                    s   g | ]
}t  |d qS ))rA   r   )r   )rv   r   basefragment_durationr:   r;   
<listcomp>6  s
    
z3TwitchVodIE._extract_storyboard.<locals>.<listcomp>)rt   r{   r   protocolacodecr   rA   rD  rK  fpsr   r   	fragments)rU   sortr   	enumerater   rY   lenr   )	r9   r  storyboard_json_urlr   specisrG  rH  r:   rM  r;   _extract_storyboard  s:   

zTwitchVodIE._extract_storyboardc           	   	   C   s   |  |}| |}| ||}| |dd}| jd||d |d | dd}|| ||d|d	 | 	| ||d
< t
j|}t
j|j}d|v r\t|d d |d< |dd urwdtd| dd| jiddgi|d< |S )Nr  r   vodr   r   r   )r   r  r   r~   tr   r   r   rechatz https://api.twitch.tv/v5/videos/z	/commentsr3   rV   )rA   r   	subtitles)	_match_idr  rB  r   r   	get_paramextendr\  rY   r   urllibparseurlparser   r   r   r   r<   )	r9   rA   rA  r  r#  access_tokenr~   
parsed_urlr   r:   r:   r;   _real_extract<  s4   

 


zTwitchVodIE._real_extractN)r   r   r   IE_NAME
_VALID_URLint_TESTSr  r(  r/  rB  r\  ri  r:   r:   r:   r;   r      s4   $")  *!%!r   c                 C   sd   t | tsJ | d}|sd S dt d| d| | d| dt| dt| dd	S )
Nr   url_transparentr0  https://www.twitch.tv/videos/r   r1  r4  r=  )_typer6   r   rA   r   r   r   r   )r   r   rY   r   r6   r   r   r  r   r:   r:   r;   _make_video_result^  s   
rr  c                   @   s4   e Zd ZdZdZddddddgZd	Zd
d ZdS )TwitchCollectionIEztwitch:collectionz@https?://(?:(?:www|go|m)\.)?twitch\.tv/collections/(?P<id>[^/]+)z0https://www.twitch.tv/collections/o9zZer3IQBhTJwo9zZer3IQBhTJwzPlaythrough Archivesr   r      rA   r   playlist_mincountr(   c           	      C   s   |  |}| || jd|idgdd d d }|d}g }|d d	 D ]}t|ts.q&|d
}t|ts9q&t|}|rD|| q&| j|||dS )NcollectionIDr  zDownloading collection GraphQLr   rH   
collectionr   r!  r  r  playlist_idplaylist_title)	ra  r   _OPERATION_NAMErY   r   r   rr  r"  playlist_result)	r9   rA   collection_idrz  r   entriesedger  r  r:   r:   r;   ri  }  s:   





z TwitchCollectionIE._real_extractN)r   r   r   rj  rk  rm  r~  ri  r:   r:   r:   r;   rs  o  s    	rs  c                   @   s   e Zd ZdZdd ZdS )TwitchPlaylistBaseIEd   c                 '   sX   d}| j |g|R  }| j d tdD ]}| }| j|d< |r(||d< | j|| j|dgd| j d| d	d
}t	|ddddt
hfdkrTtd| ddd|sY dS t| fddt}|sh dS |D ]4}	t|	tsrqj|	d| jkr{qj|	d}
t|
tsqj|
d| jkrqj| |
}|r|	d}|V  qj|rt|t
s dS qdS )z
        Subclasses must define _make_variables() and _extract_entry(),
        as well as set _OPERATION_NAME, _ENTRY_KIND, _EDGE_KIND, and _NODE_KIND
        Nr[  r   limitcursorr  r   zs GraphQL page FrC  r   rH   userr   rN   z	Channel "z" not foundTr=   c                    s   | d d d   d S )Nr   rH   r  r  r:   r7  entries_keyr:   r;   r9        z/TwitchPlaylistBaseIE._entries.<locals>.<lambda>
__typenamer  )_make_variables_ENTRY_KIND	itertoolsrG  copy_PAGE_LIMITr   r~  
_NODE_KINDr   r?  r   r   r@  r   r   rY   
_EDGE_KIND_extract_entry)r9   channel_nameargsr  variables_commonpage_numr  r[   r  r  r  entryr:   r  r;   _entries  sZ   
	




zTwitchPlaylistBaseIE._entriesN)r   r   r   r  r  r:   r:   r:   r;   r    s    r  c                   @   s(   e Zd ZdZdZdZdZedd ZdS )TwitchVideosBaseIEr)   r  	VideoEdgeVideoc                 C   s   | ||  dS )N)channelOwnerLoginr2  	videoSort)upper)r  broadcast_typerU  r:   r:   r;   r    s   z"TwitchVideosBaseIE._make_variablesN)	r   r   r   r~  r  r  r  staticmethodr  r:   r:   r:   r;   r    s    r  c                       s  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dddddddddddddddddddddddg	ZedddgZed d!Z	ed"d#ed$d%ed&d'ed(d)e	d*Z
d+Zed,d-Ze fd.d/Zed0d1 Zd2d3 Z  ZS )4TwitchVideosIEztwitch:videoszGhttps?://(?:(?:www|go|m)\.)?twitch\.tv/(?P<id>[^/]+)/(?:videos|profile)z0https://www.twitch.tv/spamfish/videos?filter=allspamfishz$spamfish - All Videos sorted by Dateru  i  rw  z;https://www.twitch.tv/spamfish/videos?filter=all&sort=viewsz'spamfish - All Videos sorted by Populari  z5https://www.twitch.tv/spamfish/videos?filter=archivesz)spamfish - Past Broadcasts sorted by Date   z7https://www.twitch.tv/spamfish/videos?filter=highlightsz$spamfish - Highlights sorted by Datez>https://www.twitch.tv/esl_csgo/videos?filter=uploads&sort=timeesl_csgoz!esl_csgo - Uploads sorted by Date   z;https://www.twitch.tv/spamfish/videos?filter=past_premieresz(spamfish - Past Premieres sorted by Dater   z)https://www.twitch.tv/spamfish/videos/allTr   z'https://m.twitch.tv/spamfish/videos/allz%https://www.twitch.tv/spamfish/videos	BroadcasttypelabelNz
All Videosr3  zPast Broadcasts	HIGHLIGHT
HighlightsUPLOADUploadsPAST_PREMIEREzPast Premieres)archives
highlightsuploadspast_premieresallDatePopular)timer  c                    s*   t  fddttfD rdS t  S )Nc                 3       | ]}|  V  qd S Nsuitablerv   ierA   r:   r;   rx   +      z*TwitchVideosIE.suitable.<locals>.<genexpr>F)anyTwitchVideosClipsIETwitchVideosCollectionsIEsuperr  clsrA   	__class__r  r;   r  (  s   
zTwitchVideosIE.suitablec                 C   s   t | S r  )rr  )r  r:   r:   r;   r  0  s   zTwitchVideosIE._extract_entryc                 C   s   |  |}t|}|ddgd }|ddgd }| j|| j}| j| ||j||| d|j d| j	|| j
 dS )	Nfilterr  r   rU  r  z - z sorted by r{  )ra  r   rY   _BROADCASTS_DEFAULT_BROADCASTr  r  r  r  
_SORTED_BY_DEFAULT_SORTED_BY)r9   rA   r  qsvideo_filterrU  	broadcastr:   r:   r;   ri  4  s   
zTwitchVideosIE._real_extract)r   r   r   rj  rk  rm  collections
namedtupler  r  r  r  r  classmethodr  r  r  ri  __classcell__r:   r:   r  r;   r    s    

>

r  c                   @   s   e Zd ZdZdZddddddd	d
dgZedddgZeddZ	edde	eddedddZ
dZdZdZdZdZedd Zedd Zd d! Zd"S )#r  ztwitch:videos:clipsz[https?://(?:(?:www|go|m)\.)?twitch\.tv/(?P<id>[^/]+)/(?:clips|videos/*?\?.*?\bfilter=clips)z<https://www.twitch.tv/vanillatv/clips?filter=clips&range=all	vanillatvzvanillatv - Clips Top Allru  r   rw  z=https://www.twitch.tv/dota2ruhub/videos?filter=clips&range=7dTr   Clipr  r  	LAST_WEEKzTop 7DLAST_DAYzTop 24H
LAST_MONTHzTop 30DALL_TIMEzTop All)24hr7d30dr     r*   clipClipEdgec                 C   s   | d|idS )Nr  )r;  criteriar:   )r  channel_filterr:   r:   r;   r  d  s   z#TwitchVideosClipsIE._make_variablesc                 C   sx   t | tsJ t| d}|sd S dt | d|| d| dt| dt| dt| d| d	d

S )NrA   rn  r   r   thumbnailURLdurationSeconds	createdAtr=  language)
rp  r6   r   rA   r   r   r   r   r   r  )	r   r   r   rY   TwitchClipsIEr6   r   r   r   )r  clip_urlr:   r:   r;   r  m  s   z"TwitchVideosClipsIE._extract_entryc                 C   sZ   |  |}t|}|ddgd }| j|| j}| j| ||j|| d|j dS )Nranger  r   z	 - Clips r{  )	ra  r   rY   _RANGE_DEFAULT_CLIPr  r  r  r  )r9   rA   r  r  
date_ranger  r:   r:   r;   ri    s   
z!TwitchVideosClipsIE._real_extractN)r   r   r   rj  rk  rm  r  r  r  r  r  r  r~  r  r  r  r  r  r  ri  r:   r:   r:   r;   r  B  s<    	


r  c                   @   sh   e Zd ZdZdZddddddd	d
ddddgZdZdZdZdZ	e
dd Ze
dd Zdd ZdS )r  ztwitch:videos:collectionszWhttps?://(?:(?:www|go|m)\.)?twitch\.tv/(?P<id>[^/]+)/videos/*?\?.*?\bfilter=collectionsz8https://www.twitch.tv/spamfish/videos?filter=collectionsr  zspamfish - Collectionsru     rw  z:https://www.twitch.tv/monstercat/videos?filter=collections
monstercatzmonstercat - Collections   r,   rz  CollectionsItemEdge
Collectionc                 C   s   d| iS )N
ownerLoginr:   )r  r:   r:   r;   r    s   z)TwitchVideosCollectionsIE._make_variablesc                 C   sl   t | tsJ | d}|sd S dt |d| | d| dt| dt| dt| dd		S )
Nr   rn  z"https://www.twitch.tv/collections/r   r  r4  	updatedAtr=  )	rp  r6   r   rA   r   r   r   r   r   )r   r   rY   rs  r6   r   r   r   )r  r  r:   r:   r;   r    s   
z(TwitchVideosCollectionsIE._extract_entryc                 C   s&   |  |}| j| ||| ddS )Nz - Collectionsr{  )ra  r  r  )r9   rA   r  r:   r:   r;   ri    s
   

z'TwitchVideosCollectionsIE._real_extractN)r   r   r   rj  rk  rm  r~  r  r  r  r  r  r  ri  r:   r:   r:   r;   r    s2    	

r  c                       s   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	ddddddd	dddddddd dd!id"gZd#Ze fd$d%Z	e
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/shroomztv12772022048	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 - @ShroomzTVTieT20150122	ShroomzTV)r   
display_idr   r   r  r   r   r   r   r   r   r   zUser does not existr   z+http://www.twitch.tv/miracle_doto#profile-0r   z)https://player.twitch.tv/?channel=lotsofszhttps://go.twitch.tv/foodzhttps://m.twitch.tv/foodz https://www.twitch.tv/monstercat40500071752r  zre:Monstercatz$md5:0945ad625e615bc8f0469396537d87d9ic20230222
Monstercatr   zre:https://.*.jpg)r   r  r   r  r   r   r   r   r   r   r   r   
Livestreamr   r   c                    s2   t  fddttttttfD rdS t  S )Nc                 3   r  r  r  r  r  r:   r;   rx     r  z*TwitchStreamIE.suitable.<locals>.<genexpr>F)	r  r   rs  r  r  r  r  r  r  r  r  r  r;   r    s   
zTwitchStreamIE.suitablec              	   C   sT   t | tr
| dsd S | d }dt d| d| | dt| dp'ddS )	Nr   rA   r0  ro  r   r<  r   )rp  r6   r   rA   r   r   )r   r   rY   r   r6   r   rq  r:   r:   r;   r    s   zTwitchStreamIE._extract_entryc                 C   s  |  | }| |d|dddd|dddddddd	d
|idgd}|d d d }|s9t| ddd|d }|sDt|dt|d}| drx| | d t	| 
|d dd }|rq|d|pmtdkrq|S | jd|d | |dd}|dp|}	| d||d |d }
| |
 |d}t|d d! tpi }|d"}t|d#d! t}tt|d$d! t}|p|}|d%}|d&v r|d'| d(7 }|	|||| ||||||
|d)kd*S )+Nr-   T)r  includeIsDJr  r.   rN   F)r  clipSlugisClipisLiveisVodOrCollectionvodIDr/   r;  zDownloading stream GraphQLr   rH   r  r	  r=   stream)r   r  r   z,: Extracting VOD to download live from startr  r   infz9Unable to extract the VOD associated with this livestreamchannelNamer   zapi/channel/hlsr   r   viewersc                 S   s   | d d d S )Nr   rH   r  r:   r7  r:   r:   r;   r9  W  s    z.TwitchStreamIE._real_extract.<locals>.<lambda>r*  c                 S   r5  )NbroadcastSettingsr   r:   r7  r:   r:   r;   r9  Z  r:  c                 S   s   | d d d d d S )Nr   rH   r  r  previewImageURLr:   r7  r:   r:   r;   r9  ]  r  r  )rerunlivez ()r	  )r   r  r   r  r  r   r   r   r   r~   r   )ra  lowerr   r   r   r   rY   rb  	to_screenr|   r  popfloatr-  r   r   r   r   r   r?  r   r   )r9   rA   r  gqlr  r  r   r  rg  	stream_idr~   r   sq_userr   r  r   r   stream_typer:   r:   r;   ri    s   







zTwitchStreamIE._real_extract)r   r   r   rj  rk  rl  rm  r  r  r  r  r  ri  r  r:   r:   r  r;   r    sp    
4
r  c                
   @   s0  e Zd ZdZdZddi ddddd	d
dddddeddddddddgdddddddeddd d!d"d#d$i dd%dd&d	d
dd'dd(dedddd)dd*dd+gdd+dd,dd-dedd.d d/d0d1gd"d2d-d3d4d-d3d5d-d3d6d-d3d7d-d3d8d-d3gZd9d: Zd;S )<r  ztwitch:clipsa2  (?x)
                    https?://
                        (?:
                            clips\.twitch\.tv/(?:embed\?.*?\bclip=|(?:[^/]+/)*)|
                            (?:(?:www|go|m)\.)?twitch\.tv/(?:[^/]+/)?clip/
                        )
                        (?P<id>[^/?#&]+)
                    z0https://clips.twitch.tv/FaintLightGullWholeWheat 761769e1eafce0ffebfb4089cb3847cdr   	396245304r  FaintLightGullWholeWheatr   r   r   z'EA Play 2016 Live from the Novo Theatrer       r   r   zre:^https?://.*\.jpgr   i]Wr   20160612creatorsEAr  
channel_id25163635channel_is_verifiedFchannel_follower_countr   stereotype_r   43566419)rA   md5r   zLhttps://www.twitch.tv/xqc/clip/CulturedAmazingKuduDatSheffy-TiZ_-ixAGYR3y2Uy e90fe616b36e722a8cfa562547c543f0
3207364882z-CulturedAmazingKuduDatSheffy-TiZ_-ixAGYR3y2UyzA day in the life of xQc<   iog20250325xQc71092938T
okSTFUdude	744085721
categorieszJust Chattingz;https://clips.twitch.tv/rflegendary/UninterestedBeeDAESuppyr   zDhttps://www.twitch.tv/sergeynixon/clip/StormyThankfulSproutFutureManzEhttps://clips.twitch.tv/embed?clip=InquisitiveBreakableYogurtJebaitedzChttps://m.twitch.tv/rossbroadcast/clip/ConfidentBraveHumanChefFrankzDhttps://go.twitch.tv/rossbroadcast/clip/ConfidentBraveHumanChefFrankz1https://m.twitch.tv/clip/FaintLightGullWholeWheatc                 C   s  |  |}| |dd|idgdd d d }|s tdd	d
|d d |d d d}t|ddthfp7i }t|ddthfpBi }g }t|d}|t|ddd dt|dhfdt	hfdt
hfdthft|hdf t|d}	t|ddd fD ]#}
|t|
d |td|
dt
|
dt|
d|	dd qg }t|d}|r|d|dd  t|d }r|d|d!d  t|d}|r||kr|d"|dd  | jd#|d! d$ d%d d&}|d'p||rt| |gnd |||d(t|d)t	hfd*t
hfd+t
hfd,thfd-d.t	httfd-d.t	hfd-d't	hfd-d/d0t
hfd-d1thfd2d.t	hfd2d't	hfd3d.t	htttfd4S )5Nr+   slugr  zDownloading clip GraphQLr   rH   r  z This clip is no longer availableTr=   playbackAccessTokenr   r   )r   r   assetsr   aspectRatiovideoQualitiesc                 S      t |d S N	sourceURLr   _r0  r:   r:   r;   r9    r:  z-TwitchClipsIE._real_extract.<locals>.<lambda>r1  r   rz   	frameRate)rA   rt   rK  rS  aspect_ratioc                 S   r/  r0  r2  r3  r:   r:   r;   r9    r:  portrait)rA   rt   rK  rS  r6  rz   r  rB   )r   rA   r   r  z%7C(\d+)(?:-\d+)?.mp4rA   zold id)rB   r   )r   _old_archive_idsr  r~   r  r   r  r=  r  broadcasterr*  	followers
totalCount	isPartnercuratorr)  )r   r   r   r   r  r  r  r  r  r   r   r)  )ra  r   r   r   r   r   rY   rc  r   r?  r   r   r"  r   r   rS   r   r   r  r  bool)r9   rA   r*  r  access_queryasset_defaultasset_portraitr~   default_aspect_ratioportrait_aspect_ratior   r  thumb_asset_default_urlthumb_asset_portrait_urlthumb_default_urlold_idr:   r:   r;   ri    s   



	




zTwitchClipsIE._real_extractN)r   r   r   rj  rk  rl  rm  ri  r:   r:   r:   r;   r  t  s    
	
	
@r  )-r  r  rV   r   rl   urllib.parserd  commonr   networking.exceptionsr   utilsr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   utils.traversalr   r   r   r   rr  rs  r  r  r  r  r  r  r  r:   r:   r:   r;   <module>   s2    T K  t%3lI8 2