U
    g=w                     @   s   d dl Z d dlZddlm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 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   )Request)	HTTPError)ExtractorErrorfloat_or_noneformat_fieldint_or_nonejwt_decode_hs256parse_age_limitparse_countparse_iso8601	qualitiestime_secondstraverse_objurl_or_noneurlencode_postdatac                   @   s   e Zd ZdZdZdZdZdZdZdZ	dZ
dedd   ZdZd	d
ddddddddddZdd Zd*ddZdd Zdd Zdd  Zdi fd!d"Zd#i fd$d%Zd&d' Zd+d(d)ZdS ),CrunchyrollBaseIEzhttps://www.crunchyroll.comzhttps://api.crunchyroll.comcrunchyrollz4Crunchyroll/1.8.0 Nintendo Switch/12.3.12.0 UE4/4.27NzBasic :)zt-kdgp2h8c3jub8fn0fqZ yfLDfMfrYvKXh4JXS1LEI2cCqu1v5Wanzar-SAde-DEzen-USzes-419zes-ESzfr-FRzit-ITzpt-BRzpt-PTzru-RUzhi-IN)arde eszes-esfritzpt-brzpt-ptruhic                 C   sX   dt |dthddfkt_d|d d |d  it_tt |dthfd	d
d dt_d S )NZ
cr_premiumZaccess_tokenZbenefits.Authorization
token_type Z
expires_ini,  )default
   )seconds)r   r   r   _IS_PREMIUM_AUTH_HEADERSr   r   _AUTH_EXPIRY)selfresponse r+   @/tmp/pip-unpacked-wheel-q5ljy6pj/yt_dlp/extractor/crunchyroll.py_set_auth_info4   s    z CrunchyrollBaseIE._set_auth_infoRequesting tokenFailed to request tokenc              
   C   s   z&| j | j dd |||t|ddW S  tk
r } zNt|jtrP|jjdkrR |jjj	
d }rvtd| dtddd	W 5 d }~X Y nX d S )
Nz/auth/v1/tokenT)noteerrnoteheadersdataimpersonatei  r4   z2Got HTTP Error 403 when using impersonate target ""a  Request blocked by Cloudflare. Install the required impersonation dependency if possible, or else navigate to Crunchyroll in your browser, then pass the fresh cookies (with --cookies-from-browser or --cookies) and your browser's User-Agent (with --user-agent)expected)_download_json	_BASE_URLr   r   
isinstancecauser   statusr*   
extensionsget)r)   r2   r3   r0   r1   errortargetr+   r+   r,   _request_token9   s&    
     z CrunchyrollBaseIE._request_tokenc              
   C   s   t js| j| j|t _t jr"d S z&| jd| ji||dddddd}W nH tk
r } z*t|j	t
r~|j	jdkr~td	d
d W 5 d }~X Y nX |d t _| j| j|t j | | d S )Nr    passwordoffline_access)usernamerB   
grant_typescopez
Logging inzFailed to log in)r2   r3   r0   r1   i  z Invalid username and/or passwordTr6   refresh_token)r   _REFRESH_TOKENcacheload_NETRC_MACHINErA   _BASIC_AUTHr   r:   r;   r   r<   storer-   )r)   rD   rB   Zlogin_responser?   r+   r+   r,   _perform_loginJ   s,     

z CrunchyrollBaseIE._perform_loginc              
   C   s   t jrt jt krd S d| ji}t jr6t jddd}nddi}t |d< z| ||}W n t	k
r } zb| 
 \}}|rt|jtr|jjdkr | d	 d t _| j| j|d  | || W Y d S d }~X Y nX | | d S )
Nr    rG   rC   )rG   rE   rF   rE   Z	client_idzETP-Anonymous-IDi  z(Refresh token has expired. Re-logging in)r   r'   r(   r   rL   rH   uuidZuuid4rA   r   Z_get_login_infor:   r;   r   r<   	to_screenrI   rM   rK   rN   r-   )r)   Zauth_headersr3   Zauth_responser?   rD   rB   r+   r+   r,   _update_autha   s,    

zCrunchyrollBaseIE._update_authc                 C   s(   | j dtdd}|r|d S | j|S )NmetadataT)Zie_keyZ	casesenser   )_configuration_argCrunchyrollBetaIE_LOCALE_LOOKUPr>   )r)   languageZconfig_localer+   r+   r,   _locale_from_language}   s    z'CrunchyrollBaseIE._locale_from_languagec                 C   sd   |    |dsd| }| }| |}|r:||d< | j| j | ||pXd| tj|dS )N/localezCalling API: )r2   query)rQ   
startswithcopyrW   r8   r9   r   r'   )r)   Zendpointinternal_idlangr0   rZ   rY   r+   r+   r,   _call_base_api   s    


   z CrunchyrollBaseIE._call_base_apiapic              
   C   s   | d| j ds&d| j d| }z(| j|||d| d| j d|d}W nF tk
r } z(t|jtr|jjdkrW Y 
d S  W 5 d }~X Y nX |std| d	|S )
Nz/content/v2/rX   Downloading z JSON ()rZ   i  z%Unexpected response when downloading z JSON)r[   _API_ENDPOINTr_   r   r:   r;   r   r<   )r)   pathr]   r^   r0   rZ   resultr?   r+   r+   r,   	_call_api   s"        

zCrunchyrollBaseIE._call_apic                 C   s   | j d| d|dddd}|s$d S g }dD ]P}t||dthf}t||dthf}|d ks,|d krfq,|| ||d	 q,|S )
Nz6https://static.crunchyroll.com/skip-events/production/z.jsonzDownloading chapter infoF)r0   fatalr1   )ZrecapZintrocreditspreviewstartend)title
start_timeZend_time)r8   r   r   append
capitalize)r)   r]   Zskip_eventschapterseventrk   rl   r+   r+   r,   _extract_chapters   s"    
   z#CrunchyrollBaseIE._extract_chaptersc              
   C   s  |s|}|    tjd| ji}z | jd| d|dd|d}W nn tk
r } zP| drx| |j g i f W Y ,S t	|j
tr|j
jdkrtd	d
d W 5 d }~X Y nX ddd|d fi}t|dtjhdd fD ] \}}d| ||d f||< qdd | dpdgD }	dd |D }
|
rdd|	krdt|	}| dd|
  | jdd
d ntttj|}t|dthf}t|	d d d }g i  }}| D ]\}}}| |kr| j|||tjdd|r| d nd d!d"\}}| j||d# nq|D ].}|d$dkr(||d%< || |d&< q|| qt|d'tjhd(fD ](\}}||g t|dd)d* q^d+}|d, }r| jt d-| d.| d/|d0d1|d2|dd3 n
| | ||fS )4Nz
User-Agentz2https://cr-play-service.prd.crunchyrollsvc.com/v1/z/console/switch/playzDownloading stream infozFailed to download stream info)r0   r1   r2   Zignore_no_formats_errori  zCYou have reached the rate-limit for active streams; try again laterTr6   r   urlZhardSubsc                 S   s   |d d S )Nr   rt   r+   )_vr+   r+   r,   <lambda>       z3CrunchyrollBaseIE._extract_stream.<locals>.<lambda>zhardsub-c                 S   s   g | ]}|d krdn|qS )noner   r+   ).0valr+   r+   r,   
<listcomp>   s     z5CrunchyrollBaseIE._extract_stream.<locals>.<listcomp>hardsubry   c                 S   s   g | ]}|r|qS r+   r+   )rz   r^   r+   r+   r,   r|      s      allzAvailable hardsub languages: z, zTo extract formats of a hardsub language, use "--extractor-args crunchyrollbeta:hardsub=<language_code or all>". See https://github.com/yt-dlp/yt-dlp#crunchyrollbeta-crunchyroll for more info)Z	only_onceZaudioLocaleFra   r"   zMPD manifest)Zmpd_idr2   rh   r0   )r@   ZacodecrV   Zquality)	subtitlesZcaptions.format)rt   extzCUnable to invalidate stream token; you may experience rate-limitingtokenz8https://cr-play-service.prd.crunchyrollsvc.com/v1/token/rX   z	/inactivePATCH)r2   methodzInvalidating stream token)rh   )!rQ   r   r'   _SWITCH_USER_AGENTr8   r   	get_paramZreport_warningZorig_msgr:   r;   r   r<   r   dictitemsrS   setrP   joinmapstrlowerr   valuesZ"_extract_mpd_formats_and_subtitlesZ_merge_subtitlesr>   extend
setdefaultro   Z_request_webpager   )r)   
identifier
display_idr2   Zstream_responser?   Zavailable_formatsZhardsub_langstreamZrequested_hardsubsZhardsub_langsZfull_format_langsaudio_localeZhardsub_preferenceformatsr   Z	format_idZ
stream_urlZadaptive_formatsZ	dash_subsfrY   Zsubtitle	error_msgZstream_tokenr+   r+   r,   _extract_stream   s    
   

  
    
"    
z!CrunchyrollBaseIE._extract_stream)r.   r/   )N)__name__
__module____qualname__r9   Z	_API_BASErK   r   rH   r'   r(   rd   base64	b64encoder   encodedecoderL   r&   rU   r-   rA   rN   rQ   rW   r_   rg   rs   r   r+   r+   r+   r,   r      s>   
r   c                   @   s   e Zd ZdZdZdddZdS )CrunchyrollCmsBaseIEZcmsNr`   c                 C   s   t jrt jt kr\| dd |dd }|d |d |d dt _|d t _t|d	 d
 t _|dsxdt j d| }| j|||d| dt jdS )Nzindex/v2zRetrieving signed policyZcms_webpolicy	signatureZkey_pair_id)Policy	SignaturezKey-Pair-IdZbucketexpiresr$   z/cms/v2rX   ra   z JSON (signed cms)rc   )r   _CMS_EXPIRYr   r_   Z
_CMS_QUERYZ_CMS_BUCKETr   r[   )r)   re   r]   r^   r0   r*   r+   r+   r,   _call_cms_api_signed   s"    

   
 z)CrunchyrollCmsBaseIE._call_cms_api_signed)r`   )r   r   r   rd   r   r   r+   r+   r+   r,   r      s   r   c                   @   s0  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eedddddgiiddddddddd d!d"d#d$d#d%dd&d'ddeed(d)d*idd+d,dd-d.d/d0d1d0d2dd3dddd4d5deed6d)didd7d8dd9d:d;d<dd=d)did>d?d@dAd:d<dBd9dCdDdEdFd*dGdHd*dGgZdIZdJdK Ze	dLdM Z
e	dNdO ZdPS )QrT   r   z(?x)
        https?://(?:beta\.|www\.)?crunchyroll\.com/
        (?:(?P<lang>\w{2}(?:-\w{2})?)/)?
        watch/(?!concert|musicvideo)(?P<id>\w+)z9https://www.crunchyroll.com/watch/GY2P1Q98Y/to-the-futureZ	GY2P1Q98Ymp4gX9@i9 Wz$md5:a022fbec4fbb023d43631032c91ed64bu*   World Trigger Episode 73 – To the FutureZ20160402zWorld TriggerZ	GR757DMKYZ	GR9P39NJ6r   zTo the FutureI   z1re:^https://www.crunchyroll.com/imgsrv/.*\.jpeg?$zcount:2   )idr   duration	timestampdescriptionrm   upload_dateseries	series_idseason	season_idseason_numberepisodeepisode_number	thumbnailrq   	age_limit
like_countdislike_countm3u8Zcrunchyrollbetar}   r   zbv[format_id~=hardsub])skip_downloadZextractor_argsr   rt   	info_dictparamsz+https://www.crunchyroll.com/watch/GYE5WKQGRZ	GYE5WKQGRgMbXv@i Xz$md5:74b67283ffddd75f6e224ca7dc031e76u:   SHELTER – Porter Robinson presents Shelter the AnimationZ20161018ZSHELTERZ	GYGG09WWYZ	GR09MGK4Rz.Porter Robinson presents Shelter the Animationr   )r   r   r   r   r   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   TzXhttps://www.crunchyroll.com/watch/GJWU2VKK3/cherry-blossom-meeting-and-a-coming-blizzardZ	GJWU2VKK3gK70@z$md5:2d1c67c0ec6ae514d9c30b0b99a625cdud   The Ice Guy and His Cool Female Colleague Episode 1 – Cherry Blossom Meeting and a Coming Blizzardz)The Ice Guy and His Cool Female ColleagueZ	GW4HM75NPZ	GY9PC21VEz,Cherry Blossom Meeting and a Coming BlizzardiXcZ20230104)r   r   r   r   rm   r   r   r   r   r   r   r   rq   r   r   r   r   r   r   z+https://www.crunchyroll.com/watch/GM8F313NQZ	GM8F313NQzGarakowa -Restore the World-z$md5:8d2f8b6b9dd77d87810882e7d2ee5608g|?58@   )r   r   rm   r   r   r   r   no longer existsrt   r   r   skipz+https://www.crunchyroll.com/watch/G62PEZ2E6Z	G62PEZ2E6gFHP@)r   r   r   r   rm      rt   r   Zplaylist_mincountz.https://www.crunchyroll.com/de/watch/GY2P1Q98Yrt   Zonly_matchingzJhttps://beta.crunchyroll.com/pt-br/watch/G8WUN8VKP/the-ruler-of-conspiracyvideoc           	   	      s   |dd\ td   dddiddthf}|sXtd	  d
dd|d}|dkrv|}n|dkr|}nr|dkrt|d}	 |sȈ
j d d| t|S  fdd}j| f|S td| jsRt|| ddfrRd| d}tjr@j|d d nj|ddd n \|d< |d<  |d < d!d" }|t|d#d$|hfd%|hfd&f |S )'Nr^   r   zobjects/zobject infoZratingstruer3   r   No video with id ) could be found (possibly region locked?)Tr6   typer   ZmovieZmovie_listing)movie_listing_metadatafirst_movie_idrX   watch/c                  3   sZ    d  d d} t| dD ]2}jj d d|d  tf|V  q"d S )Nzmovie_listings/z/moviesz
movie list)r3   .rX   r   r   )rg   r   
url_resultr9   rT   _transform_movie_response)ZmoviesZmovie_responser]   r^   r)   r+   r,   entries  s    z0CrunchyrollBetaIE._real_extract.<locals>.entrieszUnknown object type 	_metadataZis_premium_onlyThis  is for premium members onlyr7   Zvideo_idrB   r   Zmetadata_availabler   r   rq   c                 S   s    t d| d | dpdfS )Nr   Z	displayedunit)r   r   r>   )itemr+   r+   r,   calculate_count  s    z8CrunchyrollBetaIE._real_extract.<locals>.calculate_countZratingZupZdown)r   r   )_match_valid_urlgroupr   rg   r   r   r>   _transform_episode_responser   Z_yes_playlistr   r9   rT   playlist_resultr&   r   rH   raise_no_formatsraise_login_requiredr   rs   update)	r)   rt   r*   object_typerf   r   r   messager   r+   r   r,   _real_extract  sJ        


 
zCrunchyrollBetaIE._real_extractc                 C   s  t | dthfddpi }| d ddt|dt|dd	t| d
fdt | d
thfdthdd hfdddddthfdthfdthfdfdt |ddd hfdthfdthfdthfdthfdthfdt	ht
hffdt	ht
hffdd thfd!thfd"
ddS )#N)Zepisode_metadataNFget_allr   u    – z{}{}Zseason_titler   z Episode %srm   )r   rm   r   c                 S   s   |  ddS Nz\r\n
replacexr+   r+   r,   rw     rx   z?CrunchyrollBetaIE._transform_episode_response.<locals>.<lambda>imagesr   .sourcewidthheightrt   r   r   )r   r   
thumbnailsduration_msc                 S   s
   t | dS Ni  r   r   r+   r+   r,   rw     rx   r   Zseries_titler   r   r   Zsequence_numbermaturity_ratingsr   r   )
r   r   r   r   r   r   r   r   r   rV   )r   r   r   r   r	   r   r   r
   r   intr   r   r3   rR   r+   r+   r,   r     sD    
	
z-CrunchyrollBetaIE._transform_episode_responsec                 C   s   t | dthfddpi }d| d it | dthfdthdd hfd	d
dddthfdthfdthfdfdt |ddd hfddthfdS )N)Zmovie_metadatar   NFr   r   rm   r   c                 S   s   |  ddS r   r   r   r+   r+   r,   rw     rx   z=CrunchyrollBetaIE._transform_movie_response.<locals>.<lambda>r   r   .r   r   r   r   )rm   r   r   r   c                 S   s
   t | dS r   r   r   r+   r+   r,   rw     rx   r   r   )r   r   )r   r   r   r   r
   r   r   r+   r+   r,   r     s$     	
z+CrunchyrollBetaIE._transform_movie_responseN)r   r   r   IE_NAME
_VALID_URLr   _TESTSZ_RETURN_TYPEr   staticmethodr   r   r+   r+   r+   r,   rT     s   	l6
 rT   c                   @   s<   e Zd ZdZdZddddddd	d
dddgZdd ZdS )CrunchyrollBetaShowIEzcrunchyroll:playlistz|(?x)
        https?://(?:beta\.|www\.)?crunchyroll\.com/
        (?P<lang>(?:\w{2}(?:-\w{2})?/)?)
        series/(?P<id>\w+)z=https://www.crunchyroll.com/series/GY19NQ2QR/Girl-Friend-BETAZ	GY19NQ2QRzGirl Friend BETAz$md5:99c1b22ee30a74b536a8277ced8eb750r   )r   rm   r   r   r$   r   z0https://beta.crunchyroll.com/it/series/GY19NQ2QRTr   c                    s    |dd\  fdd}j|  ftd   dddd	thfd
dd hfddthfdddddthfdthfdthfdfdfS )Nr^   r   c               	   3   s    d   d} t| ddthfD ]h} d|d  |d d}t|ddthfD ]2}jj d d	|d  tft|V  q\q(d S )
Nzseasons?series_id=Zseasonsr   .zepisodes?season_id=r   zepisode listrX   r   )r   r   r   r   r9   rT   r   )Zseasons_responser   Zepisodes_responseZepisode_responser   r+   r,   r     s       z4CrunchyrollBetaShowIE._real_extract.<locals>.entrieszseries/r   r3   r   rm   r   c                 S   s   |  ddS r   r   r   r+   r+   r,   rw     rx   z5CrunchyrollBetaShowIE._real_extract.<locals>.<lambda>r   r   r   .r   r   r   r   )rm   r   r   r   )	r   r   r   r   rg   r   r   r   r
   )r)   rt   r   r+   r   r,   r     s"    
 
z#CrunchyrollBetaShowIE._real_extractN)r   r   r   r   r   r   r   r+   r+   r+   r,   r     s   r   c                   @   s   e Zd ZdZdZdddddddgd	d
gdddiddddddddgd	dgdddidddddddddgd	dd
gd	ddiddddd ddd!ddgZd"Zd#d$ Zed%d& Z	d'S )(CrunchyrollMusicIEzcrunchyroll:musicz(?x)
        https?://(?:www\.)?crunchyroll\.com/
        (?P<lang>(?:\w{2}(?:-\w{2})?/)?)
        watch/(?P<type>concert|musicvideo)/(?P<id>\w+)z9https://www.crunchyroll.com/de/watch/musicvideo/MV5B02C79r   Z	MV5B02C79zegaono-hanazEgaono HanazGoose housez5re:(?i)^https://www.crunchyroll.com/imgsrv/.*\.jpeg?$J-Pop)r   r   r   rm   trackartistsr   genresr   r   r   z7https://www.crunchyroll.com/watch/musicvideo/MV88BB7F2CZ
MV88BB7F2Czcrossing-fieldzCrossing FieldLiSAAnimer   r   z4https://www.crunchyroll.com/watch/concert/MC2E2AC135Z
MC2E2AC135z/live-is-smile-always-364joker-at-yokohama-arenaz1LiVE is Smile Always-364+JOKER- at YOKOHAMA ARENAz$md5:747444e7e6300907b7a43f0a0503072e)	r   r   r   rm   r  r  r   r   r  zEhttps://www.crunchyroll.com/de/watch/musicvideo/MV5B02C79/egaono-hanaTr   zdhttps://www.crunchyroll.com/watch/concert/MC2E2AC135/live-is-smile-always-364joker-at-yokohama-arenazFhttps://www.crunchyroll.com/watch/musicvideo/MV88BB7F2C/crossing-fieldmusicc                 C   s   |  |ddd\}}}ddd| \}}t| | d| |||dd	thf}|sltd
| ddd| |}| js|drd|dpd d}	t	j
r| j|	d|d q| j|	ddd n| d| |\|d< }
|S )Nr^   r   r   )concertszconcert info)Zmusic_videoszmusic video info)concert
musicvideorX   r3   r   r   r   Tr6   ZisPremiumOnlyr   Zmediar   r   rB   r   zmusic/r   )r   r   r   rg   r   r   _transform_music_responser&   r>   r   rH   r   r   r   )r)   rt   r^   r]   r   re   namer*   rf   r   ru   r+   r+   r,   r   Y  s"    (
z CrunchyrollMusicIE._real_extractc                 C   sf   d| d it | dddddtfdthdd hfd	d
d
dthfdthfdthfdfdddthfdS )Nr   Zslugrm   Zartistr  r   c                 S   s   |  ddpd S r   r   r   r+   r+   r,   rw   y  rx   z>CrunchyrollMusicIE._transform_music_response.<locals>.<lambda>r   .r   r   r   r   r  .ZdisplayValuer   r   )r   rm   r  r  r   r   r  r   )r   r~   r   r   r
   r   r3   r+   r+   r,   r
  p  s$     
z,CrunchyrollMusicIE._transform_music_responseN)
r   r   r   r   r   r   rd   r   r   r
  r+   r+   r+   r,   r     sl   

3r   c                   @   sR   e Zd ZdZdZddddddgd	d
dddddgZdZdd Zedd Z	dS )CrunchyrollArtistIEzcrunchyroll:artistzx(?x)
        https?://(?:www\.)?crunchyroll\.com/
        (?P<lang>(?:\w{2}(?:-\w{2})?/)?)
        artist/(?P<id>\w{10})z-https://www.crunchyroll.com/artist/MA179CB50DZ
MA179CB50Dr  r  r   ZRockz$md5:16d87de61a55c3f7d6c454b73285938e)r   rm   r  r   S   r   z2https://www.crunchyroll.com/artist/MA179CB50D/lisaTr   r  c                    sV    |dd\}}td| ||dd  fdd}j| f S )Nr^   r   zartists/zartist info)r3   r   c               	   3   sH   dD ]>\} }t  | dfD ]&}j d| d| t|V  qqd S )N))r  r  )Zvideosr	  .z/watch/rX   )r   r   r9   r   )	attributere   r]   r*   r)   r+   r,   r     s    z2CrunchyrollArtistIE._real_extract.<locals>.entries)r   r   r   rg   r   _transform_artist_response)r)   rt   r^   r]   r   r+   r  r,   r     s       z!CrunchyrollArtistIE._real_extractc                 C   sP   d| d it | ddthdd hfddddthfd	thfd
thfdfddS )Nr   r  r   c                 S   s   |  ddS r   r   r   r+   r+   r,   rw     rx   z@CrunchyrollArtistIE._transform_artist_response.<locals>.<lambda>r   .r   r   r   r   r  )rm   r   r   r  )r   r   r   r
   r  r+   r+   r,   r    s     z.CrunchyrollArtistIE._transform_artist_responseN)
r   r   r   r   r   r   rd   r   r   r  r+   r+   r+   r,   r    s$   
r  )r   rO   commonr   Z
networkingr   Znetworking.exceptionsr   utilsr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   rT   r   r   r  r+   r+   r+   r,   <module>   s   < ` a1g