| 
									
										
										
										
											2017-01-09 11:24:40 +01:00
										 |  |  | # coding: utf-8 | 
					
						
							|  |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .common import InfoExtractor | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  | from ..compat import compat_str | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  | from ..utils import ( | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |     determine_ext, | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  |     int_or_none, | 
					
						
							|  |  |  |     try_get, | 
					
						
							|  |  |  |     unified_timestamp, | 
					
						
							| 
									
										
										
										
											2018-07-21 19:08:28 +07:00
										 |  |  |     url_or_none, | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-01-09 11:24:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EggheadCourseIE(InfoExtractor): | 
					
						
							|  |  |  |     IE_DESC = 'egghead.io course' | 
					
						
							|  |  |  |     IE_NAME = 'egghead:course' | 
					
						
							| 
									
										
										
										
											2017-07-09 17:28:42 +07:00
										 |  |  |     _VALID_URL = r'https://egghead\.io/courses/(?P<id>[^/?#&]+)' | 
					
						
							| 
									
										
										
										
											2017-01-09 11:24:40 +01:00
										 |  |  |     _TEST = { | 
					
						
							|  |  |  |         'url': 'https://egghead.io/courses/professor-frisby-introduces-composable-functional-javascript', | 
					
						
							|  |  |  |         'playlist_count': 29, | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'id': '72', | 
					
						
							| 
									
										
										
										
											2017-01-09 11:24:40 +01:00
										 |  |  |             'title': 'Professor Frisby Introduces Composable Functional JavaScript', | 
					
						
							|  |  |  |             'description': 're:(?s)^This course teaches the ubiquitous.*You\'ll start composing functionality before you know it.$', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         playlist_id = self._match_id(url) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |         lessons = self._download_json( | 
					
						
							|  |  |  |             'https://egghead.io/api/v1/series/%s/lessons' % playlist_id, | 
					
						
							|  |  |  |             playlist_id, 'Downloading course lessons JSON') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         entries = [] | 
					
						
							|  |  |  |         for lesson in lessons: | 
					
						
							| 
									
										
										
										
											2018-07-21 19:08:28 +07:00
										 |  |  |             lesson_url = url_or_none(lesson.get('http_url')) | 
					
						
							|  |  |  |             if not lesson_url: | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             lesson_id = lesson.get('id') | 
					
						
							|  |  |  |             if lesson_id: | 
					
						
							|  |  |  |                 lesson_id = compat_str(lesson_id) | 
					
						
							|  |  |  |             entries.append(self.url_result( | 
					
						
							|  |  |  |                 lesson_url, ie=EggheadLessonIE.ie_key(), video_id=lesson_id)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-09 17:28:42 +07:00
										 |  |  |         course = self._download_json( | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'https://egghead.io/api/v1/series/%s' % playlist_id, | 
					
						
							|  |  |  |             playlist_id, 'Downloading course JSON', fatal=False) or {} | 
					
						
							| 
									
										
										
										
											2017-01-09 11:24:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |         playlist_id = course.get('id') | 
					
						
							|  |  |  |         if playlist_id: | 
					
						
							|  |  |  |             playlist_id = compat_str(playlist_id) | 
					
						
							| 
									
										
										
										
											2017-07-09 17:28:42 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return self.playlist_result( | 
					
						
							|  |  |  |             entries, playlist_id, course.get('title'), | 
					
						
							|  |  |  |             course.get('description')) | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EggheadLessonIE(InfoExtractor): | 
					
						
							|  |  |  |     IE_DESC = 'egghead.io lesson' | 
					
						
							|  |  |  |     IE_NAME = 'egghead:lesson' | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |     _VALID_URL = r'https://egghead\.io/(?:api/v1/)?lessons/(?P<id>[^/?#&]+)' | 
					
						
							|  |  |  |     _TESTS = [{ | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  |         'url': 'https://egghead.io/lessons/javascript-linear-data-flow-with-container-style-types-box', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'id': '1196', | 
					
						
							|  |  |  |             'display_id': 'javascript-linear-data-flow-with-container-style-types-box', | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'Create linear data flow with container style types (Box)', | 
					
						
							|  |  |  |             'description': 'md5:9aa2cdb6f9878ed4c39ec09e85a8150e', | 
					
						
							|  |  |  |             'thumbnail': r're:^https?:.*\.jpg$', | 
					
						
							|  |  |  |             'timestamp': 1481296768, | 
					
						
							|  |  |  |             'upload_date': '20161209', | 
					
						
							|  |  |  |             'duration': 304, | 
					
						
							|  |  |  |             'view_count': 0, | 
					
						
							|  |  |  |             'tags': ['javascript', 'free'], | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'params': { | 
					
						
							|  |  |  |             'skip_download': True, | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'format': 'bestvideo', | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |     }, { | 
					
						
							|  |  |  |         'url': 'https://egghead.io/api/v1/lessons/react-add-redux-to-a-react-application', | 
					
						
							|  |  |  |         'only_matching': True, | 
					
						
							|  |  |  |     }] | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |         display_id = self._match_id(url) | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         lesson = self._download_json( | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'https://egghead.io/api/v1/lessons/%s' % display_id, display_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lesson_id = compat_str(lesson['id']) | 
					
						
							|  |  |  |         title = lesson['title'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         formats = [] | 
					
						
							|  |  |  |         for _, format_url in lesson['media_urls'].items(): | 
					
						
							| 
									
										
										
										
											2018-07-21 19:08:28 +07:00
										 |  |  |             format_url = url_or_none(format_url) | 
					
						
							|  |  |  |             if not format_url: | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             ext = determine_ext(format_url) | 
					
						
							|  |  |  |             if ext == 'm3u8': | 
					
						
							|  |  |  |                 formats.extend(self._extract_m3u8_formats( | 
					
						
							|  |  |  |                     format_url, lesson_id, 'mp4', entry_protocol='m3u8', | 
					
						
							|  |  |  |                     m3u8_id='hls', fatal=False)) | 
					
						
							|  |  |  |             elif ext == 'mpd': | 
					
						
							|  |  |  |                 formats.extend(self._extract_mpd_formats( | 
					
						
							|  |  |  |                     format_url, lesson_id, mpd_id='dash', fatal=False)) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 formats.append({ | 
					
						
							|  |  |  |                     'url': format_url, | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |         self._sort_formats(formats) | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'id': lesson_id, | 
					
						
							|  |  |  |             'display_id': display_id, | 
					
						
							|  |  |  |             'title': title, | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  |             'description': lesson.get('summary'), | 
					
						
							|  |  |  |             'thumbnail': lesson.get('thumb_nail'), | 
					
						
							|  |  |  |             'timestamp': unified_timestamp(lesson.get('published_at')), | 
					
						
							|  |  |  |             'duration': int_or_none(lesson.get('duration')), | 
					
						
							|  |  |  |             'view_count': int_or_none(lesson.get('plays_count')), | 
					
						
							|  |  |  |             'tags': try_get(lesson, lambda x: x['tag_list'], list), | 
					
						
							| 
									
										
										
										
											2017-10-29 07:11:37 +07:00
										 |  |  |             'series': try_get( | 
					
						
							|  |  |  |                 lesson, lambda x: x['series']['title'], compat_str), | 
					
						
							|  |  |  |             'formats': formats, | 
					
						
							| 
									
										
										
										
											2017-07-20 23:22:36 +07:00
										 |  |  |         } |