]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/boosty.py
1 from .common
import InfoExtractor
2 from .youtube
import YoutubeIE
10 from ..utils
.traversal
import traverse_obj
13 class BoostyIE(InfoExtractor
):
14 _VALID_URL
= r
'https?://(?:www\.)?boosty\.to/(?P<user>[^/#?]+)/posts/(?P<post_id>[^/#?]+)'
17 'url': 'https://boosty.to/kuplinov/posts/e55d050c-e3bb-4873-a7db-ac7a49b40c38',
19 'id': 'd7473824-352e-48e2-ae53-d4aa39459968',
21 'channel': 'Kuplinov',
22 'channel_id': '7958701',
23 'timestamp': 1655031975,
24 'upload_date': '20220612',
25 'release_timestamp': 1655049000,
26 'release_date': '20220612',
27 'modified_timestamp': 1668680993,
28 'modified_date': '20221117',
29 'tags': ['куплинов', 'phasmophobia'],
34 'thumbnail': r
're:^https://i\.mycdn\.me/videoPreview\?',
38 'url': 'https://boosty.to/maddyson/posts/0c652798-3b35-471f-8b48-a76a0b28736f',
40 'id': '0c652798-3b35-471f-8b48-a76a0b28736f',
41 'title': 'то что не пропустил юта6',
42 'channel': 'Илья Давыдов',
43 'channel_id': '6808257',
44 'timestamp': 1694017040,
45 'upload_date': '20230906',
46 'release_timestamp': 1694017040,
47 'release_date': '20230906',
48 'modified_timestamp': 1694071178,
49 'modified_date': '20230907',
55 'id': 'cc325a9f-a563-41c6-bf47-516c1b506c9a',
56 'title': 'то что не пропустил юта6',
57 'channel': 'Илья Давыдов',
58 'channel_id': '6808257',
59 'timestamp': 1694017040,
60 'upload_date': '20230906',
61 'release_timestamp': 1694017040,
62 'release_date': '20230906',
63 'modified_timestamp': 1694071178,
64 'modified_date': '20230907',
69 'thumbnail': r
're:^https://i\.mycdn\.me/videoPreview\?',
73 'id': 'd07b0a72-9493-4512-b54e-55ce468fd4b7',
74 'title': 'то что не пропустил юта6',
75 'channel': 'Илья Давыдов',
76 'channel_id': '6808257',
77 'timestamp': 1694017040,
78 'upload_date': '20230906',
79 'release_timestamp': 1694017040,
80 'release_date': '20230906',
81 'modified_timestamp': 1694071178,
82 'modified_date': '20230907',
87 'thumbnail': r
're:^https://i\.mycdn\.me/videoPreview\?',
91 'id': '4a3bba32-78c8-422a-9432-2791aff60b42',
92 'title': 'то что не пропустил юта6',
93 'channel': 'Илья Давыдов',
94 'channel_id': '6808257',
95 'timestamp': 1694017040,
96 'upload_date': '20230906',
97 'release_timestamp': 1694017040,
98 'release_date': '20230906',
99 'modified_timestamp': 1694071178,
100 'modified_date': '20230907',
105 'thumbnail': r
're:^https://i\.mycdn\.me/videoPreview\?',
109 # single external video (youtube)
110 'url': 'https://boosty.to/denischuzhoy/posts/6094a487-bcec-4cf8-a453-43313b463c38',
113 'title': 'Послание Президента Федеральному Собранию | Класс народа',
114 'upload_date': '20210425',
115 'channel': 'Денис Чужой',
121 'thumbnail': r
're:^https://i\.ytimg\.com/',
123 'availability': 'public',
125 'channel_follower_count': int,
126 'channel_id': 'UCCzVNbWZfYpBfyofCCUD_0w',
127 'channel_is_verified': bool,
128 'channel_url': r
're:^https://www\.youtube\.com/',
129 'comment_count': int,
131 'heatmap': 'count:100',
133 'playable_in_embed': bool,
136 'uploader_url': r
're:^https://www\.youtube\.com/',
140 _MP4_TYPES
= ('tiny', 'lowest', 'low', 'medium', 'high', 'full_hd', 'quad_hd', 'ultra_hd')
142 def _extract_formats(self
, player_urls
, video_id
):
144 quality
= qualities(self
._MP
4_TYPES
)
145 for player_url
in traverse_obj(player_urls
, lambda _
, v
: url_or_none(v
['url'])):
146 url
= player_url
['url']
147 format_type
= player_url
.get('type')
148 if format_type
in ('hls', 'hls_live', 'live_ondemand_hls', 'live_playback_hls'):
149 formats
.extend(self
._extract
_m
3u8_formats
(url
, video_id
, m3u8_id
='hls', fatal
=False))
150 elif format_type
in ('dash', 'dash_live', 'live_playback_dash'):
151 formats
.extend(self
._extract
_mpd
_formats
(url
, video_id
, mpd_id
='dash', fatal
=False))
152 elif format_type
in self
._MP
4_TYPES
:
156 'format_id': format_type
,
157 'quality': quality(format_type
),
160 self
.report_warning(f
'Unknown format type: {format_type!r}')
163 def _real_extract(self
, url
):
164 user
, post_id
= self
._match
_valid
_url
(url
).group('user', 'post_id')
165 post
= self
._download
_json
(
166 f
'https://api.boosty.to/v1/blog/{user}/post/{post_id}', post_id
,
167 note
='Downloading post data', errnote
='Unable to download post data')
169 post_title
= post
.get('title')
171 self
.report_warning('Unable to extract post title. Falling back to parsing html page')
172 webpage
= self
._download
_webpage
(url
, video_id
=post_id
)
173 post_title
= self
._og
_search
_title
(webpage
, default
=None) or self
._html
_extract
_title
(webpage
)
177 **traverse_obj(post
, {
178 'channel': ('user', 'name', {str}
),
179 'channel_id': ('user', 'id', {str_or_none}
),
180 'timestamp': ('createdAt', {int_or_none}
),
181 'release_timestamp': ('publishTime', {int_or_none}
),
182 'modified_timestamp': ('updatedAt', {int_or_none}
),
183 'tags': ('tags', ..., 'title', {str}
),
184 'like_count': ('count', 'likes', {int_or_none}
),
188 for item
in traverse_obj(post
, ('data', ..., {dict}
)):
189 item_type
= item
.get('type')
190 if item_type
== 'video' and url_or_none(item
.get('url')):
191 entries
.append(self
.url_result(item
['url'], YoutubeIE
))
192 elif item_type
== 'ok_video':
193 video_id
= item
.get('id') or post_id
196 'formats': self
._extract
_formats
(item
.get('playerUrls'), video_id
),
198 **traverse_obj(item
, {
199 'title': ('title', {str}
),
200 'duration': ('duration', {int_or_none}
),
201 'view_count': ('viewsCounter', {int_or_none}
),
202 'thumbnail': (('previewUrl', 'defaultPreview'), {url_or_none}
),
206 raise ExtractorError('No videos found', expected
=True)
207 if len(entries
) == 1:
209 return self
.playlist_result(entries
, post_id
, post_title
, **common_metadata
)