Delete stream_fusion/utils/debrid/premiusize.py.save
This commit is contained in:
parent
fd0c29fb01
commit
ec6883be22
1 changed files with 0 additions and 400 deletions
|
|
@ -1,400 +0,0 @@
|
|||
import json
|
||||
|
||||
from stream_fusion.settings import settings
|
||||
from stream_fusion.utils.debrid.base_debrid import BaseDebrid
|
||||
from stream_fusion.utils.general import get_info_hash_from_magnet, season_episode_in_filename
|
||||
from stream_fusion.logging_config import logger
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
|
||||
class Premiumize(BaseDebrid):
|
||||
def __init__(self, config, session=None):
|
||||
super().__init__(config, session=session)
|
||||
self.base_url = "https://www.premiumize.me/api"
|
||||
self.api_key = config.get('PMToken') or settings.pm_token
|
||||
if not self.api_key:
|
||||
logger.error("No Premiumize API key found in config or settings")
|
||||
raise ValueError("Premiumize API key is required")
|
||||
|
||||
# Note: La vérification du token est maintenant asynchrone et ne peut pas être appelée dans __init__
|
||||
# Elle sera appelée à la première utilisation de l'API
|
||||
|
||||
async def _check_token(self):
|
||||
"""Vérifier la validité du token en appelant l'API account/info"""
|
||||
url = f"{self.base_url}/account/info"
|
||||
response = await self.json_response(
|
||||
url,
|
||||
method='post',
|
||||
data={'apikey': self.api_key}
|
||||
)
|
||||
|
||||
if not response or response.get("status") != "success":
|
||||
logger.error(f"Invalid Premiumize API key: {self.api_key}")
|
||||
raise ValueError("Invalid Premiumize API key")
|
||||
|
||||
logger.info("Premiumize API key is valid")
|
||||
|
||||
async def add_magnet(self, magnet, ip=None):
|
||||
url = f"{self.base_url}/transfer/create?apikey={self.api_key}"
|
||||
|
||||
# Vérifier si c'est un pack de saison
|
||||
info_hash = get_info_hash_from_magnet(magnet)
|
||||
is_season_pack = self._check_if_season_pack(magnet)
|
||||
|
||||
# Créer le dictionnaire de formulaire
|
||||
form = {'src': magnet}
|
||||
|
||||
# Ajouter folder_name seulement si c'est un pack de saison
|
||||
if is_season_pack:
|
||||
form['folder_name'] = f"season_pack_{info_hash}"
|
||||
|
||||
# Ajouter des logs pour le débogage
|
||||
logger.debug(f"Premiumize: Sending add_magnet request with data: {form}")
|
||||
|
||||
response = await self.json_response(url, method='post', data=form)
|
||||
|
||||
if is_season_pack and response and response.get("status") == "success":
|
||||
# Si c'est un pack de saison, on attend que tous les fichiers soient disponibles
|
||||
transfer_id = response.get("id")
|
||||
if transfer_id:
|
||||
# Attendre que le transfert soit terminé
|
||||
if await self._wait_for_season_pack(transfer_id):
|
||||
# Une fois terminé, récupérer les détails du dossier
|
||||
folder_details = await self.get_folder_or_file_details(transfer_id)
|
||||
if folder_details and folder_details.get("content"):
|
||||
# Trier les fichiers par taille pour prendre le plus gros fichier vidéo
|
||||
video_files = [f for f in folder_details["content"]
|
||||
if f.get("mime_type", "").startswith("video/")]
|
||||
if video_files:
|
||||
largest_file = max(video_files, key=lambda x: x.get("size", 0))
|
||||
response["selected_file"] = {
|
||||
"id": largest_file.get("id"),
|
||||
"name": largest_file.get("name"),
|
||||
"size": largest_file.get("size"),
|
||||
"link": largest_file.get("link"),
|
||||
"stream_link": largest_file.get("stream_link")
|
||||
}
|
||||
|
||||
return response
|
||||
|
||||
def _check_if_season_pack(self, magnet):
|
||||
"""Vérifie si le magnet link correspond à un pack de saison"""
|
||||
# Vérifie les patterns communs dans le nom du torrent
|
||||
name = magnet.lower()
|
||||
season_indicators = [
|
||||
"complete.season",
|
||||
"season.complete",
|
||||
"s01.complete",
|
||||
"saison.complete",
|
||||
"season.pack",
|
||||
"pack.saison",
|
||||
".s01.",
|
||||
".s02.",
|
||||
".s03.",
|
||||
".s04.",
|
||||
".s05.",
|
||||
"saison"
|
||||
]
|
||||
return any(indicator in name for indicator in season_indicators)
|
||||
|
||||
async def _wait_for_season_pack(self, transfer_id, timeout=300):
|
||||
"""Attend que tous les fichiers d'un pack de saison soient disponibles"""
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < timeout:
|
||||
transfer_info = await self.get_folder_or_file_details(transfer_id)
|
||||
if transfer_info and transfer_info.get("status") == "success":
|
||||
# Vérifier si des fichiers vidéo sont présents
|
||||
if transfer_info.get("content"):
|
||||
video_files = [f for f in transfer_info["content"]
|
||||
if f.get("mime_type", "").startswith("video/")]
|
||||
if video_files:
|
||||
return True
|
||||
await asyncio.sleep(5) # Utiliser asyncio.sleep au lieu de time.sleep
|
||||
return False
|
||||
|
||||
async def add_torrent(self, torrent_file):
|
||||
url = f"{self.base_url}/transfer/create?apikey={self.api_key}"
|
||||
form = {'file': torrent_file}
|
||||
return await self.json_response(url, method='post', data=form)
|
||||
|
||||
async def list_transfers(self):
|
||||
url = f"{self.base_url}/transfer/list?apikey={self.api_key}"
|
||||
return await self.json_response(url)
|
||||
|
||||
async def get_folder_or_file_details(self, item_id, is_folder=True):
|
||||
if is_folder:
|
||||
logger.info(f"Getting folder details with id: {item_id}")
|
||||
url = f"{self.base_url}/folder/list?id={item_id}&apikey={self.api_key}"
|
||||
else:
|
||||
logger.info(f"Getting file details with id: {item_id}")
|
||||
url = f"{self.base_url}/item/details?id={item_id}&apikey={self.api_key}"
|
||||
|
||||
return await self.json_response(url)
|
||||
|
||||
async def get_availability(self, hash):
|
||||
"""Get availability for a single hash"""
|
||||
url = f"{self.base_url}/cache/check?apikey={self.api_key}&items[]={hash}"
|
||||
response = await self.json_response(url)
|
||||
|
||||
if not response or response.get("status") != "success":
|
||||
logger.error("Invalid response from Premiumize API")
|
||||
return {"transcoded": [False]}
|
||||
|
||||
return {
|
||||
"transcoded": response.get("transcoded", [False])
|
||||
}
|
||||
|
||||
async def get_availability_bulk(self, hashes_or_magnets, ip=None):
|
||||
"""Get availability for multiple hashes or magnets"""
|
||||
if not hashes_or_magnets:
|
||||
return {}
|
||||
|
||||
logger.info(f"Checking availability for {len(hashes_or_magnets)} items")
|
||||
logger.debug(f"Using Premiumize API key: {self.api_key}")
|
||||
|
||||
# Construire l'URL avec les paramètres
|
||||
params = []
|
||||
for hash in hashes_or_magnets:
|
||||
params.append(f"items[]={hash}")
|
||||
|
||||
url = f"{self.base_url}/cache/check"
|
||||
response = await self.json_response(
|
||||
url,
|
||||
method='post',
|
||||
data={
|
||||
'apikey': self.api_key,
|
||||
'items[]': hashes_or_magnets
|
||||
}
|
||||
)
|
||||
|
||||
logger.info(f"Raw Premiumize response: {response}")
|
||||
|
||||
if not response or response.get("status") != "success":
|
||||
logger.error("Invalid response from Premiumize API")
|
||||
return {}
|
||||
|
||||
# Format response to match expected structure
|
||||
result = {}
|
||||
for i, hash_or_magnet in enumerate(hashes_or_magnets):
|
||||
# Vérifier si le fichier est disponible en utilisant le champ response
|
||||
is_available = bool(response.get("response", [])[i]) if isinstance(response.get("response", []), list) and i < len(response["response"]) else False
|
||||
|
||||
# Récupérer le nom du fichier s'il est disponible
|
||||
filename = None
|
||||
if isinstance(response.get("filename", []), list) and i < len(response["filename"]):
|
||||
filename = response["filename"][i]
|
||||
|
||||
# Récupérer la taille du fichier et la convertir en entier
|
||||
filesize = 0
|
||||
if isinstance(response.get("filesize", []), list) and i < len(response["filesize"]):
|
||||
try:
|
||||
filesize = int(response["filesize"][i]) if response["filesize"][i] is not None else 0
|
||||
except (ValueError, TypeError):
|
||||
filesize = 0
|
||||
|
||||
result[hash_or_magnet] = {
|
||||
"transcoded": is_available,
|
||||
"filename": filename,
|
||||
"filesize": filesize
|
||||
}
|
||||
|
||||
logger.info(f"Formatted response: {result}")
|
||||
logger.info(f"Got availability for {len(result)} items")
|
||||
return result
|
||||
|
||||
async def start_background_caching(self, magnet, query=None):
|
||||
"""Start caching a magnet link in the background."""
|
||||
# Afficher le début du magnet dans les logs
|
||||
if isinstance(magnet, str):
|
||||
magnet_preview = magnet[:50] + "..." if len(magnet) > 50 else magnet
|
||||
logger.info(f"Starting background caching for magnet: {magnet_preview}")
|
||||
else:
|
||||
logger.info(f"Starting background caching for magnet object: {type(magnet)}")
|
||||
|
||||
try:
|
||||
# Extraire le magnet si c'est un dictionnaire
|
||||
if isinstance(magnet, dict) and magnet.get("magnet"):
|
||||
magnet = magnet.get("magnet")
|
||||
|
||||
# Vérifier si c'est un pack de saison
|
||||
info_hash = get_info_hash_from_magnet(magnet)
|
||||
is_season_pack = self._check_if_season_pack(magnet)
|
||||
|
||||
# Créer le dictionnaire de formulaire
|
||||
form = {'src': magnet}
|
||||
|
||||
# Ajouter folder_name seulement si c'est un pack de saison
|
||||
if is_season_pack:
|
||||
form['folder_name'] = f"season_pack_{info_hash}"
|
||||
|
||||
# Ajouter l'apikey
|
||||
url = f"{self.base_url}/transfer/create"
|
||||
|
||||
# Ajouter des logs pour le débogage
|
||||
logger.debug(f"Premiumize: Sending background caching request with data: {form}")
|
||||
|
||||
response = await self.json_response(url, method='post', data={**form, 'apikey': self.api_key})
|
||||
|
||||
if not response:
|
||||
logger.error("Premiumize: Aucune réponse reçue de l'API pour start_background_caching")
|
||||
return False
|
||||
elif response.get("status") != "success":
|
||||
logger.error(f"Premiumize: Échec du démarrage du caching en arrière-plan. Réponse: {response}")
|
||||
return False
|
||||
|
||||
transfer_id = response.get("id")
|
||||
if not transfer_id:
|
||||
logger.error("Premiumize: Aucun ID de transfert retourné")
|
||||
return False
|
||||
|
||||
logger.info(f"Premiumize: Démarrage réussi du caching en arrière-plan avec l'ID de transfert: {transfer_id}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Premiumize: Erreur lors du démarrage du caching en arrière-plan: {str(e)}")
|
||||
return False
|
||||
|
||||
async def get_stream_link(self, query, config, ip=None):
|
||||
"""Get a stream link for a magnet link"""
|
||||
if not query:
|
||||
logger.warning("Premiumize: Aucun query fourni pour get_stream_link")
|
||||
return None
|
||||
|
||||
# Afficher le début du magnet dans les logs
|
||||
if isinstance(query, str):
|
||||
query_preview = query[:50] + "..." if len(query) > 50 else query
|
||||
logger.info(f"Premiumize: Récupération du lien de streaming pour le magnet: {query_preview}")
|
||||
elif isinstance(query, dict) and query.get("magnet"):
|
||||
magnet_preview = query["magnet"][:50] + "..." if len(query["magnet"]) > 50 else query["magnet"]
|
||||
logger.info(f"Premiumize: Récupération du lien de streaming pour le magnet: {magnet_preview}")
|
||||
else:
|
||||
logger.info(f"Premiumize: Récupération du lien de streaming pour l'objet query: {type(query)}")
|
||||
|
||||
# Vérifier si c'est une série et extraire la saison/épisode
|
||||
season = None
|
||||
episode = None
|
||||
if isinstance(query, dict):
|
||||
magnet = query.get("magnet")
|
||||
if not magnet:
|
||||
logger.error("No magnet link in query")
|
||||
return None
|
||||
|
||||
# Vérifier si c'est une série
|
||||
if query.get("type") == "series" and query.get("season") and query.get("episode"):
|
||||
season = query["season"].replace("S", "") if isinstance(query["season"], str) else query["season"]
|
||||
episode = query["episode"].replace("E", "") if isinstance(query["episode"], str) else query["episode"]
|
||||
try:
|
||||
season = int(season)
|
||||
episode = int(episode)
|
||||
except (ValueError, TypeError):
|
||||
logger.error(f"Invalid season/episode format: {season}/{episode}")
|
||||
return None
|
||||
else:
|
||||
magnet = query
|
||||
|
||||
# Essayer d'abord le téléchargement direct
|
||||
try:
|
||||
response = await self.json_response(
|
||||
f"{self.base_url}/transfer/directdl",
|
||||
method="post",
|
||||
data={"apikey": self.api_key, "src": magnet}
|
||||
)
|
||||
|
||||
if response and response.get("status") == "success":
|
||||
logger.info("Got direct download response")
|
||||
if "content" in response and response["content"]:
|
||||
# Si c'est une série, chercher l'épisode correspondant
|
||||
if season is not None and episode is not None:
|
||||
matching_files = []
|
||||
for file in response["content"]:
|
||||
filename = file.get("path", "").split("/")[-1]
|
||||
if season_episode_in_filename(filename, season, episode):
|
||||
matching_files.append(file)
|
||||
|
||||
if matching_files:
|
||||
# Prendre le plus gros fichier parmi ceux qui correspondent
|
||||
selected_file = max(matching_files, key=lambda x: x.get("size", 0))
|
||||
stream_link = selected_file.get("stream_link") or selected_file.get("link")
|
||||
if stream_link:
|
||||
logger.info(f"Found matching episode stream link: {stream_link[:50]}...")
|
||||
return stream_link
|
||||
|
||||
# Si ce n'est pas une série ou si aucun fichier ne correspond,
|
||||
# prendre le plus gros fichier vidéo
|
||||
video_files = [f for f in response["content"]
|
||||
if isinstance(f.get("path", ""), str) and
|
||||
f.get("path", "").lower().endswith((".mkv", ".mp4", ".avi", ".m4v"))]
|
||||
|
||||
if video_files:
|
||||
largest_file = max(video_files, key=lambda x: x.get("size", 0))
|
||||
stream_link = largest_file.get("stream_link") or largest_file.get("link")
|
||||
if stream_link:
|
||||
logger.info(f"Found stream link: {stream_link[:50]}...")
|
||||
return stream_link
|
||||
elif response.get("location"):
|
||||
logger.info(f"Found direct location: {response['location'][:50]}...")
|
||||
return response["location"]
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in direct download: {str(e)}")
|
||||
# Continue avec la méthode standard si le téléchargement direct échoue
|
||||
|
||||
# Si le téléchargement direct a échoué, essayer la méthode standard
|
||||
logger.info(f"Premiumize: Tentative d'ajout du magnet: {magnet[:50]}...")
|
||||
response = await self.add_magnet(magnet, ip)
|
||||
|
||||
if not response:
|
||||
logger.error("Premiumize: Aucune réponse reçue de l'API pour add_magnet")
|
||||
return None
|
||||
elif response.get("status") != "success":
|
||||
logger.error(f"Premiumize: Échec de l'ajout du magnet. Réponse: {response}")
|
||||
return None
|
||||
|
||||
logger.info(f"Premiumize: Magnet ajouté avec succès. ID: {response.get('id')}")
|
||||
|
||||
|
||||
# Récupérer l'ID du transfert
|
||||
transfer_id = response.get("id")
|
||||
if not transfer_id:
|
||||
logger.error("No transfer ID in response")
|
||||
return None
|
||||
|
||||
# Attendre que le transfert soit terminé
|
||||
if not await self._wait_for_season_pack(transfer_id):
|
||||
logger.error("Transfer timed out")
|
||||
return None
|
||||
|
||||
# Récupérer les détails du dossier
|
||||
folder_details = await self.get_folder_or_file_details(transfer_id)
|
||||
if not folder_details or not folder_details.get("content"):
|
||||
logger.error("No content in folder details")
|
||||
return None
|
||||
|
||||
# Filtrer les fichiers vidéo
|
||||
video_files = [f for f in folder_details["content"]
|
||||
if isinstance(f.get("mime_type", ""), str) and
|
||||
f.get("mime_type", "").startswith("video/")]
|
||||
|
||||
# Si c'est une série, chercher l'épisode correspondant
|
||||
if season is not None and episode is not None:
|
||||
matching_files = []
|
||||
for file in video_files:
|
||||
filename = file.get("name", "")
|
||||
if season_episode_in_filename(filename, season, episode):
|
||||
matching_files.append(file)
|
||||
|
||||
if matching_files:
|
||||
# Prendre le plus gros fichier parmi ceux qui correspondent
|
||||
selected_file = max(matching_files, key=lambda x: x.get("size", 0))
|
||||
logger.info(f"Selected matching episode file: {selected_file.get('name')}")
|
||||
return selected_file.get("stream_link")
|
||||
|
||||
# Si ce n'est pas une série ou si aucun fichier ne correspond,
|
||||
# prendre le plus gros fichier vidéo
|
||||
if video_files:
|
||||
selected_file = max(video_files, key=lambda x: x.get("size", 0))
|
||||
logger.info(f"Selected largest video file: {selected_file.get('name')}")
|
||||
return selected_file.get("stream_link")
|
||||
|
||||
logger.error("No suitable video file found")
|
||||
return None
|
||||
Loading…
Reference in a new issue