]>
Commit | Line | Data |
---|---|---|
3fa6b6e2 PH |
1 | from __future__ import unicode_literals |
2 | ||
462dc88b PH |
3 | import re |
4 | ||
5 | from .common import InfoExtractor | |
6 | from ..utils import ( | |
7fee3377 | 7 | extract_attributes, |
462dc88b | 8 | ExtractorError, |
7fee3377 RA |
9 | get_element_by_class, |
10 | js_to_json, | |
462dc88b PH |
11 | ) |
12 | ||
13 | ||
14 | class SteamIE(InfoExtractor): | |
1f27d2c0 PH |
15 | _VALID_URL = r"""(?x) |
16 | https?://store\.steampowered\.com/ | |
17 | (agecheck/)? | |
18 | (?P<urltype>video|app)/ #If the page is only for videos or for a game | |
19 | (?P<gameID>\d+)/? | |
20 | (?P<videoID>\d*)(?P<extra>\??) # For urltype == video we sometimes get the videoID | |
21 | | | |
22 | https?://(?:www\.)?steamcommunity\.com/sharedfiles/filedetails/\?id=(?P<fileID>[0-9]+) | |
23 | """ | |
462dc88b PH |
24 | _VIDEO_PAGE_TEMPLATE = 'http://store.steampowered.com/video/%s/' |
25 | _AGECHECK_TEMPLATE = 'http://store.steampowered.com/agecheck/video/%s/?snr=1_agecheck_agecheck__age-gate&ageDay=1&ageMonth=January&ageYear=1970' | |
1f27d2c0 | 26 | _TESTS = [{ |
611c1dd9 S |
27 | 'url': 'http://store.steampowered.com/video/105600/', |
28 | 'playlist': [ | |
08217714 | 29 | { |
7fee3377 | 30 | 'md5': '6a294ee0c4b1f47f5bb76a65e31e3592', |
611c1dd9 | 31 | 'info_dict': { |
7fee3377 RA |
32 | 'id': '2040428', |
33 | 'ext': 'mp4', | |
34 | 'title': 'Terraria 1.3 Trailer', | |
3fa6b6e2 | 35 | 'playlist_index': 1, |
08217714 PH |
36 | } |
37 | }, | |
38 | { | |
7fee3377 | 39 | 'md5': '911672b20064ca3263fa89650ba5a7aa', |
611c1dd9 | 40 | 'info_dict': { |
7fee3377 RA |
41 | 'id': '2029566', |
42 | 'ext': 'mp4', | |
43 | 'title': 'Terraria 1.2 Trailer', | |
3fa6b6e2 | 44 | 'playlist_index': 2, |
08217714 PH |
45 | } |
46 | } | |
7f9c31df | 47 | ], |
7fee3377 RA |
48 | 'info_dict': { |
49 | 'id': '105600', | |
50 | 'title': 'Terraria', | |
51 | }, | |
7f9c31df PH |
52 | 'params': { |
53 | 'playlistend': 2, | |
54 | } | |
1f27d2c0 PH |
55 | }, { |
56 | 'url': 'http://steamcommunity.com/sharedfiles/filedetails/?id=242472205', | |
57 | 'info_dict': { | |
7fee3377 | 58 | 'id': 'X8kpJBlzD2E', |
1f27d2c0 | 59 | 'ext': 'mp4', |
7fee3377 RA |
60 | 'upload_date': '20140617', |
61 | 'title': 'FRONTIERS - Trapping', | |
62 | 'description': 'md5:bf6f7f773def614054089e5769c12a6e', | |
1f27d2c0 PH |
63 | 'uploader': 'AAD Productions', |
64 | 'uploader_id': 'AtomicAgeDogGames', | |
65 | } | |
66 | }] | |
08217714 | 67 | |
462dc88b | 68 | def _real_extract(self, url): |
1f27d2c0 PH |
69 | m = re.match(self._VALID_URL, url) |
70 | fileID = m.group('fileID') | |
71 | if fileID: | |
72 | videourl = url | |
73 | playlist_id = fileID | |
74 | else: | |
75 | gameID = m.group('gameID') | |
76 | playlist_id = gameID | |
77 | videourl = self._VIDEO_PAGE_TEMPLATE % playlist_id | |
78 | webpage = self._download_webpage(videourl, playlist_id) | |
462dc88b PH |
79 | |
80 | if re.search('<h2>Please enter your birth date to continue:</h2>', webpage) is not None: | |
1f27d2c0 | 81 | videourl = self._AGECHECK_TEMPLATE % playlist_id |
462dc88b | 82 | self.report_age_confirmation() |
1f27d2c0 PH |
83 | webpage = self._download_webpage(videourl, playlist_id) |
84 | ||
7fee3377 RA |
85 | flash_vars = self._parse_json(self._search_regex( |
86 | r'(?s)rgMovieFlashvars\s*=\s*({.+?});', webpage, | |
87 | 'flash vars'), playlist_id, js_to_json) | |
88 | ||
89 | playlist_title = None | |
90 | entries = [] | |
1f27d2c0 | 91 | if fileID: |
7fee3377 RA |
92 | playlist_title = get_element_by_class('workshopItemTitle', webpage) |
93 | for movie in flash_vars.values(): | |
94 | if not movie: | |
95 | continue | |
96 | youtube_id = movie.get('YOUTUBE_VIDEO_ID') | |
97 | if not youtube_id: | |
98 | continue | |
99 | entries.append({ | |
100 | '_type': 'url', | |
101 | 'url': youtube_id, | |
102 | 'ie_key': 'Youtube', | |
103 | }) | |
1f27d2c0 | 104 | else: |
7fee3377 RA |
105 | playlist_title = get_element_by_class('apphub_AppName', webpage) |
106 | for movie_id, movie in flash_vars.items(): | |
107 | if not movie: | |
108 | continue | |
109 | video_id = self._search_regex(r'movie_(\d+)', movie_id, 'video id', fatal=False) | |
110 | title = movie.get('MOVIE_NAME') | |
111 | if not title or not video_id: | |
112 | continue | |
113 | entry = { | |
1f27d2c0 | 114 | 'id': video_id, |
7fee3377 RA |
115 | 'title': title.replace('+', ' '), |
116 | } | |
117 | formats = [] | |
118 | flv_url = movie.get('FILENAME') | |
119 | if flv_url: | |
120 | formats.append({ | |
121 | 'format_id': 'flv', | |
122 | 'url': flv_url, | |
123 | }) | |
124 | highlight_element = self._search_regex( | |
125 | r'(<div[^>]+id="highlight_movie_%s"[^>]+>)' % video_id, | |
126 | webpage, 'highlight element', fatal=False) | |
127 | if highlight_element: | |
128 | highlight_attribs = extract_attributes(highlight_element) | |
129 | if highlight_attribs: | |
130 | entry['thumbnail'] = highlight_attribs.get('data-poster') | |
131 | for quality in ('', '-hd'): | |
132 | for ext in ('webm', 'mp4'): | |
133 | video_url = highlight_attribs.get('data-%s%s-source' % (ext, quality)) | |
134 | if video_url: | |
135 | formats.append({ | |
136 | 'format_id': ext + quality, | |
137 | 'url': video_url, | |
138 | }) | |
139 | if not formats: | |
140 | continue | |
141 | entry['formats'] = formats | |
142 | entries.append(entry) | |
143 | if not entries: | |
1f27d2c0 | 144 | raise ExtractorError('Could not find any videos') |
462dc88b | 145 | |
7fee3377 | 146 | return self.playlist_result(entries, playlist_id, playlist_title) |