]>
Raphaël G. Git Repositories - youtubedl/blob - youtube_dl/extractor/adn.py
   2 from __future__ 
import unicode_literals
 
  10 from .common 
import InfoExtractor
 
  11 from ..aes 
import aes_cbc_decrypt
 
  12 from ..compat 
import ( 
  24     srt_subtitles_timecode
, 
  30 class ADNIE(InfoExtractor
): 
  31     IE_DESC 
= 'Anime Digital Network' 
  32     _VALID_URL 
= r
'https?://(?:www\.)?animedigitalnetwork\.fr/video/[^/]+/(?P<id>\d+)' 
  34         'url': 'http://animedigitalnetwork.fr/video/blue-exorcist-kyoto-saga/7778-episode-1-debut-des-hostilites', 
  35         'md5': 'e497370d847fd79d9d4c74be55575c7a', 
  39             'title': 'Blue Exorcist - Kyôto Saga - Épisode 1', 
  40             'description': 'md5:2f7b5aa76edbc1a7a92cedcda8a528d5', 
  43     _BASE_URL 
= 'http://animedigitalnetwork.fr' 
  44     _RSA_KEY 
= (0xc35ae1e4356b65a73b551493da94b8cb443491c0aa092a357a5aee57ffc14dda85326f42d716e539a34542a0d3f363adf16c5ec222d713d5997194030ee2e4f0d1fb328c01a81cf6868c090d50de8e169c6b13d1675b9eeed1cbc51e1fffca9b38af07f37abd790924cd3bee59d0257cfda4fe5f3f0534877e21ce5821447d1b, 65537) 
  46     def _get_subtitles(self
, sub_path
, video_id
): 
  50         enc_subtitles 
= self
._download
_webpage
( 
  51             urljoin(self
._BASE
_URL
, sub_path
), 
  52             video_id
, fatal
=False) 
  56         # http://animedigitalnetwork.fr/components/com_vodvideo/videojs/adn-vjs.min.js 
  57         dec_subtitles 
= intlist_to_bytes(aes_cbc_decrypt( 
  58             bytes_to_intlist(compat_b64decode(enc_subtitles
[24:])), 
  59             bytes_to_intlist(binascii
.unhexlify(self
._K 
+ '9032ad7083106400')), 
  60             bytes_to_intlist(compat_b64decode(enc_subtitles
[:24])) 
  62         subtitles_json 
= self
._parse
_json
( 
  63             dec_subtitles
[:-compat_ord(dec_subtitles
[-1])].decode(), 
  65         if not subtitles_json
: 
  69         for sub_lang
, sub 
in subtitles_json
.items(): 
  71             for num
, current 
in enumerate(sub
): 
  73                     float_or_none(current
.get('startTime')), 
  74                     float_or_none(current
.get('endTime')), 
  76                 if start 
is None or end 
is None or text 
is None: 
  78                 srt 
+= os
.linesep
.join( 
  82                             srt_subtitles_timecode(start
), 
  83                             srt_subtitles_timecode(end
)), 
  88             if sub_lang 
== 'vostf': 
  90             subtitles
.setdefault(sub_lang
, []).extend([{ 
  92                 'data': json
.dumps(sub
), 
  99     def _real_extract(self
, url
): 
 100         video_id 
= self
._match
_id
(url
) 
 101         webpage 
= self
._download
_webpage
(url
, video_id
) 
 102         player_config 
= self
._parse
_json
(self
._search
_regex
( 
 103             r
'playerConfig\s*=\s*({.+});', webpage
, 'player config'), video_id
) 
 106         video_info_str 
= self
._search
_regex
( 
 107             r
'videoInfo\s*=\s*({.+});', webpage
, 
 108             'video info', fatal
=False) 
 110             video_info 
= self
._parse
_json
( 
 111                 video_info_str
, video_id
, fatal
=False) or {} 
 113         options 
= player_config
.get('options') or {} 
 114         metas 
= options
.get('metas') or {} 
 115         links 
= player_config
.get('links') or {} 
 116         sub_path 
= player_config
.get('subtitles') 
 119             links_url 
= player_config
.get('linksurl') or options
['videoUrl'] 
 120             token 
= options
['token'] 
 121             self
._K 
= ''.join([random
.choice('0123456789abcdef') for _ 
in range(16)]) 
 122             message 
= bytes_to_intlist(json
.dumps({ 
 127             padded_message 
= intlist_to_bytes(pkcs1pad(message
, 128)) 
 129             encrypted_message 
= long_to_bytes(pow(bytes_to_long(padded_message
), e
, n
)) 
 130             authorization 
= base64
.b64encode(encrypted_message
).decode() 
 131             links_data 
= self
._download
_json
( 
 132                 urljoin(self
._BASE
_URL
, links_url
), video_id
, headers
={ 
 133                     'Authorization': 'Bearer ' + authorization
, 
 135             links 
= links_data
.get('links') or {} 
 136             metas 
= metas 
or links_data
.get('meta') or {} 
 137             sub_path 
= (sub_path 
or links_data
.get('subtitles')) + '&token=' + token
 
 138             error 
= links_data
.get('error') 
 139         title 
= metas
.get('title') or video_info
['title'] 
 142         for format_id
, qualities 
in links
.items(): 
 143             if not isinstance(qualities
, dict): 
 145             for load_balancer_url 
in qualities
.values(): 
 146                 load_balancer_data 
= self
._download
_json
( 
 147                     load_balancer_url
, video_id
, fatal
=False) or {} 
 148                 m3u8_url 
= load_balancer_data
.get('location') 
 151                 m3u8_formats 
= self
._extract
_m
3u8_formats
( 
 152                     m3u8_url
, video_id
, 'mp4', 'm3u8_native', 
 153                     m3u8_id
=format_id
, fatal
=False) 
 154                 if format_id 
== 'vf': 
 155                     for f 
in m3u8_formats
: 
 157                 formats
.extend(m3u8_formats
) 
 159             error 
= options
.get('error') 
 160         if not formats 
and error
: 
 161             raise ExtractorError('%s said: %s' % (self
.IE_NAME
, error
), expected
=True) 
 162         self
._sort
_formats
(formats
) 
 167             'description': strip_or_none(metas
.get('summary') or video_info
.get('resume')), 
 168             'thumbnail': video_info
.get('image'), 
 170             'subtitles': self
.extract_subtitles(sub_path
, video_id
), 
 171             'episode': metas
.get('subtitle') or video_info
.get('videoTitle'), 
 172             'series': video_info
.get('playlistTitle'),