Compare commits

...

1 commit
master ... host

Author SHA1 Message Date
Telkaoss
88743c101d update 2025-10-14 13:36:53 +02:00
8 changed files with 100 additions and 31 deletions

View file

@ -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):

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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")

View file

@ -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(

View file

@ -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.

View file

@ -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)}"