]> jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/threespeak.py
[youtube:comments] Add more options for limiting number of comments extracted (#1626)
[yt-dlp.git] / yt_dlp / extractor / threespeak.py
1 # coding: utf-8
2 from __future__ import unicode_literals
3
4 import re
5
6 from .common import InfoExtractor
7 from ..utils import (
8 try_get,
9 unified_strdate,
10 )
11
12
13 class ThreeSpeakIE(InfoExtractor):
14 _VALID_URL = r'https?://(?:www\.)?3speak\.tv/watch\?v\=[^/]+/(?P<id>[^/$&#?]+)'
15
16 _TESTS = [{
17 'url': 'https://3speak.tv/watch?v=dannyshine/wjgoxyfy',
18 'info_dict': {
19 'id': 'wjgoxyfy',
20 'ext': 'mp4',
21 'title': 'Can People who took the Vax think Critically',
22 'uploader': 'dannyshine',
23 'description': 'md5:181aa7ccb304afafa089b5af3bca7a10',
24 'tags': ['sex', 'covid', 'antinatalism', 'comedy', 'vaccines'],
25 'thumbnail': 'https://img.3speakcontent.co/wjgoxyfy/thumbnails/default.png',
26 'upload_date': '20211021',
27 'duration': 2703.867833,
28 'filesize': 1620054781,
29 },
30 'params': {'skip_download': True}
31 }]
32
33 def _real_extract(self, url):
34 id = self._match_id(url)
35 webpage = self._download_webpage(url, id)
36 json_str = self._html_search_regex(r'JSON\.parse\(\'([^\']+)\'\)', webpage, 'json')
37 # The json string itself is escaped. Hence the double parsing
38 data_json = self._parse_json(self._parse_json(f'"{json_str}"', id), id)
39 video_json = self._parse_json(data_json['json_metadata'], id)
40 formats, subtitles = [], {}
41 og_m3u8 = self._html_search_regex(r'<meta\s?property=\"ogvideo\"\s?content=\"([^\"]+)\">', webpage, 'og m3u8', fatal=False)
42 if og_m3u8:
43 https_frmts, https_subs = self._extract_m3u8_formats_and_subtitles(og_m3u8, id, fatal=False, m3u8_id='https')
44 formats.extend(https_frmts)
45 subtitles = self._merge_subtitles(subtitles, https_subs)
46 ipfs_m3u8 = try_get(video_json, lambda x: x['video']['info']['ipfs'])
47 if ipfs_m3u8:
48 ipfs_frmts, ipfs_subs = self._extract_m3u8_formats_and_subtitles(f'https://ipfs.3speak.tv/ipfs/{ipfs_m3u8}',
49 id, fatal=False, m3u8_id='ipfs')
50 formats.extend(ipfs_frmts)
51 subtitles = self._merge_subtitles(subtitles, ipfs_subs)
52 mp4_file = try_get(video_json, lambda x: x['video']['info']['file'])
53 if mp4_file:
54 formats.append({
55 'url': f'https://threespeakvideo.b-cdn.net/{id}/{mp4_file}',
56 'ext': 'mp4',
57 'format_id': 'https-mp4',
58 'duration': try_get(video_json, lambda x: x['video']['info']['duration']),
59 'filesize': try_get(video_json, lambda x: x['video']['info']['filesize']),
60 'quality': 11,
61 'format_note': 'Original file',
62 })
63 self._sort_formats(formats)
64 return {
65 'id': id,
66 'title': data_json.get('title') or data_json.get('root_title'),
67 'uploader': data_json.get('author'),
68 'description': try_get(video_json, lambda x: x['video']['content']['description']),
69 'tags': try_get(video_json, lambda x: x['video']['content']['tags']),
70 'thumbnail': try_get(video_json, lambda x: x['image'][0]),
71 'upload_date': unified_strdate(data_json.get('created')),
72 'formats': formats,
73 'subtitles': subtitles,
74 }
75
76
77 class ThreeSpeakUserIE(InfoExtractor):
78 _VALID_URL = r'https?://(?:www\.)?3speak\.tv/user/(?P<id>[^/$&?#]+)'
79
80 _TESTS = [{
81 'url': 'https://3speak.tv/user/theycallmedan',
82 'info_dict': {
83 'id': 'theycallmedan',
84 },
85 'playlist_mincount': 115,
86 }]
87
88 def _real_extract(self, url):
89 id = self._match_id(url)
90 webpage = self._download_webpage(url, id)
91 entries = [
92 self.url_result(
93 'https://3speak.tv/watch?v=%s' % video,
94 ie=ThreeSpeakIE.ie_key())
95 for video in re.findall(r'data-payout\s?\=\s?\"([^\"]+)\"', webpage) if video
96 ]
97 return self.playlist_result(entries, id)