3 from .common
import InfoExtractor
4 from ..networking
import Request
5 from ..networking
.exceptions
import HTTPError
15 class HRTiBaseIE(InfoExtractor
):
17 Base Information Extractor for Croatian Radiotelevision
18 video on demand site https://hrti.hrt.hr
19 Reverse engineered from the JavaScript app in app.min.js
21 _NETRC_MACHINE
= 'hrti'
25 _APP_PUBLICATION_ID
= 'all_in_one'
26 _API_URL
= 'http://clientapi.hrt.hr/client_api.php/config/identify/format/json'
29 def _initialize_pre_login(self
):
31 'application_publication_id': self
._APP
_PUBLICATION
_ID
,
34 uuid
= self
._download
_json
(
35 self
._API
_URL
, None, note
='Downloading uuid',
36 errnote
='Unable to download uuid',
37 data
=json
.dumps(init_data
).encode())['uuid']
41 'application_publication_id': self
._APP
_PUBLICATION
_ID
,
42 'application_version': self
._APP
_VERSION
,
45 req
= Request(self
._API
_URL
, data
=json
.dumps(app_data
).encode())
46 req
.get_method
= lambda: 'PUT'
48 resources
= self
._download
_json
(
49 req
, None, note
='Downloading session information',
50 errnote
='Unable to download session information')
52 self
._session
_id
= resources
['session_id']
54 modules
= resources
['modules']
56 self
._search
_url
= modules
['vod_catalog']['resources']['search']['uri'].format(
57 language
=self
._APP
_LANGUAGE
,
58 application_id
=self
._APP
_PUBLICATION
_ID
)
60 self
._login
_url
= (modules
['user']['resources']['login']['uri']
61 + '/format/json').format(session_id
=self
._session
_id
)
63 self
._logout
_url
= modules
['user']['resources']['logout']['uri']
65 def _perform_login(self
, username
, password
):
72 auth_info
= self
._download
_json
(
73 self
._login
_url
, None, note
='Logging in', errnote
='Unable to log in',
74 data
=json
.dumps(auth_data
).encode())
75 except ExtractorError
as e
:
76 if isinstance(e
.cause
, HTTPError
) and e
.cause
.status
== 406:
77 auth_info
= self
._parse
_json
(e
.cause
.response
.read().encode(), None)
81 error_message
= auth_info
.get('error', {}).get('message')
84 f
'{self.IE_NAME} said: {error_message}',
87 self
._token
= auth_info
['secure_streaming_token']
89 def _real_initialize(self
):
91 # TODO: figure out authentication with cookies
92 self
.raise_login_required(method
='password')
95 class HRTiIE(HRTiBaseIE
):
98 hrti:(?P<short_id>[0-9]+)|
100 hrti\.hrt\.hr/(?:\#/)?video/show/(?P<id>[0-9]+)/(?P<display_id>[^/]+)?
104 'url': 'https://hrti.hrt.hr/#/video/show/2181385/republika-dokumentarna-serija-16-hd',
107 'display_id': 'republika-dokumentarna-serija-16-hd',
109 'title': 'REPUBLIKA, dokumentarna serija (1/6) (HD)',
110 'description': 'md5:48af85f620e8e0e1df4096270568544f',
113 'average_rating': int,
114 'episode_number': int,
115 'season_number': int,
118 'skip': 'Requires account credentials',
120 'url': 'https://hrti.hrt.hr/#/video/show/2181385/',
121 'only_matching': True,
123 'url': 'hrti:2181385',
124 'only_matching': True,
126 'url': 'https://hrti.hrt.hr/video/show/3873068/cuvar-dvorca-dramska-serija-14',
127 'only_matching': True,
130 def _real_extract(self
, url
):
131 mobj
= self
._match
_valid
_url
(url
)
132 video_id
= mobj
.group('short_id') or mobj
.group('id')
133 display_id
= mobj
.group('display_id') or video_id
135 video
= self
._download
_json
(
136 f
'{self._search_url}/video_id/{video_id}/format/json',
137 display_id
, 'Downloading video metadata JSON')['video'][0]
139 title_info
= video
['title']
140 title
= title_info
['title_long']
142 movie
= video
['video_assets']['movie'][0]
143 m3u8_url
= movie
['url'].format(TOKEN
=self
._token
)
144 formats
= self
._extract
_m
3u8_formats
(
145 m3u8_url
, display_id
, 'mp4', entry_protocol
='m3u8_native',
148 description
= clean_html(title_info
.get('summary_long'))
149 age_limit
= parse_age_limit(video
.get('parental_control', {}).get('rating'))
150 view_count
= int_or_none(video
.get('views'))
151 average_rating
= int_or_none(video
.get('user_rating'))
152 duration
= int_or_none(movie
.get('duration'))
156 'display_id': display_id
,
158 'description': description
,
159 'duration': duration
,
160 'view_count': view_count
,
161 'average_rating': average_rating
,
162 'age_limit': age_limit
,
167 class HRTiPlaylistIE(HRTiBaseIE
):
168 _VALID_URL
= r
'https?://hrti\.hrt\.hr/(?:#/)?video/list/category/(?P<id>[0-9]+)/(?P<display_id>[^/]+)?'
170 'url': 'https://hrti.hrt.hr/#/video/list/category/212/ekumena',
175 'playlist_mincount': 8,
176 'skip': 'Requires account credentials',
178 'url': 'https://hrti.hrt.hr/#/video/list/category/212/',
179 'only_matching': True,
181 'url': 'https://hrti.hrt.hr/video/list/category/212/ekumena',
182 'only_matching': True,
185 def _real_extract(self
, url
):
186 mobj
= self
._match
_valid
_url
(url
)
187 category_id
= mobj
.group('id')
188 display_id
= mobj
.group('display_id') or category_id
190 response
= self
._download
_json
(
191 f
'{self._search_url}/category_id/{category_id}/format/json',
192 display_id
, 'Downloading video metadata JSON')
195 response
, lambda x
: x
['video_listings'][0]['alternatives'][0]['list'],
196 list) or [video
['id'] for video
in response
.get('videos', []) if video
.get('id')]
198 entries
= [self
.url_result(f
'hrti:{video_id}') for video_id
in video_ids
]
200 return self
.playlist_result(entries
, category_id
, display_id
)