
    yf9                     l   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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mZmZmZmZmZmZmZmZ  G d de      Z G d	 d
e      Z d Z! G d de      Z" G d de      Z# G d de#      Z$ G d de#      Z% G d de#      Z& G d de      Z' G d de      Z(y)    N   )InfoExtractor   )compat_parse_qs
compat_strcompat_urllib_parse_urlparse)ExtractorErrorUserNotLivebase_url
clean_htmldict_getfloat_or_noneint_or_nonemake_archive_idparse_durationparse_iso8601parse_qs	qualitiesstr_or_nonetraverse_objtry_getunified_timestampupdate_url_queryurl_or_noneurljoinc                   ~    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        Zd Zd ZddZddZd Zd Zd Zy)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@27111f1b382effad0b6def325caef1909c733fe6a4fbabf54f8d491ef2cf2f14@a937f1d22e269e39a03b509f65a7490f9fc247d7f83d6ac1421523e3b68042cb@b73ad2bfaecfd30a9e6c28fada15bd97032c83ec77a0440766a56fe0bd632777@447aec6a0cc1e8d0a8d7732d47eb0762c336a2294fdb009e9c9d854e49d484b9@a647c2a13599e5991e175155f798ca7f1ecddde73f7f341f39009c14dbf59962@e1edae8122517d013405f237ffcc124515dc6ded82480a88daef69c83b53ac01@36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11@3006e77e51b128d838fa4e835723ca4dc9a05c5efd4466c1085215c6e437e65c@49b5b8f268cdeb259d75b58dcb0c1a748e3b575003448a2333dc5cdafd49adad@8d2793384aac3773beab5e59bd5d6f585aedb923d292800119e03d40cd0f9b41@07e99e4d56c5a7c67117a154777b0baf85a5ffefa393b213f4bc712ccaf85dd6)CollectionSideBarFilterableVideoTower_VideosClipsCards__UserChannelCollectionsContentStreamMetadataComscoreStreamingQueryVideoAccessToken_ClipVideoPreviewOverlayVideoMetadata$VideoPlayer_ChapterSelectButtonVideo"VideoPlayer_VODSeekbarPreviewVideoc                 4    | j                  ddgdd      d   S )N	client_idue6666qo983tsx6so1t0vnawi233waTwitchT)ie_key	casesenser   )_configuration_arg)selfs    9/usr/lib/python3/dist-packages/yt_dlp/extractor/twitch.py
_CLIENT_IDzTwitchBaseIE._CLIENT_ID;   s3    &&:;HX\ ' ^^_a 	a    c           	      .    d  fd} j                   j                  d d      \  }}d|v r t        |              |||d|| j                  d      \  }}|sy t	        j
                  d|        j                  d      } |||d	|d
d       y y )Nc                 "    t        d| z  d      )Nz Unable to login. Twitch said: %sTexpected)r	   )messages    r=   failz)TwitchBaseIE._perform_login.<locals>.failA   s     2W<tM Mr?   c                    j                  |       }|j                  |       |j                  }j                  d| dj                  d      }t        ||      }|ddd}j                  |d |t        j                  |      j                         |d	      }t        |d
      }	|	r |	       d|j                  dd      v ryt        ||j                  d      xs |d         }
j                  |
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 successfullyrD    )NNredirectredirect_pathzDownloading login redirect page)rO   )_hidden_inputsupdaterG   _search_regex_LOGIN_POST_URLr   _download_jsonjsondumpsencoder   get_download_webpage_handle)pageurlhnoterN   formpage_urlpost_urlrO   responserQ   redirect_urlrE   r<   s              r=   
login_stepz/TwitchBaseIE._perform_login.<locals>.login_stepE   s   &&t,DKKxxH))94D$8$8 * GH x2H $1 :G **$4::d+;+B+B+D + 6H X'STEU+x||Ir/JJ!"Z(EH_,EGL 00d$E 1 ! !r?   zDownloading login pageblacklist_messagez
Logging in)usernamepasswordr6   z$(?i)<form[^>]+id="two-factor-submit"ztwo-factor authentication tokenzSubmitting TFA tokentrue)authy_tokenremember_2fa)r`   _LOGIN_FORM_URLr   r>   research_get_tfa_info)	r<   rk   rl   ri   
login_pagehandleredirect_page	tfa_tokenrE   s	   `       @r=   _perform_loginzTwitchBaseIE._perform_login@   s    	M	!B "::  $(@B
F *,J'( *$$!__/!v 99<mLX**+LMI}f.D( &G  Yr?   c                     	 t        d |D              }d|d<   y # t        $ r& |D ]  }d|d   v s|j                  ddd         Y y w xY w)Nc              3   2   K   | ]  }|d    dk(  s|  yw)	format_idSourceN ).0fs     r=   	<genexpr>z.TwitchBaseIE._prefer_source.<locals>.<genexpr>   s     K+(0J!Ks   
   qualityz	/chunked/rG   r|   )r   format_note)nextStopIterationrX   )r<   formatssourcer   s       r=   _prefer_sourcezTwitchBaseIE._prefer_source   sb    		KWKKF "F9 	 !E(*HH#%'/ 	s    A	A	A	c                     d| j                   d}| j                  d      j                  d      }|rd|j                  z   |d<   | j	                  d||t        j                  |      j                         ||      S )	NrJ   )rM   z	Client-IDzhttps://gql.twitch.tvz
auth-tokenzOAuth Authorizationzhttps://gql.twitch.tv/gql)rN   rO   fatal)r>   _get_cookiesr_   valuer[   r\   r]   r^   )r<   video_idopsrc   r   rO   gql_auths          r=   _download_base_gqlzTwitchBaseIE._download_base_gql   s    6
 $$%<=AA,O'/(..'@GO$""'4C'')5 # * 	*r?   c                 j    |D ]  }dd| j                   |d      di|d<    | j                  |||      S )NpersistedQueryr   operationName)version
sha256Hash
extensions)_OPERATION_HASHESr   )r<   r   r   rc   r   ops         r=   _download_gqlzTwitchBaseIE._download_gql   sR     	B  "&"8"8O9L"M# B|	 &&xd;;r?   c                 `    d|z  }dd|d|d|di}| j                  ||d|z        d   |   S )	Nz%sPlaybackAccessTokenqueryz{
              z(
                z: "a  ",
                params: {
                  platform: "web",
                  playerBackend: "mediaplayer",
                  playerType: "site"
                }
              )
              {
                value
                signature
              }
            }z#Downloading %s access token GraphQLrN   )r   )r<   r   
token_kind
param_namemethodr   s         r=   _download_access_tokenz#TwitchBaseIE._download_access_token   sZ    (:5 J2
  &&c1J>@@FHHNP 	Pr?   c                 F    |rt        j                  dd|      ddd|igS d S )Nz\d+x\d+(\.\w+)($|(?=[?#]))z0x0\g<1>r   rG   
preferencerG   )rq   sub)r<   	thumbnails     r=   _get_thumbnailszTwitchBaseIE._get_thumbnails   sB     	 667iP
 9
 	"
 "	"r?   c                    | j                  | j                   d| d| d|ddddt        j                  dd      ddd	d||d

      }|D ]2  }|j	                  d      s|d   j                  d      s*dddgi|d<   4 |S )N/z.m3u8mp4rm   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   vcodecav01ffmpeg_args_outz-fdownloader_options)_extract_m3u8_formats_USHER_BASErandomrandintr_   
startswith)r<   pathr   r   	signaturer   fmts          r=   _extract_twitch_m3u8_formatsz)TwitchBaseIE._extract_twitch_m3u8_formats   s    ,, $q
%8(E &$*!'^^GX6!%$3.4 R -   	OCwwx S]%=%=f%E->u,N()	O
 r?   N)T)__name__
__module____qualname___VALID_URL_BASE	_API_BASEr   rp   rZ   _NETRC_MACHINEr   propertyr>   rx   r   r   r   r   r   r   r}   r?   r=   r   r   $   s    ?O'I+K3O8ON `'i^%g\"d!ca[0r.p a a>@
*<P,"r?   r   c                      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dA ZdB ZdC Z	dD Z
dE ZdF ZyG)H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rG   	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rG   r   r   skipz/http://player.twitch.tv/?t=5m10s&video=v6528877rG   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   r{   r   r   r   r   r   r   r   r   r   r   r   columnsrows)formatr   )rc   rG   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)rc   rG   r   r   expected_warningsz8https://www.twitch.tv/tangotek/schedule?vodID=1822395420c           	          | j                  |dd|dddd|dddd|ddgd	      }t        |d
d      }|t        d| dd      t        |d      |d<   t        |ddddt        hfd      |d<   |S )Nr2   rT   )channelLoginvideoIDr   	variablesr3   F)includePrivater   r4   z#Downloading stream metadata GraphQL).rN   video)get_allzVideo z does not existTrB   ).rN   r   momentsedges.noder   .rN   r   seekPreviewsURL
storyboard)r   r   r	   r   )r<   item_idrN   r   s       r=   _download_infozTwitchVodIE._download_info  s    !!!0$&& "H&+& "F&+&& 2)3, T#95I= 6'/!BTRR'.efi*3):[MJTY[l r?   c                    |j                  d      }|dk(  rd}n
|dk(  rd}nd }d}t        |      }g }|j                  d      }t        |t              rE|j	                         D ]2  \  }}	t        |	      }	|	s||vr|j                  |	 ||      d       4 |d	   |j                  d
      xs d|j                  d      t        |j                  d            ||j                  di       j                  d      |j                  di       j                  d      t        |j                  d            t        |j                  d            |ddS )Nstatus	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   )	r_   r   
isinstancedictitemsr   appendr   r   )
r<   infor  r  
_QUALITIESquality_keyr  r  thumbnail_idthumbnail_urls
             r=   _extract_infozTwitchVodIE._extract_info  sM   (#[ Gz!GG1

+
((9%gt$/6}} 	+m +M :$z1!!("-l";# 	 u+XXg&>*>88M2#DHHX$67$B/33NC88Ir266v>&txx'>?%dhhw&78
 	
r?   c              #   V  K   |j                  d      st        |d      }|rd|i y |d   D ]w  }t        |j                  d      d      }t        |j                  d      d      }t        |j                  d            }||| j	                  d| |       m|||z   |d	 y y w)
Nr   )gamedisplayNamer   positionMillisecondsi  durationMillisecondsr  z2Important chapter information missing for chapter r   )r_   r   r   r   report_warning)r<   r  r  r#  momentr   r   r  s           r=   _extract_chapterszTwitchVodIE._extract_chapters  s     xx	"&=>Do%9o 	F$VZZ0F%GNJ"6::.D#EtLHvzz-89D!X%5##&XY]X^$_ahi(&1 	s   B'B)c                 @   |j                  d      xs |}|d   dk7  rd|z  }t        |j                  d            }d }|rt        j                  d|      rd\  }}nd}||j                  d	      xs d
|j                  d      t	        |j                  d            | j                  |      t        |d t              t        |d t              t        |j                  d            t	        |j                  d            t        | j                  ||            |ddS )Nr   r   vzv%spreviewThumbnailURLz/404_processing_[^.?#]+\.png)TNFr   r   r  lengthSecondsc                     | d   d   S )Nownerr$  r}   xs    r=   <lambda>z/TwitchVodIE._extract_info_gql.<locals>.<lambda>  s    '
=0I r?   c                     | d   d   S )Nr/  loginr}   r0  s    r=   r2  z/TwitchVodIE._extract_info_gql.<locals>.<lambda>  s    1W:g3F r?   publishedAt	viewCountT)r   r   r  r   r  r   r   r   r   r   r  r   )r_   r   rq   findallr   r   r   r   r   listr)  )r<   r  r  vod_idr   r  s         r=   _extract_info_gqlzTwitchVodIE._extract_info_gql  s   $*7!9V^F)> ?@	zz99E%/" XXg&>*>88M2#DHH_$=>..y9&I:V"4)F
S*488M+BC%dhh{&;<T33D'BC
 	
r?   c              #   r  K   |r|sy | j                  ||dd      xs g }|j                  d d       t        |      }t        |      D ]  \  }}t	        |j                  d            }|j                  d      }	|	r|s6|t        |	      z  }
d	| d
ddddt        ||	d         t	        |j                  d            t	        |j                  d            ||z  t	        |j                  d            t	        |j                  d            |	D cg c]  }t        ||      |
d c}d  y c c}w w)Nz$Downloading storyboard metadata JSONFr   c                 >    t        | j                  d            xs dS )Nwidthr   )r   r_   r0  s    r=   r2  z1TwitchVodIE._extract_storyboard.<locals>.<lambda>	  s    AEE'N ; @q r?   T)keyreversecountimagessbr  r   noner   r>  heightr   cols)rG   r   )r{   r   r   protocolacodecr   rG   r>  rE  fpsr   r   	fragments)r[   sortr   	enumerater   r_   lenr   )r<   r  storyboard_json_urlr   specbaseisrA  rB  fragment_durationr   s               r=   _extract_storyboardzTwitchVodIE._extract_storyboard  sB    2""#6Agot"u{y{ 			@$	O+,dO 	DAqg/EUU8_Fu (3v; 6!!X+#  tVAY/$QUU7^4%aeeHo6x'#AEE&M2&quuV}5 %&  #4. 1 & 	&&s   DD7D2(D7c           	      N   | j                  |      }| j                  |      }| j                  ||      }| j                  |dd      }| j	                  d||d   |d         }|j                  | j                  ||j                  d      |j                  d                   | j                  |       ||d<   t        |      }t        |j                        }d	|v rt        |d	   d
         |d<   |j                  d      $dt        d|z  d| j                  i      ddgi|d<   |S )Nr   r   vodr   r   r  r   r   tr   r   r   rechatz+https://api.twitch.tv/v5/videos/%s/commentsr6   r\   )rG   r   	subtitles)	_match_idr  r:  r   r   extendrT  r_   r   r   r   r   r   r   r>   )	r<   rG   r9  r   r  access_tokenr   
parsed_urlr   s	            r=   _real_extractzTwitchVodIE._real_extract$  s=   $##F+%%eV42267DI336<0,{2KMt//		,8OQUQYQYZdQefgG$!Y1#6

 0 01%<!/c
1!>D88K ,+EN'Q " !D r?   N)r   r   r   IE_NAME
_VALID_URLint_TESTSr  r!  r)  r:  rT  r^  r}   r?   r=   r   r      sv   GJ B61#%$& #$ %0 &'
. T
/: :)1#%"%
 T
 ,'* A 6 = D ; 8!$&#% #$ #0 #& $3 #' %"" &19
> T
A#H 7!$&#% #$ #0 #& $3 #' %"" &1? 
D !
I(R *8O$&#% #$ $0 &1%
* T
 \\58 JIgFRB#
J*
8Br?   r   c                 0   t        | t              sJ | j                  d      }|sy dt        j	                         d|z   d|z  | j                  d      | j                  d      t        | j                  d            t        | j                  d            d	S )
Nr   url_transparentr+  zhttps://www.twitch.tv/videos/%sr   r,  r-  r6  )_typer9   r   rG   r   r   r   r   )r  r  r_   r   r9   r   r   )r  r   s     r=   _make_video_resultrf  E  s    dD!!!xx~H"$$&Hn08;'"XX34!$((?";<!$((;"78	 	r?   c                   .    e Zd ZdZddddddgZdZd	 Zy
)TwitchCollectionIEz@https?://(?:(?:www|go|m)\.)?twitch\.tv/collections/(?P<id>[^/]+)z0https://www.twitch.tv/collections/wlDCoH0zEBZZbQwlDCoH0zEBZZbQz'Overthrow Nook, capitalism for childrenr   r      rG   r   playlist_mincountr*   c                    | j                  |      }| j                  || j                  d|idgd      d   d   d   }|j                  d      }g }|d   d	   D ]T  }t	        |t
              s|j                  d
      }t	        |t
              s6t        |      }|sD|j                  |       V | j                  |||      S )NcollectionIDr   zDownloading collection GraphQLr   rN   
collectionr   r  r   r  playlist_idplaylist_title)	rZ  r   _OPERATION_NAMEr_   r  r  rf  r  playlist_result)	r<   rG   collection_idrp  r   entriesedger  r   s	            r=   r^  z TwitchCollectionIE._real_extractd  s    s+''!%!5!5,m<  -.
 /01
 289
 :FG
 w'w'0 	&DdD)88F#DdD)&t,Eu%	& ##u $ F 	Fr?   N)r   r   r   r`  rb  rt  r^  r}   r?   r=   rh  rh  V  s6    TJ B">
   F *OFr?   rh  c                       e Zd ZdZd Zy)TwitchPlaylistBaseIEd   c           	   '     K   d } | j                   |g| }d| j                  z  t        j                  d      D ]-  }|j	                         }| j
                  |d<   |r||d<   | j                  || j                  |dgd| j                  d|d	      }|s y t        |fd
t              }|s y |D ]  }	t        |	t              s|	j                  d      | j                  k7  r3|	j                  d      }
t        |
t              sU|
j                  d      | j                  k7  rt| j                  |
      }|s|	j                  d      }|  |rt        |t               r. y  y w)Nz%ssr   limitcursorr   zDownloading zs GraphQL page Fr<  c                 &    | d   d   d      d   S )Nr   rN   userr   r}   )r1  entries_keys    r=   r2  z/TwitchPlaylistBaseIE._entries.<locals>.<lambda>  s    !VV 4[ A' J r?   
__typenamer  )_make_variables_ENTRY_KIND	itertoolsrA  copy_PAGE_LIMITr   rt  
_NODE_KINDr   r8  r  r  r_   
_EDGE_KIND_extract_entryr   )r<   channel_nameargsr~  variables_commonpage_numr   ra   r   rx  r  entryr  s               @r=   _entrieszTwitchPlaylistBaseIE._entries~  sv    /4//DtDd...!* !	H(--/I!%!1!1Ig&,	(#%%%)%9%9!*   6:__hO & D JDRE  !$-88L)T__<xx'!$-88L)T__<++D1!XXh/FK  FJ!?C!	s   D<E/ )E/+E/N)r   r   r   r  r  r}   r?   r=   rz  rz  {  s    K%r?   rz  c                   p    e 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j                  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d.Zd/Zd0Zd1Ze fd2       Zed3        Zed4        Zd5 Z xZS )6TwitchVideosIEzGhttps?://(?:(?:www|go|m)\.)?twitch\.tv/(?P<id>[^/]+)/(?:videos|profile)z0https://www.twitch.tv/spamfish/videos?filter=allspamfishz$spamfish - All Videos sorted by Daterj  i  rl  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 Datei  z>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 VideosARCHIVEzPast Broadcasts	HIGHLIGHT
HighlightsUPLOADUploadsPAST_PREMIEREzPast Premieres)archives
highlightsuploadspast_premieresallDatePopular)timer  r+   r   	VideoEdgeVideoc                 l    t        fdt        t        fD              rdS t        t        |         S )Nc              3   @   K   | ]  }|j                          y wNsuitabler~   ierG   s     r=   r   z*TwitchVideosIE.suitable.<locals>.<genexpr>  s      0Br{{3' 0   F)anyTwitchVideosClipsIETwitchVideosCollectionsIEsuperr  r  clsrG   	__class__s    `r=   r  zTwitchVideosIE.suitable  sB      0'-3/ 0 0  	? >38=		?r?   c                 *    | ||j                         dS )N)channelOwnerLoginbroadcastType	videoSort)upper)r  broadcast_typerK  s      r=   r  zTwitchVideosIE._make_variables  s     ".+
 	
r?   c                     t        |       S r  )rf  )r  s    r=   r  zTwitchVideosIE._extract_entry
  s    !$''r?   c                    | j                  |      }t        |      }|j                  ddg      d   }|j                  ddg      d   }| j                  j                  || j                        }| j                  | j                  ||j                  |      ||d|j                  d| j                  j                  || j                              S )	Nfilterr  r   rK  r  z - z sorted by rq  )rZ  r   r_   _BROADCASTS_DEFAULT_BROADCASTru  r  r  r  
_SORTED_BY_DEFAULT_SORTED_BY)r<   rG   r  qsr  rK  	broadcasts          r=   r^  zTwitchVideosIE._real_extract  s    ~~c*c]5'*1-vvfvh'*$$((1H1HI	##MM,	=$Y__""4)@)@AC $ D 	Dr?   )r   r   r   r`  rb  collections
namedtupler  r  r  r  r  rt  r  r  r  classmethodr  staticmethodr  r  r^  __classcell__r  s   @r=   r  r    s   [J B;
 ! M>
 ! G@
   I;
 ! P8
  M?
  ; 9 7m9Fv '&&{VW4EFI"46i):;\:Xy1#O5EF!K  "J
 4OKJJ? ? 
 
 ( (Dr?   r  c                       e Zd ZdZdddddddd	d
gZ ej                  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        Zed        Zd Zy)r  z[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 Allrj  r   rl  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                     | d|idS )Nr  )r4  criteriar}   )r  r  s     r=   r  z#TwitchVideosClipsIE._make_variables>  s     "&
 	
r?   c                    t        | t              sJ t        | j                  d            }|sy dt        j                         | j                  d      || j                  d      | j                  d      t        | j                  d            t        | j                  d            t        | j                  d            | j                  d	      d

S )NrG   rd  r   r   thumbnailURLdurationSeconds	createdAtr6  language)
re  r9   r   rG   r   r   r   r   r   r  )	r  r  r   r_   TwitchClipsIEr9   r   r   r   )r  clip_urls     r=   r  z"TwitchVideosClipsIE._extract_entryG  s    $%%%txx/&#**,((4.XXg&.1%dhh/@&AB*488K+@A%dhh{&;<,
 	
r?   c                 ,   | j                  |      }t        |      }|j                  ddg      d   }| j                  j                  || j                        }| j                  | j                  ||j                        ||d|j                        S )Nranger  r   z	 - Clips rq  )	rZ  r   r_   _RANGE_DEFAULT_CLIPru  r  r  r  )r<   rG   r  r  r  r  s         r=   r^  z!TwitchVideosClipsIE._real_extractZ  s    ~~c*c]w'*{{ud&8&89##MM,4$.:DJJG $ I 	Ir?   N)r   r   r   r`  rb  r  r  r  r  r  r  rt  r  r  r  r  r  r  r^  r}   r?   r=   r  r    s    oJ N0
  OF ";!!&8W*=>Dh/MZ+L),J	*	F K(OKJJ
 
 
 
$Ir?   r  c                   j    e 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        Z
e	d        Zd Zy)r  zWhttps?://(?:(?:www|go|m)\.)?twitch\.tv/(?P<id>[^/]+)/videos/*?\?.*?\bfilter=collectionsz8https://www.twitch.tv/spamfish/videos?filter=collectionsr  zspamfish - Collectionsrj     rl  z:https://www.twitch.tv/monstercat/videos?filter=collections
monstercatzmonstercat - Collectionsrk  r-   rp  CollectionsItemEdge
Collectionc                 
    d| iS )N
ownerLoginr}   )r  s    r=   r  z)TwitchVideosCollectionsIE._make_variables~  s     ,
 	
r?   c                 \   t        | t              sJ | j                  d      }|sy dt        j	                         |d|z  | j                  d      | j                  d      t        | j                  d            t        | j                  d            t        | j                  d            d		S )
Nr   rd  z$https://www.twitch.tv/collections/%sr   r  r-  	updatedAtr6  )	re  r9   r   rG   r   r   r   r   r   )r  r  r_   rh  r9   r   r   r   )r  rv  s     r=   r  z(TwitchVideosCollectionsIE._extract_entry  s    $%%%&(//19MIXXg&.1%dhh&?@*488K+@A%dhh{&;<

 
	
r?   c                 p    | j                  |      }| j                  | j                  |      |d|z        S )Nz%s - Collectionsrq  )rZ  ru  r  )r<   rG   r  s      r=   r^  z'TwitchVideosCollectionsIE._real_extract  s>    ~~c*##MM,'\-< $ > 	>r?   N)r   r   r   r`  rb  rt  r  r  r  r  r  r  r^  r}   r?   r=   r  r  e  s    kJ J-
  L/
  F" 2OK&JJ
 

 
 
">r?   r  c                        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e fd#       Zd$ Z	 x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   c           	          t        fdt        t        t        t        t
        t        fD              rdS t        t        | '        S )Nc              3   @   K   | ]  }|j                          y wr  r  r  s     r=   r   z*TwitchStreamIE.suitable.<locals>.<genexpr>  s      $Br{{3' $r  F)
r  r   rh  r  r  r  r  r  r  r  r  s    `r=   r  zTwitchStreamIE.suitable  sN      $&"'-!3# $ $  	? >38=	?r?   c                    | j                  |      j                         }| j                  |dd|idd|dddddddd	d
|idgd      }|d   d   d   }|st        d|z  d      |d   }|st	        |      | j                  |dd      }|j                  d      xs |}| j                  d||d   |d         }| j                  |       |j                  d      }	t        |j                  d            }
t        |d t              xs i }|j                  d      }t        |d t              }t        t        |d t                    }|xs |}|j                  d      }|dv r|d |z  z  }||||| j                  |      |||
|	||d!k(  d"S )#Nr.   r   r   r/   rT   FT)r  clipSlugisClipisLiveisVodOrCollectionvodIDr1   r4  zDownloading stream GraphQLr   rN   r  z%s does not existrB   stream)r   channelNamer   zapi/channel/hlsr   r   viewersr  c                     | d   d   d   S )Nr   rN   r  r}   r0  s    r=   r2  z.TwitchStreamIE._real_extract.<locals>.<lambda>  s    1ff)= r?   r$  c                     | d   d   S )NbroadcastSettingsr   r}   r0  s    r=   r2  z.TwitchStreamIE._real_extract.<locals>.<lambda>  s    q!45g> r?   c                 $    | d   d   d   d   d   S )Nr   rN   r  r  previewImageURLr}   r0  s    r=   r2  z.TwitchStreamIE._real_extract.<locals>.<lambda>  s    1Q4</9:KL r?   r  )rerunlivez (%s)r  )r   r  r   r  r  r   r   r   r   r   r  )rZ  lowerr   r	   r
   r   r_   r   r   r   r   r  r   r   r   )r<   rG   r  gqlr  r  r\  	stream_idr   r   r   sq_userr   r  r   r   stream_types                    r=   r^  zTwitchStreamIE._real_extract  s   ~~c*002  !1,l; ":+ "#").
 "7%|4" )%*( 1vf~f% #l2TC C h|4422(M3 JJt$4	33|\'-BLQ\D]_G$ZZ	*
%fjj&=>	#=tDJ;;}->
L  L! 	 (Ljj(++W{**E &&..y9 '"$"f,
 	
r?   )r   r   r   r_  r`  ra  rb  r  r  r^  r  r  s   @r=   r  r    s    GJ 0%Rd#%#&
 T
 &'* = ; + * 2&$A#%$'$,
 \
!A3Fj 	? 	?G
r?   r  c                   n    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gZd Zy)r  ztwitch:clipsa2  (?x)
                    https?://
                        (?:
                            clips\.twitch\.tv/(?:embed\?.*?\bclip=|(?:[^/]+/)*)|
                            (?:(?:www|go|m)\.)?twitch\.tv/(?:[^/]+/)?clip/
                        )
                        (?P<id>[^/?#&]+)
                    z0https://clips.twitch.tv/FaintLightGullWholeWheat 761769e1eafce0ffebfb4089cb3847cd42850523FaintLightGullWholeWheatr   z'EA Play 2016 Live from the Novo Theatrezre:^https?://.*\.jpgi]W20160612EAstereotype_43566419)
r   r  r   r   r   r   r   creatorr   r   )rG   md5r   z;https://clips.twitch.tv/rflegendary/UninterestedBeeDAESuppyTr   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                    | j                  |      }| j                  |dd|idgd      d   d   d   }|st        dd	
      |d   d   |d   d   d}| j                  |dd|z  idd      }|rt	        |d t
              xs |}g }|j                  dg       D ]  }t        |t
              st        |j                  d            }|s1|j                  t        ||      |j                  d      t        |j                  d            t        |j                  d            d        g }	dD ]  }
|j                  |
      }|s|
|d}t        j                  d|      }|rD|j                  t        |j!                  d            t        |j!                  d            d       |	j                  |        | j#                  d |d!   d"   d#d $      }|j                  d%      xs ||rt%        | |      gnd ||j                  d&      |t        |j                  d'            t        |j                  d(            t'        |j                  d)            |	t	        |d* t(              t	        |d+ t(              t	        |d, t(              d-S ).Nr0   slugr   z%Downloading clip access token GraphQLr   rN   r  z This clip is no longer availableTrB   playbackAccessTokenr   r   )r   r   r   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Downloading clip GraphQLFr<  c                     | d   d   S )NrN   r  r}   r0  s    r=   r2  z-TwitchClipsIE._real_extract.<locals>.<lambda>  s    1V9V+< r?   videoQualities	sourceURLr   	frameRate)rG   r{   rE  rI  )tinyr
  r  )r   rG   z-(\d+)x(\d+)\.r   r   )rE  r>  z%7C(\d+)(?:-\d+)?.mp4rG   zold id)rH   r   r   r  r6  r  c                     | d   d   S )Nbroadcasterr$  r}   r0  s    r=   r2  z-TwitchClipsIE._real_extract.<locals>.<lambda>  s    q/?/N r?   c                     | d   d   S )Ncuratorr$  r}   r0  s    r=   r2  z-TwitchClipsIE._real_extract.<locals>.<lambda>  s    )]0K r?   c                     | d   d   S )Nr*  r   r}   r0  s    r=   r2  z-TwitchClipsIE._real_extract.<locals>.<lambda>  s    1Y<3E r?   )r   _old_archive_idsr  r   r   r   r   r   r  r  r   r   )rZ  r   r	   r   r   r  r_   r  r   r  r   r   rq   rr   rX   ra  rI   rY   r   r   r   )r<   rG   r   r  access_queryrN   r   optionr   r  r  r   thumbmobjold_ids                  r=   r^  zTwitchClipsIE._real_extractb  s   >>#&!!!8H  45 678 9?@ AGH  2TC C -.{;/09

 && . /0 -E3 ' ;6 4!<dCKtDhh/4 	Ffd+ K!89FNN'=#ZZ	2%fjj&;<"6::k#:;	 	 
7 	%L HH\2M "$E 99.>D!$**Q-0 A/  e$	%  ##$<gbk%>PRZdh#i ((4.,HCIv!> ?t"XXg&#DHH->$?@%dhh{&;<*488K+@A$t%NPZ[&KZX"4)EzR
 	
r?   N)r   r   r   r_  r`  rb  r^  r}   r?   r=   r  r  3  s    GJ B14>0#%%%
" M
 V W U V C?"FHa
r?   r  ))r  r  r\   r   rq   commonr   compatr   r   r   utilsr	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rf  rh  rz  r  r  r  r  r  r}   r?   r=   <module>r5     s        	 ! 
     .p= pfk, k\""F "FJ(< (VsD) sDlFI. FIR5> 4 5>pS
\ S
lP
L P
r?   