Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88743c101d |
8 changed files with 100 additions and 31 deletions
10
stream_fusion/utils/cache/cache.py
vendored
10
stream_fusion/utils/cache/cache.py
vendored
|
|
@ -19,7 +19,15 @@ def search_public(media):
|
|||
cache_search["language"] = cache_search["languages"][0]
|
||||
# Wtf, why do we need to use __dict__ here? And also, why is it stuck when we use media directly?
|
||||
response = requests.get(url, json=cache_search)
|
||||
return response.json()
|
||||
try:
|
||||
response.raise_for_status() # Lève une exception pour les codes d'état HTTP d'erreur (4xx ou 5xx)
|
||||
return response.json()
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Search: Erreur lors de la récupération des résultats du cache public: {e}")
|
||||
return None
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"Search: Erreur de décodage JSON pour le cache public: {e}. Contenu de la réponse: {response.text[:200]}")
|
||||
return None
|
||||
|
||||
|
||||
def cache_public(torrents: List[TorrentItem], media):
|
||||
|
|
|
|||
|
|
@ -105,18 +105,26 @@ class Torbox(BaseDebrid):
|
|||
|
||||
if existing_torrent:
|
||||
logger.info(f"Torbox: Found existing torrent with ID: {existing_torrent['id']}")
|
||||
torrent_info = existing_torrent
|
||||
if not torrent_info or "id" not in torrent_info:
|
||||
logger.error("Torbox: Failed to add or find torrent.")
|
||||
torrent_id = existing_torrent["id"]
|
||||
# Get full torrent info with files
|
||||
torrent_response = self.get_torrent_info(torrent_id)
|
||||
if not torrent_response or "data" not in torrent_response:
|
||||
logger.error("Torbox: Failed to get torrent info.")
|
||||
return None
|
||||
torrent_id = torrent_info["id"]
|
||||
torrent_info = torrent_response["data"]
|
||||
else:
|
||||
# Add the magnet or torrent file
|
||||
torrent_info = self.add_magnet_or_torrent(magnet, torrent_download)
|
||||
if not torrent_info or "torrent_id" not in torrent_info:
|
||||
add_response = self.add_magnet_or_torrent(magnet, torrent_download)
|
||||
if not add_response or "torrent_id" not in add_response:
|
||||
logger.error("Torbox: Failed to add or find torrent.")
|
||||
return None
|
||||
torrent_id = torrent_info["torrent_id"]
|
||||
torrent_id = add_response["torrent_id"]
|
||||
# Get full torrent info with files
|
||||
torrent_response = self.get_torrent_info(torrent_id)
|
||||
if not torrent_response or "data" not in torrent_response:
|
||||
logger.error("Torbox: Failed to get torrent info.")
|
||||
return None
|
||||
torrent_info = torrent_response["data"]
|
||||
|
||||
logger.info(f"Torbox: Working with torrent ID: {torrent_id}")
|
||||
|
||||
|
|
@ -237,14 +245,27 @@ class Torbox(BaseDebrid):
|
|||
logger.error(f"Torbox: Invalid season/episode format: {season}/{episode}")
|
||||
return None
|
||||
|
||||
matching_files = [
|
||||
file for file in files
|
||||
if season_episode_in_filename(file["short_name"], numeric_season, numeric_episode) and is_video_file(file["short_name"])
|
||||
]
|
||||
logger.info(f"Torbox: DEBUG - Traitement de {len(files)} fichiers au total")
|
||||
for i, file in enumerate(files):
|
||||
logger.info(f"Torbox: DEBUG - Fichier {i+1}: {file['short_name']} (taille: {file['size']}, is_video: {is_video_file(file['short_name'])})")
|
||||
|
||||
matching_files = []
|
||||
for file in files:
|
||||
if is_video_file(file["short_name"]):
|
||||
logger.info(f"Torbox: Vérification fichier vidéo: {file['short_name']}")
|
||||
if season_episode_in_filename(file["short_name"], numeric_season, numeric_episode):
|
||||
logger.info(f"Torbox: ✓ Match RTN pour {file['short_name']}")
|
||||
matching_files.append(file)
|
||||
else:
|
||||
logger.info(f"Torbox: ✗ Pas de match RTN pour {file['short_name']}")
|
||||
else:
|
||||
logger.info(f"Torbox: Fichier ignoré (pas vidéo): {file['short_name']}")
|
||||
|
||||
logger.info(f"Torbox: {len(matching_files)} fichiers trouvés avec RTN pour S{numeric_season:02d}E{numeric_episode:02d}")
|
||||
|
||||
if matching_files:
|
||||
largest_matching_file = max(matching_files, key=lambda x: x["size"])
|
||||
logger.info(f"Torbox: Selected largest matching file (ID: {largest_matching_file['id']}, Name: {largest_matching_file['name']}, Size: {largest_matching_file['size']}) for series")
|
||||
logger.info(f"Torbox: Selected largest matching file (ID: {largest_matching_file['id']}, Name: {largest_matching_file['short_name']}, Size: {largest_matching_file['size']}) for series")
|
||||
return largest_matching_file["id"]
|
||||
else:
|
||||
logger.warning(f"Torbox: No matching files found for S{numeric_season:02d}E{numeric_episode:02d}, trying smart fallback")
|
||||
|
|
@ -259,10 +280,27 @@ class Torbox(BaseDebrid):
|
|||
for file in files if is_video_file(file["short_name"])
|
||||
]
|
||||
|
||||
logger.info(f"Torbox: Appel du smart fallback avec {len(fallback_files)} fichiers")
|
||||
for f in fallback_files:
|
||||
logger.info(f"Torbox: Fichier fallback: {f.get('name')} (taille: {f.get('size')}, ID: {f.get('index')})")
|
||||
|
||||
fallback_file = smart_episode_fallback(fallback_files, numeric_season, numeric_episode)
|
||||
if fallback_file:
|
||||
logger.info(f"Torbox: Smart fallback selected file: {fallback_file.get('name')} (ID: {fallback_file.get('index')})")
|
||||
logger.info(f"Torbox: Smart fallback a sélectionné: {fallback_file.get('name')} (ID: {fallback_file.get('index')})")
|
||||
return fallback_file.get('index')
|
||||
else:
|
||||
logger.error(f"Torbox: Smart fallback also failed for S{numeric_season:02d}E{numeric_episode:02d}")
|
||||
return None
|
||||
logger.info("Torbox: Smart fallback n'a rien trouvé, essai du fallback final pour fichier unique")
|
||||
# Final fallback: for single-file torrents, just take the only video file
|
||||
video_files = [f for f in files if is_video_file(f["short_name"])]
|
||||
logger.info(f"Torbox: DEBUG - Trouvé {len(video_files)} fichiers vidéo dans le fallback final")
|
||||
for vf in video_files:
|
||||
logger.info(f"Torbox: DEBUG - Fichier vidéo: {vf['short_name']} (ID: {vf['id']})")
|
||||
|
||||
if len(video_files) == 1:
|
||||
single_file = video_files[0]
|
||||
logger.info(f"Torbox: Fichier vidéo unique détecté, utilisation: {single_file['short_name']} (ID: {single_file['id']})")
|
||||
return single_file["id"]
|
||||
else:
|
||||
logger.error(f"Torbox: Le fallback intelligent a aussi échoué pour S{numeric_season:02d}E{numeric_episode:02d}")
|
||||
logger.error(f"Torbox: Trouvé {len(video_files)} fichiers vidéo, attendu exactement 1 pour le fallback fichier unique")
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -30,12 +30,16 @@ class TMDB(MetadataProvider):
|
|||
languages=self.config['languages']
|
||||
)
|
||||
else:
|
||||
tmdb_id = data["tv_results"][0]["id"]
|
||||
season_num = int(full_id[1])
|
||||
episode_num = int(full_id[2])
|
||||
|
||||
result = Series(
|
||||
id=id,
|
||||
tmdb_id = data["tv_results"][0]["id"],
|
||||
tmdb_id=tmdb_id,
|
||||
titles=[self.replace_weird_characters(data["tv_results"][0]["name"])],
|
||||
season="S{:02d}".format(int(full_id[1])),
|
||||
episode="E{:02d}".format(int(full_id[2])),
|
||||
season="S{:02d}".format(season_num),
|
||||
episode="E{:02d}".format(episode_num),
|
||||
languages=self.config['languages']
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -7,3 +7,15 @@ class Series(Media):
|
|||
self.season = season
|
||||
self.episode = episode
|
||||
self.seasonfile = None
|
||||
|
||||
def get_season_number(self) -> int:
|
||||
"""Extract season number from season string (e.g., 'S02' -> 2)"""
|
||||
if self.season and self.season.startswith('S'):
|
||||
return int(self.season[1:])
|
||||
return 0
|
||||
|
||||
def get_episode_number(self) -> int:
|
||||
"""Extract episode number from episode string (e.g., 'E05' -> 5)"""
|
||||
if self.episode and self.episode.startswith('E'):
|
||||
return int(self.episode[1:])
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ class TorrentService:
|
|||
|
||||
if season[0] in parsed_file.seasons and episode[0] in parsed_file.episodes:
|
||||
episode_files.append({
|
||||
"file_index": file_index,
|
||||
"file_index": None, # Let debrid service handle file selection
|
||||
"title": file,
|
||||
"size": files["length"]
|
||||
})
|
||||
|
|
@ -266,7 +266,9 @@ class TorrentService:
|
|||
# Doesn't that need to be indented?
|
||||
file_index += 1
|
||||
|
||||
return max(episode_files, key=lambda file: file["size"])
|
||||
if episode_files:
|
||||
return max(episode_files, key=lambda file: file["size"])
|
||||
return None
|
||||
|
||||
def __find_full_index(self, file_structure):
|
||||
self.logger.debug("Starting to build full index of video files")
|
||||
|
|
|
|||
|
|
@ -544,7 +544,9 @@ class TorrentSmartContainer:
|
|||
return
|
||||
file = max(files, key=lambda file: file["size"])
|
||||
torrent_item.availability = debrid
|
||||
torrent_item.file_index = file["file_index"]
|
||||
# Only update file_index if it wasn't set to None for intelligent selection
|
||||
if torrent_item.file_index is not None:
|
||||
torrent_item.file_index = file["file_index"]
|
||||
torrent_item.file_name = file["title"]
|
||||
torrent_item.size = file["size"]
|
||||
self.logger.debug(
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ class YggflixAPI:
|
|||
def __init__(
|
||||
self,
|
||||
pool_connections=10,
|
||||
pool_maxsize=10,
|
||||
max_retries=3,
|
||||
timeout=10,
|
||||
pool_maxsize=50,
|
||||
max_retries=0,
|
||||
timeout=8,
|
||||
):
|
||||
"""
|
||||
Initialize the YggflixAPI class.
|
||||
|
|
|
|||
|
|
@ -474,13 +474,16 @@ async def get_results(
|
|||
|
||||
if len(filtered_results) < min_results:
|
||||
logger.info(
|
||||
f"Search: Insufficient filtered results ({len(filtered_results)}). Performing new search."
|
||||
f"Search: Insufficient filtered results ({len(filtered_results)}). Searching for new torrents to add."
|
||||
)
|
||||
await redis_cache.delete(cache_key)
|
||||
unfiltered_results = await get_search_results(media, config)
|
||||
unfiltered_results_dict = [item.to_dict() for item in unfiltered_results]
|
||||
await redis_cache.set(cache_key, unfiltered_results_dict, expiration=settings.redis_expiration)
|
||||
filtered_results = filter_items(unfiltered_results, media, config=config)
|
||||
# Ne pas supprimer le cache, chercher de nouveaux torrents
|
||||
new_results = await get_search_results(media, config)
|
||||
# Fusionner anciens + nouveaux (merge_items déduplique automatiquement)
|
||||
all_results = merge_items(unfiltered_results, new_results)
|
||||
# Mettre à jour le cache avec tous les résultats
|
||||
await redis_cache.set(cache_key, [item.to_dict() for item in all_results], expiration=settings.redis_expiration)
|
||||
# Refiltrer avec tous les résultats
|
||||
filtered_results = filter_items(all_results, media, config=config)
|
||||
|
||||
logger.success(
|
||||
f"Search: Final number of filtered results: {len(filtered_results)}"
|
||||
|
|
|
|||
Loading…
Reference in a new issue