From 1c8939805480dad884bc8cd286845e09118813e1 Mon Sep 17 00:00:00 2001 From: None <62809003+Arrowar@users.noreply.github.com> Date: Sun, 18 May 2025 14:16:44 +0200 Subject: [PATCH] Fix telegram and proxy (#322) * Add ENABLE_VIDEO * Fix proxy * Add error proxy * Update config.json * Fix telegram_bot (#312) * Update config.json * Fix telegram_bot * fix bug * Fix StreamingCommunity site * Delete console.log * fix doppio string_to_search * Update __init__.py * Update site.py * Update config.json * Update site.py * Update config.json * Update __init__.py * Update __init__.py * Fix proxy (#319) * Add ENABLE_VIDEO * Fix proxy * Add error proxy * Update config.json * Refactor user input handling and improve messaging in __init__.py --------- Co-authored-by: None <62809003+Arrowar@users.noreply.github.com> Co-authored-by: l1n00 <> * Fix proxy __init__ * Update os.py --------- Co-authored-by: l1n00 --- README.md | 18 +-- StreamingCommunity/Api/Player/vixcloud.py | 8 +- .../Api/Site/1337xx/__init__.py | 4 +- .../Api/Site/altadefinizione/__init__.py | 2 +- .../Api/Site/animeunity/__init__.py | 2 +- .../Api/Site/animeunity/util/ScrapeSerie.py | 44 +++--- .../Api/Site/animeworld/__init__.py | 2 +- .../Api/Site/cb01new/__init__.py | 2 +- .../Api/Site/guardaserie/__init__.py | 2 +- .../Api/Site/raiplay/__init__.py | 2 +- .../Api/Site/streamingcommunity/__init__.py | 127 ++++++++++------ .../Api/Site/streamingcommunity/film.py | 4 +- .../Api/Site/streamingcommunity/series.py | 2 +- .../Api/Site/streamingcommunity/site.py | 2 +- .../Api/Site/streamingwatch/__init__.py | 8 +- StreamingCommunity/Api/Template/site.py | 143 ++++++++++++------ StreamingCommunity/Lib/Proxies/proxy.py | 2 +- StreamingCommunity/TelegramHelp/config.json | 62 ++++++++ .../TelegramHelp/telegram_bot.py | 4 + 19 files changed, 293 insertions(+), 147 deletions(-) create mode 100644 StreamingCommunity/TelegramHelp/config.json diff --git a/README.md b/README.md index 8018fc1..7ff53c4 100644 --- a/README.md +++ b/README.md @@ -748,26 +748,24 @@ The `run-container` command mounts also the `config.json` file, so any change to The bot was created to replace terminal commands and allow interaction via Telegram. Each download runs within a screen session, enabling multiple downloads to run simultaneously. To run the bot in the background, simply start it inside a screen session and then press Ctrl + A, followed by D, to detach from the session without stopping the bot. - - -
-๐Ÿค– Bot Commands Command Functions: ๐Ÿ”น /start โ€“ Starts a new search for a download. This command performs the same operations as manually running the script in the terminal with test_run.py. ๐Ÿ”น /list โ€“ Displays the status of active downloads, with options to: -- Stop an incorrect download using /stop -- View the real-time output of a download using /screen + +Stop an incorrect download using /stop . + +View the real-time output of a download using /screen . โš  Warning: If a download is interrupted, incomplete files may remain in the folder specified in config.json. These files must be deleted manually to avoid storage or management issues. -
-
-๐Ÿ”ง Environment Setup +๐Ÿ›  Configuration: Currently, the bot's settings are stored in the config.json file, which is located in the same directory as the telegram_bot.py script. -Create an `.env` file with: +## .env Example: + +You need to create an .env file and enter your Telegram token and user ID to authorize only one user to use it ``` TOKEN_TELEGRAM=IlTuo2131TOKEN$12D3Telegram diff --git a/StreamingCommunity/Api/Player/vixcloud.py b/StreamingCommunity/Api/Player/vixcloud.py index 0c9d881..ed3c871 100644 --- a/StreamingCommunity/Api/Player/vixcloud.py +++ b/StreamingCommunity/Api/Player/vixcloud.py @@ -1,6 +1,6 @@ # 01.03.24 -import sys +import time import logging from urllib.parse import urlparse, parse_qs, urlencode, urlunparse @@ -24,7 +24,7 @@ console = Console() class VideoSource: - def __init__(self, url: str, is_series: bool, media_id: int = None): + def __init__(self, url: str, is_series: bool, media_id: int = None, proxy: str = None): """ Initialize video source for streaming site. @@ -35,6 +35,7 @@ class VideoSource: """ self.headers = {'user-agent': get_userAgent()} self.url = url + self.proxy = proxy self.is_series = is_series self.media_id = media_id self.iframe_src = None @@ -55,7 +56,7 @@ class VideoSource: } try: - response = httpx.get(f"{self.url}/iframe/{self.media_id}", params=params, timeout=MAX_TIMEOUT) + response = httpx.get(f"{self.url}/iframe/{self.media_id}", headers=self.headers, params=params, timeout=MAX_TIMEOUT, proxy=self.proxy) response.raise_for_status() # Parse response with BeautifulSoup to get iframe source @@ -81,6 +82,7 @@ class VideoSource: self.window_video = WindowVideo(converter.get('video')) self.window_streams = StreamsCollection(converter.get('streams')) self.window_parameter = WindowParameter(converter.get('masterPlaylist')) + time.sleep(0.5) except Exception as e: logging.error(f"Error parsing script: {e}") diff --git a/StreamingCommunity/Api/Site/1337xx/__init__.py b/StreamingCommunity/Api/Site/1337xx/__init__.py index 983a41a..637c639 100644 --- a/StreamingCommunity/Api/Site/1337xx/__init__.py +++ b/StreamingCommunity/Api/Site/1337xx/__init__.py @@ -24,7 +24,7 @@ indice = 3 _useFor = "Torrent" _priority = 0 _engineDownload = "Torrent" -_deprecate = False +_deprecate = True console = Console() msg = Prompt() @@ -62,7 +62,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager, len_database) download_title(select_title) else: diff --git a/StreamingCommunity/Api/Site/altadefinizione/__init__.py b/StreamingCommunity/Api/Site/altadefinizione/__init__.py index 8e7452a..cdbc08d 100644 --- a/StreamingCommunity/Api/Site/altadefinizione/__init__.py +++ b/StreamingCommunity/Api/Site/altadefinizione/__init__.py @@ -110,7 +110,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ bot = get_bot_instance() if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager, len_database) process_search_result(select_title, selections) else: diff --git a/StreamingCommunity/Api/Site/animeunity/__init__.py b/StreamingCommunity/Api/Site/animeunity/__init__.py index 1dfc7fa..990e9bc 100644 --- a/StreamingCommunity/Api/Site/animeunity/__init__.py +++ b/StreamingCommunity/Api/Site/animeunity/__init__.py @@ -109,7 +109,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ bot = get_bot_instance() if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager,len_database) process_search_result(select_title, selections) else: diff --git a/StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py b/StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py index fd76d1d..218c1f2 100644 --- a/StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +++ b/StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py @@ -43,40 +43,38 @@ class ScrapeSerieAnime: def get_count_episodes(self): """ Retrieve total number of episodes for the selected media. + This includes partial episodes (like episode 6.5). Returns: - int: Total episode count + int: Total episode count including partial episodes """ - try: - - response = httpx.get( - url=f"{self.url}/info_api/{self.media_id}/", - headers=self.headers, - timeout=max_timeout - ) - response.raise_for_status() - - # Parse JSON response and return episode count - return response.json()["episodes_count"] - - except Exception as e: - logging.error(f"Error fetching episode count: {e}") - return None + if self.episodes_cache is None: + self._fetch_all_episodes() + + if self.episodes_cache: + return len(self.episodes_cache) + return None def _fetch_all_episodes(self): """ Fetch all episodes data at once and cache it """ try: - all_episodes = [] - count = self.get_count_episodes() - if not count: - return + # Get initial episode count + response = httpx.get( + url=f"{self.url}/info_api/{self.media_id}/", + headers=self.headers, + timeout=max_timeout + ) + response.raise_for_status() + initial_count = response.json()["episodes_count"] - # Fetch episodes + all_episodes = [] start_range = 1 - while start_range <= count: - end_range = min(start_range + 119, count) + + # Fetch episodes in chunks + while start_range <= initial_count: + end_range = min(start_range + 119, initial_count) response = httpx.get( url=f"{self.url}/info_api/{self.media_id}/1", diff --git a/StreamingCommunity/Api/Site/animeworld/__init__.py b/StreamingCommunity/Api/Site/animeworld/__init__.py index da58834..530bf0c 100644 --- a/StreamingCommunity/Api/Site/animeworld/__init__.py +++ b/StreamingCommunity/Api/Site/animeworld/__init__.py @@ -75,7 +75,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager,len_database) process_search_result(select_title, selections) else: diff --git a/StreamingCommunity/Api/Site/cb01new/__init__.py b/StreamingCommunity/Api/Site/cb01new/__init__.py index c48ddc2..5f3f7f8 100644 --- a/StreamingCommunity/Api/Site/cb01new/__init__.py +++ b/StreamingCommunity/Api/Site/cb01new/__init__.py @@ -62,7 +62,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager,len_database) process_search_result(select_title) else: diff --git a/StreamingCommunity/Api/Site/guardaserie/__init__.py b/StreamingCommunity/Api/Site/guardaserie/__init__.py index 6970ec1..8abf18b 100644 --- a/StreamingCommunity/Api/Site/guardaserie/__init__.py +++ b/StreamingCommunity/Api/Site/guardaserie/__init__.py @@ -75,7 +75,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager,len_database) process_search_result(select_title, selections) else: diff --git a/StreamingCommunity/Api/Site/raiplay/__init__.py b/StreamingCommunity/Api/Site/raiplay/__init__.py index ace9a0d..d1b7e23 100644 --- a/StreamingCommunity/Api/Site/raiplay/__init__.py +++ b/StreamingCommunity/Api/Site/raiplay/__init__.py @@ -84,7 +84,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager,len_database) process_search_result(select_title, selections) else: diff --git a/StreamingCommunity/Api/Site/streamingcommunity/__init__.py b/StreamingCommunity/Api/Site/streamingcommunity/__init__.py index ca47530..b6346f8 100644 --- a/StreamingCommunity/Api/Site/streamingcommunity/__init__.py +++ b/StreamingCommunity/Api/Site/streamingcommunity/__init__.py @@ -26,48 +26,72 @@ from .series import download_series # Variable indice = 0 -_useFor = "Film_&_Serie" +_useFor = "Film_&_Serie" # "Movies_&_Series" _priority = 0 _engineDownload = "hls" _deprecate = False msg = Prompt() console = Console() +proxy = None def get_user_input(string_to_search: str = None): """ Asks the user to input a search term. Handles both Telegram bot input and direct input. + If string_to_search is provided, it's returned directly (after stripping). """ - if string_to_search is None: - if site_constant.TELEGRAM_BOT: - bot = get_bot_instance() - string_to_search = bot.ask( - "key_search", - f"Enter the search term\nor type 'back' to return to the menu: ", - None - ) + if string_to_search is not None: + return string_to_search.strip() - if string_to_search == 'back': + if site_constant.TELEGRAM_BOT: + bot = get_bot_instance() + user_response = bot.ask( + "key_search", # Request type + "Enter the search term\nor type 'back' to return to the menu: ", + None + ) + if user_response is None: + bot.send_message("Timeout: No search term entered.", None) + return None + + if user_response.lower() == 'back': + bot.send_message("Returning to the main menu...", None) + + try: # Restart the script subprocess.Popen([sys.executable] + sys.argv) sys.exit() - else: - string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip() - - return string_to_search + + except Exception as e: + bot.send_message(f"Error during restart attempt: {e}", None) + return None # Return None if restart fails + + return user_response.strip() + + else: + return msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip() def process_search_result(select_title, selections=None, proxy=None): """ Handles the search result and initiates the download for either a film or series. Parameters: - select_title (MediaItem): The selected media item + select_title (MediaItem): The selected media item. Can be None if selection fails. selections (dict, optional): Dictionary containing selection inputs that bypass manual input - {'season': season_selection, 'episode': episode_selection} + e.g., {'season': season_selection, 'episode': episode_selection} + proxy (str, optional): The proxy to use for downloads. """ + if not select_title: + if site_constant.TELEGRAM_BOT: + bot = get_bot_instance() + bot.send_message("No title selected or selection cancelled.", None) + else: + console.print("[yellow]No title selected or selection cancelled.") + return + if select_title.type == 'tv': season_selection = None episode_selection = None @@ -77,57 +101,64 @@ def process_search_result(select_title, selections=None, proxy=None): episode_selection = selections.get('episode') download_series(select_title, season_selection, episode_selection, proxy) - + else: - download_film(select_title) + download_film(select_title, proxy) def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None): """ Main function of the application for search. Parameters: - string_to_search (str, optional): String to search for - get_onlyDatabase (bool, optional): If True, return only the database object - direct_item (dict, optional): Direct item to process (bypass search) + string_to_search (str, optional): String to search for. Can be passed from run.py. + If 'back', special handling might occur in get_user_input. + get_onlyDatabase (bool, optional): If True, return only the database search manager object. + direct_item (dict, optional): Direct item to process (bypasses search). selections (dict, optional): Dictionary containing selection inputs that bypass manual input - {'season': season_selection, 'episode': episode_selection} + for series (season/episode). """ + bot = None + if site_constant.TELEGRAM_BOT: + bot = get_bot_instance() + if direct_item: - select_title = MediaItem(**direct_item) - process_search_result(select_title, selections) + select_title_obj = MediaItem(**direct_item) + process_search_result(select_title_obj, selections, proxy) + return + + # Check proxy if not already set + finder = ProxyFinder(site_constant.FULL_URL) + proxy = finder.find_fast_proxy() + + actual_search_query = get_user_input(string_to_search) + + # Handle cases where user input is empty, or 'back' was handled (sys.exit or None return) + if not actual_search_query: + if bot: + if actual_search_query is None: # Specifically for timeout from bot.ask or failed restart + bot.send_message("Search term not provided or operation cancelled. Returning.", None) return - if string_to_search is None: - if site_constant.TELEGRAM_BOT: - bot = get_bot_instance() - string_to_search = bot.ask( - "key_search", - f"Enter the search term\nor type 'back' to return to the menu: ", - None - ) - - if string_to_search == 'back': - - # Restart the script - subprocess.Popen([sys.executable] + sys.argv) - sys.exit() - else: - string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip() - - # Search on database + # Perform search on the database using the obtained query finder = ProxyFinder(site_constant.FULL_URL) proxy = finder.find_fast_proxy() len_database = title_search(string_to_search, proxy) - # If only the database is needed, return the manager + # If only the database object (media_search_manager populated by title_search) is needed if get_onlyDatabase: - return media_search_manager + return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager, len_database) process_search_result(select_title, selections, proxy) else: - # If no results are found, ask again - console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}") - search() \ No newline at end of file + no_results_message = f"No results found for: '{actual_search_query}'" + if bot: + bot.send_message(no_results_message, None) + else: + console.print(f"\n[red]Nothing matching was found for[white]: [purple]{actual_search_query}") + + # Do not call search() recursively here to avoid infinite loops on no results. + # The flow should return to the caller (e.g., main menu in run.py). + return \ No newline at end of file diff --git a/StreamingCommunity/Api/Site/streamingcommunity/film.py b/StreamingCommunity/Api/Site/streamingcommunity/film.py index d70b162..6cbe862 100644 --- a/StreamingCommunity/Api/Site/streamingcommunity/film.py +++ b/StreamingCommunity/Api/Site/streamingcommunity/film.py @@ -27,7 +27,7 @@ from StreamingCommunity.Api.Player.vixcloud import VideoSource console = Console() -def download_film(select_title: MediaItem) -> str: +def download_film(select_title: MediaItem, proxy: str = None) -> str: """ Downloads a film using the provided film ID, title name, and domain. @@ -55,7 +55,7 @@ def download_film(select_title: MediaItem) -> str: console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] โ†’ [cyan]{select_title.name}[/cyan] \n") # Init class - video_source = VideoSource(f"{site_constant.FULL_URL}/it", False, select_title.id) + video_source = VideoSource(f"{site_constant.FULL_URL}/it", False, select_title.id, proxy) # Retrieve scws and if available master playlist video_source.get_iframe(select_title.id) diff --git a/StreamingCommunity/Api/Site/streamingcommunity/series.py b/StreamingCommunity/Api/Site/streamingcommunity/series.py index 1fde4e1..f75517d 100644 --- a/StreamingCommunity/Api/Site/streamingcommunity/series.py +++ b/StreamingCommunity/Api/Site/streamingcommunity/series.py @@ -154,7 +154,7 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis start_message() # Init class - video_source = VideoSource(f"{site_constant.FULL_URL}/it", True, select_season.id) + video_source = VideoSource(f"{site_constant.FULL_URL}/it", True, select_season.id, proxy) scrape_serie = GetSerieInfo(f"{site_constant.FULL_URL}/it", select_season.id, select_season.slug, proxy) # Collect information about season diff --git a/StreamingCommunity/Api/Site/streamingcommunity/site.py b/StreamingCommunity/Api/Site/streamingcommunity/site.py index f42631d..2b58043 100644 --- a/StreamingCommunity/Api/Site/streamingcommunity/site.py +++ b/StreamingCommunity/Api/Site/streamingcommunity/site.py @@ -120,4 +120,4 @@ def title_search(query: str, proxy: str) -> int: bot.send_message(f"Lista dei risultati:", choices) # Return the number of titles found - return media_search_manager.get_length() \ No newline at end of file + return media_search_manager.get_length() diff --git a/StreamingCommunity/Api/Site/streamingwatch/__init__.py b/StreamingCommunity/Api/Site/streamingwatch/__init__.py index fbf7cf4..b8dffd0 100644 --- a/StreamingCommunity/Api/Site/streamingwatch/__init__.py +++ b/StreamingCommunity/Api/Site/streamingwatch/__init__.py @@ -27,6 +27,7 @@ _deprecate = False msg = Prompt() console = Console() +proxy = None def get_user_input(string_to_search: str = None): @@ -74,10 +75,15 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ select_title = MediaItem(**direct_item) process_search_result(select_title, selections) # DONT SUPPORT PROXY FOR NOW return + + # Check proxy if not already set + finder = ProxyFinder(site_constant.FULL_URL) + proxy = finder.find_fast_proxy() if string_to_search is None: string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip() + # Perform search on the database using the obtained query finder = ProxyFinder(url=f"{site_constant.FULL_URL}/serie/euphoria/") proxy = finder.find_fast_proxy() len_database = title_search(string_to_search, proxy) @@ -87,7 +93,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_ return media_search_manager if len_database > 0: - select_title = get_select_title(table_show_manager, media_search_manager) + select_title = get_select_title(table_show_manager, media_search_manager,len_database) process_search_result(select_title, selections, proxy) else: diff --git a/StreamingCommunity/Api/Template/site.py b/StreamingCommunity/Api/Template/site.py index ac2ef86..8f1d135 100644 --- a/StreamingCommunity/Api/Template/site.py +++ b/StreamingCommunity/Api/Template/site.py @@ -7,78 +7,123 @@ import sys from rich.console import Console +# Internal utilities +from StreamingCommunity.Api.Template.config_loader import site_constant +from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance + # Variable console = Console() available_colors = ['red', 'magenta', 'yellow', 'cyan', 'green', 'blue', 'white'] column_to_hide = ['Slug', 'Sub_ita', 'Last_air_date', 'Seasons_count', 'Url', 'Image', 'Path_id'] -def get_select_title(table_show_manager, media_search_manager): +def get_select_title(table_show_manager, media_search_manager, num_results_available): """ Display a selection of titles and prompt the user to choose one. + Handles both console and Telegram bot input. + + Parameters: + table_show_manager: Manager for console table display. + media_search_manager: Manager holding the list of media items. + num_results_available (int): The number of media items available for selection. Returns: - MediaItem: The selected media item. + MediaItem: The selected media item, or None if no selection is made or an error occurs. """ - # Determine column_info dynamically for (search site) if not media_search_manager.media_list: - console.print("\n[red]No media items available.") + + # console.print("\n[red]No media items available.") return None - - # Example of available colors for columns - available_colors = ['red', 'magenta', 'yellow', 'cyan', 'green', 'blue', 'white'] - - # Retrieve the keys of the first media item as column headers - first_media_item = media_search_manager.media_list[0] - column_info = {"Index": {'color': available_colors[0]}} # Always include Index with a fixed color - # Assign colors to the remaining keys dynamically - color_index = 1 - for key in first_media_item.__dict__.keys(): + if site_constant.TELEGRAM_BOT: + bot = get_bot_instance() + prompt_message = f"Inserisci il numero del titolo che vuoi selezionare (da 0 a {num_results_available - 1}):" + + user_input_str = bot.ask( + "select_title_from_list_number", + prompt_message, + None + ) - if key.capitalize() in column_to_hide: - continue + if user_input_str is None: + bot.send_message("Timeout: nessuna selezione ricevuta.", None) + return None - if key in ('id', 'type', 'name', 'score'): # Custom prioritization of colors - if key == 'type': - column_info["Type"] = {'color': 'yellow'} - elif key == 'name': - column_info["Name"] = {'color': 'magenta'} - elif key == 'score': - column_info["Score"] = {'color': 'cyan'} + try: + chosen_index = int(user_input_str) + if 0 <= chosen_index < num_results_available: + selected_item = media_search_manager.get(chosen_index) + if selected_item: + return selected_item + + else: + bot.send_message(f"Errore interno: Impossibile recuperare il titolo con indice {chosen_index}.", None) + return None + else: + bot.send_message(f"Selezione '{chosen_index}' non valida. Inserisci un numero compreso tra 0 e {num_results_available - 1}.", None) + return None + + except ValueError: + bot.send_message(f"Input '{user_input_str}' non valido. Devi inserire un numero.", None) + return None + + except Exception as e: + bot.send_message(f"Si รจ verificato un errore durante la selezione: {e}", None) + return None - else: - column_info[key.capitalize()] = {'color': available_colors[color_index % len(available_colors)]} - color_index += 1 - - table_show_manager.add_column(column_info) - - # Populate the table with title information - for i, media in enumerate(media_search_manager.media_list): - media_dict = {'Index': str(i)} + else: + + # Logica originale per la console + if not media_search_manager.media_list: + console.print("\n[red]No media items available.") + return None + + first_media_item = media_search_manager.media_list[0] + column_info = {"Index": {'color': available_colors[0]}} + color_index = 1 for key in first_media_item.__dict__.keys(): if key.capitalize() in column_to_hide: continue + if key in ('id', 'type', 'name', 'score'): + if key == 'type': column_info["Type"] = {'color': 'yellow'} + elif key == 'name': column_info["Name"] = {'color': 'magenta'} + elif key == 'score': column_info["Score"] = {'color': 'cyan'} + else: + column_info[key.capitalize()] = {'color': available_colors[color_index % len(available_colors)]} + color_index += 1 - # Ensure all values are strings for rich add table - media_dict[key.capitalize()] = str(getattr(media, key)) + table_show_manager.clear() + table_show_manager.add_column(column_info) - table_show_manager.add_tv_show(media_dict) + for i, media in enumerate(media_search_manager.media_list): + media_dict = {'Index': str(i)} + for key in first_media_item.__dict__.keys(): + if key.capitalize() in column_to_hide: + continue + media_dict[key.capitalize()] = str(getattr(media, key)) + table_show_manager.add_tv_show(media_dict) - # Run the table and handle user input - last_command = table_show_manager.run(force_int_input=True, max_int_input=len(media_search_manager.media_list)) - table_show_manager.clear() + last_command_str = table_show_manager.run(force_int_input=True, max_int_input=len(media_search_manager.media_list)) + table_show_manager.clear() - # Handle user's quit command - if last_command == "q" or last_command == "quit": - console.print("\n[red]Quit ...") - sys.exit(0) + if last_command_str is None or last_command_str.lower() in ["q", "quit"]: + console.print("\n[red]Selezione annullata o uscita.") + return None - # Check if the selected index is within range - if 0 <= int(last_command) < len(media_search_manager.media_list): - return media_search_manager.get(int(last_command)) - - else: - console.print("\n[red]Wrong index") - sys.exit(0) \ No newline at end of file + try: + + selected_index = int(last_command_str) + + if 0 <= selected_index < len(media_search_manager.media_list): + return media_search_manager.get(selected_index) + + else: + console.print("\n[red]Indice errato o non valido.") + # sys.exit(0) + return None + + except ValueError: + console.print("\n[red]Input non numerico ricevuto dalla tabella.") + # sys.exit(0) + return None diff --git a/StreamingCommunity/Lib/Proxies/proxy.py b/StreamingCommunity/Lib/Proxies/proxy.py index 3d03e5b..b42590e 100644 --- a/StreamingCommunity/Lib/Proxies/proxy.py +++ b/StreamingCommunity/Lib/Proxies/proxy.py @@ -32,7 +32,7 @@ class ProxyFinder: proxy, source = proxy_info try: start = time.time() - print(f"[yellow]Testing proxy...") + print(f"[yellow]Testing proxy for URL: {self.url}...") with httpx.Client(proxy=proxy, timeout=self.timeout_threshold) as client: response = client.get(self.url, headers=get_headers()) diff --git a/StreamingCommunity/TelegramHelp/config.json b/StreamingCommunity/TelegramHelp/config.json new file mode 100644 index 0000000..7ef4c0f --- /dev/null +++ b/StreamingCommunity/TelegramHelp/config.json @@ -0,0 +1,62 @@ +{ + "DEFAULT": { + "debug": false, + "show_message": true, + "clean_console": true, + "show_trending": true, + "use_api": true, + "not_close": false, + "telegram_bot": true, + "download_site_data": true, + "validate_github_config": true + }, + "OUT_FOLDER": { + "root_path": "/mnt/data/media/", + "movie_folder_name": "films", + "serie_folder_name": "serie_tv", + "anime_folder_name": "Anime", + "map_episode_name": "E%(episode)_%(episode_name)", + "add_siteName": false + }, + "QBIT_CONFIG": { + "host": "192.168.1.51", + "port": "6666", + "user": "admin", + "pass": "adminadmin" + }, + "M3U8_DOWNLOAD": { + "tqdm_delay": 0.01, + "default_video_workser": 12, + "default_audio_workser": 12, + "segment_timeout": 8, + "download_audio": true, + "merge_audio": true, + "specific_list_audio": [ + "ita" + ], + "download_subtitle": true, + "merge_subs": true, + "specific_list_subtitles": [ + "ita", + "eng" + ], + "cleanup_tmp_folder": true + }, + "M3U8_CONVERSION": { + "use_codec": false, + "use_vcodec": true, + "use_acodec": true, + "use_bitrate": true, + "use_gpu": false, + "default_preset": "ultrafast" + }, + "M3U8_PARSER": { + "force_resolution": "Best", + "get_only_link": false + }, + "REQUESTS": { + "verify": false, + "timeout": 20, + "max_retry": 8 + } +} diff --git a/StreamingCommunity/TelegramHelp/telegram_bot.py b/StreamingCommunity/TelegramHelp/telegram_bot.py index d24b68d..85eb4c9 100644 --- a/StreamingCommunity/TelegramHelp/telegram_bot.py +++ b/StreamingCommunity/TelegramHelp/telegram_bot.py @@ -575,6 +575,10 @@ class TelegramBot: cleaned_output = cleaned_output.replace( "\n\n", "\n" ) # Rimuovi newline multipli + + # Inizializza le variabili + cleaned_output_0 = None # o "" + cleaned_output_1 = None # o "" # Dentro cleaned_output c'รจ una stringa recupero quello che si trova tra ## ## download_section = re.search(r"##(.*?)##", cleaned_output, re.DOTALL)