anime-downloader/anime_downloader/extractors/kwik.py

123 lines
3.7 KiB
Python

from base64 import b64decode
import requests
import logging
import re
from anime_downloader.extractors.base_extractor import BaseExtractor
from anime_downloader.sites import helpers
from subprocess import CalledProcessError
from anime_downloader import util
logger = logging.getLogger(__name__)
class Kwik(BaseExtractor):
YTSM = re.compile(r"ysmm = '([^']+)")
KWIK_PARAMS_RE = re.compile(r'\("(\w+)",\d+,"(\w+)",(\d+),(\d+),\d+\)')
KWIK_D_URL = re.compile(r'action="([^"]+)"')
KWIK_D_TOKEN = re.compile(r'value="([^"]+)"')
CHARACTER_MAP = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
def get_string(self, content: str, s1: int, s2: int) -> str:
slice_2 = self.CHARACTER_MAP[0:s2]
acc = 0
for n, i in enumerate(content[::-1]):
acc += int(i if i.isdigit() else 0) * s1**n
k = ''
while acc > 0:
k = slice_2[int(acc % s2)] + k
acc = (acc - (acc % s2)) / s2
return k or '0'
def decrypt(self, full_string: str, key: str, v1: int, v2: int) -> str:
v1, v2 = int(v1), int(v2)
r, i = "", 0
while i < len(full_string):
s = ""
while (full_string[i] != key[v2]):
s += full_string[i]
i += 1
j = 0
while j < len(key):
s = s.replace(key[j], str(j))
j += 1
r += chr(int(self.get_string(s, v2, 10)) - v1)
i += 1
return r
def decode_adfly(self, coded_key: str) -> str:
r, j = '', ''
for n, l in enumerate(coded_key):
if not n % 2:
r += l
else:
j = l + j
encoded_uri = list(r + j)
numbers = ((i, n) for i, n in enumerate(encoded_uri) if str.isdigit(n))
for first, second in zip(numbers, numbers):
xor = int(first[1]) ^ int(second[1])
if xor < 10:
encoded_uri[first[0]] = str(xor)
return b64decode(("".join(encoded_uri)).encode("utf-8")
)[16:-16].decode('utf-8', errors='ignore')
def bypass_adfly(self, adfly_url):
session = requests.session()
response_code = 302
while response_code != 200:
adfly_content = session.get(
session.get(
adfly_url,
allow_redirects=False).headers.get('location'),
allow_redirects=False)
response_code = adfly_content.status_code
return self.decode_adfly(self.YTSM.search(adfly_content.text).group(1))
def get_stream_url_from_kwik(self, adfly_url):
session = requests.session()
f_content = requests.get(
self.bypass_adfly(adfly_url),
headers={
'referer': 'https://kwik.cx/'
}
)
decrypted = self.decrypt(
*
self.KWIK_PARAMS_RE.search(
f_content.text
).group(
1, 2,
3, 4
)
)
code = 419
while code != 302:
content = session.post(
self.KWIK_D_URL.search(decrypted).group(1),
allow_redirects=False,
data={
'_token': self.KWIK_D_TOKEN.search(decrypted).group(1)},
headers={
'referer': str(f_content.url),
'cookie': f_content.headers.get('set-cookie')})
code = content.status_code
return content.headers.get('location')
def _get_data(self):
return {
'stream_url': self.get_stream_url_from_kwik(self.url),
'referer': None
}