From 4ae18a5a9318a302b2cde0c19a8126f6b35814be Mon Sep 17 00:00:00 2001 From: Jamil Karami Date: Fri, 17 Feb 2023 16:56:39 +0100 Subject: [PATCH 1/6] Add kick.com support --- youtube_dl/extractor/extractors.py | 1 + youtube_dl/extractor/kick.py | 42 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 youtube_dl/extractor/kick.py diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index 3a87f9e33..4aaeddaca 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -554,6 +554,7 @@ from .khanacademy import ( KhanAcademyIE, KhanAcademyUnitIE, ) +from .kick import KickIE from .kickstarter import KickStarterIE from .kinja import KinjaEmbedIE from .kinopoisk import KinoPoiskIE diff --git a/youtube_dl/extractor/kick.py b/youtube_dl/extractor/kick.py new file mode 100644 index 000000000..558790589 --- /dev/null +++ b/youtube_dl/extractor/kick.py @@ -0,0 +1,42 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor + + +class KickIE(InfoExtractor): + _VALID_URL = r'https?://(?:www\.)?kick\.com/video/(?P[0-9a-zA-Z-]+)' + _TEST = { + 'url': 'https://kick.com/video/82a3c11d-7a17-4747-aecb-2e61413eb11f', + 'md5': 'f052bc1046cd9ca6751925dd12420010', + 'info_dict': { + 'id': '82a3c11d-7a17-4747-aecb-2e61413eb11f', + 'ext': 'm3u8', + 'title': 'Weekly Stake Stream', + 'uploader': 'Eddie', + 'thumbnail': r're:^https?://.*\.jpg.*$', + } + } + + def _real_extract(self, url): + id = self._match_id(url) + + headers = { + 'Accept': 'application/json', + 'User-Agent': 'Mozilla', + } + + data = self._download_json('https://kick.com/api/v1/video/%s' % id, id, headers=headers) + + video_url = data['source'] + title = data['livestream']['session_title'] + uploader = data['livestream']['channel']['user']['username'] + thumbnail = data['livestream']['thumbnail'] + + return { + 'url': video_url, + 'id': id, + 'title': title, + 'uploader': uploader, + 'thumbnail': thumbnail, + } \ No newline at end of file From 4790abc01d845f4af1302fcd76e5f414dbed377f Mon Sep 17 00:00:00 2001 From: Jamil Karami Date: Sat, 18 Feb 2023 14:59:37 +0100 Subject: [PATCH 2/6] Fix formatting --- youtube_dl/extractor/kick.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/youtube_dl/extractor/kick.py b/youtube_dl/extractor/kick.py index 558790589..9464eb661 100644 --- a/youtube_dl/extractor/kick.py +++ b/youtube_dl/extractor/kick.py @@ -29,6 +29,9 @@ class KickIE(InfoExtractor): data = self._download_json('https://kick.com/api/v1/video/%s' % id, id, headers=headers) video_url = data['source'] + formats = self._extract_m3u8_formats( + data['source'], id, 'mp4') + self._sort_formats(formats) title = data['livestream']['session_title'] uploader = data['livestream']['channel']['user']['username'] thumbnail = data['livestream']['thumbnail'] @@ -39,4 +42,5 @@ class KickIE(InfoExtractor): 'title': title, 'uploader': uploader, 'thumbnail': thumbnail, + 'formats': formats, } \ No newline at end of file From 2631b3384d0750178153b0a21d1fd2455d10bff2 Mon Sep 17 00:00:00 2001 From: Jamil Karami Date: Sat, 18 Feb 2023 15:02:45 +0100 Subject: [PATCH 3/6] Add newline eof (flake8) --- youtube_dl/extractor/kick.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/youtube_dl/extractor/kick.py b/youtube_dl/extractor/kick.py index 9464eb661..31fd7a3bf 100644 --- a/youtube_dl/extractor/kick.py +++ b/youtube_dl/extractor/kick.py @@ -43,4 +43,4 @@ class KickIE(InfoExtractor): 'uploader': uploader, 'thumbnail': thumbnail, 'formats': formats, - } \ No newline at end of file + } From 457c8a8d9e7fd3a718e56b98d8ebfa8e42cd2170 Mon Sep 17 00:00:00 2001 From: Jamil Karami Date: Mon, 20 Feb 2023 20:25:02 +0100 Subject: [PATCH 4/6] Incorporate review comments --- youtube_dl/extractor/kick.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/youtube_dl/extractor/kick.py b/youtube_dl/extractor/kick.py index 31fd7a3bf..0c8d75276 100644 --- a/youtube_dl/extractor/kick.py +++ b/youtube_dl/extractor/kick.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from .common import InfoExtractor +from ..utils import url_or_none, traverse_obj, strip_or_none, float_or_none, parse_iso8601, int_or_none class KickIE(InfoExtractor): @@ -11,10 +12,12 @@ class KickIE(InfoExtractor): 'md5': 'f052bc1046cd9ca6751925dd12420010', 'info_dict': { 'id': '82a3c11d-7a17-4747-aecb-2e61413eb11f', - 'ext': 'm3u8', + 'ext': 'mp4', 'title': 'Weekly Stake Stream', 'uploader': 'Eddie', 'thumbnail': r're:^https?://.*\.jpg.*$', + 'timestamp': 1676890314, + 'upload_date': '20230220', } } @@ -23,24 +26,28 @@ class KickIE(InfoExtractor): headers = { 'Accept': 'application/json', - 'User-Agent': 'Mozilla', } data = self._download_json('https://kick.com/api/v1/video/%s' % id, id, headers=headers) - video_url = data['source'] formats = self._extract_m3u8_formats( data['source'], id, 'mp4') self._sort_formats(formats) - title = data['livestream']['session_title'] - uploader = data['livestream']['channel']['user']['username'] - thumbnail = data['livestream']['thumbnail'] + livestream = data['livestream'] + strip_lambda = lambda x: strip_or_none(x) or None return { - 'url': video_url, 'id': id, - 'title': title, - 'uploader': uploader, - 'thumbnail': thumbnail, 'formats': formats, + 'title': livestream.get('session_title'), + 'uploader': traverse_obj(livestream, ('channel', 'user', 'username'), expected_type=strip_lambda), + 'thumbnail': url_or_none(livestream.get('thumbnail')), + 'duration': float_or_none(data['livestream'].get('duration'), scale=1000), + 'timestamp': traverse_obj(data, 'updated_at', 'created_at', expected_type=parse_iso8601), + 'release_timestamp': parse_iso8601(data.get('created_at')), + 'view_count': int_or_none(data.get('views')), + 'is_live': data['livestream'].get('is_live'), + 'channel': traverse_obj(data['livestream'], ('channel', 'slug'), expected_type=strip_lambda), + 'categories': traverse_obj(data, ('categories', Ellipsis, 'name'), expected_type=strip_lambda) or None, + 'tags': traverse_obj(data, ('categories', Ellipsis, 'tags', Ellipsis), expected_type=strip_lambda) or None, } From f5cb8c0b1cc589403ce335bfd016edf7a8e0e1be Mon Sep 17 00:00:00 2001 From: Jamil Karami Date: Tue, 21 Feb 2023 12:57:02 +0100 Subject: [PATCH 5/6] Incorporate review comments n2 --- youtube_dl/extractor/kick.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/youtube_dl/extractor/kick.py b/youtube_dl/extractor/kick.py index 0c8d75276..1f0c337e6 100644 --- a/youtube_dl/extractor/kick.py +++ b/youtube_dl/extractor/kick.py @@ -2,12 +2,20 @@ from __future__ import unicode_literals from .common import InfoExtractor -from ..utils import url_or_none, traverse_obj, strip_or_none, float_or_none, parse_iso8601, int_or_none +from ..utils import ( + float_or_none, + int_or_none, + parse_iso8601, + strip_or_none, + traverse_obj, + url_or_none, +) + class KickIE(InfoExtractor): _VALID_URL = r'https?://(?:www\.)?kick\.com/video/(?P[0-9a-zA-Z-]+)' - _TEST = { + _TESTS = [{ 'url': 'https://kick.com/video/82a3c11d-7a17-4747-aecb-2e61413eb11f', 'md5': 'f052bc1046cd9ca6751925dd12420010', 'info_dict': { @@ -19,7 +27,7 @@ class KickIE(InfoExtractor): 'timestamp': 1676890314, 'upload_date': '20230220', } - } + }] def _real_extract(self, url): id = self._match_id(url) @@ -42,12 +50,12 @@ class KickIE(InfoExtractor): 'title': livestream.get('session_title'), 'uploader': traverse_obj(livestream, ('channel', 'user', 'username'), expected_type=strip_lambda), 'thumbnail': url_or_none(livestream.get('thumbnail')), - 'duration': float_or_none(data['livestream'].get('duration'), scale=1000), + 'duration': float_or_none(livestream.get('duration'), scale=1000), 'timestamp': traverse_obj(data, 'updated_at', 'created_at', expected_type=parse_iso8601), 'release_timestamp': parse_iso8601(data.get('created_at')), 'view_count': int_or_none(data.get('views')), - 'is_live': data['livestream'].get('is_live'), - 'channel': traverse_obj(data['livestream'], ('channel', 'slug'), expected_type=strip_lambda), + 'is_live': livestream.get('is_live'), + 'channel': traverse_obj(livestream, ('channel', 'slug'), expected_type=strip_lambda), 'categories': traverse_obj(data, ('categories', Ellipsis, 'name'), expected_type=strip_lambda) or None, 'tags': traverse_obj(data, ('categories', Ellipsis, 'tags', Ellipsis), expected_type=strip_lambda) or None, } From 95b55103cd6be592661091d81af7b23f0cdb4347 Mon Sep 17 00:00:00 2001 From: Jamil Karami Date: Wed, 22 Feb 2023 11:18:42 +0100 Subject: [PATCH 6/6] flake8 fix --- youtube_dl/extractor/kick.py | 1 - 1 file changed, 1 deletion(-) diff --git a/youtube_dl/extractor/kick.py b/youtube_dl/extractor/kick.py index 1f0c337e6..c98625568 100644 --- a/youtube_dl/extractor/kick.py +++ b/youtube_dl/extractor/kick.py @@ -10,7 +10,6 @@ from ..utils import ( traverse_obj, url_or_none, ) - class KickIE(InfoExtractor):