Skip to content

Commit

Permalink
feat: alldebrid support
Browse files Browse the repository at this point in the history
  • Loading branch information
g0ldyy committed Jul 5, 2024
1 parent fbee0b2 commit afd27c0
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 34 deletions.
56 changes: 37 additions & 19 deletions comet/api/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,28 @@ async def stream(request: Request, b64config: str, type: str, id: str):
season = int(info[1])
episode = int(info[2])

get_metadata = await session.get(
f"https://v3.sg.media-imdb.com/suggestion/a/{id}.json"
)
metadata = await get_metadata.json()
try:
get_metadata = await session.get(
f"https://v3.sg.media-imdb.com/suggestion/a/{id}.json"
)
metadata = await get_metadata.json()

name = metadata["d"][0 if len(metadata["d"]) == 1 else 1]["l"]
except Exception as e:
logger.warning(
f"Exception while getting metadata for {id}: {e}"
)

return {
"streams": [
{
"name": "[⚠️] Comet",
"title": f"Can't get metadata for {id}",
"url": "https://comet.fast",
}
]
}

name = metadata["d"][0 if len(metadata["d"]) == 1 else 1]["l"]
name = translate(name)
logName = name
if type == "series":
Expand Down Expand Up @@ -153,14 +169,14 @@ async def stream(request: Request, b64config: str, type: str, id: str):
)

zilean_hashes_count = 0
try:
if settings.ZILEAN_URL:
if settings.ZILEAN_URL:
try:
get_dmm = await session.post(
f"{settings.ZILEAN_URL}/dmm/search", json={"queryText": name}
)
get_dmm = await get_dmm.json()

if "status" not in get_dmm:
if isinstance(get_dmm, list):
for result in get_dmm:
zilean_hashes_count += 1

Expand All @@ -178,28 +194,29 @@ async def stream(request: Request, b64config: str, type: str, id: str):

torrents.append(object)

logger.info(
f"{zilean_hashes_count} torrents found for {logName} with Zilean API"
)
except Exception as e:
logger.warning(
f"Exception while getting torrents for {logName} with Zilean API: {e}"
)
logger.info(
f"{zilean_hashes_count} torrents found for {logName} with Zilean API"
)
except Exception as e:
logger.warning(
f"Exception while getting torrents for {logName} with Zilean API: {e}"
)

if len(torrents) == 0:
return {"streams": []}

tasks = []
filtered = 0
filter_title = config["filterTitles"]
name_lower = name.lower()
for torrent in torrents:
if filter_title:
parsed_torrent = parse(
torrent["Title"]
if indexer_manager_type == "jackett"
else torrent["title"]
)
if not title_match(name.lower(), parsed_torrent.parsed_title.lower()):
if not title_match(name_lower, parsed_torrent.parsed_title.lower()):
filtered += 1
continue

Expand All @@ -215,8 +232,7 @@ async def stream(request: Request, b64config: str, type: str, id: str):
if len(torrent_hashes) == 0:
return {"streams": []}

availability = await debrid.get_availability(torrent_hashes)
files = await debrid.get_files(availability, type, season, episode)
files = await debrid.get_files(torrent_hashes, type, season, episode)

ranked_files = set()
for hash in files:
Expand Down Expand Up @@ -314,7 +330,9 @@ async def stream_content(headers: dict):
end = int(end) if end else ""
range = f"bytes={start}-{end}"

async with await session.get(download_link, headers={"Range": f"bytes={start}-{end}"}) as response:
async with await session.get(
download_link, headers={"Range": f"bytes={start}-{end}"}
) as response:
await session.close()

if response.status == 206:
Expand Down
129 changes: 129 additions & 0 deletions comet/debrid/alldebrid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import aiohttp

from RTN import parse

from comet.utils.general import is_video
from comet.utils.logger import logger
from comet.utils.models import settings


class AllDebrid:
def __init__(self, session: aiohttp.ClientSession, debrid_api_key: str):
session.headers["Authorization"] = f"Bearer {debrid_api_key}"
self.session = session

self.api_url = "http://api.alldebrid.com/v4"
self.agent = "comet"

async def check_premium(self):
try:
check_premium = await self.session.get(
f"{self.api_url}/user?agent={self.agent}"
)
check_premium = await check_premium.text()
if '"isPremium": true' in check_premium:
return True
except Exception as e:
logger.warning(
f"Exception while checking premium status on All Debrid: {e}"
)

return False

async def get_files(self, torrent_hashes: list, type: str, season: str, episode: str):
try:
get_instant = await self.session.get(
f"{self.api_url}/magnet/instant?agent={self.agent}&magnets[]={'&magnets[]='.join(hash for hash in torrent_hashes)}"
)
availability = await get_instant.json()
except Exception as e:
logger.warning(
f"Exception while checking hash cache on All Debrid for {hash}: {e}"
)

return {}

if not "status" in availability or availability["status"] != "success":
return {}

files = {}
for magnet in availability["data"]["magnets"]:
if not magnet["instant"]:
continue

if type == "series":
for file in magnet["files"]:
filename = file["n"]

if not is_video(filename):
continue

filename_parsed = parse(filename)
if (
season in filename_parsed.season
and episode in filename_parsed.episode
):
files[magnet["hash"]] = {
"index": magnet["files"].index(file),
"title": filename,
"size": file["s"],
}

continue

for file in magnet["files"]:
filename = file["n"]

if not is_video(filename):
continue

files[magnet["hash"]] = {
"index": magnet["files"].index(file),
"title": filename,
"size": file["s"],
}

return files

async def generate_download_link(self, hash: str, index: str):
try:
check_blacklisted = await self.session.get(
f"{self.api_url}/magnet/upload?agent=comet&magnets[]={hash}"
)
check_blacklisted = await check_blacklisted.text()
proxy = None
if "NO_SERVER" in check_blacklisted:
proxy = settings.DEBRID_PROXY_URL
if not proxy:
logger.warning(
"All-Debrid blacklisted server's IP. No proxy found."
)
else:
logger.warning(
f"All-Debrid blacklisted server's IP. Switching to proxy {proxy} for {hash}|{index}"
)

upload_magnet = await self.session.get(
f"{self.api_url}/magnet/upload?agent=comet&magnets[]={hash}",
proxy=proxy,
)
upload_magnet = await upload_magnet.json()

get_magnet_status = await self.session.get(
f"{self.api_url}/magnet/status?agent=comet&id={upload_magnet['data']['magnets'][0]['id']}",
proxy=proxy,
)
get_magnet_status = await get_magnet_status.json()

unlock_link = await self.session.get(
f"{self.api_url}/link/unlock?agent=comet&link={get_magnet_status['data']['magnets']['links'][int(index)]['link']}",
proxy=proxy,
)
unlock_link = await unlock_link.json()

return unlock_link["data"]["link"]
except Exception as e:
logger.warning(
f"Exception while getting download link from All Debrid for {hash}|{index}: {e}"
)
return "https://comet.fast"
3 changes: 3 additions & 0 deletions comet/debrid/manager.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import aiohttp

from .realdebrid import RealDebrid
from .alldebrid import AllDebrid


def getDebrid(session: aiohttp.ClientSession, config: dict):
debrid_service = config["debridService"]
debrid_api_key = config["debridApiKey"]
if debrid_service == "realdebrid":
return RealDebrid(session, debrid_api_key)
if debrid_service == "alldebrid":
return AllDebrid(session, debrid_api_key)
17 changes: 7 additions & 10 deletions comet/debrid/realdebrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class RealDebrid:
def __init__(self, session: aiohttp.ClientSession, debrid_api_key: str):
session.headers["Authorization"] = f"Bearer {debrid_api_key}"
self.session = session

self.api_url = "https://api.real-debrid.com/rest/1.0"

async def check_premium(self):
Expand All @@ -25,7 +25,7 @@ async def check_premium(self):
logger.warning(
f"Exception while checking premium status on Real Debrid: {e}"
)

return False

async def get_instant(self, hash: str):
Expand All @@ -36,27 +36,24 @@ async def get_instant(self, hash: str):
return await response.json()
except Exception as e:
logger.warning(
f"Exception while checking hash cache on Real Debrid for {hash}: {e}"
f"Exception while checking hash instant availability on Real Debrid for {hash}: {e}"
)
return

async def get_availability(self, hashes: list):
async def get_files(self, torrent_hashes: list, type: str, season: str, episode: str):
tasks = []
for hash in hashes:
for hash in torrent_hashes:
tasks.append(self.get_instant(hash))

responses = await asyncio.gather(*tasks)

availability = {}
for response in responses:
if not response:
if response is None:
continue

availability.update(response)

return availability

async def get_files(self, availability: dict, type: str, season: str, episode: str):

files = {}
for hash, details in availability.items():
if "rd" not in details:
Expand Down
1 change: 1 addition & 0 deletions comet/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@
<div class="form-item">
<sl-select id="debridService" value="realdebrid" label="Debrid Service" placeholder="Select debrid service">
<sl-option value="realdebrid">Real-Debrid</sl-option>
<sl-option value="alldebrid">All-Debrid</sl-option>
</sl-select>
</div>

Expand Down
2 changes: 0 additions & 2 deletions comet/utils/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

async def setup_database():
try:
# Ensure the database directory exists
os.makedirs(os.path.dirname(settings.DATABASE_PATH), exist_ok=True)

# Ensure the database file exists
if not os.path.exists(settings.DATABASE_PATH):
open(settings.DATABASE_PATH, "a").close()

Expand Down
9 changes: 6 additions & 3 deletions comet/utils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ class ConfigModel(BaseModel):

@field_validator("indexers")
def check_indexers(cls, v, values):
if not any(indexer in settings.INDEXER_MANAGER_INDEXERS for indexer in v):
valid_indexers = [
indexer for indexer in v if indexer in settings.INDEXER_MANAGER_INDEXERS
]
if not valid_indexers:
raise ValueError(
f"At least one indexer must be from {settings.INDEXER_MANAGER_INDEXERS}"
)
return v
return valid_indexers

@field_validator("maxResults")
def check_max_results(cls, v):
Expand All @@ -60,7 +63,7 @@ def check_max_results(cls, v):

@field_validator("debridService")
def check_debrid_service(cls, v):
if v not in ["realdebrid"]:
if v not in ["realdebrid", "alldebrid"]:
raise ValueError("Invalid debridService")
return v

Expand Down

0 comments on commit afd27c0

Please sign in to comment.