import re import requests from six.moves.urllib_parse import parse_qs, urlencode from resources.lib.modules import cleantitle from resources.lib.modules import client from resources.lib.modules import client_utils from resources.lib.modules import scrape_sources from resources.lib.modules import log_utils DOM = client_utils.parseDOM class source: def __init__(self): self.results = [] self.domains = ['goojara.to', 'supernova.to'] self.base_link = 'https://goojara.to' self.search_link = '/?s=%s' self.php_entrypoint = '/xhrr.php' self.sess = requests.Session() self.notes = 'Pulled in defs from mbebe to resolve goojara links' def movie(self, imdb, tmdb, title, localtitle, aliases, year): url = {'imdb': imdb, 'title': title, 'aliases': aliases, 'year': year} url = urlencode(url) return url def tvshow(self, imdb, tmdb, tvdb, tvshowtitle, localtvshowtitle, aliases, year): url = {'imdb': imdb, 'tvshowtitle': tvshowtitle, 'aliases': aliases, 'year': year} url = urlencode(url) return url def episode(self, url, imdb, tmdb, tvdb, title, premiered, season, episode): if not url: return url = parse_qs(url) url = dict([(i, url[i][0]) if url[i] else (i, '') for i in url]) url['title'], url['premiered'], url['season'], url['episode'] = title, premiered, season, episode url = urlencode(url) return url # written by mbebe on GitHub: https://github.com/mbebe/blomqvist # License: https://github.com/mbebe/blomqvist/blob/master/LICENSE def createCook(self, a, e, cook): b = a[-4:] c = a[7:10] + b d = a[-2:] e = e.split() f = e[int(d[0])].lower() g = e[int(d[1])] h = '_' + f[int(b[0])] i = g[int(c[0])] h += ''.join(f[int(char)] for char in b[1:]) i += ''.join(g[int(char)] for char in c[1:]) nt = self.amu(i) cook[h] = nt.upper() return cook # written by mbebe on GitHub: https://github.com/mbebe/blomqvist # License: https://github.com/mbebe/blomqvist/blob/master/LICENSE def amu(self, zz): import ctypes import math zz += chr(128) a = zz g = [1518500249, 1859775393, 2400959708, 3395469782] b = [1732584193, 4023233417, 2562383102, 271733878, 3285377520] l = math.ceil((float(len(a)) / 4 + 2) / 16) m = {} for h in range(int(l)): m = {h: [''] * 16 for _ in range(16)} d = 0 for d in range(16): try: a1 = ord(a[64 * h + 4 * d]) << 24 except: a1 = 0 try: a2 = ord(a[64 * h + 4 * d + 1]) << 16 except: a2 = 0 try: a4 = ord(a[64 * h + 4 * d + 3]) except: a4 = 0 try: a3 = ord(a[64 * h + 4 * d + 2]) << 8 except: a3 = 0 m[h][d] = a1 | a2 | a3 | a4 m[l - 1][14] = 8 * (len(a) - 1) / math.pow(2, 32) m[l - 1][14] = math.floor(m[l - 1][14]) m[l - 1][15] = 8 * (len(a) - 1) & 4294967295 d = [] def qq2(aa, e, f, gg): if aa == 0: return ctypes.c_int(e & f ^ ~e & gg).value elif aa == 1: return ctypes.c_int(e ^ f ^ gg).value elif aa == 2: return ctypes.c_int(e & f ^ e & gg ^ f & gg).value elif aa == 3: return ctypes.c_int(e ^ f ^ gg).value def unsigned32(signed): return signed % 0x100000000 def zero_fill_right_shift(val, nn): return (val >> nn) if val >= 0 else ((val + 0x100000000) >> nn) def qq(ab, eb): af = unsigned32(ab) >> 32 - eb return ctypes.c_int(ab << eb | zero_fill_right_shift(ab, 32 - eb)).value for ff in range(80): d.append('') for h in range(int(l)): for c in range(16): d[c] = int(m[h][c]) for c in range(16, 80): b1 = int(d[c - 3]) b2 = int(d[c - 8]) b3 = int(d[c - 14]) b4 = int(d[c - 16]) d[c] = qq(b1 ^ b2 ^ b3 ^ b4, 1) n = b[0] p = b[1] q = b[2] r = b[3] u = b[4] for c in range(80): t = int(math.floor(c / 20)) t = ctypes.c_int(zero_fill_right_shift((qq(n, 5) + qq2(t, p, q, r) + u + g[t] + d[c]), 0)).value u = r r = q q = ctypes.c_int(zero_fill_right_shift(qq(p, 30), 0)).value p = n n = t b[0] = unsigned32(b[0] + n) >> 0 b[1] = unsigned32(b[1] + p) >> 0 b[2] = unsigned32(b[2] + q) >> 0 b[3] = unsigned32(b[3] + r) >> 0 b[4] = unsigned32(b[4] + u) >> 0 for g in range(len(b)): z = (hex(b[g]).lstrip('0x').rstrip("L")) b[g] = ("00000000" + z)[-8:] return (','.join(b)).replace(',', '') # written by mbebe on GitHub: https://github.com/mbebe/blomqvist # License: https://github.com/mbebe/blomqvist/blob/master/LICENSE def wootly(self, wurl): UAx = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36' headers2 = { 'Host': 'www.wootly.ch', 'Upgrade-Insecure-Requests': '1', 'User-Agent': UAx, 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Language': 'en-US,en;q=0.9,pl;q=0.8', } response = self.sess.get(wurl, headers=headers2, verify=None) response_content = response.content.decode(encoding='utf-8', errors='strict') nturl = re.findall('iframe src="([^"]+)', response_content)[0] headers2.update({'Referer': wurl}) # response = self.sess.get(nturl, headers=headers2, verify=None) headers = { 'Host': 'www.wootly.ch', 'Upgrade-Insecure-Requests': '1', 'User-Agent': UAx, 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-User': '?1', 'Sec-Fetch-Dest': 'document', 'Referer': nturl, 'Accept-Language': 'en-US,en;q=0.9,pl;q=0.8', } response = self.sess.get('https://www.wootly.ch/prime', headers=headers, verify=None) response_content = response.content.decode(encoding='utf-8', errors='strict') cn = re.findall('cn="([^"]+)', response_content, re.DOTALL)[0] cv = re.findall('cv="([^"]+)', response_content, re.DOTALL)[0] gg = self.sess.cookies.get_dict() gg[cn] = cv data = {'qdf': '1'} response = self.sess.post(nturl, headers=headers, cookies=gg, data=data, verify=None) response_content = response.content.decode(encoding='utf-8', errors='strict') tk = re.findall('tk="([^"]+)', response_content, re.DOTALL)[0] vd = re.findall('vd="([^"]+)', response_content, re.DOTALL)[0] url2 = 'https://wootly.ch/grabd' + "?t=" + tk + "&id=" + vd wootlycookies = self.sess.cookies response = self.sess.get(url2, headers=headers, cookies=wootlycookies, verify=None) response_content = response.content.decode(encoding='utf-8', errors='strict') link = response_content link = 'https:' + link if link.startswith('//') else link link += '|User-Agent='+UAx+'&Referer='+link return link # written by mbebe on GitHub: https://github.com/mbebe/blomqvist # License: https://github.com/mbebe/blomqvist/blob/master/LICENSE def GetPlayLink(self, url, headers, lastkuk): response = self.sess.get(url.replace('supernova.to', 'goojara.to'), headers=headers, cookies=lastkuk, verify=None) link = response.url if 'wootly' in link.lower(): try: self.sess.close() link = self.wootly(link) except: return link return link # written by mbebe on GitHub: https://github.com/mbebe/blomqvist # License: https://github.com/mbebe/blomqvist/blob/master/LICENSE def GetCook(self, ref): UAx = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36' ref = ref.replace('www.supernova.to', 'www.goojara.to') headers = { 'upgrade-insecure-requests': '1', 'user-agent': UAx, 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'sec-fetch-site': 'none', 'sec-fetch-mode': 'navigate', 'sec-fetch-user': '?1', 'sec-fetch-dest': 'document', 'accept-language': 'en-US,en;q=0.9', } response = self.sess.get(ref, headers=headers, verify=None) response_content = response.content.decode(encoding='utf-8', errors='strict') dtinsshd = re.findall('shd" data-ins="(.+?)"', response_content, re.DOTALL)[0] gg = self.sess.cookies.get_dict() ck, ck2 = re.findall("""_3chk\(['"](.+?)['"],['"](.+?)['"]""", response_content, re.DOTALL)[0] gg[ck] = ck2 refe = ref.replace('www.supernova.to', 'www.goojara.to') headers = { 'Host': 'www.goojara.to', 'user-agent': UAx, 'content-type': 'application/x-www-form-urlencoded', 'accept': '*/*', 'origin': 'https://www.goojara.to', 'sec-fetch-site': 'same-origin', 'sec-fetch-mode': 'cors', 'sec-fetch-dest': 'empty', 'referer': refe, 'accept-language': 'en-US,en;q=0.9', } params = ( ('p', '2'), ) data = {"act": "1"} response = self.sess.post(refe, headers=headers, params=params, cookies=gg, data=data, verify=None) response_content = response.content.decode(encoding='utf-8', errors='strict') last_cook = self.createCook(dtinsshd, response_content, gg) return headers, last_cook def sources(self, url, hostDict): try: if not url: return self.results data = parse_qs(url) data = dict([(i, data[i][0]) if data[i] else (i, '') for i in data]) aliases = eval(data['aliases']) title = data['tvshowtitle'] if 'tvshowtitle' in data else data['title'] season, episode = (data['season'], data['episode']) if 'tvshowtitle' in data else ('0', '0') year = data['premiered'].split('-')[0] if 'tvshowtitle' in data else data['year'] check_term = '%s - Season %s' % (title, season) if 'tvshowtitle' in data else title if not self.base_link.startswith('https://www.'): self.base_link = 'https://www.' + self.base_link.split('://')[1] headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate', 'Referer': self.base_link, 'Content-type': 'application/x-www-form-urlencoded', 'Origin': self.base_link, 'Connection': 'keep-alive', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'TE': 'trailers', } postdata = {'q': title.lower()} url = self.base_link + self.php_entrypoint self.cookie = client.request(self.base_link, output='cookie', timeout='30') cookie_dict = {cookie.split('=')[0]: cookie.split('=')[1] for cookie in self.cookie.split('; ')} rPost = self.sess.post(url, headers=headers, data=postdata, cookies=cookie_dict) r = (rPost.content).decode(encoding='utf-8', errors='strict') r = DOM(r, 'ul') r = list(zip(DOM(r, 'a', ret='href'), DOM(r, 'div'))) r = [(url, client_utils.remove_tags(html)) for url, html in r] r = [(url, re.sub(r'\(\d{4}\)', '', html), re.findall(r'\((\d{4})\)', html)[0]) for url, html in r] r = [(i[0], i[1], i[2]) for i in r if len(i[0]) > 0 and len(i[1]) > 0 and len(i[2]) > 0] r = [(i[0], i[1].strip(), i[2]) for i in r if len(i[0]) > 0 and len(i[1]) > 0 and len(i[2]) > 0] # goojara tv show year are incorrect, sometimes. try: result_url = next(i[0] for i in r if cleantitle.match_alias(i[1], aliases) and cleantitle.match_year(i[2], data.get('year'))) except StopIteration: try: year2 = data.get('year') result_url = next(i[0] for i in r if cleantitle.match_alias(i[1], aliases) and cleantitle.match_year(i[2], year2)) except StopIteration: result_url = next(i[0] for i in r if cleantitle.match_alias(i[1], aliases)) if not result_url: return result_url = result_url.replace('ww1.', 'www.') if 'ww1.' in result_url else result_url r = client.scrapePage(result_url).text if 'tvshowtitle' in data: # get the season and episode data_id = DOM(r, 'div', attrs={'id': 'seon'}, ret='data-id')[0] postdata = {'s': season, 't': data_id} rPost = self.sess.post(url, headers=headers, data=postdata, cookies=cookie_dict) r = (rPost.content).decode(encoding='utf-8', errors='strict') r = list(zip(DOM(r, 'a', ret='href'), DOM(r, 'span', attrs={'class': 'sea'}))) check_episode = episode.zfill(2) # add leading zero found_url = [i[0] for i in r if check_episode == i[1]][0] result_url = self.base_link + found_url r = client.scrapePage(result_url).text r = [i for i in DOM(r, 'div', attrs={'class': 'lxbx'}) if 'Direct Links' in i][0] result_links = list(zip(DOM(r, 'a', ret='href'), [re.sub(r'.*?', '', site).strip() for site in DOM(r, 'a')])) vurls = [] result_url = result_url.replace('ww1.','www.') headers, last_cookie = self.GetCook(result_url) for link, host in result_links: try: mylink = self.GetPlayLink(link, headers, last_cookie) vurls.append((mylink, host)) except: # log_utils.log('FAILED: link =' + repr(link), 1) pass for link, host in vurls: if 'wootly' in link.lower(): source = { 'source': host, 'quality': 'SD', 'info': '', 'url': link, 'direct': False, } self.results.append(source) else: for source in scrape_sources.process(hostDict, link): self.results.append(source) return self.results except: return self.results def resolve(self, url): return url