anime-downloader/anime_downloader/extractors/kwik.py

123 lines
3.7 KiB
Python
Raw Normal View History

2021-08-20 08:58:51 -07:00
from base64 import b64decode
import requests
import logging
import re
Fixes AnimePahe and Kwik (#316) * Rely on AnimePahe for episode naming * Remove use of enumerate * Add useful debug info for mp4upload * Fix minor regex mishap for mp4upload * Better title naming for mp4upload * Minor tweaks complete * MP4Upload regex minor improvement * Make collection of sources look better * Revert back to using enumerate for episode numbering * Added utility function to parse episode range * Replace episode range collecting with utility function to parse episode range * Add grammar option to cli.py * Make grammar more consistent * Implement grammar parser and add as util function * Added search to gogoanime * Enable getting episode sources for Gogoanime * Minor refactor for grammar parser * Use new episode parser by default and add gogoanime to provider choices * Fix minor oversight to identify None type passed to episode parser * Remove explicit checks for None type in episode string parsers * Enable retries for request session * Make cfscrape capable of retrying * Make provider list more readable in cli.py * Handle failure to find stream URL better in MP4Upload extractor * Revert changes to match master * Update gogoanime domain * Fix failure to skip already downloaded files * Fix potential bug * Enable ranged download to resume stopped download * Avoid constantly opening and closing file in downloader * Make init the same as main forks * Changed files to match main * Add new line * Modify init * Added animefreak * Add useful comment for animefreak * Added animefreak to README.md * Use json method in helpers.get * Update title test for animefreak * Prioritise mp4upload as source and fix mp4upload source url * Better title handling and more explicit errors * More informative mp4upload exception * Adds changes for new animepahe API usage and fixes title handling * Fixes kwik * Minor fix for kwik
2020-04-14 11:34:47 -07:00
from anime_downloader.extractors.base_extractor import BaseExtractor
from anime_downloader.sites import helpers
from subprocess import CalledProcessError
2021-08-20 08:58:51 -07:00
from anime_downloader import util
logger = logging.getLogger(__name__)
class Kwik(BaseExtractor):
2021-08-20 08:58:51 -07:00
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 {
2021-08-20 08:58:51 -07:00
'stream_url': self.get_stream_url_from_kwik(self.url),
'referer': None
}