]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/storyfire.py
2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
15 class StoryFireBaseIE(InfoExtractor
):
16 _VALID_URL_BASE
= r
'https?://(?:www\.)?storyfire\.com/'
18 def _call_api(self
, path
, video_id
, resource
, query
=None):
19 return self
._download
_json
(
20 'https://storyfire.com/app/%s/%s' % (path
, video_id
), video_id
,
21 'Downloading %s JSON metadata' % resource
, query
=query
)
23 def _parse_video(self
, video
):
24 title
= video
['title']
25 vimeo_id
= self
._search
_regex
(
26 r
'https?://player\.vimeo\.com/external/(\d+)',
27 video
['vimeoVideoURL'], 'vimeo id')
29 uploader_id
= video
.get('hostID')
32 '_type': 'url_transparent',
35 'description': video
.get('description'),
37 'https://player.vimeo.com/video/' + vimeo_id
, {
39 'Referer': 'https://storyfire.com/',
42 'thumbnail': video
.get('storyImage'),
43 'view_count': int_or_none(video
.get('views')),
44 'like_count': int_or_none(video
.get('likesCount')),
45 'comment_count': int_or_none(video
.get('commentsCount')),
46 'duration': int_or_none(video
.get('videoDuration')),
47 'timestamp': int_or_none(video
.get('publishDate')),
48 'uploader': video
.get('username'),
49 'uploader_id': uploader_id
,
50 'uploader_url': format_field(uploader_id
, template
='https://storyfire.com/user/%s/video'),
51 'episode_number': int_or_none(video
.get('episodeNumber') or video
.get('episode_number')),
55 class StoryFireIE(StoryFireBaseIE
):
56 _VALID_URL
= StoryFireBaseIE
._VALID
_URL
_BASE
+ r
'video-details/(?P<id>[0-9a-f]{24})'
58 'url': 'https://storyfire.com/video-details/5df1d132b6378700117f9181',
59 'md5': 'caec54b9e4621186d6079c7ec100c1eb',
63 'title': 'Buzzfeed Teaches You About Memes',
64 'uploader_id': 'ntZAJFECERSgqHSxzonV5K2E89s1',
65 'timestamp': 1576129028,
66 'description': 'md5:0b4e28021548e144bed69bb7539e62ea',
68 'upload_date': '20191212',
75 'skip_download': True,
77 'expected_warnings': ['Unable to download JSON metadata']
80 def _real_extract(self
, url
):
81 video_id
= self
._match
_id
(url
)
82 video
= self
._call
_api
(
83 'generic/video-detail', video_id
, 'video')['video']
84 return self
._parse
_video
(video
)
87 class StoryFireUserIE(StoryFireBaseIE
):
88 _VALID_URL
= StoryFireBaseIE
._VALID
_URL
_BASE
+ r
'user/(?P<id>[^/]+)/video'
90 'url': 'https://storyfire.com/user/UQ986nFxmAWIgnkZQ0ftVhq4nOk2/video',
92 'id': 'UQ986nFxmAWIgnkZQ0ftVhq4nOk2',
94 'playlist_mincount': 151,
98 def _fetch_page(self
, user_id
, page
):
99 videos
= self
._call
_api
(
100 'publicVideos', user_id
, 'page %d' % (page
+ 1), {
101 'skip': page
* self
._PAGE
_SIZE
,
104 yield self
._parse
_video
(video
)
106 def _real_extract(self
, url
):
107 user_id
= self
._match
_id
(url
)
108 entries
= OnDemandPagedList(functools
.partial(
109 self
._fetch
_page
, user_id
), self
._PAGE
_SIZE
)
110 return self
.playlist_result(entries
, user_id
)
113 class StoryFireSeriesIE(StoryFireBaseIE
):
114 _VALID_URL
= StoryFireBaseIE
._VALID
_URL
_BASE
+ r
'write/series/stories/(?P<id>[^/?&#]+)'
116 'url': 'https://storyfire.com/write/series/stories/-Lq6MsuIHLODO6d2dDkr/',
118 'id': '-Lq6MsuIHLODO6d2dDkr',
120 'playlist_mincount': 13,
122 'url': 'https://storyfire.com/write/series/stories/the_mortal_one/',
124 'id': 'the_mortal_one',
129 def _extract_videos(self
, stories
):
130 for story
in stories
.values():
131 if story
.get('hasVideo'):
132 yield self
._parse
_video
(story
)
134 def _real_extract(self
, url
):
135 series_id
= self
._match
_id
(url
)
136 stories
= self
._call
_api
(
137 'seriesStories', series_id
, 'series stories')
138 return self
.playlist_result(self
._extract
_videos
(stories
), series_id
)