mirror of
https://codeberg.org/polarisfm/youtube-dl
synced 2024-11-30 04:08:01 +01:00
[wetv] Add new extractor
This commit is contained in:
parent
d65d89183f
commit
9c42c640eb
@ -1409,6 +1409,10 @@ from .weibo import (
|
|||||||
WeiboMobileIE
|
WeiboMobileIE
|
||||||
)
|
)
|
||||||
from .weiqitv import WeiqiTVIE
|
from .weiqitv import WeiqiTVIE
|
||||||
|
from .wetv import (
|
||||||
|
WeTvIE,
|
||||||
|
WeTvPlaylistIE,
|
||||||
|
)
|
||||||
from .wistia import WistiaIE
|
from .wistia import WistiaIE
|
||||||
from .worldstarhiphop import WorldStarHipHopIE
|
from .worldstarhiphop import WorldStarHipHopIE
|
||||||
from .wsj import (
|
from .wsj import (
|
||||||
|
489
youtube_dl/extractor/wetv.py
Normal file
489
youtube_dl/extractor/wetv.py
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
|
||||||
|
from ctypes import c_int32
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..compat import (
|
||||||
|
compat_chr,
|
||||||
|
compat_ord,
|
||||||
|
compat_str,
|
||||||
|
compat_urllib_parse_unquote,
|
||||||
|
compat_urllib_parse_urlencode,
|
||||||
|
compat_urlparse,
|
||||||
|
)
|
||||||
|
from ..utils import (
|
||||||
|
int_or_none,
|
||||||
|
parse_duration,
|
||||||
|
smuggle_url,
|
||||||
|
std_headers,
|
||||||
|
strip_jsonp,
|
||||||
|
unescapeHTML,
|
||||||
|
unsmuggle_url,
|
||||||
|
url_or_none,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WeTvBaseInfoExtractor(InfoExtractor):
|
||||||
|
@staticmethod
|
||||||
|
def parse_video_info(video_info):
|
||||||
|
thumbnails = []
|
||||||
|
for key, value in video_info.items():
|
||||||
|
if key.startswith('pic_'):
|
||||||
|
try:
|
||||||
|
width, height = key[4:].split('_')
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
thumbnails.append({
|
||||||
|
'width': int_or_none(width),
|
||||||
|
'height': int_or_none(height),
|
||||||
|
'url': url_or_none(value),
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': video_info['vid'],
|
||||||
|
'title': unescapeHTML(video_info['title']),
|
||||||
|
'description': unescapeHTML(video_info.get('desc')),
|
||||||
|
'duration': parse_duration(video_info.get('duration')),
|
||||||
|
'episode_number': int_or_none(video_info.get('episode')),
|
||||||
|
'thumbnails': thumbnails,
|
||||||
|
}
|
||||||
|
|
||||||
|
def extract_info_from_page(self, webpage, video_id):
|
||||||
|
inputs = self._hidden_inputs(webpage)
|
||||||
|
info = self._parse_json(inputs.get('data_sync', ''), video_id, compat_urllib_parse_unquote)
|
||||||
|
|
||||||
|
return info, info['langInfo']['langId'], info['langInfo']['areaCode']
|
||||||
|
|
||||||
|
|
||||||
|
class WeTvIE(WeTvBaseInfoExtractor):
|
||||||
|
IE_NAME = 'wetv'
|
||||||
|
IE_DESC = 'WeTV.vip'
|
||||||
|
_VALID_URL = r'''(?x)
|
||||||
|
(?:
|
||||||
|
wetv:|
|
||||||
|
https?://(?:m\.)?wetv\.vip/
|
||||||
|
(?:(?P<language>[a-z]{2}(?:-[a-z]{2})?)/)?
|
||||||
|
(?:play/){,2}
|
||||||
|
(?:(?P<playlist_id>[a-z\d]{15})(?:-[^/]*)?/)?
|
||||||
|
(?:play\?vid=)?
|
||||||
|
)
|
||||||
|
(?P<id>[a-z\d]{11})
|
||||||
|
(?:$|[^a-z\d])'''
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://wetv.vip/play?vid=o00318x0wds',
|
||||||
|
'md5': '6b07174a61ed9c1dfb8defab3b40ba12',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'o00318x0wds',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': "EP1\uff1aThe King's Avatar",
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'url': 'https://wetv.vip/en/play/jenizogwk2t8400/o00318x0wds',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# user video
|
||||||
|
'url': 'https://wetv.vip/en/play/a3150lwr4jn-Ve-Po-Ad%20Review%20%2F%20HowTo',
|
||||||
|
'md5': 'b053543f584bb4ae10767b5c6bf67807',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'a3150lwr4jn',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Ve-Po-Ad Review / HowTo',
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
# non-m3u8
|
||||||
|
'url': 'https://wetv.vip/en/play/h31438yuulr',
|
||||||
|
'md5': 'c1b83ac4653d38b2d5e423caeab4148b',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'h31438yuulr',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Gokukoku no Brynhildr - "Ichiban Boshi" \u2014 Full Ending',
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_guid():
|
||||||
|
return ''.join([random.choice(string.digits + string.ascii_lowercase) for _ in range(32)])
|
||||||
|
|
||||||
|
def _real_initialize(self):
|
||||||
|
self.ckey = CKey()
|
||||||
|
self.default_quality = 'hd'
|
||||||
|
self.common_params = {
|
||||||
|
'charge': 0,
|
||||||
|
'defaultfmt': 'auto',
|
||||||
|
'otype': 'json',
|
||||||
|
'platform': 4830201,
|
||||||
|
'sdtfrom': 1002,
|
||||||
|
'defnpayver': 0,
|
||||||
|
'appVer': '3.5.57',
|
||||||
|
'sphttps': 1,
|
||||||
|
'spwm': 4,
|
||||||
|
'fhdswitch': 0,
|
||||||
|
'show1080p': 0,
|
||||||
|
'isHLS': 1,
|
||||||
|
'dtype': 3,
|
||||||
|
'sphls': 2,
|
||||||
|
'spgzip': 1,
|
||||||
|
'dlver': 2,
|
||||||
|
'drm': 32,
|
||||||
|
'spau': 1,
|
||||||
|
'spaudio': 15,
|
||||||
|
'spsrt': 1,
|
||||||
|
'spvideo': 16,
|
||||||
|
'defsrc': 2,
|
||||||
|
'encryptVer': '8.1',
|
||||||
|
'fp2p': 1,
|
||||||
|
'spadseg': 1,
|
||||||
|
'guid': WeTvIE.create_guid(),
|
||||||
|
'logintoken': '{"main_login":"","openid":"","appid":"","access_token":"","vuserid":"","vusession":""}',
|
||||||
|
}
|
||||||
|
|
||||||
|
def generate_jsonp_url(self, quality, video_id, url, playlist_id, lang_code, country_code):
|
||||||
|
parsed_url = compat_urlparse.urlparse(url)
|
||||||
|
timestamp = time.time()
|
||||||
|
|
||||||
|
params = self.common_params.copy()
|
||||||
|
params.update({
|
||||||
|
'defn': quality,
|
||||||
|
'vid': video_id,
|
||||||
|
'cid': playlist_id,
|
||||||
|
'lang_code': lang_code,
|
||||||
|
'country_code': country_code,
|
||||||
|
'flowid': '{}_{}'.format(WeTvIE.create_guid(), params['platform']),
|
||||||
|
'host': parsed_url.netloc,
|
||||||
|
'refer': parsed_url.netloc,
|
||||||
|
'ehost': compat_urlparse.urlunparse((parsed_url.scheme, parsed_url.netloc, parsed_url.path, None, None, None)),
|
||||||
|
'tm': int(timestamp),
|
||||||
|
'_{}'.format(int(timestamp * 1000)): '',
|
||||||
|
'callback': 'txplayerJsonpCallBack_getinfo_{}'.format(random.randint(10000, 1000000)),
|
||||||
|
})
|
||||||
|
params['cKey'] = self.ckey.make(
|
||||||
|
video_id, compat_str(params['tm']), params['appVer'], params['guid'],
|
||||||
|
compat_str(params['platform']), url, std_headers['User-Agent'])
|
||||||
|
|
||||||
|
return 'https://play.wetv.vip/getvinfo?{}'.format(compat_urllib_parse_urlencode(params))
|
||||||
|
|
||||||
|
def get_jsonp_data(self, quality, video_id, *args):
|
||||||
|
jsonp_url = self.generate_jsonp_url(quality, video_id, *args)
|
||||||
|
# "accept-encoding: gzip" results in
|
||||||
|
# EOFError: Compressed file ended before the end-of-stream marker was reached
|
||||||
|
return self._download_json(jsonp_url, video_id, transform_source=strip_jsonp,
|
||||||
|
note='Downloading {} metadata'.format(quality),
|
||||||
|
headers={'Accept-Encoding': 'deflate'})
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def extract_qualities(data):
|
||||||
|
qualities = []
|
||||||
|
for quality in data['fl']['fi']:
|
||||||
|
id = quality['name']
|
||||||
|
qualities.append({
|
||||||
|
'format_id': id,
|
||||||
|
'format_note': quality['cname'],
|
||||||
|
'filesize_approx': quality['fs'],
|
||||||
|
})
|
||||||
|
|
||||||
|
return qualities
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def extract_format(data):
|
||||||
|
video_info = data['vl']['vi'][0]
|
||||||
|
|
||||||
|
url = video_info['ul']['ui'][random.randint(0, 2)]['url']
|
||||||
|
if 'fvkey' in video_info:
|
||||||
|
url += '{}?vkey={}'.format(video_info['fn'], video_info['fvkey'])
|
||||||
|
elif url.endswith('/'):
|
||||||
|
url += '{}.m3u8?ver=4'.format(video_info['fn'])
|
||||||
|
|
||||||
|
return {
|
||||||
|
'url': url,
|
||||||
|
'ext': 'mp4',
|
||||||
|
'width': int_or_none(video_info.get('vw')),
|
||||||
|
'height': int_or_none(video_info.get('vh')),
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_formats_and_data(self, *args):
|
||||||
|
formats = []
|
||||||
|
|
||||||
|
default_quality_data = self.get_jsonp_data(self.default_quality, *args)
|
||||||
|
qualities = WeTvIE.extract_qualities(default_quality_data)
|
||||||
|
|
||||||
|
for quality in qualities:
|
||||||
|
id = quality['format_id']
|
||||||
|
if id == self.default_quality:
|
||||||
|
data = default_quality_data
|
||||||
|
else:
|
||||||
|
data = self.get_jsonp_data(id, *args)
|
||||||
|
|
||||||
|
quality.update(WeTvIE.extract_format(data))
|
||||||
|
|
||||||
|
formats.append(quality)
|
||||||
|
|
||||||
|
return formats, default_quality_data
|
||||||
|
|
||||||
|
def _get_subtitles(self, data):
|
||||||
|
subtitles = {}
|
||||||
|
for subtitle_info in data['sfl'].get('fi', []):
|
||||||
|
subtitles[subtitle_info['lang'].lower()] = [{'url': subtitle_info['url']}]
|
||||||
|
|
||||||
|
return subtitles
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
url, smuggled_data = unsmuggle_url(url)
|
||||||
|
|
||||||
|
mobj = re.match(self._VALID_URL, url)
|
||||||
|
video_id = mobj.group('id')
|
||||||
|
language = mobj.group('language')
|
||||||
|
# urls like this: https://wetv.vip/en/play/jenizogwk2t8400/play?vid=p0031yjo98d
|
||||||
|
# when opened in new tab - load series page (and start playing the first episode)
|
||||||
|
# when clicked on the website - load clicked episode
|
||||||
|
# solution: use https://wetv.vip/en/play/p0031yjo98d instead
|
||||||
|
good_url = 'https://wetv.vip/{}/play/{}'.format(language or 'en', video_id)
|
||||||
|
|
||||||
|
if smuggled_data:
|
||||||
|
# playlist extractor sets the metadata like title, duration, etc.,
|
||||||
|
# no need to load the webpage again
|
||||||
|
result = {}
|
||||||
|
playlist_id = smuggled_data['playlist_id']
|
||||||
|
lang_code = smuggled_data['lang_code']
|
||||||
|
country_code = smuggled_data['country_code']
|
||||||
|
else:
|
||||||
|
webpage = self._download_webpage(good_url, video_id)
|
||||||
|
|
||||||
|
full_url = self._og_search_url(webpage)
|
||||||
|
mobj = re.match(self._VALID_URL, full_url)
|
||||||
|
playlist_id = mobj.group('playlist_id') or ''
|
||||||
|
|
||||||
|
info, lang_code, country_code = self.extract_info_from_page(webpage, video_id)
|
||||||
|
result = WeTvBaseInfoExtractor.parse_video_info(info['videoInfo'])
|
||||||
|
|
||||||
|
formats, data = self.get_formats_and_data(video_id, good_url, playlist_id, lang_code, country_code)
|
||||||
|
|
||||||
|
subtitles = self.extract_subtitles(data)
|
||||||
|
|
||||||
|
result.update({
|
||||||
|
'id': video_id,
|
||||||
|
'url': 'http://example.com/example.mp4',
|
||||||
|
'formats': formats,
|
||||||
|
'subtitles': subtitles,
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class WeTvPlaylistIE(WeTvBaseInfoExtractor):
|
||||||
|
IE_NAME = 'wetv:playlist'
|
||||||
|
IE_DESC = 'WeTV.vip playlists'
|
||||||
|
_VALID_URL = r'''(?x)
|
||||||
|
https?://(?:m\.)?wetv\.vip/
|
||||||
|
(?:[a-z]{2}(?:-[a-z]{2})?/)?
|
||||||
|
play(?:/|\?cid=)
|
||||||
|
(?P<id>[a-z\d]{15})
|
||||||
|
(?:$|[^a-z\d])'''
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://wetv.vip/en/play/jenizogwk2t8400',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'jenizogwk2t8400',
|
||||||
|
'title': "The King's Avatar",
|
||||||
|
'description': 'md5:eca1c149133af485673d7676d4eff0c9',
|
||||||
|
},
|
||||||
|
'playlist_count': 40,
|
||||||
|
}, {
|
||||||
|
'url': 'https://wetv.vip/play?cid=jenizogwk2t8400',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
playlist_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, playlist_id)
|
||||||
|
|
||||||
|
info, lang_code, country_code = self.extract_info_from_page(webpage, playlist_id)
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
for video_info in info['videoList']:
|
||||||
|
parsed_info = WeTvBaseInfoExtractor.parse_video_info(video_info)
|
||||||
|
smuggled_url = smuggle_url(
|
||||||
|
'wetv:{}'.format(parsed_info['id'], ),
|
||||||
|
{
|
||||||
|
'playlist_id': playlist_id,
|
||||||
|
'lang_code': lang_code,
|
||||||
|
'country_code': country_code,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
parsed_info.update({
|
||||||
|
'_type': 'url_transparent',
|
||||||
|
'url': smuggled_url,
|
||||||
|
'ie_key': WeTvIE.ie_key(),
|
||||||
|
})
|
||||||
|
entries.append(parsed_info)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'_type': 'playlist',
|
||||||
|
'id': playlist_id,
|
||||||
|
'title': info.get('coverInfo', {}).get('title'),
|
||||||
|
'description': info.get('coverInfo', {}).get('description'),
|
||||||
|
'entries': entries,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CKey:
|
||||||
|
def __init__(self):
|
||||||
|
self.encryption_arrays = [[
|
||||||
|
1332468387, -1641050960, 2136896045, -1629555948,
|
||||||
|
1399201960, -850809832, -1307058635, 751381793,
|
||||||
|
-1933648423, 1106735553, -203378700, -550927659,
|
||||||
|
766369351, 1817882502, -1615200142, 1083409063,
|
||||||
|
-104955314, -1780208184, 173944250, 1254993693,
|
||||||
|
1422337688, -1054667952, -880990486, -2119136777,
|
||||||
|
-1822404972, 1380140484, -1723964626, 412019417,
|
||||||
|
-890799303, -1734066435, 26893779, 420787978,
|
||||||
|
-1337058067, 686432784, 695238595, 811911369,
|
||||||
|
-391724567, -1068702727, -381903814, -648522509,
|
||||||
|
-1266234148, 1959407397, -1644776673, 1152313324]]
|
||||||
|
d = [None] * 256
|
||||||
|
f = d.copy()
|
||||||
|
g = d.copy()
|
||||||
|
h = d.copy()
|
||||||
|
j = d.copy()
|
||||||
|
o = d.copy()
|
||||||
|
for i in range(256):
|
||||||
|
o[i] = i << 1 if i < 128 else i << 1 ^ 283
|
||||||
|
|
||||||
|
t = 0
|
||||||
|
u = 0
|
||||||
|
for i in range(256):
|
||||||
|
v = u ^ u << 1 ^ u << 2 ^ u << 3 ^ u << 4
|
||||||
|
v = CKey.rshift(v, 8) ^ 255 & v ^ 99
|
||||||
|
d[t] = v
|
||||||
|
x = o[t]
|
||||||
|
z = o[o[x]]
|
||||||
|
A = CKey.int32(257 * o[v] ^ 16843008 * v)
|
||||||
|
f[t] = CKey.int32(A << 24 | CKey.rshift(A, 8))
|
||||||
|
g[t] = CKey.int32(A << 16 | CKey.rshift(A, 16))
|
||||||
|
h[t] = CKey.int32(A << 8 | CKey.rshift(A, 24))
|
||||||
|
j[t] = A
|
||||||
|
if t == 0:
|
||||||
|
t = 1
|
||||||
|
u = 1
|
||||||
|
else:
|
||||||
|
t = x ^ o[o[o[z ^ x]]]
|
||||||
|
u ^= o[o[u]]
|
||||||
|
|
||||||
|
self.encryption_arrays.append(f)
|
||||||
|
self.encryption_arrays.append(g)
|
||||||
|
self.encryption_arrays.append(h)
|
||||||
|
self.encryption_arrays.append(j)
|
||||||
|
self.encryption_arrays.append(d)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def rshift(val, n):
|
||||||
|
return (val & 0xFFFFFFFF) >> n
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def int32(val):
|
||||||
|
return c_int32(val).value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def encode_text(text):
|
||||||
|
length = len(text)
|
||||||
|
arr = [0] * (length // 4)
|
||||||
|
for i in range(length):
|
||||||
|
arr[i // 4] |= (255 & ord(text[i])) << 24 - i % 4 * 8
|
||||||
|
return arr, length
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def decode_text(arr, length):
|
||||||
|
text_array = []
|
||||||
|
for i in range(length):
|
||||||
|
text_array.append('{:02x}'.format(
|
||||||
|
CKey.rshift(arr[i // 4], 24 - i % 4 * 8) & 255))
|
||||||
|
|
||||||
|
return ''.join(text_array)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def calculate_hash(text):
|
||||||
|
result = 0
|
||||||
|
for char in text:
|
||||||
|
result = CKey.int32(result << 5) - result + compat_ord(char)
|
||||||
|
return compat_str(result)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def pad_text(text):
|
||||||
|
pad_length = 16 - len(text) % 16
|
||||||
|
return text + compat_chr(pad_length) * pad_length
|
||||||
|
|
||||||
|
def encrypt(self, arr):
|
||||||
|
for i in range(0, len(arr), 4):
|
||||||
|
self.main_algorithm(arr, i)
|
||||||
|
|
||||||
|
def main_algorithm(self, a, b):
|
||||||
|
c, d, e, f, g, h = self.encryption_arrays
|
||||||
|
|
||||||
|
if b == 0:
|
||||||
|
xor_arr = [22039283, 1457920463, 776125350, -1941999367]
|
||||||
|
else:
|
||||||
|
xor_arr = a[b - 4: b]
|
||||||
|
|
||||||
|
for i, val in enumerate(xor_arr):
|
||||||
|
a[b + i] ^= val
|
||||||
|
|
||||||
|
j = a[b] ^ c[0]
|
||||||
|
k = a[b + 1] ^ c[1]
|
||||||
|
l = a[b + 2] ^ c[2]
|
||||||
|
m = a[b + 3] ^ c[3]
|
||||||
|
n = 4
|
||||||
|
for _ in range(9):
|
||||||
|
q = (d[CKey.rshift(j, 24)] ^ e[CKey.rshift(k, 16) & 255]
|
||||||
|
^ f[CKey.rshift(l, 8) & 255] ^ g[255 & m] ^ c[n])
|
||||||
|
s = (d[CKey.rshift(k, 24)] ^ e[CKey.rshift(l, 16) & 255]
|
||||||
|
^ f[CKey.rshift(m, 8) & 255] ^ g[255 & j] ^ c[n + 1])
|
||||||
|
t = (d[CKey.rshift(l, 24)] ^ e[CKey.rshift(m, 16) & 255]
|
||||||
|
^ f[CKey.rshift(j, 8) & 255] ^ g[255 & k] ^ c[n + 2])
|
||||||
|
m = (d[CKey.rshift(m, 24)] ^ e[CKey.rshift(j, 16) & 255]
|
||||||
|
^ f[CKey.rshift(k, 8) & 255] ^ g[255 & l] ^ c[n + 3])
|
||||||
|
j = q
|
||||||
|
k = s
|
||||||
|
l = t
|
||||||
|
n += 4
|
||||||
|
|
||||||
|
q = CKey.int32(h[CKey.rshift(j, 24)] << 24
|
||||||
|
| h[CKey.rshift(k, 16) & 255] << 16
|
||||||
|
| h[CKey.rshift(l, 8) & 255] << 8
|
||||||
|
| h[255 & m]) ^ c[n]
|
||||||
|
s = CKey.int32(h[CKey.rshift(k, 24)] << 24
|
||||||
|
| h[CKey.rshift(l, 16) & 255] << 16
|
||||||
|
| h[CKey.rshift(m, 8) & 255] << 8
|
||||||
|
| h[255 & j]) ^ c[n + 1]
|
||||||
|
t = CKey.int32(h[CKey.rshift(l, 24)] << 24
|
||||||
|
| h[CKey.rshift(m, 16) & 255] << 16
|
||||||
|
| h[CKey.rshift(j, 8) & 255] << 8
|
||||||
|
| h[255 & k]) ^ c[n + 2]
|
||||||
|
m = CKey.int32(h[CKey.rshift(m, 24)] << 24
|
||||||
|
| h[CKey.rshift(j, 16) & 255] << 16
|
||||||
|
| h[CKey.rshift(k, 8) & 255] << 8
|
||||||
|
| h[255 & l]) ^ c[n + 3]
|
||||||
|
a[b] = q
|
||||||
|
a[b + 1] = s
|
||||||
|
a[b + 2] = t
|
||||||
|
a[b + 3] = m
|
||||||
|
|
||||||
|
def make(self, vid, tm, app_ver, guid, platform, url,
|
||||||
|
# user_agent is shortened anyway
|
||||||
|
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.',
|
||||||
|
referer='', nav_code_name='Mozilla',
|
||||||
|
nav_name='Netscape', nav_platform='Win32'):
|
||||||
|
text_parts = [
|
||||||
|
'', vid, tm, 'mg3c3b04ba', app_ver, guid, platform,
|
||||||
|
url[:48], user_agent[:48].lower(), referer[:48],
|
||||||
|
nav_code_name, nav_name, nav_platform, '00', ''
|
||||||
|
]
|
||||||
|
text_parts.insert(1, CKey.calculate_hash('|'.join(text_parts)))
|
||||||
|
|
||||||
|
text = CKey.pad_text('|'.join(text_parts))
|
||||||
|
[arr, length] = CKey.encode_text(text)
|
||||||
|
self.encrypt(arr)
|
||||||
|
return CKey.decode_text(arr, length).upper()
|
Loading…
Reference in New Issue
Block a user