U
    y^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 |d}|r:td| j||df ddd S )Nerrorz%s returned error: %s - %smessageTexpected)
isinstancedictgetr   IE_NAME)selfresponser    r"   NC:\Users\TaGoRe\Desktop\beinconnect-dl\binaries\youtube_dl\extractor\twitch.py_handle_error*   s    

zTwitchBaseIE._handle_errorc                 O   sR   | di  }| j|d< ||d< | jd| j|f |f|t|}| | |S )Nheaders	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   |    d S N)_loginr    r"   r"   r#   _real_initialize=   s    zTwitchBaseIE._real_initializec                    s     \}}|d krd S dd   fdd}jd d\}}d|krV t| |||d||jd\}}|szd S td	|d k	rd
}|||d|dd d S )Nc                 S   s   t d|  ddd S )Nz Unable to login. Twitch said: %sTr   )r   )r   r"   r"   r#   failE   s     z!TwitchBaseIE._login.<locals>.failc                    s    | }|| | }jd| djdd}t||}||dd}j|d |t|	 |dd}|
d	pz|
d
}	|	r |	 d|
ddkrdS t||
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    )NNredirectZredirect_pathzDownloading login redirect page)r%   )_hidden_inputsupdategeturl_search_regex_LOGIN_POST_URLr   r)   jsondumpsencoder   _download_webpage_handle)pageurlhnoter:   formpage_urlpost_urlr%   r!   r   redirect_urlr4   r    r"   r#   
login_stepI   sL    

   
      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_inforH   _LOGIN_FORM_URLr   r(   research_get_tfa_info)r    rR   rS   rQ   
login_pagehandleZredirect_pageZ	tfa_tokenr"   rP   r#   r1   @   s:    !    
zTwitchBaseIE._loginc              	   C   sh   zt dd |D }d|d< W n: tk
rX   |D ] }d|d kr2|ddd q2Y nX | | 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/r5   r^   )rc   format_note)nextStopIterationrA   _sort_formats)r    formatssourcer`   r"   r"   r#   _prefer_source   s    zTwitchBaseIE._prefer_sourceN)__name__
__module____qualname___VALID_URL_BASEr*   _USHER_BASErW   rD   r(   _NETRC_MACHINEr$   r/   r3   r1   rj   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"   |  | 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   s*  |  | j|}| d| j|f |d| j }g }|d }t| }tt|  ddD ]\}}g }	t|D ]X\}
}||
 }|d ||dkrdndd	}t	
d
|}|rt|d|d< |	| ql| |	 t|}d|d |f |d< d|d |f |d< |	|d< || qX| ||d |d S )Nzapi/videos/%s%szDownloading %s playlist JSONchunksr   )startr5   liver   )r5   r]   rc   z^(?P<height>\d+)[Pp]heightz%s_%didz
%s part %dtitlerh   )ru   _ITEM_SHORTCUTr/   rs   listkeys	enumeratezipvaluesrX   rY   intr7   appendrg   r   playlist_result)r    r,   infor!   entriesrv   	qualitiesnumfragmentrh   Zfmt_numZfragment_fmtr]   fmtmentryr"   r"   r#   _extract_media   s8     
zTwitchItemBaseIE._extract_mediac                 C   s   | d}|dkrd}n|dkr&d}nd }|d | dp<d| d	t| d
| d| di  d| di  dt| dt| d|d
S )Nstatus	recordingTrecordedF_idr{   Untitled Broadcastdescriptionlengthpreviewchanneldisplay_namenameZrecorded_atviews)
rz   r{   r   duration	thumbnailuploaderuploader_id	timestamp
view_countis_live)r   r   r   )r    r   r   r   r"   r"   r#   rr      s"    
zTwitchItemBaseIE._extract_infoc                 C   s   |  | |S r0   )r   	_match_idr    r5   r"   r"   r#   _real_extract   s    zTwitchItemBaseIE._real_extractN)rk   rl   rm   ru   r   rr   r   r"   r"   r"   r#   rq      s   rq   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rz   r{      HTTP Error 404: Not Foundr5   	info_dictplaylist_mincountskipN)
rk   rl   rm   r   r   rn   
_VALID_URLrs   r|   _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 @ Nordschleifer      r   r   z,http://www.twitch.tv/tsm_theoddone/c/2349361Tr5   only_matchingN)
rk   rl   rm   r   r   rn   r   rs   r|   _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  )rz   extr{   r   r   r   upload_dater   r   r   
start_timeskip_downloadTr5   r   paramsz(http://www.twitch.tv/belkao_o/v/11230755Z	v11230755r   if  iU20150816ZBelkAO_oZbelkao_o)
rz   r   r{   r   r   r   r   r   r   r   r   )r5   r   r   r   z/http://player.twitch.tv/?t=5m10s&video=v6528877r   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|}| d| |d| j }| jd| j|tddddd|d |d df |d	d
d}| | ||d< t	|}t
|j}d|krt|d d |d< |dd k	rd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?%srU   	twitchwebtokensig)allow_sourceallow_audio_onlyallow_spectreplayerplaylist_include_framerateZnauthZnauthsigr   m3u8_native)entry_protocolrh   tr   r   r   Zrechatz+https://api.twitch.tv/v5/videos/%s/commentsrT   rE   )r5   r   	subtitles)r   ru   r|   r/   rs   _extract_m3u8_formatsro   r	   rj   r
   r   queryr   r   r   r(   )r    r5   r,   r   access_tokenrh   
parsed_urlr   r"   r"   r#   r   8  sV    
    

 
zTwitchVodIE._real_extractN)
rk   rl   rm   r   r   rs   r|   r   r   r   r"   r"   r"   r#   r      sn     8r   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=%dd   c                    s    d| |d}|dp$|d}g }d} j}d}d }tdD ]}	   j|||f |d j|pj|	f }
 |
}|s qt|
d	}|s|rt	||kr 
d
| d}|}d}qF|| |s|rt	||kr q||7 }qF  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 | ]}  |qS r"   )_make_url_result)r_   r   r2   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"   r2   r#   _extract_playlisth  sR     


 z&TwitchPlaylistBaseIE._extract_playlistc                 C   sH   z$dt | }| j|t  |dW S  tk
rB   | | Y S X d S )Nzv%s)video_id)r   r   
url_resultie_keyAssertionError)r    r5   r   r"   r"   r#   r     s
    z%TwitchPlaylistBaseIE._make_url_resultc                 C   s    | d}|rdd |D S g S )Nvideosc                 S   s   g | ]}|d  qS r5   r"   )r_   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   |  | |S r0   )r   r   r   r"   r"   r#   r     s    z"TwitchPlaylistBaseIE._real_extractN)	rk   rl   rm   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	VanillaTVr   i  r5   r   r   z$http://m.twitch.tv/vanillatv/profileTr   N)	rk   rl   rm   r   r   rn   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)rk   rl   rm   r   rn   _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Spamfishr   ie  r   z'https://m.twitch.tv/spamfish/videos/allTr   N
rk   rl   rm   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   r   r   r   z+https://m.twitch.tv/spamfish/videos/uploadsTr   Nr   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   r   r   r   z3https://m.twitch.tv/spamfish/videos/past-broadcastsTr   Nr   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   r   i%  r   z.https://m.twitch.tv/spamfish/videos/highlightsTr   Nr   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 - @ShroomzTVTieTZ20150122Z	ShroomzTV)rz   
display_idr   r{   r   r   r   r   r   r   r   r   r   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/foodc                    s<   t  fddttttttttt	f	D r,dS t
t|  S )Nc                 3   s   | ]}|  V  qd S r0   )suitable)r_   ier   r"   r#   ra   2  s     z*TwitchStreamIE.suitable.<locals>.<genexpr>F)anyr   r   r   r   r   r   r   r   TwitchClipsIEsuperr   r   )clsr5   	__class__r   r#   r   /  s    zTwitchStreamIE.suitablec                 C   s  |  |}| d|  |dd}|s:td| dd|di dpR| }| d	| |d
}dddtddddd|d d|d dd	}| d| j	|t
|f |d}| | |d}t|d}|d }	| |	dp|	d}
|	d}g }|d  D ]F\}}td|}|s4q||t|dt|dd qt|d ||
|||	d|	d|||dd S )!Nz!kraken/streams/%s?stream_type=allzDownloading stream JSONstreamz%s is offlineTr   r   r   zapi/channels/%s/access_tokenz Downloading channel access tokenrU   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$widthry   )r5   r	  ry   r   )rz   r   r{   r   
thumbnailsr   r   r   r   rh   r   )r   r/   lowerr   r   randomrandintrG   r   ro   r	   rj   r   _live_titleitemsrX   rY   r   r   r7   r   )r    r5   r   r  r   r   rh   r   r   r   r{   r   r
  thumbnail_keythumbnail_urlr   r"   r"   r#   r   >  sz    

  
 



zTwitchStreamIE._real_extract)rk   rl   rm   r   r   r   r   classmethodr   r   __classcell__r"   r"   r  r#   r     sF   
 !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)	rz   r   r{   r   r   r   creatorr   r   )r5   md5r   z;https://clips.twitch.tv/rflegendary/UninterestedBeeDAESuppyTr   zDhttps://www.twitch.tv/sergeynixon/clip/StormyThankfulSproutFutureManzEhttps://clips.twitch.tv/embed?clip=InquisitiveBreakableYogurtJebaitedc                 C   s  |  |}| jd|tdd| i d| jidd d }|sLtdd	d
g }|dg D ]R}t|t	slq\t
|d}|sq\|||dt|dt|dd q\| | g }dD ]^}||}	|	sq||	d}
td|	}|r|
t|dt|dd ||
 q|dp0||dp>||t|dt|dt|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
  }
}r&   )r:   r%   r:   clipz This clip is no longer availableTr   ZvideoQualities	sourceURLrc   	frameRate)r5   r]   ry   fps)tinysmallmedium)rz   r5   z-(\d+)x(\d+)\.r   r   )ry   r	  rz   r{   ZdurationSeconds	viewCount	createdAtc                 S   s   | d d S )NZbroadcasterdisplayNamer"   xr"   r"   r#   <lambda>      z-TwitchClipsIE._real_extract.<locals>.<lambda>c                 S   s   | d d S )Ncuratorr  r"   r   r"   r"   r#   r"    r#  c                 S   s   | d d S )Nr$  rz   r"   r   r"   r"   r#   r"    r#  )
rz   r{   rh   r   r   r   r
  r  r   r   )r   r)   rE   rF   rG   r(   r   r   r   r   r   r   r   rg   rX   rY   rA   r   r7   r   r   r   )r    r5   r   r  rh   optionri   r
  thumbnail_idr  thumbmobjr"   r"   r#   r     s~    
     



zTwitchClipsIE._real_extractN)rk   rl   rm   r   r   r   r   r"   r"   r"   r#   r     s4   r   )(
__future__r   r   rX   r  rE   commonr   compatr   r   r   r	   r
   utilsr   r   r   r   r   r   r   r   r   r   r   r   rq   r   r   r   r   r   r   r   r   r   r   r   r   r"   r"   r"   r#   <module>   s,   4r<q< 