From 5abcd988a2bbbccbd8496ec255dd771f02bfef27 Mon Sep 17 00:00:00 2001 From: Valeriy Litkovskyy Date: Sat, 30 Apr 2022 20:10:49 +0200 Subject: [PATCH] [cozytv] Add new extractor --- youtube_dl/extractor/cozytv.py | 172 +++++++++++++++++++++++++++++ youtube_dl/extractor/extractors.py | 4 + 2 files changed, 176 insertions(+) create mode 100644 youtube_dl/extractor/cozytv.py diff --git a/youtube_dl/extractor/cozytv.py b/youtube_dl/extractor/cozytv.py new file mode 100644 index 000000000..99d127f7e --- /dev/null +++ b/youtube_dl/extractor/cozytv.py @@ -0,0 +1,172 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( + float_or_none, + int_or_none, + unified_timestamp, + ExtractorError, +) + + +class CozyTVBaseIE(InfoExtractor): + _API_BASE = 'https://api.cozy.tv' + + def _join_url(self, *parts): + return '/'.join(parts).rstrip('/') + + def _user_status(self, user, video_id): + url = self._join_url(self._API_BASE, 'cache', user, 'status') + return self._download_json(url, video_id) + + def _extend_formats(self, formats, cdn_url, video_id, live=False): + formats.extend(self._extract_m3u8_formats( + cdn_url + '/index.m3u8', + video_id, + ext='mp4', + m3u8_id='hls', + preference=-1, + live=live)) + formats.extend(self._extract_m3u8_formats( + cdn_url + '/index-ts-audio.m3u8', + video_id, + ext='mp4', + m3u8_id='hls-audio', + preference=-2, + fatal=False, + live=live)) + self._sort_formats(formats) + + +class CozyTVStreamIE(CozyTVBaseIE): + _VALID_URL = r'https?://(?:www\.)?cozy\.tv/(?P[^/?#]+)' + _TEST = { + 'url': 'https://cozy.tv/alexjones', + 'info_dict': { + 'id': 'alexjones', + 'title': 'The Alex Jones Show - Infowars.com', + 'ext': 'mp4', + 'uploader': 'AlexJones', + 'timestamp': 1658422904, + 'upload_date': '20220721', + 'uploader_id': 'alexjones', + 'uploader_url': 'https://cozy.tv/alexjones', + 'view_count': int, + 'is_live': True, + }, + 'params': { + 'skip_download': True, + }, + } + + def _real_extract(self, url): + video_id, user = re.match(self._VALID_URL, url).group('user', 'user') + user_status = self._user_status(user, video_id) + is_live = user_status['isLive'] + + if is_live is None: + raise ExtractorError('%s is offline' % user, expected=True) + + cdn_url = self._join_url(user_status['livecdns'][0], 'live', user) + + info = { + 'id': video_id, + 'title': user_status['title'], + } + + timestamp = unified_timestamp(is_live) + formats = [] + self._extend_formats(formats, cdn_url, video_id, live=True) + + info.update({ + 'display_id': video_id, + 'formats': formats, + 'timestamp': timestamp, + 'uploader': user_status.get('displayName') or user, + 'uploader_id': user, + 'uploader_url': 'https://cozy.tv/' + user, + 'view_count': int_or_none(user_status.get('viewers')), + 'is_live': True, + }) + + return info + + +class CozyTVReplayIE(CozyTVBaseIE): + _VALID_URL = r'https?://(?:www\.)?cozy\.tv/(?P[^/]+)/replays/(?P\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])(?:_\d+)?)' + _TESTS = [ + { + 'url': 'https://cozy.tv/althype/replays/2022-05-24_2', + 'info_dict': { + 'id': '628d070e3f2f1a99756b6c2f', + 'title': 'Secret Stream: Making Video', + 'ext': 'mp4', + 'display_id': '2022-05-24_2', + 'thumbnail': r're:^https?://.*/replays/althype/2022-05-24_2/thumb\.webp$', + 'uploader': 'AltHype', + 'timestamp': 1653409506, + 'upload_date': '20220524', + 'uploader_id': 'althype', + 'uploader_url': 'https://cozy.tv/althype', + 'duration': 9303.0, + 'view_count': 217, + }, + 'params': { + 'skip_download': True, + }, + }, + { + 'url': 'https://cozy.tv/nick/replays/2022-07-28', + 'info_dict': { + 'id': '62e23d1c4a22de6fb37b83f5', + 'title': 'GAY PANDEMIC: Biden Admin To Declare MONKEYPOX EMERGENCY | America First Ep. 1037', + 'ext': 'mp4', + 'display_id': '2022-07-28', + 'thumbnail': r're:^https?://.*/replays/nick/2022-07-28/thumb\.webp$', + 'uploader': 'Nick', + 'timestamp': 1658993895, + 'upload_date': '20220728', + 'uploader_id': 'nick', + 'uploader_url': 'https://cozy.tv/nick', + 'duration': 16410.0, + 'view_count': 6281, + }, + 'params': { + 'skip_download': True, + }, + }, + ] + + def _real_extract(self, url): + video_id, user = re.match(self._VALID_URL, url).group('id', 'user') + user_status = self._user_status(user, video_id) + data_url = self._join_url(self._API_BASE, 'cache', user, 'replay', video_id) + data = self._download_json(data_url, video_id) + + cdn_url = self._join_url(data['cdns'][0], 'replays', user, video_id) + + info = { + 'id': data.get('_id') or video_id, + 'title': data['title'], + } + + timestamp = unified_timestamp(data.get('date')) + formats = [] + self._extend_formats(formats, cdn_url, video_id) + + info.update({ + 'display_id': video_id, + 'duration': float_or_none(data.get('duration')), + 'formats': formats, + 'thumbnail': cdn_url + '/thumb.webp', + 'timestamp': timestamp, + 'uploader': user_status.get('displayName') or user, + 'uploader_id': user, + 'uploader_url': 'https://cozy.tv/' + user, + 'view_count': int_or_none(data.get('peakViewers')), + }) + + return info diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index 452caeade..02a523caa 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -247,6 +247,10 @@ from .cnn import ( CNNArticleIE, ) from .coub import CoubIE +from .cozytv import ( + CozyTVReplayIE, + CozyTVStreamIE, +) from .comedycentral import ( ComedyCentralIE, ComedyCentralTVIE,