]>
Commit | Line | Data |
---|---|---|
a08dfd27 PH |
1 | import binascii |
2 | import base64 | |
3 | import hashlib | |
4 | import re | |
5 | ||
6 | from .common import InfoExtractor | |
7 | from ..utils import ( | |
8 | compat_ord, | |
9 | compat_urllib_parse, | |
10 | ||
11 | ExtractorError, | |
12 | ) | |
13 | ||
14 | ||
15 | ||
16 | class MyVideoIE(InfoExtractor): | |
17 | """Information Extractor for myvideo.de.""" | |
18 | ||
19 | _VALID_URL = r'(?:http://)?(?:www\.)?myvideo\.de/watch/([0-9]+)/([^?/]+).*' | |
20 | IE_NAME = u'myvideo' | |
21 | ||
22 | # Original Code from: https://github.com/dersphere/plugin.video.myvideo_de.git | |
23 | # Released into the Public Domain by Tristan Fischer on 2013-05-19 | |
24 | # https://github.com/rg3/youtube-dl/pull/842 | |
25 | def __rc4crypt(self,data, key): | |
26 | x = 0 | |
27 | box = list(range(256)) | |
28 | for i in list(range(256)): | |
29 | x = (x + box[i] + compat_ord(key[i % len(key)])) % 256 | |
30 | box[i], box[x] = box[x], box[i] | |
31 | x = 0 | |
32 | y = 0 | |
33 | out = '' | |
34 | for char in data: | |
35 | x = (x + 1) % 256 | |
36 | y = (y + box[x]) % 256 | |
37 | box[x], box[y] = box[y], box[x] | |
38 | out += chr(compat_ord(char) ^ box[(box[x] + box[y]) % 256]) | |
39 | return out | |
40 | ||
41 | def __md5(self,s): | |
42 | return hashlib.md5(s).hexdigest().encode() | |
43 | ||
44 | def _real_extract(self,url): | |
45 | mobj = re.match(self._VALID_URL, url) | |
46 | if mobj is None: | |
47 | raise ExtractorError(u'invalid URL: %s' % url) | |
48 | ||
49 | video_id = mobj.group(1) | |
50 | ||
51 | GK = ( | |
52 | b'WXpnME1EZGhNRGhpTTJNM01XVmhOREU0WldNNVpHTTJOakpt' | |
53 | b'TW1FMU5tVTBNR05pWkRaa05XRXhNVFJoWVRVd1ptSXhaVEV3' | |
54 | b'TnpsbA0KTVRkbU1tSTRNdz09' | |
55 | ) | |
56 | ||
57 | # Get video webpage | |
58 | webpage_url = 'http://www.myvideo.de/watch/%s' % video_id | |
59 | webpage = self._download_webpage(webpage_url, video_id) | |
60 | ||
61 | mobj = re.search('source src=\'(.+?)[.]([^.]+)\'', webpage) | |
62 | if mobj is not None: | |
63 | self.report_extraction(video_id) | |
64 | video_url = mobj.group(1) + '.flv' | |
65 | ||
66 | video_title = self._html_search_regex('<title>([^<]+)</title>', | |
67 | webpage, u'title') | |
68 | ||
69 | video_ext = self._search_regex('[.](.+?)$', video_url, u'extension') | |
70 | ||
71 | return [{ | |
72 | 'id': video_id, | |
73 | 'url': video_url, | |
74 | 'uploader': None, | |
75 | 'upload_date': None, | |
76 | 'title': video_title, | |
77 | 'ext': video_ext, | |
78 | }] | |
79 | ||
80 | # try encxml | |
81 | mobj = re.search('var flashvars={(.+?)}', webpage) | |
82 | if mobj is None: | |
83 | raise ExtractorError(u'Unable to extract video') | |
84 | ||
85 | params = {} | |
86 | encxml = '' | |
87 | sec = mobj.group(1) | |
88 | for (a, b) in re.findall('(.+?):\'(.+?)\',?', sec): | |
89 | if not a == '_encxml': | |
90 | params[a] = b | |
91 | else: | |
92 | encxml = compat_urllib_parse.unquote(b) | |
93 | if not params.get('domain'): | |
94 | params['domain'] = 'www.myvideo.de' | |
95 | xmldata_url = '%s?%s' % (encxml, compat_urllib_parse.urlencode(params)) | |
96 | if 'flash_playertype=MTV' in xmldata_url: | |
97 | self._downloader.report_warning(u'avoiding MTV player') | |
98 | xmldata_url = ( | |
99 | 'http://www.myvideo.de/dynamic/get_player_video_xml.php' | |
100 | '?flash_playertype=D&ID=%s&_countlimit=4&autorun=yes' | |
101 | ) % video_id | |
102 | ||
103 | # get enc data | |
104 | enc_data = self._download_webpage(xmldata_url, video_id).split('=')[1] | |
105 | enc_data_b = binascii.unhexlify(enc_data) | |
106 | sk = self.__md5( | |
107 | base64.b64decode(base64.b64decode(GK)) + | |
108 | self.__md5( | |
109 | str(video_id).encode('utf-8') | |
110 | ) | |
111 | ) | |
112 | dec_data = self.__rc4crypt(enc_data_b, sk) | |
113 | ||
114 | # extracting infos | |
115 | self.report_extraction(video_id) | |
116 | ||
117 | video_url = None | |
118 | mobj = re.search('connectionurl=\'(.*?)\'', dec_data) | |
119 | if mobj: | |
120 | video_url = compat_urllib_parse.unquote(mobj.group(1)) | |
121 | if 'myvideo2flash' in video_url: | |
122 | self._downloader.report_warning(u'forcing RTMPT ...') | |
123 | video_url = video_url.replace('rtmpe://', 'rtmpt://') | |
124 | ||
125 | if not video_url: | |
126 | # extract non rtmp videos | |
127 | mobj = re.search('path=\'(http.*?)\' source=\'(.*?)\'', dec_data) | |
128 | if mobj is None: | |
129 | raise ExtractorError(u'unable to extract url') | |
130 | video_url = compat_urllib_parse.unquote(mobj.group(1)) + compat_urllib_parse.unquote(mobj.group(2)) | |
131 | ||
132 | video_file = self._search_regex('source=\'(.*?)\'', dec_data, u'video file') | |
133 | video_file = compat_urllib_parse.unquote(video_file) | |
134 | ||
135 | if not video_file.endswith('f4m'): | |
136 | ppath, prefix = video_file.split('.') | |
137 | video_playpath = '%s:%s' % (prefix, ppath) | |
138 | video_hls_playlist = '' | |
139 | else: | |
140 | video_playpath = '' | |
141 | video_hls_playlist = ( | |
142 | video_file | |
143 | ).replace('.f4m', '.m3u8') | |
144 | ||
145 | video_swfobj = self._search_regex('swfobject.embedSWF\(\'(.+?)\'', webpage, u'swfobj') | |
146 | video_swfobj = compat_urllib_parse.unquote(video_swfobj) | |
147 | ||
148 | video_title = self._html_search_regex("<h1(?: class='globalHd')?>(.*?)</h1>", | |
149 | webpage, u'title') | |
150 | ||
151 | return [{ | |
152 | 'id': video_id, | |
153 | 'url': video_url, | |
154 | 'tc_url': video_url, | |
155 | 'uploader': None, | |
156 | 'upload_date': None, | |
157 | 'title': video_title, | |
158 | 'ext': u'flv', | |
159 | 'play_path': video_playpath, | |
160 | 'video_file': video_file, | |
161 | 'video_hls_playlist': video_hls_playlist, | |
162 | 'player_url': video_swfobj, | |
163 | }] | |
164 |