]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/storyfire.py
3 from .common
import InfoExtractor
12 class StoryFireBaseIE(InfoExtractor
):
13 _VALID_URL_BASE
= r
'https?://(?:www\.)?storyfire\.com/'
15 def _call_api(self
, path
, video_id
, resource
, query
=None):
16 return self
._download
_json
(
17 'https://storyfire.com/app/%s/%s' % (path
, video_id
), video_id
,
18 'Downloading %s JSON metadata' % resource
, query
=query
)
20 def _parse_video(self
, video
):
21 title
= video
['title']
22 vimeo_id
= self
._search
_regex
(
23 r
'https?://player\.vimeo\.com/external/(\d+)',
24 video
['vimeoVideoURL'], 'vimeo id')
26 uploader_id
= video
.get('hostID')
29 '_type': 'url_transparent',
32 'description': video
.get('description'),
34 'https://player.vimeo.com/video/' + vimeo_id
, {
36 'Referer': 'https://storyfire.com/',
39 'thumbnail': video
.get('storyImage'),
40 'view_count': int_or_none(video
.get('views')),
41 'like_count': int_or_none(video
.get('likesCount')),
42 'comment_count': int_or_none(video
.get('commentsCount')),
43 'duration': int_or_none(video
.get('videoDuration')),
44 'timestamp': int_or_none(video
.get('publishDate')),
45 'uploader': video
.get('username'),
46 'uploader_id': uploader_id
,
47 'uploader_url': format_field(uploader_id
, None, 'https://storyfire.com/user/%s/video'),
48 'episode_number': int_or_none(video
.get('episodeNumber') or video
.get('episode_number')),
52 class StoryFireIE(StoryFireBaseIE
):
53 _VALID_URL
= StoryFireBaseIE
._VALID
_URL
_BASE
+ r
'video-details/(?P<id>[0-9a-f]{24})'
55 'url': 'https://storyfire.com/video-details/5df1d132b6378700117f9181',
56 'md5': 'caec54b9e4621186d6079c7ec100c1eb',
60 'title': 'Buzzfeed Teaches You About Memes',
61 'uploader_id': 'ntZAJFECERSgqHSxzonV5K2E89s1',
62 'timestamp': 1576129028,
63 'description': 'md5:0b4e28021548e144bed69bb7539e62ea',
65 'upload_date': '20191212',
72 'skip_download': True,
74 'expected_warnings': ['Unable to download JSON metadata']
77 def _real_extract(self
, url
):
78 video_id
= self
._match
_id
(url
)
79 video
= self
._call
_api
(
80 'generic/video-detail', video_id
, 'video')['video']
81 return self
._parse
_video
(video
)
84 class StoryFireUserIE(StoryFireBaseIE
):
85 _VALID_URL
= StoryFireBaseIE
._VALID
_URL
_BASE
+ r
'user/(?P<id>[^/]+)/video'
87 'url': 'https://storyfire.com/user/UQ986nFxmAWIgnkZQ0ftVhq4nOk2/video',
89 'id': 'UQ986nFxmAWIgnkZQ0ftVhq4nOk2',
91 'playlist_mincount': 151,
95 def _fetch_page(self
, user_id
, page
):
96 videos
= self
._call
_api
(
97 'publicVideos', user_id
, 'page %d' % (page
+ 1), {
98 'skip': page
* self
._PAGE
_SIZE
,
101 yield self
._parse
_video
(video
)
103 def _real_extract(self
, url
):
104 user_id
= self
._match
_id
(url
)
105 entries
= OnDemandPagedList(functools
.partial(
106 self
._fetch
_page
, user_id
), self
._PAGE
_SIZE
)
107 return self
.playlist_result(entries
, user_id
)
110 class StoryFireSeriesIE(StoryFireBaseIE
):
111 _VALID_URL
= StoryFireBaseIE
._VALID
_URL
_BASE
+ r
'write/series/stories/(?P<id>[^/?&#]+)'
113 'url': 'https://storyfire.com/write/series/stories/-Lq6MsuIHLODO6d2dDkr/',
115 'id': '-Lq6MsuIHLODO6d2dDkr',
117 'playlist_mincount': 13,
119 'url': 'https://storyfire.com/write/series/stories/the_mortal_one/',
121 'id': 'the_mortal_one',
126 def _extract_videos(self
, stories
):
127 for story
in stories
.values():
128 if story
.get('hasVideo'):
129 yield self
._parse
_video
(story
)
131 def _real_extract(self
, url
):
132 series_id
= self
._match
_id
(url
)
133 stories
= self
._call
_api
(
134 'seriesStories', series_id
, 'series stories')
135 return self
.playlist_result(self
._extract
_videos
(stories
), series_id
)