diff options
author | Pccode66 <49125134+Pccode66@users.noreply.github.com> | 2021-02-24 15:45:56 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-25 00:15:56 +0530 |
commit | 7a5c1cfe93924351387b44919b3c0b2f66c4b883 (patch) | |
tree | 6da63f3d7b16cf7d4b9fdb29b029125cab8bd0d3 /yt_dlp/extractor/egghead.py | |
parent | c4218ac3f1146daac20308439cdc374e3561101a (diff) |
Completely change project name to yt-dlp (#85)
* All modules and binary names are changed
* All documentation references changed
* yt-dlp no longer loads youtube-dlc config files
* All URLs changed to point to organization account
Co-authored-by: Pccode66
Co-authored-by: pukkandan
Diffstat (limited to 'yt_dlp/extractor/egghead.py')
-rw-r--r-- | yt_dlp/extractor/egghead.py | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/yt_dlp/extractor/egghead.py b/yt_dlp/extractor/egghead.py new file mode 100644 index 000000000..aff9b88c0 --- /dev/null +++ b/yt_dlp/extractor/egghead.py @@ -0,0 +1,134 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor +from ..compat import compat_str +from ..utils import ( + determine_ext, + int_or_none, + try_get, + unified_timestamp, + url_or_none, +) + + +class EggheadBaseIE(InfoExtractor): + def _call_api(self, path, video_id, resource, fatal=True): + return self._download_json( + 'https://app.egghead.io/api/v1/' + path, + video_id, 'Downloading %s JSON' % resource, fatal=fatal) + + +class EggheadCourseIE(EggheadBaseIE): + IE_DESC = 'egghead.io course' + IE_NAME = 'egghead:course' + _VALID_URL = r'https://egghead\.io/courses/(?P<id>[^/?#&]+)' + _TEST = { + 'url': 'https://egghead.io/courses/professor-frisby-introduces-composable-functional-javascript', + 'playlist_count': 29, + 'info_dict': { + 'id': '72', + '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) + series_path = 'series/' + playlist_id + lessons = self._call_api( + series_path + '/lessons', playlist_id, 'course lessons') + + entries = [] + for lesson in lessons: + lesson_url = url_or_none(lesson.get('http_url')) + if not lesson_url: + 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)) + + course = self._call_api( + series_path, playlist_id, 'course', False) or {} + + playlist_id = course.get('id') + if playlist_id: + playlist_id = compat_str(playlist_id) + + return self.playlist_result( + entries, playlist_id, course.get('title'), + course.get('description')) + + +class EggheadLessonIE(EggheadBaseIE): + IE_DESC = 'egghead.io lesson' + IE_NAME = 'egghead:lesson' + _VALID_URL = r'https://egghead\.io/(?:api/v1/)?lessons/(?P<id>[^/?#&]+)' + _TESTS = [{ + 'url': 'https://egghead.io/lessons/javascript-linear-data-flow-with-container-style-types-box', + 'info_dict': { + 'id': '1196', + 'display_id': 'javascript-linear-data-flow-with-container-style-types-box', + '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': 'count:2', + }, + 'params': { + 'skip_download': True, + 'format': 'bestvideo', + }, + }, { + 'url': 'https://egghead.io/api/v1/lessons/react-add-redux-to-a-react-application', + 'only_matching': True, + }] + + def _real_extract(self, url): + display_id = self._match_id(url) + + lesson = self._call_api( + 'lessons/' + display_id, display_id, 'lesson') + + lesson_id = compat_str(lesson['id']) + title = lesson['title'] + + formats = [] + for _, format_url in lesson['media_urls'].items(): + format_url = url_or_none(format_url) + if not format_url: + 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) + + return { + 'id': lesson_id, + 'display_id': display_id, + 'title': title, + '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), + 'series': try_get( + lesson, lambda x: x['series']['title'], compat_str), + 'formats': formats, + } |