feat: insane new debrid stream proxy (allows to use debrid service on multiple IPs at same time)

This commit is contained in:
Goldy
2024-07-05 01:01:18 +02:00
parent 19990134eb
commit ba1f78eb84
7 changed files with 76 additions and 24 deletions
+4 -1
View File
@@ -13,4 +13,7 @@ INDEXER_MANAGER_TIMEOUT=60 # maximum time to obtain search results from indexer
INDEXER_MANAGER_INDEXERS='["EXAMPLE1_CHANGETHIS", "EXAMPLE2_CHANGETHIS"]'
GET_TORRENT_TIMEOUT=5 # maximum time to obtain the torrent info hash in seconds
ZILEAN_URL=None # for DMM search - https://github.com/iPromKnight/zilean
CUSTOM_HEADER_HTML=None # only set it if you know what it is
CUSTOM_HEADER_HTML=None # only set it if you know what it is
PROXY_DEBRID_STREAM=False # Proxy Debrid Streams (very useful to use your debrid service on multiple IPs at same time)
PROXY_DEBRID_STREAM_PASSWORD=CHANGE_ME # Secret password to enter on configuration page to prevent people from abusing your debrid stream proxy
PROXY_DEBRID_STREAM_BYTES_PER_CHUNK=102400 # 10MB per chunks
+45 -3
View File
@@ -5,7 +5,7 @@ import time
import aiohttp
from fastapi import APIRouter, Request
from fastapi.responses import RedirectResponse
from fastapi.responses import RedirectResponse, StreamingResponse
from RTN import Torrent, parse, sort_torrents, title_match
from comet.debrid.manager import getDebrid
@@ -279,7 +279,7 @@ async def playback(b64config: str, hash: str, index: str):
@streams.get("/{b64config}/playback/{hash}/{index}")
async def playback(b64config: str, hash: str, index: str):
async def playback(request: Request, b64config: str, hash: str, index: str):
config = config_check(b64config)
if not config:
return
@@ -288,4 +288,46 @@ async def playback(b64config: str, hash: str, index: str):
debrid = getDebrid(session, config)
download_link = await debrid.generate_download_link(hash, index)
return RedirectResponse(download_link, status_code=302)
if (
settings.PROXY_DEBRID_STREAM
and settings.PROXY_DEBRID_STREAM_PASSWORD
== config["debridStreamProxyPassword"]
):
async def stream_content(headers: dict):
async with aiohttp.ClientSession() as session:
response = await session.get(download_link, headers=headers)
while True:
chunk = await response.content.read(
settings.PROXY_DEBRID_STREAM_BYTES_PER_CHUNK
) # 10 MB chunks
if not chunk:
break
yield chunk
range = None
range_header = request.headers.get("range")
if range_header:
range_value = range_header.strip().split("=")[1]
start, end = range_value.split("-")
start = int(start)
end = int(end) if end else ""
range = f"bytes={start}-{end}"
response = await session.get(
download_link, headers={"Range": f"bytes={start}-{end}"}
)
if response.status == 206:
return StreamingResponse(
stream_content({"Range": range}),
status_code=206,
headers={
"Content-Range": response.headers["Content-Range"],
"Content-Length": response.headers["Content-Length"],
"Accept-Ranges": "bytes",
},
)
return
return RedirectResponse(download_link, status_code=302)
+1 -1
View File
@@ -7,4 +7,4 @@ 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)
return RealDebrid(session, debrid_api_key)
+2 -5
View File
@@ -16,9 +16,7 @@ class RealDebrid:
async def check_premium(self):
try:
check_premium = await self.session.get(
f"{self.api_url}/user"
)
check_premium = await self.session.get(f"{self.api_url}/user")
check_premium = await check_premium.text()
if '"type": "premium"' not in check_premium:
return False
@@ -29,7 +27,7 @@ class RealDebrid:
f"Exception while checking premium status on Real Debrid: {e}"
)
return False
async def get_instant(self, hash: str):
try:
response = await self.session.get(
@@ -58,7 +56,6 @@ class RealDebrid:
return availability
async def get_files(self, availability: dict, type: str, season: str, episode: str):
files = {}
for hash, details in availability.items():
+9 -3
View File
@@ -514,6 +514,10 @@
<sl-checkbox id="filterTitles" checked help-text="Should Comet check for title mismatch?">Filter Titles</sl-checkbox>
</div>
<div class="form-item">
<sl-input id="debridStreamProxyPassword" label="Debrid Stream Proxy Password" placeholder="Enter secret password" help-text="Debrid Stream Proxying allows you to use your Debrid Service from multiple IPs at same time!"></sl-input>
</div>
<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>
@@ -578,18 +582,20 @@
const filterTitles = document.getElementById("filterTitles").checked;
const debridService = document.getElementById("debridService").value;
const debridApiKey = document.getElementById("debridApiKey").value;
const debridStreamProxyPassword = document.getElementById("debridStreamProxyPassword").value;
const selectedLanguages = languages.length === defaultLanguages.length && languages.every((val, index) => val === defaultLanguages[index]) ? ["All"] : languages;
const selectedResolutions = resolutions.length === defaultResolutions.length && resolutions.every((val, index) => val === defaultResolutions[index]) ? ["All"] : resolutions;
const settings = {
debridService: debridService,
debridApiKey: debridApiKey,
indexers: indexers,
maxResults: parseInt(maxResults),
filterTitles: filterTitles,
resolutions: selectedResolutions,
languages: selectedLanguages
languages: selectedLanguages,
debridService: debridService,
debridApiKey: debridApiKey,
debridStreamProxyPassword: debridStreamProxyPassword,
};
navigator.clipboard.writeText(`${window.location.origin}/${btoa(JSON.stringify(settings))}/manifest.json`).then(() => {
+14 -10
View File
@@ -10,22 +10,25 @@ from RTN import RTN, BaseRankingModel, SettingsModel
class AppSettings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
ADDON_ID: str = "stremio.comet.fast"
ADDON_NAME: str = "Comet"
FASTAPI_HOST: str = "0.0.0.0"
FASTAPI_PORT: int = 8000
FASTAPI_WORKERS: int = 2 * (os.cpu_count() or 1)
DATABASE_PATH: str = "data/comet.db"
CACHE_TTL: int = 86400
ADDON_ID: Optional[str] = "stremio.comet.fast"
ADDON_NAME: Optional[str] = "Comet"
FASTAPI_HOST: Optional[str] = "0.0.0.0"
FASTAPI_PORT: Optional[int] = 8000
FASTAPI_WORKERS: Optional[int] = 2 * (os.cpu_count() or 1)
DATABASE_PATH: Optional[str] = "data/comet.db"
CACHE_TTL: Optional[int] = 86400
DEBRID_PROXY_URL: Optional[str] = None
INDEXER_MANAGER_TYPE: str = "jackett"
INDEXER_MANAGER_URL: str = "http://127.0.0.1:9117"
INDEXER_MANAGER_API_KEY: str = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
INDEXER_MANAGER_TIMEOUT: int = 30
INDEXER_MANAGER_API_KEY: str
INDEXER_MANAGER_TIMEOUT: Optional[int] = 30
INDEXER_MANAGER_INDEXERS: List[str] = ["EXAMPLE1_CHANGETHIS", "EXAMPLE2_CHANGETHIS"]
GET_TORRENT_TIMEOUT: int = 5
GET_TORRENT_TIMEOUT: Optional[int] = 5
ZILEAN_URL: Optional[str] = None
CUSTOM_HEADER_HTML: Optional[str] = None
PROXY_DEBRID_STREAM: Optional[bool] = False
PROXY_DEBRID_STREAM_PASSWORD: Optional[str] = "CHANGE_ME"
PROXY_DEBRID_STREAM_BYTES_PER_CHUNK: Optional[int] = 102400
settings = AppSettings()
@@ -39,6 +42,7 @@ class ConfigModel(BaseModel):
filterTitles: Optional[bool] = True
debridService: str
debridApiKey: str
debridStreamProxyPassword: Optional[str] = ""
@field_validator("indexers")
def check_indexers(cls, v, values):
Generated
+1 -1
View File
@@ -2279,4 +2279,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "ddb74ca11fc846b4142969b7027d42c765ef58952405c241fb759cf5e9f2df53"
content-hash = "24f9bb0c3506c9138b89c473f41e1633b6c41b05274bc4d3dc67c4688a4a1b82"