first commit

This commit is contained in:
Viren070
2025-02-18 14:07:52 +00:00
commit 3e311b50c8
37 changed files with 7042 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
from abc import ABC, abstractmethod
from typing import Dict, List
class StreamingService(ABC):
@abstractmethod
async def get_streams(self, meta_id: str) -> List[Dict]:
pass
@property
@abstractmethod
def name(self) -> str:
pass
+67
View File
@@ -0,0 +1,67 @@
import base64
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.config import config
from utils.logger import logger
from .base import StreamingService
class CometService(StreamingService):
def __init__(self):
self.base_url = config.get("addon_config", "comet", "base_url")
self.debrid_api_key = config.get_addon_debrid_api_key("comet")
self.debrid_service = config.get_addon_debrid_service("comet")
self.options = f"""{{
"indexers": ["bitsearch", "eztv", "thepiratebay", "therarbg", "yts"],
"maxResults": 0,
"maxResultsPerResolution": 0,
"maxSize": 0,
"reverseResultOrder": false,
"removeTrash": true,
"resultFormat": ["All"],
"resolutions": ["All"],
"languages": ["All"],
"debridService": "{self.debrid_service}",
"debridApiKey": "{self.debrid_api_key}",
"stremthruUrl": "",
"debridStreamProxyPassword": ""
}}"""
self.options_encoded = base64.b64encode(self.options.encode()).decode("utf-8")
@property
def name(self) -> str:
return "Comet"
async def _fetch_from_comet(self, url: str) -> Dict:
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"Comet response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"Comet request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options_encoded}/stream/{meta_id}"
logger.debug(f"Comet stream url: {url}")
data = await self._fetch_from_comet(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
stream_name = stream.get("name", "")
if stream_name.startswith("["):
prefix = stream_name[1:stream_name.find("]")] if "]" in stream_name else ""
stream["is_cached"] = "" in prefix
else:
stream["is_cached"] = True
return streams
+53
View File
@@ -0,0 +1,53 @@
import base64
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.config import config
from utils.logger import logger
from .base import StreamingService
class DebridioService(StreamingService):
def __init__(self):
self.base_url = "https://debridio.adobotec.com"
self.debrid_api_key = config.get_addon_debrid_api_key("debridio")
self.debrid_service = config.get_addon_debrid_service("debridio")
self.options = f'{{"provider":"{self.debrid_service}","apiKey":"{self.debrid_api_key}","disableUncached":false,"qualityOrder":[],"excludeSize":"","maxReturnPerQuality":""}}'
self.options_encoded = base64.b64encode(self.options.encode()).decode("utf-8")
@property
def name(self) -> str:
return "Debridio"
async def _fetch_from_debridio(self, url: str) -> Dict:
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"Debridio response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"Debridio request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options_encoded}/stream/{meta_id}"
logger.debug(f"Debridio stream url: {url}")
data = await self._fetch_from_debridio(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
stream_name = stream.get("name", "")
if stream_name.startswith("["):
prefix = stream_name[1:stream_name.find("]")] if "]" in stream_name else ""
stream["is_cached"] = "+" in prefix
else:
stream["is_cached"] = True
return streams
+46
View File
@@ -0,0 +1,46 @@
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.logger import logger
from .base import StreamingService
class EasynewsService(StreamingService):
def __init__(self):
self.base_url = "https://ea627ddf0ee7-easynews.baby-beamup.club"
self.username = os.getenv("EASYNEWS_USERNAME")
self.password = os.getenv("EASYNEWS_PASSWORD")
self.options = f"%7B%22username%22%3A%22{self.username}%22%2C%22password%22%3A%22{self.password}%22%7D"
@property
def name(self) -> str:
return "Easynews"
async def _fetch_from_easynews(self, url: str) -> Dict:
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"Easynews response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"Easynews request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options}/stream/{meta_id}"
logger.debug(f"Easynews stream url: {url}")
data = await self._fetch_from_easynews(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
# Easynews doesn't have a cache
stream["is_cached"] = True
return streams
+45
View File
@@ -0,0 +1,45 @@
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.logger import logger
from .base import StreamingService
class MediaFusionService(StreamingService):
def __init__(self):
self.base_url = "https://mediafusion.elfhosted.com"
# Generate a MediaFusion URL, then copy the data between https://mediafusion.elfhosted.com/ and /manifest.json
self.options = os.getenv("MEDIAFUSION_OPTIONS")
@property
def name(self) -> str:
return "MediaFusion"
async def _fetch_from_mediafusion(self, url: str) -> Dict:
async with httpx.AsyncClient(timeout=15) as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"MediaFusion response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"MediaFusion request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options}/stream/{meta_id}"
logger.debug(f"MediaFusion stream url: {url}")
data = await self._fetch_from_mediafusion(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
if "" in stream["name"]:
stream["is_cached"] = True
return streams
+48
View File
@@ -0,0 +1,48 @@
import base64
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.config import config
from utils.logger import logger
from .base import StreamingService
class PeerflixService(StreamingService):
def __init__(self):
self.base_url = "https://peerflix-addon.onrender.com"
self.debrid_api_key = config.get_addon_debrid_api_key("peerflix")
self.debrid_service = config.get_addon_debrid_service("peerflix")
self.options = f'language=en,es|debridoptions=nocatalog,nodownloadlinks|{self.debrid_service}={self.debrid_api_key}|sort=quality-desc'
@property
def name(self) -> str:
return "Peerflix"
async def _fetch_from_peerflix(self, url: str) -> Dict:
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"Peerflix response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"Peerflix request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options}/stream/{meta_id}"
logger.debug(f"Peerflix stream url: {url}")
data = await self._fetch_from_peerflix(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
# Peerflix streams are always cached
stream["is_cached"] = True
return streams
+41
View File
@@ -0,0 +1,41 @@
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.logger import logger
from .base import StreamingService
class TorboxService(StreamingService):
def __init__(self):
self.base_url = "https://stremio.torbox.app"
self.debrid_api_key = os.getenv("DEBRID_API_KEY")
self.options = f"{self.debrid_api_key}"
@property
def name(self) -> str:
return "TorBox"
async def _fetch_from_torbox(self, url: str) -> Dict:
async with httpx.AsyncClient(timeout=15) as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"TorBox response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"TorBox request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options}/stream/{meta_id}"
logger.debug(f"TorBox stream url: {url}")
data = await self._fetch_from_torbox(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
return streams
+51
View File
@@ -0,0 +1,51 @@
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.config import config
from utils.logger import logger
from .base import StreamingService
class TorrentioService(StreamingService):
def __init__(self):
self.base_url = "https://torrentio.strem.fun"
self.debrid_api_key = config.get_addon_debrid_api_key("torrentio")
self.debrid_service = config.get_addon_debrid_service("torrentio")
self.options = f"debridoptions=nocatalog|{self.debrid_service}={self.debrid_api_key}"
@property
def name(self) -> str:
return "Torrentio"
async def _fetch_from_torrentio(self, url: str) -> Dict:
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"Torrentio response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"Torrentio request failed: {str(e)}")
raise HTTPException(status_code=502, detail="Upstream service error")
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/{self.options}/stream/{meta_id}"
logger.debug(f"Torrentio stream url: {url}")
data = await self._fetch_from_torrentio(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
stream_name = stream.get("name", "")
if stream_name.startswith("["):
prefix = stream_name[1:stream_name.find("]")] if "]" in stream_name else ""
stream["is_cached"] = "+" in prefix
else:
stream["is_cached"] = True
return streams
+39
View File
@@ -0,0 +1,39 @@
import os
from typing import Dict, List
import httpx
from fastapi import HTTPException
from utils.logger import logger
from .base import StreamingService
class WatchHubService(StreamingService):
def __init__(self):
self.base_url = "https://watchhub.stkc.win"
@property
def name(self) -> str:
return "WatchHub"
async def _fetch_from_watchhub(self, url: str) -> Dict:
async with httpx.AsyncClient() as client:
try:
response = await client.get(url)
response.raise_for_status()
data = response.json()
logger.debug(f"WatchHub response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"WatchHub request failed: {str(e)}")
return {"streams": []}
async def get_streams(self, meta_id: str) -> List[Dict]:
url = f"{self.base_url}/stream/{meta_id}"
logger.debug(f"WatchHub stream url: {url}")
data = await self._fetch_from_watchhub(url)
streams = data.get("streams", [])
for stream in streams:
stream["service"] = self.name
return streams