1 from __future__
import unicode_literals
7 from .common
import InfoExtractor
22 class LinuxAcademyIE(InfoExtractor
):
25 (?:www\.)?linuxacademy\.com/cp/
27 courses/lesson/course/(?P<chapter_id>\d+)/lesson/(?P<lesson_id>\d+)|
28 modules/view/id/(?P<course_id>\d+)
32 'url': 'https://linuxacademy.com/cp/courses/lesson/course/1498/lesson/2/module/154',
36 'title': "Introduction to the Practitioner's Brief",
39 'skip_download': True,
41 'skip': 'Requires Linux Academy account credentials',
43 'url': 'https://linuxacademy.com/cp/courses/lesson/course/1498/lesson/2',
44 'only_matching': True,
46 'url': 'https://linuxacademy.com/cp/modules/view/id/154',
49 'title': 'AWS Certified Cloud Practitioner',
50 'description': 'md5:039db7e60e4aac9cf43630e0a75fa834',
53 'skip': 'Requires Linux Academy account credentials',
56 _AUTHORIZE_URL
= 'https://login.linuxacademy.com/authorize'
57 _ORIGIN_URL
= 'https://linuxacademy.com'
58 _CLIENT_ID
= 'KaWxNn1C2Gc7n83W9OFeXltd8Utb5vvx'
59 _NETRC_MACHINE
= 'linuxacademy'
61 def _real_initialize(self
):
65 username
, password
= self
._get
_login
_info
()
71 random
.choice('0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~')
74 webpage
, urlh
= self
._download
_webpage
_handle
(
75 self
._AUTHORIZE
_URL
, None, 'Downloading authorize page', query
={
76 'client_id': self
._CLIENT
_ID
,
77 'response_type': 'token id_token',
78 'redirect_uri': self
._ORIGIN
_URL
,
79 'scope': 'openid email user_impersonation profile',
80 'audience': self
._ORIGIN
_URL
,
81 'state': random_string(),
82 'nonce': random_string(),
85 login_data
= self
._parse
_json
(
87 r
'atob\(\s*(["\'])(?P
<value
>(?
:(?
!\
1).)+)\
1', webpage,
88 'login info
', group='value
'), None,
89 transform_source=lambda x: compat_b64decode(x).decode('utf
-8')
93 'client_id
': self._CLIENT_ID,
94 'redirect_uri
': self._ORIGIN_URL,
95 'tenant
': 'lacausers
',
96 'connection
': 'Username
-Password
-Authentication
',
102 login_state_url = compat_str(urlh.geturl())
105 login_page = self._download_webpage(
106 'https
://login
.linuxacademy
.com
/usernamepassword
/login
', None,
107 'Downloading login page
', data=json.dumps(login_data).encode(),
109 'Content
-Type
': 'application
/json
',
110 'Origin
': 'https
://login
.linuxacademy
.com
',
111 'Referer
': login_state_url,
113 except ExtractorError as e:
114 if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:
115 error = self._parse_json(e.cause.read(), None)
116 message = error.get('description
') or error['code
']
117 raise ExtractorError(
118 '%s said
: %s' % (self.IE_NAME, message), expected=True)
121 callback_page, urlh = self._download_webpage_handle(
122 'https
://login
.linuxacademy
.com
/login
/callback
', None,
123 'Downloading callback page
',
124 data=urlencode_postdata(self._hidden_inputs(login_page)),
126 'Content
-Type
': 'application
/x
-www
-form
-urlencoded
',
127 'Origin
': 'https
://login
.linuxacademy
.com
',
128 'Referer
': login_state_url,
131 access_token = self._search_regex(
132 r'access_token
=([^
=&]+)', compat_str(urlh.geturl()),
135 self._download_webpage(
136 'https
://linuxacademy
.com
/cp
/login
/tokenValidateLogin
/token
/%s'
137 % access_token, None, 'Downloading token validation page
')
139 def _real_extract(self, url):
140 mobj = re.match(self._VALID_URL, url)
141 chapter_id, lecture_id, course_id = mobj.group('chapter_id
', 'lesson_id
', 'course_id
')
142 item_id = course_id if course_id else '%s-%s' % (chapter_id, lecture_id)
144 webpage = self._download_webpage(url, item_id)
150 urljoin(url, lesson_url), ie=LinuxAcademyIE.ie_key())
151 for lesson_url in orderedSet(re.findall(
152 r'<a
[^
>]+\bhref
=["\'](/cp/courses/lesson/course/\d+/lesson/\d+/module/\d+)',
154 title = unescapeHTML(self._html_search_regex(
155 (r'class=["\']course
-title
["\'][^>]*>(?P<value>[^<]+)',
156 r'var\s+title\s*=\s*(["\'])(?P
<value
>(?
:(?
!\
1).)+)\
1'),
157 webpage, 'title
', default=None, group='value
'))
158 description = unescapeHTML(self._html_search_regex(
159 r'var\s
+description\s
*=\s
*(["\'])(?P<value>(?:(?!\1).)+)\1',
160 webpage, 'description', default=None, group='value'))
161 return self.playlist_result(entries, course_id, title, description)
164 info = self._extract_jwplayer_data(
165 webpage, item_id, require_title=False, m3u8_id='hls',)
166 title = self._search_regex(
167 (r'>Lecture\s*:\s*(?P<value>[^<]+)',
168 r'lessonName\s*=\s*(["\'])(?P
<value
>(?
:(?
!\
1).)+)\
1'), webpage,
169 'title
', group='value
')