]>
jfr.im git - yt-dlp.git/blob - youtube_dl/extractor/noco.py
2 from __future__
import unicode_literals
8 from .common
import InfoExtractor
10 compat_urllib_request
,
19 class NocoIE(InfoExtractor
):
20 _VALID_URL
= r
'http://(?:(?:www\.)?noco\.tv/emission/|player\.noco\.tv/\?idvideo=)(?P<id>\d+)'
21 _LOGIN_URL
= 'http://noco.tv/do.php'
22 _API_URL_TEMPLATE
= 'https://api.noco.tv/1.1/%s?ts=%s&tk=%s'
23 _NETRC_MACHINE
= 'noco'
26 'url': 'http://noco.tv/emission/11538/nolife/ami-ami-idol-hello-france/',
27 'md5': '0a993f0058ddbcd902630b2047ef710e',
31 'title': 'Ami Ami Idol - Hello! France',
32 'description': 'md5:4eaab46ab68fa4197a317a88a53d3b86',
33 'upload_date': '20140412',
38 'skip': 'Requires noco account',
41 def _real_initialize(self
):
45 (username
, password
) = self
._get
_login
_info
()
55 request
= compat_urllib_request
.Request(self
._LOGIN
_URL
, compat_urllib_parse
.urlencode(login_form
))
56 request
.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
58 login
= self
._download
_json
(request
, None, 'Logging in as %s' % username
)
61 raise ExtractorError('Unable to login: %s' % clean_html(login
['erreur']), expected
=True)
63 def _call_api(self
, path
, video_id
, note
):
64 ts
= compat_str(int(time
.time() * 1000))
65 tk
= hashlib
.md5(hashlib
.md5(ts
).hexdigest() + '#8S?uCraTedap6a').hexdigest()
66 url
= self
._API
_URL
_TEMPLATE
% (path
, ts
, tk
)
68 resp
= self
._download
_json
(url
, video_id
, note
)
70 if isinstance(resp
, dict) and resp
.get('error'):
71 self
._raise
_error
(resp
['error'], resp
['description'])
75 def _raise_error(self
, error
, description
):
77 '%s returned error: %s - %s' % (self
.IE_NAME
, error
, description
),
80 def _real_extract(self
, url
):
81 mobj
= re
.match(self
._VALID
_URL
, url
)
82 video_id
= mobj
.group('id')
84 medias
= self
._call
_api
(
85 'shows/%s/medias' % video_id
,
86 video_id
, 'Downloading video JSON')
88 qualities
= self
._call
_api
(
90 video_id
, 'Downloading qualities JSON')
94 for format_id
, fmt
in medias
['fr']['video_list']['none']['quality_list'].items():
96 video
= self
._call
_api
(
97 'shows/%s/video/%s/fr' % (video_id
, format_id
.lower()),
98 video_id
, 'Downloading %s video JSON' % format_id
)
100 file_url
= video
['file']
104 if file_url
in ['forbidden', 'not found']:
105 popmessage
= video
['popmessage']
106 self
._raise
_error
(popmessage
['title'], popmessage
['message'])
110 'format_id': format_id
,
111 'width': fmt
['res_width'],
112 'height': fmt
['res_lines'],
113 'abr': fmt
['audiobitrate'],
114 'vbr': fmt
['videobitrate'],
115 'filesize': fmt
['filesize'],
116 'format_note': qualities
[format_id
]['quality_name'],
117 'preference': qualities
[format_id
]['priority'],
120 self
._sort
_formats
(formats
)
122 show
= self
._call
_api
(
123 'shows/by_id/%s' % video_id
,
124 video_id
, 'Downloading show JSON')[0]
126 upload_date
= unified_strdate(show
['online_date_start_utc'])
127 uploader
= show
['partner_name']
128 uploader_id
= show
['partner_key']
129 duration
= show
['duration_ms'] / 1000.0
132 for thumbnail_key
, thumbnail_url
in show
.items():
133 m
= re
.search(r
'^screenshot_(?P<width>\d+)x(?P<height>\d+)$', thumbnail_key
)
137 'url': thumbnail_url
,
138 'width': int(m
.group('width')),
139 'height': int(m
.group('height')),
142 episode
= show
.get('show_TT') or show
.get('show_OT')
143 family
= show
.get('family_TT') or show
.get('family_OT')
144 episode_number
= show
.get('episode_number')
150 title
+= ' #' + compat_str(episode_number
)
152 title
+= ' - ' + episode
154 description
= show
.get('show_resume') or show
.get('family_resume')
159 'description': description
,
160 'thumbnails': thumbnails
,
161 'upload_date': upload_date
,
162 'uploader': uploader
,
163 'uploader_id': uploader_id
,
164 'duration': duration
,