From ab846a76134fa2c0ebf6091a878bf3f0aeb93ff4 Mon Sep 17 00:00:00 2001 From: Goldy <153996346+g0ldyy@users.noreply.github.com> Date: Sun, 7 Jul 2024 02:34:34 +0200 Subject: [PATCH] feat: premiumize support --- comet/api/core.py | 4 +- comet/api/stream.py | 10 ++- comet/debrid/alldebrid.py | 6 +- comet/debrid/manager.py | 3 + comet/debrid/premiumize.py | 151 +++++++++++++++++++++++++++++++++++++ comet/debrid/realdebrid.py | 6 +- comet/templates/index.html | 3 + comet/utils/general.py | 6 +- comet/utils/models.py | 2 +- 9 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 comet/debrid/premiumize.py diff --git a/comet/api/core.py b/comet/api/core.py index 77b0fac..6ac4306 100644 --- a/comet/api/core.py +++ b/comet/api/core.py @@ -68,8 +68,10 @@ async def manifest(b64config: str = None): debrid_extension = None if config["debridService"] == "realdebrid": debrid_extension = "RD" - if config["debridService"] == "alldebrid": + elif config["debridService"] == "alldebrid": debrid_extension = "AD" + elif config["debridService"] == "premiumize": + debrid_extension = "PM" return { "id": settings.ADDON_ID, diff --git a/comet/api/stream.py b/comet/api/stream.py index 4acf252..72114c3 100644 --- a/comet/api/stream.py +++ b/comet/api/stream.py @@ -126,11 +126,12 @@ async def stream(request: Request, b64config: str, type: str, id: str): ) sorted_ranked_files = json.loads(sorted_ranked_files[0]) - debrid_extension = "EZ" if config["debridService"] == "realdebrid": debrid_extension = "RD" - if config["debridService"] == "alldebrid": + elif config["debridService"] == "alldebrid": debrid_extension = "AD" + elif config["debridService"] == "premiumize": + debrid_extension = "PM" balanced_hashes = await get_balanced_hashes(sorted_ranked_files, config) results = [] @@ -273,11 +274,12 @@ async def stream(request: Request, b64config: str, type: str, id: str): ) logger.info(f"Results have been cached for {logName}") - debrid_extension = "EZ" if config["debridService"] == "realdebrid": debrid_extension = "RD" - if config["debridService"] == "alldebrid": + elif config["debridService"] == "alldebrid": debrid_extension = "AD" + elif config["debridService"] == "premiumize": + debrid_extension = "PM" balanced_hashes = await get_balanced_hashes(sorted_ranked_files, config) results = [] diff --git a/comet/debrid/alldebrid.py b/comet/debrid/alldebrid.py index 6c31981..47a344d 100644 --- a/comet/debrid/alldebrid.py +++ b/comet/debrid/alldebrid.py @@ -27,7 +27,7 @@ async def check_premium(self): return True except Exception as e: logger.warning( - f"Exception while checking premium status on All Debrid: {e}" + f"Exception while checking premium status on All-Debrid: {e}" ) return False @@ -40,7 +40,7 @@ async def get_instant(self, chunk: list): return await get_instant.json() except Exception as e: logger.warning( - f"Exception while checking hashes instant availability on All Debrid: {e}" + f"Exception while checking hashes instant availability on All-Debrid: {e}" ) return @@ -146,6 +146,6 @@ async def generate_download_link(self, hash: str, index: str): return unlock_link["data"]["link"] except Exception as e: logger.warning( - f"Exception while getting download link from All Debrid for {hash}|{index}: {e}" + f"Exception while getting download link from All-Debrid for {hash}|{index}: {e}" ) return diff --git a/comet/debrid/manager.py b/comet/debrid/manager.py index 4b35cce..3003a02 100644 --- a/comet/debrid/manager.py +++ b/comet/debrid/manager.py @@ -2,6 +2,7 @@ from .realdebrid import RealDebrid from .alldebrid import AllDebrid +from .premiumize import Premiumize def getDebrid(session: aiohttp.ClientSession, config: dict): @@ -11,3 +12,5 @@ def getDebrid(session: aiohttp.ClientSession, config: dict): return RealDebrid(session, debrid_api_key) if debrid_service == "alldebrid": return AllDebrid(session, debrid_api_key) + if debrid_service == "premiumize": + return Premiumize(session, debrid_api_key) diff --git a/comet/debrid/premiumize.py b/comet/debrid/premiumize.py new file mode 100644 index 0000000..5e98430 --- /dev/null +++ b/comet/debrid/premiumize.py @@ -0,0 +1,151 @@ +import aiohttp +import asyncio + +from RTN import parse + +from comet.utils.general import is_video +from comet.utils.logger import logger + + +class Premiumize: + def __init__(self, session: aiohttp.ClientSession, debrid_api_key: str): + self.session = session + self.proxy = None + self.debrid_api_key = debrid_api_key + + self.api_url = "https://premiumize.me/api" + + async def check_premium(self): + try: + check_premium = await self.session.get( + f"{self.api_url}/account/info?apikey={self.debrid_api_key}" + ) + check_premium = await check_premium.text() + if ( + '"status":"success"' in check_premium + and '"premium_until":null' not in check_premium + ): + return True + except Exception as e: + logger.warning( + f"Exception while checking premium status on Premiumize: {e}" + ) + + return False + + async def get_instant(self, chunk: list): + try: + response = await self.session.get( + f"{self.api_url}/cache/check?apikey={self.debrid_api_key}&items[]={'&items[]='.join(hash for hash in chunk)}" + ) + + response = await response.json() + response["hashes"] = chunk + + return response + except Exception as e: + logger.warning( + f"Exception while checking hash instant availability on Premiumize: {e}" + ) + return + + async def get_files( + self, torrent_hashes: list, type: str, season: str, episode: str + ): + chunk_size = 100 + chunks = [ + torrent_hashes[i : i + chunk_size] + for i in range(0, len(torrent_hashes), chunk_size) + ] + + tasks = [] + for chunk in chunks: + tasks.append(self.get_instant(chunk)) + + responses = await asyncio.gather(*tasks) + + availability = [] + for response in responses: + if response is None: + continue + + availability.append(response) + + files = {} + for result in availability: + if result["status"] != "success": + continue + + responses = result["response"] + filenames = result["filename"] + filesizes = result["filesize"] + hashes = result["hashes"] + for index, response in enumerate(responses): + if response is False: + continue + + if filesizes[index] is None: + continue + + filename = filenames[index] + if type == "series": + filename_parsed = parse(filename) + if ( + season in filename_parsed.season + and episode in filename_parsed.episode + ): + files[hashes[index]] = { + "index": f"{season}|{episode}", + "title": filename, + "size": int(filesizes[index]), + } + + continue + + files[hashes[index]] = { + "index": 0, + "title": filename, + "size": int(filesizes[index]), + } + + return files + + async def generate_download_link(self, hash: str, index: str): + try: + add_magnet = await self.session.post( + f"{self.api_url}/transfer/directdl?apikey={self.debrid_api_key}&src=magnet:?xt=urn:btih:{hash}", + proxy=self.proxy, + ) + add_magnet = await add_magnet.json() + + season = None + if "|" in index: + index = index.split("|") + season = int(index[0]) + episode = int(index[1]) + + content = add_magnet["content"] + for file in content: + filename = file["path"] + if "/" in filename: + filename = filename.split("/")[1] + + if not is_video(filename): + content.remove(file) + continue + + if season is not None: + filename_parsed = parse(filename) + if ( + season in filename_parsed.season + and episode in filename_parsed.episode + ): + return file["link"] + + max_size_item = max(content, key=lambda x: x["size"]) + return max_size_item["link"] + except Exception as e: + logger.warning( + f"Exception while getting download link from Premiumize for {hash}|{index}: {e}" + ) + return diff --git a/comet/debrid/realdebrid.py b/comet/debrid/realdebrid.py index 3a7509b..ac56e58 100644 --- a/comet/debrid/realdebrid.py +++ b/comet/debrid/realdebrid.py @@ -24,7 +24,7 @@ async def check_premium(self): return True except Exception as e: logger.warning( - f"Exception while checking premium status on Real Debrid: {e}" + f"Exception while checking premium status on Real-Debrid: {e}" ) return False @@ -37,7 +37,7 @@ async def get_instant(self, chunk: list): return await response.json() except Exception as e: logger.warning( - f"Exception while checking hash instant availability on Real Debrid: {e}" + f"Exception while checking hash instant availability on Real-Debrid: {e}" ) return @@ -155,6 +155,6 @@ async def generate_download_link(self, hash: str, index: str): return unrestrict_link["download"] except Exception as e: logger.warning( - f"Exception while getting download link from Real Debrid for {hash}|{index}: {e}" + f"Exception while getting download link from Real-Debrid for {hash}|{index}: {e}" ) return diff --git a/comet/templates/index.html b/comet/templates/index.html index 64bee73..a9611e8 100644 --- a/comet/templates/index.html +++ b/comet/templates/index.html @@ -535,6 +535,7 @@ Real-Debrid All-Debrid + Premiumize @@ -555,6 +556,8 @@ apiKeyLink.href = "https://real-debrid.com/apitoken"; } else if (selectedService === "alldebrid") { apiKeyLink.href = "https://alldebrid.fr/apikeys"; + } else if (selectedService === "premiumize") { + apiKeyLink.href = "https://premiumize.me/account"; } }); diff --git a/comet/utils/general.py b/comet/utils/general.py index 00de527..29bbf38 100644 --- a/comet/utils/general.py +++ b/comet/utils/general.py @@ -246,10 +246,10 @@ async def get_torrent_hash( session: aiohttp.ClientSession, indexer_manager_type: str, torrent: dict ): if "InfoHash" in torrent and torrent["InfoHash"] is not None: - return torrent["InfoHash"] + return torrent["InfoHash"].lower() if "infoHash" in torrent: - return torrent["infoHash"] + return torrent["infoHash"].lower() url = ( torrent["Link"] if indexer_manager_type == "jackett" else torrent["downloadUrl"] @@ -274,7 +274,7 @@ async def get_torrent_hash( hash = match.group(1).upper() - return hash + return hash.lower() except Exception as e: logger.warning( f"Exception while getting torrent info hash for {torrent['indexer'] if 'indexer' in torrent else (torrent['Tracker'] if 'Tracker' in torrent else '')}|{url}: {e}" diff --git a/comet/utils/models.py b/comet/utils/models.py index 7122ae6..87cbd39 100644 --- a/comet/utils/models.py +++ b/comet/utils/models.py @@ -62,7 +62,7 @@ def check_max_results(cls, v): @field_validator("debridService") def check_debrid_service(cls, v): - if v not in ["realdebrid", "alldebrid"]: + if v not in ["realdebrid", "alldebrid", "premiumize"]: raise ValueError("Invalid debridService") return v