diff --git a/Src/API/onlineserietv.py b/Src/API/onlineserietv.py new file mode 100644 index 0000000..b6782d8 --- /dev/null +++ b/Src/API/onlineserietv.py @@ -0,0 +1,142 @@ +from Src.Utilities.info import get_info_imdb, is_movie, get_info_tmdb +from bs4 import BeautifulSoup,SoupStrainer +import Src.Utilities.config as config +from fake_headers import Headers +from Src.Utilities.loadenv import load_env +import json, random +import re +from Src.Utilities.eval import eval_solver +OST_DOMAIN = config.OST_DOMAIN +OST_PROXY = config.OST_PROXY +env_vars = load_env() +proxies = {} +if OST_PROXY == "1": + PROXY_CREDENTIALS = env_vars.get('PROXY_CREDENTIALS') + proxy_list = json.loads(PROXY_CREDENTIALS) + proxy = random.choice(proxy_list) + if proxy == "": + proxies = {} + else: + proxies = { + "http": proxy, + "https": proxy + } +OST_ForwardProxy = config.OST_ForwardProxy +if OST_ForwardProxy == "1": + ForwardProxy = env_vars.get('ForwardProxy') +else: + ForwardProxy = "" +headers = { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36', + 'Accept': '*/*', + 'Accept-Language': 'en-US,en;q=0.5', + # 'Accept-Encoding': 'gzip, deflate, br, zstd', + 'X-Requested-With': 'XMLHttpRequest', + 'DNT': '1', + 'Sec-GPC': '1', + 'Connection': 'keep-alive', + 'Referer': f'https://onlineserietv.{OST_DOMAIN}/', + # 'Cookie': 'player_opt=fx', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'Pragma': 'no-cache', + 'Cache-Control': 'no-cache', +} + +async def search(showname,date,client,ismovie,episode,season): + cookies = { + 'player_opt': 'fx', + } + params = { + 's': showname, + 'action': 'searchwp_live_search', + 'swpengine': 'default', + 'swpquery': showname, + 'origin_id': '50141', + 'searchwp_live_search_client_nonce': 'undefined', + } + response = await client.get(ForwardProxy + f"https://onlineserietv.{OST_DOMAIN}/wp-admin/admin-ajax.php", headers=headers, params=params, cookies=cookies, impersonate = "chrome124", proxies = proxies) + print(response) + soup = BeautifulSoup(response.text, 'lxml', parse_only=SoupStrainer('a')) + a_tags_with_href = soup.find_all("a", href=True) + for a_tag in a_tags_with_href: + href = a_tag.get("href") + if ismovie == 1: + if "film" in href: + response = await client.get(ForwardProxy + href, headers=headers, impersonate = "chrome124", proxies = proxies) + year_match = re.search(r'Anno: (\d{4})', response.text) + year = year_match.group(1) if year_match else None + if year == date: + pattern = r'https://uprot\.net/fxf/[^\s"<>]+' + match = re.search(pattern, response.text) + if match: + name = a_tag.text + flexy_link = match.group(1) + return flexy_link,name + else: + print("No flexy link found.") + else: + continue + elif ismovie == 0: + if "serietv" in href: + response = await client.get(ForwardProxy + href, headers=headers, impersonate = "chrome124", proxies = proxies) + print(response) + year_match = re.search(r'Anno: (\d{4})', response.text) + year = year_match.group(1) if year_match else None + if year == date: + season = season.zfill(2) + episode = episode.zfill(2) + pattern = rf'{season}x{episode}.*? +# +# written by Stefano Sanfilippo +# +# usage: +# +# if detect(some_string): +# unpacked = unpack(some_string) +# + +"""Unpacker for Dean Edward's p.a.c.k.e.r""" +import re +from bs4 import BeautifulSoup, SoupStrainer + +def detect(source): + if "eval(function(p,a,c,k,e,d)" in source: + mystr = "smth" + return mystr is not None + + +def unpack(source): + """Unpacks P.A.C.K.E.R. packed js code.""" + payload, symtab, radix, count = _filterargs(source) + + if count != len(symtab): + raise UnpackingError("Malformed p.a.c.k.e.r. symtab.") + + try: + unbase = Unbaser(radix) + except TypeError: + raise UnpackingError("Unknown p.a.c.k.e.r. encoding.") + + def lookup(match): + """Look up symbols in the synthetic symtab.""" + word = match.group(0) + return symtab[unbase(word)] or word + + payload = payload.replace("\\\\", "\\").replace("\\'", "'") + source = re.sub(r"\b\w+\b", lookup, payload) + return _replacestrings(source) + + +def _filterargs(source): + """Juice from a source file the four args needed by decoder.""" + juicers = [ + (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)"), + (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\)"), + ] + for juicer in juicers: + args = re.search(juicer, source, re.DOTALL) + if args: + a = args.groups() + if a[1] == "[]": + a = list(a) + a[1] = 62 + a = tuple(a) + try: + return a[0], a[3].split("|"), int(a[1]), int(a[2]) + except ValueError: + raise UnpackingError("Corrupted p.a.c.k.e.r. data.") + + # could not find a satisfying regex + raise UnpackingError( + "Could not make sense of p.a.c.k.e.r data (unexpected code structure)" + ) + + +def _replacestrings(source): + """Strip string lookup table (list) and replace values in source.""" + match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL) + + if match: + varname, strings = match.groups() + startpoint = len(match.group(0)) + lookup = strings.split('","') + variable = "%s[%%d]" % varname + for index, value in enumerate(lookup): + source = source.replace(variable % index, '"%s"' % value) + return source[startpoint:] + return source + + +class Unbaser(object): + """Functor for a given base. Will efficiently convert + strings to natural numbers.""" + + ALPHABET = { + 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + 95: ( + " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + ), + } + + def __init__(self, base): + self.base = base + + # fill elements 37...61, if necessary + if 36 < base < 62: + if not hasattr(self.ALPHABET, self.ALPHABET[62][:base]): + self.ALPHABET[base] = self.ALPHABET[62][:base] + # attrs = self.ALPHABET + # print ', '.join("%s: %s" % item for item in attrs.items()) + # If base can be handled by int() builtin, let it do it for us + if 2 <= base <= 36: + self.unbase = lambda string: int(string, base) + else: + # Build conversion dictionary cache + try: + self.dictionary = dict( + (cipher, index) for index, cipher in enumerate(self.ALPHABET[base]) + ) + except KeyError: + raise TypeError("Unsupported base encoding.") + + self.unbase = self._dictunbaser + + def __call__(self, string): + return self.unbase(string) + + def _dictunbaser(self, string): + """Decodes a value to an integer.""" + ret = 0 + for index, cipher in enumerate(string[::-1]): + ret += (self.base**index) * self.dictionary[cipher] + return ret +class UnpackingError(Exception): + """Badly packed source or general error. Argument is a + meaningful description.""" + + pass + + + +async def eval_solver(stream_link,client): + headers = {} + headers["user-agent"] = "Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36" + headers["User-Agent"] = "Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36" + response = await client.get( stream_link, allow_redirects=True, timeout=30, headers = headers) + soup = BeautifulSoup(response.text, "lxml",parse_only=SoupStrainer("script")) + script_all = soup.find_all("script") + for i in script_all: + if detect(i.text): + unpacked_code = unpack(i.text) + match = re.search(r'sources:\s*\[\{\s*src:\s*"([^"]+)"', unpacked_code) + if match: + m3u8_url = match.group(1) + return m3u8_url diff --git a/run.py b/run.py index 1840083..0e32d83 100644 --- a/run.py +++ b/run.py @@ -16,6 +16,7 @@ from Src.API.animeworld import animeworld from Src.Utilities.dictionaries import okru,STREAM,extra_sources,webru_vary,webru_dlhd,provider_map,skystreaming from Src.API.epg import tivu, tivu_get,epg_guide,convert_bho_1,convert_bho_2,convert_bho_3 from Src.API.webru import webru,get_skystreaming +from Src.API.onlineserietv import onlineserietv from curl_cffi.requests import AsyncSession from slowapi import Limiter from slowapi.util import get_remote_address @@ -51,6 +52,7 @@ CB = config.CB DDL = config.DDL GS = config.GS GHD = config.GHD +OST = config.OST HOST = config.HOST PORT = int(config.PORT) Icon = config.Icon @@ -395,6 +397,11 @@ async def addon_stream(request: Request,config, type, id,): if url_guardahd: print(f"GuardaHD Found Results for {id}") streams['streams'].append({'name': f"{Name}",'title': f'{Icon}GuardaHD', 'url': url_guardahd, 'behaviorHints': {'bingeGroup': 'guardahd'}}) + if provider_maps['ONLINESERIETV'] == "1" and OST == "1": + url_onlineserietv,name = await onlineserietv(id,client) + if url_onlineserietv: + print(f"OnlineSerieTV Found Results for {id}") + streams['streams'].append({'name': f"{Name}",'title': f'{Icon}OnlineSerieTV\n{name}', 'url': url_onlineserietv, 'behaviorHints': {'proxyHeaders': {'request': {"User-Agent": 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36', "Referer": "https://flexy.stream/"}}, 'bingeGroup': 'onlineserietv', 'notWebReady': True}}) if not streams['streams']: raise HTTPException(status_code=404) diff --git a/static/static.py b/static/static.py index 1f66e7d..494e9f5 100644 --- a/static/static.py +++ b/static/static.py @@ -214,6 +214,11 @@ HTML = """ GuardaHD +
+ +