3 from .common
import InfoExtractor
12 class ITProTVBaseIE(InfoExtractor
):
14 'course': 'course?url={}&brand=00002560-0000-3fa9-0000-1d61000035f3',
15 'episode': 'brand/00002560-0000-3fa9-0000-1d61000035f3/episode?url={}'
18 def _call_api(self
, ep
, item_id
, webpage
):
19 return self
._download
_json
(
20 f
'https://api.itpro.tv/api/urza/v3/consumer-web/{self._ENDPOINTS[ep].format(item_id)}',
21 item_id
, note
=f
'Fetching {ep} data API',
22 headers
={'Authorization': f'Bearer {self._fetch_jwt(webpage)}
'})[ep]
24 def _fetch_jwt(self, webpage):
25 return self._search_regex(r'{"passedToken":"([\w-]+\.[\w-]+\.[\w-]+)",', webpage, 'jwt
')
27 def _check_if_logged_in(self, webpage):
28 if re.match(r'{\s
*member\s
*:\s
*null
', webpage):
29 self.raise_login_required()
32 class ITProTVIE(ITProTVBaseIE):
33 _VALID_URL = r'https?
://app\
.itpro\
.tv
/course
/(?P
<course
>[\w
-]+)/(?P
<id>[\w
-]+)'
35 'url
': 'https
://app
.itpro
.tv
/course
/guided
-tour
/introductionitprotv
',
36 'md5
': 'bca4a28c2667fd1a63052e71a94bb88c
',
38 'id': 'introductionitprotv
',
40 'title
': 'An Introduction to ITProTV
101',
41 'thumbnail
': 'https
://itprotv
-image
-bucket
.s3
.amazonaws
.com
/getting
-started
/itprotv
-101-introduction
-PGM
.11_39_56_02.Still001
.png
',
42 'description
': 'md5
:b175c2c3061ce35a4dd33865b2c1da4e
',
44 'series
': 'ITProTV
101',
45 'series_id
': 'guided
-tour
',
46 'availability
': 'needs_auth
',
47 'chapter
': 'ITProTV
101',
49 'chapter_id
': '5dbb3de426b46c0010b5d1b6
'
53 'url
': 'https
://app
.itpro
.tv
/course
/beyond
-tech
/job
-interview
-tips
',
54 'md5
': '101a299b98c47ccf4c67f9f0951defa8
',
56 'id': 'job
-interview
-tips
',
58 'title
': 'Job Interview Tips
',
59 'thumbnail
': 'https
://s3
.amazonaws
.com
:443/production
-itprotv
-thumbnails
/2f370bf5
-294d
-4bbe
-ab80
-c0b5781630ea
.png
',
60 'description
': 'md5
:30d8ba483febdf89ec85623aad3c3cb6
',
62 'series
': 'Beyond Tech
',
63 'series_id
': 'beyond
-tech
',
64 'availability
': 'needs_auth
',
65 'chapter
': 'Job Development
',
67 'chapter_id
': '5f7c78d424330c000edf04d9
'
71 def _real_extract(self, url):
72 episode_id, course_name = self._match_valid_url(url).group('id', 'course
')
73 webpage = self._download_webpage(url, episode_id)
74 self._check_if_logged_in(webpage)
75 course = self._call_api('course
', course_name, webpage)
76 episode = self._call_api('episode
', episode_id, webpage)
78 chapter_number, chapter = next((
79 (i, topic) for i, topic in enumerate(course.get('topics
') or [], 1)
80 if traverse_obj(topic, 'id') == episode.get('topic
')), {})
84 'title
': episode.get('title
'),
85 'description
': episode.get('description
'),
86 'thumbnail
': episode.get('thumbnail
'),
88 {'url': episode[f'jwVideo{h}Embed'], 'height': h
}
89 for h
in (320, 480, 720, 1080) if episode
.get(f
'jwVideo{h}Embed')
91 'duration': int_or_none(episode
.get('length')),
92 'series': course
.get('name'),
93 'series_id': course
.get('url'),
94 'chapter': str_or_none(chapter
.get('title')),
95 'chapter_number': chapter_number
,
96 'chapter_id': str_or_none(chapter
.get('id')),
98 'en': [{'ext': 'vtt', 'data': episode['enCaptionData']}
]
99 } if episode
.get('enCaptionData') else None,
103 class ITProTVCourseIE(ITProTVBaseIE
):
104 _VALID_URL
= r
'https?://app\.itpro\.tv/course/(?P<id>[\w-]+)/?(?:$|[#?])'
107 'url': 'https://app.itpro.tv/course/guided-tour',
110 'description': 'md5:b175c2c3061ce35a4dd33865b2c1da4e',
111 'title': 'ITProTV 101',
116 'url': 'https://app.itpro.tv/course/beyond-tech',
119 'description': 'md5:44cd99855e7f81a15ce1269bd0621fed',
120 'title': 'Beyond Tech'
126 def _real_extract(self
, url
):
127 course_id
= self
._match
_id
(url
)
128 webpage
= self
._download
_webpage
(url
, course_id
)
129 self
._check
_if
_logged
_in
(webpage
)
130 course
= self
._call
_api
('course', course_id
, webpage
)
132 entries
= [self
.url_result(
133 urljoin(url
, f
'{course_id}/{episode["url"]}'), ITProTVIE
,
134 episode
['url'], episode
.get('title'), url_transparent
=True)
135 for episode
in course
['episodes']]
137 return self
.playlist_result(
138 entries
, course_id
, course
.get('name'), course
.get('description'))