From b81c1d9eefbd6e759d552f04ef6123d514bac7c8 Mon Sep 17 00:00:00 2001 From: Andrew Udvare Date: Sun, 23 Sep 2018 17:19:44 -0400 Subject: [PATCH 1/3] [SnapchatStory] Add new extractor --- youtube_dl/extractor/extractors.py | 1 + youtube_dl/extractor/snapchat.py | 75 ++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 youtube_dl/extractor/snapchat.py diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index 7dc56972498..5c6f1c802c1 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -1011,6 +1011,7 @@ SmotriUserIE, SmotriBroadcastIE, ) +from .snapchat import SnapchatStoryIE from .snotr import SnotrIE from .sohu import SohuIE from .sonyliv import SonyLIVIE diff --git a/youtube_dl/extractor/snapchat.py b/youtube_dl/extractor/snapchat.py new file mode 100644 index 00000000000..11c2bc87772 --- /dev/null +++ b/youtube_dl/extractor/snapchat.py @@ -0,0 +1,75 @@ +# coding: utf-8 +from __future__ import unicode_literals + +from .common import InfoExtractor +from ..compat import compat_urllib_parse_urlencode +from ..utils import ExtractorError, int_or_none + + +class SnapchatStoryIE(InfoExtractor): + _VALID_URL = r'https?://(?:story|play)\.snapchat\.com/(?:s/)?(?P[^/?#&]+)' + _TEST = { + 'url': 'https://story.snapchat.com/s/m:W7_EDlXWTBiXAEEniNoMPwAAYHNdO123IQ281AWXc-zodAWXc-ziUAHanAA', + 'md5': '3eebf8f327752d100959db3fa0879bfb', + 'info_dict': { + 'id': 'W7_EDlXWTBiXAEEniNoMPwAAYHNdO123IQ281AWXc-zodAWXc-ziUAHanAA', + 'ext': 'mp4', + 'title': 'Dunn, North Carolina', + 'thumbnail': 'https://s.sc-cdn.net/N_FHqfPfsuaDG2vf33HsmA4ipcDtMBuW5SM3dBiME38=/default/preview_overlay.jpg', + }, + } + + def _entries(self, story, title, alt_title): + for snap in story.get('snaps', []): + media = snap.get('media', {}) + + if not media.get('type', '').startswith('VIDEO'): + continue + + if len(media.keys()) == 0: + continue + + formats = [] + + for key in ('mediaStreamingUrl', 'mediaUrl'): + if key not in media: + continue + + format_info = {'url': media[key], 'format_id': 'direct'} + + if key == 'mediaStreamingUrl': + format_info['format_id'] = 'streaming' + format_info['ext'] = 'mp4' + format_info['protocol'] = 'm3u8' + + formats.append(format_info) + + if len(formats) == 0: + continue + + info = { + 'id': snap['id'], + 'title': title, + 'alt_title': alt_title, + 'thumbnail': media.get('mediaPreviewUrl'), + 'duration': int_or_none(snap.get('captureTimeSecs')), + 'formats': formats, + } + + yield info + + def _real_extract(self, url): + snap_id = self._match_id(url) + data_url = 'https://storysharing.snapchat.com/v1/fetch/%s' % snap_id + data = self._download_json(data_url, + snap_id, + query=dict(request_origin='ORIGIN_WEB_PLAYER')) + + story = data['story'] + title = story['metadata']['title'] + alt_title = story['metadata'].get('subTitles') + + return self.playlist_result(self._entries(story, title, alt_title), + playlist_title=title, + playlist_id=snap_id, + playlist_description=alt_title) From 3c945d26a6af4a421c47b7796ab6437ea025855d Mon Sep 17 00:00:00 2001 From: Andrew Udvare Date: Thu, 27 Sep 2018 04:55:36 -0400 Subject: [PATCH 2/3] [SnapchatStory] Make use of try_get() --- youtube_dl/extractor/snapchat.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/youtube_dl/extractor/snapchat.py b/youtube_dl/extractor/snapchat.py index 11c2bc87772..eac32e68ff0 100644 --- a/youtube_dl/extractor/snapchat.py +++ b/youtube_dl/extractor/snapchat.py @@ -2,8 +2,8 @@ from __future__ import unicode_literals from .common import InfoExtractor -from ..compat import compat_urllib_parse_urlencode -from ..utils import ExtractorError, int_or_none +from ..compat import compat_str, compat_urllib_parse_urlencode +from ..utils import ExtractorError, int_or_none, try_get class SnapchatStoryIE(InfoExtractor): @@ -66,8 +66,12 @@ def _real_extract(self, url): query=dict(request_origin='ORIGIN_WEB_PLAYER')) story = data['story'] - title = story['metadata']['title'] - alt_title = story['metadata'].get('subTitles') + title = try_get(story, lambda x: x['metadata']['title'], compat_str) + if not title: + title = 'Untitled' + alt_title = try_get(story, + lambda x: x['metadata']['subTitles'], + compat_str) return self.playlist_result(self._entries(story, title, alt_title), playlist_title=title, From 677b0fc48a8ba008a1cf9f7ff0ca90d1b779c8db Mon Sep 17 00:00:00 2001 From: Andrew Udvare Date: Sun, 30 Sep 2018 03:53:29 -0400 Subject: [PATCH 3/3] [SnapchatMap] Add new extractor --- youtube_dl/extractor/extractors.py | 2 +- youtube_dl/extractor/snapchat.py | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index 5c6f1c802c1..82bec5bc95d 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -1011,7 +1011,7 @@ SmotriUserIE, SmotriBroadcastIE, ) -from .snapchat import SnapchatStoryIE +from .snapchat import SnapchatMapIE, SnapchatStoryIE from .snotr import SnotrIE from .sohu import SohuIE from .sonyliv import SonyLIVIE diff --git a/youtube_dl/extractor/snapchat.py b/youtube_dl/extractor/snapchat.py index eac32e68ff0..b4c73e5a4e4 100644 --- a/youtube_dl/extractor/snapchat.py +++ b/youtube_dl/extractor/snapchat.py @@ -2,8 +2,8 @@ from __future__ import unicode_literals from .common import InfoExtractor -from ..compat import compat_str, compat_urllib_parse_urlencode -from ..utils import ExtractorError, int_or_none, try_get +from ..compat import compat_str +from ..utils import int_or_none, try_get class SnapchatStoryIE(InfoExtractor): @@ -77,3 +77,22 @@ def _real_extract(self, url): playlist_title=title, playlist_id=snap_id, playlist_description=alt_title) + + +class SnapchatMapIE(InfoExtractor): + _VALID_URL = r'https?://map\.snapchat\.com/(?:story|ttp)/[0-9a-f]+/snap/(?P[^/?#&]+)' + _TEST = { + 'url': 'https://map.snapchat.com/story/1e8e6ce5c27f8623/snap/q4_OINadScux6p1c6OgxRwAAEs-Al6eIEtvT_AWYnxYFbAWYnxX26AAFRgA/@40.811408,-77.855252,13.00z', + 'md5': '966330c423dcf7d49fa9077c46bbb86d', + 'info_dict': { + 'id': 'q4_OINadScux6p1c6OgxRwAAEs-Al6eIEtvT_AWYnxYFbAWYnxX26AAFRgA', + 'title': 'State College, Pennsylvania', + 'ext': 'mp4', + 'thumbnail': 'https://s.sc-cdn.net/DScgzJV_rSLcJUubC03fcZECpi8KARIFRVtq5rEav2M=/default/preview_overlay.jpg', + }, + } + + def _real_extract(self, url): + snap_id = self._match_id(url) + return self.url_result('https://story.snapchat.com/s/m:%s' % snap_id, + ie=SnapchatStoryIE.ie_key())