]>
Commit | Line | Data |
---|---|---|
1 | import base64 | |
2 | import os.path | |
3 | import re | |
4 | ||
5 | from .common import InfoExtractor | |
6 | from ..compat import compat_urllib_parse_unquote | |
7 | from ..utils import ( | |
8 | ExtractorError, | |
9 | update_url_query, | |
10 | url_basename, | |
11 | ) | |
12 | ||
13 | ||
14 | class DropboxIE(InfoExtractor): | |
15 | _VALID_URL = r'https?://(?:www\.)?dropbox\.com/(?:(?:e/)?scl/fi|sh?)/(?P<id>\w+)' | |
16 | _TESTS = [ | |
17 | { | |
18 | 'url': 'https://www.dropbox.com/s/nelirfsxnmcfbfh/youtube-dl%20test%20video%20%27%C3%A4%22BaW_jenozKc.mp4?dl=0', | |
19 | 'info_dict': { | |
20 | 'id': 'nelirfsxnmcfbfh', | |
21 | 'ext': 'mp4', | |
22 | 'title': 'youtube-dl test video \'รค"BaW_jenozKc' | |
23 | } | |
24 | }, { | |
25 | 'url': 'https://www.dropbox.com/s/nelirfsxnmcfbfh', | |
26 | 'only_matching': True, | |
27 | }, { | |
28 | 'url': 'https://www.dropbox.com/sh/2mgpiuq7kv8nqdf/AABy-fW4dkydT4GmWi2mdOUDa?dl=0&preview=Drone+Shot.mp4', | |
29 | 'only_matching': True, | |
30 | }, { | |
31 | 'url': 'https://www.dropbox.com/scl/fi/r2kd2skcy5ylbbta5y1pz/DJI_0003.MP4?dl=0&rlkey=wcdgqangn7t3lnmmv6li9mu9h', | |
32 | 'only_matching': True, | |
33 | }, { | |
34 | 'url': 'https://www.dropbox.com/e/scl/fi/r2kd2skcy5ylbbta5y1pz/DJI_0003.MP4?dl=0&rlkey=wcdgqangn7t3lnmmv6li9mu9h', | |
35 | 'only_matching': True, | |
36 | }, | |
37 | ] | |
38 | ||
39 | def _real_extract(self, url): | |
40 | mobj = self._match_valid_url(url) | |
41 | video_id = mobj.group('id') | |
42 | webpage = self._download_webpage(url, video_id) | |
43 | fn = compat_urllib_parse_unquote(url_basename(url)) | |
44 | title = os.path.splitext(fn)[0] | |
45 | ||
46 | password = self.get_param('videopassword') | |
47 | if (self._og_search_title(webpage) == 'Dropbox - Password Required' | |
48 | or 'Enter the password for this link' in webpage): | |
49 | ||
50 | if password: | |
51 | content_id = self._search_regex(r'content_id=(.*?)["\']', webpage, 'content_id') | |
52 | payload = f'is_xhr=true&t={self._get_cookies("https://www.dropbox.com").get("t").value}&content_id={content_id}&password={password}&url={url}' | |
53 | response = self._download_json( | |
54 | 'https://www.dropbox.com/sm/auth', video_id, 'POSTing video password', data=payload.encode('UTF-8'), | |
55 | headers={'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'}) | |
56 | ||
57 | if response.get('status') != 'authed': | |
58 | raise ExtractorError('Authentication failed!', expected=True) | |
59 | webpage = self._download_webpage(url, video_id) | |
60 | elif self._get_cookies('https://dropbox.com').get('sm_auth'): | |
61 | webpage = self._download_webpage(url, video_id) | |
62 | else: | |
63 | raise ExtractorError('Password protected video, use --video-password <password>', expected=True) | |
64 | ||
65 | formats, subtitles, has_anonymous_download = [], {}, False | |
66 | for encoded in reversed(re.findall(r'registerStreamedPrefetch\s*\(\s*"[\w/+=]+"\s*,\s*"([\w/+=]+)"', webpage)): | |
67 | decoded = base64.b64decode(encoded).decode('utf-8', 'ignore') | |
68 | if not has_anonymous_download: | |
69 | has_anonymous_download = self._search_regex( | |
70 | r'(anonymous:\tanonymous)', decoded, 'anonymous', default=False) | |
71 | transcode_url = self._search_regex( | |
72 | r'\n.(https://[^\x03\x08\x12\n]+\.m3u8)', decoded, 'transcode url', default=None) | |
73 | if not transcode_url: | |
74 | continue | |
75 | formats, subtitles = self._extract_m3u8_formats_and_subtitles(transcode_url, video_id, 'mp4') | |
76 | break | |
77 | ||
78 | # downloads enabled we can get the original file | |
79 | if has_anonymous_download: | |
80 | formats.append({ | |
81 | 'url': update_url_query(url, {'dl': '1'}), | |
82 | 'format_id': 'original', | |
83 | 'format_note': 'Original', | |
84 | 'quality': 1 | |
85 | }) | |
86 | ||
87 | return { | |
88 | 'id': video_id, | |
89 | 'title': title, | |
90 | 'formats': formats, | |
91 | 'subtitles': subtitles | |
92 | } |