StreamingCommunity 3.0.5__py3-none-any.whl → 3.0.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of StreamingCommunity might be problematic. Click here for more details.

Files changed (33) hide show
  1. StreamingCommunity/Api/Player/maxstream.py +141 -0
  2. StreamingCommunity/Api/Player/vixcloud.py +5 -3
  3. StreamingCommunity/Api/Site/1337xx/__init__.py +4 -4
  4. StreamingCommunity/Api/Site/altadefinizione/__init__.py +3 -3
  5. StreamingCommunity/Api/Site/altadefinizione/film.py +15 -35
  6. StreamingCommunity/Api/Site/animeunity/__init__.py +2 -2
  7. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +21 -23
  8. StreamingCommunity/Api/Site/animeworld/__init__.py +3 -3
  9. StreamingCommunity/Api/Site/cb01new/__init__.py +72 -0
  10. StreamingCommunity/Api/Site/cb01new/film.py +62 -0
  11. StreamingCommunity/Api/Site/cb01new/site.py +78 -0
  12. StreamingCommunity/Api/Site/guardaserie/__init__.py +3 -3
  13. StreamingCommunity/Api/Site/raiplay/__init__.py +3 -3
  14. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +87 -39
  15. StreamingCommunity/Api/Site/streamingcommunity/film.py +2 -2
  16. StreamingCommunity/Api/Site/streamingcommunity/series.py +4 -4
  17. StreamingCommunity/Api/Site/streamingcommunity/site.py +9 -6
  18. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +6 -3
  19. StreamingCommunity/Api/Site/streamingwatch/__init__.py +12 -6
  20. StreamingCommunity/Api/Site/streamingwatch/site.py +12 -5
  21. StreamingCommunity/Api/Template/site.py +103 -58
  22. StreamingCommunity/Lib/Proxies/proxy.py +14 -174
  23. StreamingCommunity/TelegramHelp/config.json +62 -0
  24. StreamingCommunity/TelegramHelp/telegram_bot.py +4 -0
  25. StreamingCommunity/Upload/version.py +1 -1
  26. StreamingCommunity/Util/config_json.py +7 -2
  27. StreamingCommunity/run.py +25 -40
  28. {streamingcommunity-3.0.5.dist-info → streamingcommunity-3.0.7.dist-info}/METADATA +31 -13
  29. {streamingcommunity-3.0.5.dist-info → streamingcommunity-3.0.7.dist-info}/RECORD +33 -28
  30. {streamingcommunity-3.0.5.dist-info → streamingcommunity-3.0.7.dist-info}/WHEEL +1 -1
  31. {streamingcommunity-3.0.5.dist-info → streamingcommunity-3.0.7.dist-info}/entry_points.txt +0 -0
  32. {streamingcommunity-3.0.5.dist-info → streamingcommunity-3.0.7.dist-info}/licenses/LICENSE +0 -0
  33. {streamingcommunity-3.0.5.dist-info → streamingcommunity-3.0.7.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,7 @@ from rich.prompt import Prompt
12
12
 
13
13
  # Internal utilities
14
14
  from StreamingCommunity.Api.Template import get_select_title
15
+ from StreamingCommunity.Lib.Proxies.proxy import ProxyFinder
15
16
  from StreamingCommunity.Api.Template.config_loader import site_constant
16
17
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
17
18
  from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
@@ -25,48 +26,72 @@ from .series import download_series
25
26
 
26
27
  # Variable
27
28
  indice = 0
28
- _useFor = "film_serie"
29
+ _useFor = "Film_&_Serie" # "Movies_&_Series"
29
30
  _priority = 0
30
31
  _engineDownload = "hls"
31
32
  _deprecate = False
32
33
 
33
34
  msg = Prompt()
34
35
  console = Console()
36
+ proxy = None
35
37
 
36
38
 
37
39
  def get_user_input(string_to_search: str = None):
38
40
  """
39
41
  Asks the user to input a search term.
40
42
  Handles both Telegram bot input and direct input.
43
+ If string_to_search is provided, it's returned directly (after stripping).
41
44
  """
42
- if string_to_search is None:
43
- if site_constant.TELEGRAM_BOT:
44
- bot = get_bot_instance()
45
- string_to_search = bot.ask(
46
- "key_search",
47
- f"Enter the search term\nor type 'back' to return to the menu: ",
48
- None
49
- )
50
-
51
- if string_to_search == 'back':
52
-
45
+ if string_to_search is not None:
46
+ return string_to_search.strip()
47
+
48
+ if site_constant.TELEGRAM_BOT:
49
+ bot = get_bot_instance()
50
+ user_response = bot.ask(
51
+ "key_search", # Request type
52
+ "Enter the search term\nor type 'back' to return to the menu: ",
53
+ None
54
+ )
55
+
56
+ if user_response is None:
57
+ bot.send_message("Timeout: No search term entered.", None)
58
+ return None
59
+
60
+ if user_response.lower() == 'back':
61
+ bot.send_message("Returning to the main menu...", None)
62
+
63
+ try:
53
64
  # Restart the script
54
65
  subprocess.Popen([sys.executable] + sys.argv)
55
66
  sys.exit()
56
- else:
57
- string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
58
-
59
- return string_to_search
67
+
68
+ except Exception as e:
69
+ bot.send_message(f"Error during restart attempt: {e}", None)
70
+ return None # Return None if restart fails
71
+
72
+ return user_response.strip()
73
+
74
+ else:
75
+ return msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
60
76
 
61
- def process_search_result(select_title, selections=None):
77
+ def process_search_result(select_title, selections=None, proxy=None):
62
78
  """
63
79
  Handles the search result and initiates the download for either a film or series.
64
80
 
65
81
  Parameters:
66
- select_title (MediaItem): The selected media item
82
+ select_title (MediaItem): The selected media item. Can be None if selection fails.
67
83
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
68
- {'season': season_selection, 'episode': episode_selection}
84
+ e.g., {'season': season_selection, 'episode': episode_selection}
85
+ proxy (str, optional): The proxy to use for downloads.
69
86
  """
87
+ if not select_title:
88
+ if site_constant.TELEGRAM_BOT:
89
+ bot = get_bot_instance()
90
+ bot.send_message("No title selected or selection cancelled.", None)
91
+ else:
92
+ console.print("[yellow]No title selected or selection cancelled.")
93
+ return
94
+
70
95
  if select_title.type == 'tv':
71
96
  season_selection = None
72
97
  episode_selection = None
@@ -75,42 +100,65 @@ def process_search_result(select_title, selections=None):
75
100
  season_selection = selections.get('season')
76
101
  episode_selection = selections.get('episode')
77
102
 
78
- download_series(select_title, season_selection, episode_selection)
79
-
103
+ download_series(select_title, season_selection, episode_selection, proxy)
104
+
80
105
  else:
81
- download_film(select_title)
106
+ download_film(select_title, proxy)
82
107
 
83
108
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
84
109
  """
85
110
  Main function of the application for search.
86
111
 
87
112
  Parameters:
88
- string_to_search (str, optional): String to search for
89
- get_onlyDatabase (bool, optional): If True, return only the database object
90
- direct_item (dict, optional): Direct item to process (bypass search)
113
+ string_to_search (str, optional): String to search for. Can be passed from run.py.
114
+ If 'back', special handling might occur in get_user_input.
115
+ get_onlyDatabase (bool, optional): If True, return only the database search manager object.
116
+ direct_item (dict, optional): Direct item to process (bypasses search).
91
117
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
92
- {'season': season_selection, 'episode': episode_selection}
118
+ for series (season/episode).
93
119
  """
120
+ bot = None
121
+ if site_constant.TELEGRAM_BOT:
122
+ bot = get_bot_instance()
123
+
94
124
  if direct_item:
95
- select_title = MediaItem(**direct_item)
96
- process_search_result(select_title, selections)
125
+ select_title_obj = MediaItem(**direct_item)
126
+ process_search_result(select_title_obj, selections, proxy)
97
127
  return
128
+
129
+ # Check proxy if not already set
130
+ finder = ProxyFinder(site_constant.FULL_URL)
131
+ proxy = finder.find_fast_proxy()
132
+
133
+ actual_search_query = get_user_input(string_to_search)
98
134
 
99
- if string_to_search is None:
100
- string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
135
+ # Handle cases where user input is empty, or 'back' was handled (sys.exit or None return)
136
+ if not actual_search_query:
137
+ if bot:
138
+ if actual_search_query is None: # Specifically for timeout from bot.ask or failed restart
139
+ bot.send_message("Search term not provided or operation cancelled. Returning.", None)
140
+ return
101
141
 
102
- # Search on database
103
- len_database = title_search(string_to_search)
142
+ # Perform search on the database using the obtained query
143
+ finder = ProxyFinder(site_constant.FULL_URL)
144
+ proxy = finder.find_fast_proxy()
145
+ len_database = title_search(string_to_search, proxy)
104
146
 
105
- # If only the database is needed, return the manager
147
+ # If only the database object (media_search_manager populated by title_search) is needed
106
148
  if get_onlyDatabase:
107
- return media_search_manager
149
+ return media_search_manager
108
150
 
109
151
  if len_database > 0:
110
- select_title = get_select_title(table_show_manager, media_search_manager)
111
- process_search_result(select_title, selections)
152
+ select_title = get_select_title(table_show_manager, media_search_manager, len_database)
153
+ process_search_result(select_title, selections, proxy)
112
154
 
113
155
  else:
114
- # If no results are found, ask again
115
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
116
- search()
156
+ no_results_message = f"No results found for: '{actual_search_query}'"
157
+ if bot:
158
+ bot.send_message(no_results_message, None)
159
+ else:
160
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{actual_search_query}")
161
+
162
+ # Do not call search() recursively here to avoid infinite loops on no results.
163
+ # The flow should return to the caller (e.g., main menu in run.py).
164
+ return
@@ -27,7 +27,7 @@ from StreamingCommunity.Api.Player.vixcloud import VideoSource
27
27
  console = Console()
28
28
 
29
29
 
30
- def download_film(select_title: MediaItem) -> str:
30
+ def download_film(select_title: MediaItem, proxy: str = None) -> str:
31
31
  """
32
32
  Downloads a film using the provided film ID, title name, and domain.
33
33
 
@@ -55,7 +55,7 @@ def download_film(select_title: MediaItem) -> str:
55
55
  console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
56
56
 
57
57
  # Init class
58
- video_source = VideoSource(site_constant.FULL_URL, False, select_title.id)
58
+ video_source = VideoSource(f"{site_constant.FULL_URL}/it", False, select_title.id, proxy)
59
59
 
60
60
  # Retrieve scws and if available master playlist
61
61
  video_source.get_iframe(select_title.id)
@@ -142,7 +142,7 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, vid
142
142
  break
143
143
 
144
144
 
145
- def download_series(select_season: MediaItem, season_selection: str = None, episode_selection: str = None) -> None:
145
+ def download_series(select_season: MediaItem, season_selection: str = None, episode_selection: str = None, proxy = None) -> None:
146
146
  """
147
147
  Handle downloading a complete series.
148
148
 
@@ -154,8 +154,8 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis
154
154
  start_message()
155
155
 
156
156
  # Init class
157
- video_source = VideoSource(site_constant.FULL_URL, True, select_season.id)
158
- scrape_serie = GetSerieInfo(site_constant.FULL_URL, select_season.id, select_season.slug)
157
+ video_source = VideoSource(f"{site_constant.FULL_URL}/it", True, select_season.id, proxy)
158
+ scrape_serie = GetSerieInfo(f"{site_constant.FULL_URL}/it", select_season.id, select_season.slug, proxy)
159
159
 
160
160
  # Collect information about season
161
161
  scrape_serie.getNumberSeason()
@@ -219,4 +219,4 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis
219
219
  # Get script_id
220
220
  script_id = TelegramSession.get_session()
221
221
  if script_id != "unknown":
222
- TelegramSession.deleteScriptId(script_id)
222
+ TelegramSession.deleteScriptId(script_id)
@@ -28,7 +28,7 @@ table_show_manager = TVShowManager()
28
28
  max_timeout = config_manager.get_int("REQUESTS", "timeout")
29
29
 
30
30
 
31
- def title_search(query: str) -> int:
31
+ def title_search(query: str, proxy: str) -> int:
32
32
  """
33
33
  Search for titles based on a search query.
34
34
 
@@ -46,9 +46,10 @@ def title_search(query: str) -> int:
46
46
 
47
47
  try:
48
48
  response = httpx.get(
49
- site_constant.FULL_URL,
49
+ f"{site_constant.FULL_URL}/it",
50
50
  headers={'user-agent': get_userAgent()},
51
- timeout=max_timeout
51
+ timeout=max_timeout,
52
+ proxy=proxy
52
53
  )
53
54
  response.raise_for_status()
54
55
 
@@ -56,10 +57,11 @@ def title_search(query: str) -> int:
56
57
  version = json.loads(soup.find('div', {'id': "app"}).get("data-page"))['version']
57
58
 
58
59
  except Exception as e:
60
+ if "WinError" in str(e) or "Errno" in str(e): console.print("\n[bold yellow]Please make sure you have enabled and configured a valid proxy.[/bold yellow]")
59
61
  console.print(f"[red]Site: {site_constant.SITE_NAME} version, request error: {e}")
60
62
  return 0
61
63
 
62
- search_url = f"{site_constant.FULL_URL}/search?q={query}"
64
+ search_url = f"{site_constant.FULL_URL}/it/search?q={query}"
63
65
  console.print(f"[cyan]Search url: [yellow]{search_url}")
64
66
 
65
67
  try:
@@ -71,7 +73,8 @@ def title_search(query: str) -> int:
71
73
  'x-inertia': 'true',
72
74
  'x-inertia-version': version
73
75
  },
74
- timeout=max_timeout
76
+ timeout=max_timeout,
77
+ proxy=proxy
75
78
  )
76
79
  response.raise_for_status()
77
80
 
@@ -117,4 +120,4 @@ def title_search(query: str) -> int:
117
120
  bot.send_message(f"Lista dei risultati:", choices)
118
121
 
119
122
  # Return the number of titles found
120
- return media_search_manager.get_length()
123
+ return media_search_manager.get_length()
@@ -20,7 +20,7 @@ max_timeout = config_manager.get_int("REQUESTS", "timeout")
20
20
 
21
21
 
22
22
  class GetSerieInfo:
23
- def __init__(self, url, media_id: int = None, series_name: str = None):
23
+ def __init__(self, url, media_id: int = None, series_name: str = None, proxy = None):
24
24
  """
25
25
  Initialize the GetSerieInfo class for scraping TV series information.
26
26
 
@@ -32,6 +32,7 @@ class GetSerieInfo:
32
32
  self.is_series = False
33
33
  self.headers = {'user-agent': get_userAgent()}
34
34
  self.url = url
35
+ self.proxy = proxy
35
36
  self.media_id = media_id
36
37
  self.seasons_manager = SeasonManager()
37
38
 
@@ -50,7 +51,8 @@ class GetSerieInfo:
50
51
  response = httpx.get(
51
52
  url=f"{self.url}/titles/{self.media_id}-{self.series_name}",
52
53
  headers=self.headers,
53
- timeout=max_timeout
54
+ timeout=max_timeout,
55
+ proxy=self.proxy
54
56
  )
55
57
  response.raise_for_status()
56
58
 
@@ -104,7 +106,8 @@ class GetSerieInfo:
104
106
  'x-inertia': 'true',
105
107
  'x-inertia-version': self.version,
106
108
  },
107
- timeout=max_timeout
109
+ timeout=max_timeout,
110
+ proxy=self.proxy
108
111
  )
109
112
 
110
113
  # Extract episodes from JSON response
@@ -19,14 +19,15 @@ from .series import download_series
19
19
 
20
20
 
21
21
  # Variable
22
- indice = 8
23
- _useFor = "film_serie"
24
- _priority = 10 # !!! MOLTO LENTO
22
+ indice = 7
23
+ _useFor = "Film_&_Serie"
24
+ _priority = 0
25
25
  _engineDownload = "hls"
26
26
  _deprecate = False
27
27
 
28
28
  msg = Prompt()
29
29
  console = Console()
30
+ proxy = None
30
31
 
31
32
 
32
33
  def get_user_input(string_to_search: str = None):
@@ -74,20 +75,25 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
74
75
  select_title = MediaItem(**direct_item)
75
76
  process_search_result(select_title, selections) # DONT SUPPORT PROXY FOR NOW
76
77
  return
78
+
79
+ # Check proxy if not already set
80
+ finder = ProxyFinder(site_constant.FULL_URL)
81
+ proxy = finder.find_fast_proxy()
77
82
 
78
83
  if string_to_search is None:
79
84
  string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
80
85
 
86
+ # Perform search on the database using the obtained query
81
87
  finder = ProxyFinder(url=f"{site_constant.FULL_URL}/serie/euphoria/")
82
- proxy, response_serie, _ = finder.find_fast_proxy()
83
- len_database = title_search(string_to_search, [proxy, response_serie])
88
+ proxy = finder.find_fast_proxy()
89
+ len_database = title_search(string_to_search, proxy)
84
90
 
85
91
  # If only the database is needed, return the manager
86
92
  if get_onlyDatabase:
87
93
  return media_search_manager
88
94
 
89
95
  if len_database > 0:
90
- select_title = get_select_title(table_show_manager, media_search_manager)
96
+ select_title = get_select_title(table_show_manager, media_search_manager,len_database)
91
97
  process_search_result(select_title, selections, proxy)
92
98
 
93
99
  else:
@@ -27,9 +27,16 @@ table_show_manager = TVShowManager()
27
27
  max_timeout = config_manager.get_int("REQUESTS", "timeout")
28
28
 
29
29
 
30
- def extract_nonce(response_) -> str:
30
+ def extract_nonce(proxy) -> str:
31
31
  """Extract nonce value from the page script"""
32
- soup = BeautifulSoup(response_.content, 'html.parser')
32
+ response = httpx.get(
33
+ site_constant.FULL_URL,
34
+ headers={'user-agent': get_userAgent()},
35
+ timeout=max_timeout,
36
+ proxy=proxy
37
+ )
38
+
39
+ soup = BeautifulSoup(response.content, 'html.parser')
33
40
  script = soup.find('script', id='live-search-js-extra')
34
41
  if script:
35
42
  match = re.search(r'"admin_ajax_nonce":"([^"]+)"', script.text)
@@ -38,7 +45,7 @@ def extract_nonce(response_) -> str:
38
45
  return ""
39
46
 
40
47
 
41
- def title_search(query: str, additionalData: list) -> int:
48
+ def title_search(query: str, proxy: str) -> int:
42
49
  """
43
50
  Search for titles based on a search query.
44
51
 
@@ -51,12 +58,11 @@ def title_search(query: str, additionalData: list) -> int:
51
58
  media_search_manager.clear()
52
59
  table_show_manager.clear()
53
60
 
54
- proxy, response_serie = additionalData
55
61
  search_url = f"{site_constant.FULL_URL}/wp-admin/admin-ajax.php"
56
62
  console.print(f"[cyan]Search url: [yellow]{search_url}")
57
63
 
58
64
  try:
59
- _wpnonce = extract_nonce(response_serie)
65
+ _wpnonce = extract_nonce(proxy)
60
66
 
61
67
  if not _wpnonce:
62
68
  console.print("[red]Error: Failed to extract nonce")
@@ -82,6 +88,7 @@ def title_search(query: str, additionalData: list) -> int:
82
88
  soup = BeautifulSoup(response.text, 'html.parser')
83
89
 
84
90
  except Exception as e:
91
+ if "WinError" in str(e) or "Errno" in str(e): console.print("\n[bold yellow]Please make sure you have enabled and configured a valid proxy.[/bold yellow]")
85
92
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
86
93
  return 0
87
94
 
@@ -7,78 +7,123 @@ import sys
7
7
  from rich.console import Console
8
8
 
9
9
 
10
+ # Internal utilities
11
+ from StreamingCommunity.Api.Template.config_loader import site_constant
12
+ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
13
+
10
14
  # Variable
11
15
  console = Console()
12
16
  available_colors = ['red', 'magenta', 'yellow', 'cyan', 'green', 'blue', 'white']
13
17
  column_to_hide = ['Slug', 'Sub_ita', 'Last_air_date', 'Seasons_count', 'Url', 'Image', 'Path_id']
14
18
 
15
19
 
16
- def get_select_title(table_show_manager, media_search_manager):
20
+ def get_select_title(table_show_manager, media_search_manager, num_results_available):
17
21
  """
18
22
  Display a selection of titles and prompt the user to choose one.
23
+ Handles both console and Telegram bot input.
24
+
25
+ Parameters:
26
+ table_show_manager: Manager for console table display.
27
+ media_search_manager: Manager holding the list of media items.
28
+ num_results_available (int): The number of media items available for selection.
19
29
 
20
30
  Returns:
21
- MediaItem: The selected media item.
31
+ MediaItem: The selected media item, or None if no selection is made or an error occurs.
22
32
  """
23
- # Determine column_info dynamically for (search site)
24
33
  if not media_search_manager.media_list:
25
- console.print("\n[red]No media items available.")
34
+
35
+ # console.print("\n[red]No media items available.")
26
36
  return None
27
-
28
- # Example of available colors for columns
29
- available_colors = ['red', 'magenta', 'yellow', 'cyan', 'green', 'blue', 'white']
30
-
31
- # Retrieve the keys of the first media item as column headers
32
- first_media_item = media_search_manager.media_list[0]
33
- column_info = {"Index": {'color': available_colors[0]}} # Always include Index with a fixed color
34
-
35
- # Assign colors to the remaining keys dynamically
36
- color_index = 1
37
- for key in first_media_item.__dict__.keys():
38
-
39
- if key.capitalize() in column_to_hide:
40
- continue
41
-
42
- if key in ('id', 'type', 'name', 'score'): # Custom prioritization of colors
43
- if key == 'type':
44
- column_info["Type"] = {'color': 'yellow'}
45
- elif key == 'name':
46
- column_info["Name"] = {'color': 'magenta'}
47
- elif key == 'score':
48
- column_info["Score"] = {'color': 'cyan'}
49
-
50
- else:
51
- column_info[key.capitalize()] = {'color': available_colors[color_index % len(available_colors)]}
52
- color_index += 1
53
-
54
- table_show_manager.add_column(column_info)
55
-
56
- # Populate the table with title information
57
- for i, media in enumerate(media_search_manager.media_list):
58
- media_dict = {'Index': str(i)}
59
37
 
38
+ if site_constant.TELEGRAM_BOT:
39
+ bot = get_bot_instance()
40
+ prompt_message = f"Inserisci il numero del titolo che vuoi selezionare (da 0 a {num_results_available - 1}):"
41
+
42
+ user_input_str = bot.ask(
43
+ "select_title_from_list_number",
44
+ prompt_message,
45
+ None
46
+ )
47
+
48
+ if user_input_str is None:
49
+ bot.send_message("Timeout: nessuna selezione ricevuta.", None)
50
+ return None
51
+
52
+ try:
53
+ chosen_index = int(user_input_str)
54
+ if 0 <= chosen_index < num_results_available:
55
+ selected_item = media_search_manager.get(chosen_index)
56
+ if selected_item:
57
+ return selected_item
58
+
59
+ else:
60
+ bot.send_message(f"Errore interno: Impossibile recuperare il titolo con indice {chosen_index}.", None)
61
+ return None
62
+ else:
63
+ bot.send_message(f"Selezione '{chosen_index}' non valida. Inserisci un numero compreso tra 0 e {num_results_available - 1}.", None)
64
+ return None
65
+
66
+ except ValueError:
67
+ bot.send_message(f"Input '{user_input_str}' non valido. Devi inserire un numero.", None)
68
+ return None
69
+
70
+ except Exception as e:
71
+ bot.send_message(f"Si è verificato un errore durante la selezione: {e}", None)
72
+ return None
73
+
74
+ else:
75
+
76
+ # Logica originale per la console
77
+ if not media_search_manager.media_list:
78
+ console.print("\n[red]No media items available.")
79
+ return None
80
+
81
+ first_media_item = media_search_manager.media_list[0]
82
+ column_info = {"Index": {'color': available_colors[0]}}
83
+
84
+ color_index = 1
60
85
  for key in first_media_item.__dict__.keys():
61
86
  if key.capitalize() in column_to_hide:
62
87
  continue
63
-
64
- # Ensure all values are strings for rich add table
65
- media_dict[key.capitalize()] = str(getattr(media, key))
66
-
67
- table_show_manager.add_tv_show(media_dict)
68
-
69
- # Run the table and handle user input
70
- last_command = table_show_manager.run(force_int_input=True, max_int_input=len(media_search_manager.media_list))
71
- table_show_manager.clear()
72
-
73
- # Handle user's quit command
74
- if last_command == "q" or last_command == "quit":
75
- console.print("\n[red]Quit ...")
76
- sys.exit(0)
77
-
78
- # Check if the selected index is within range
79
- if 0 <= int(last_command) < len(media_search_manager.media_list):
80
- return media_search_manager.get(int(last_command))
81
-
82
- else:
83
- console.print("\n[red]Wrong index")
84
- sys.exit(0)
88
+ if key in ('id', 'type', 'name', 'score'):
89
+ if key == 'type': column_info["Type"] = {'color': 'yellow'}
90
+ elif key == 'name': column_info["Name"] = {'color': 'magenta'}
91
+ elif key == 'score': column_info["Score"] = {'color': 'cyan'}
92
+ else:
93
+ column_info[key.capitalize()] = {'color': available_colors[color_index % len(available_colors)]}
94
+ color_index += 1
95
+
96
+ table_show_manager.clear()
97
+ table_show_manager.add_column(column_info)
98
+
99
+ for i, media in enumerate(media_search_manager.media_list):
100
+ media_dict = {'Index': str(i)}
101
+ for key in first_media_item.__dict__.keys():
102
+ if key.capitalize() in column_to_hide:
103
+ continue
104
+ media_dict[key.capitalize()] = str(getattr(media, key))
105
+ table_show_manager.add_tv_show(media_dict)
106
+
107
+ last_command_str = table_show_manager.run(force_int_input=True, max_int_input=len(media_search_manager.media_list))
108
+ table_show_manager.clear()
109
+
110
+ if last_command_str is None or last_command_str.lower() in ["q", "quit"]:
111
+ console.print("\n[red]Selezione annullata o uscita.")
112
+ return None
113
+
114
+ try:
115
+
116
+ selected_index = int(last_command_str)
117
+
118
+ if 0 <= selected_index < len(media_search_manager.media_list):
119
+ return media_search_manager.get(selected_index)
120
+
121
+ else:
122
+ console.print("\n[red]Indice errato o non valido.")
123
+ # sys.exit(0)
124
+ return None
125
+
126
+ except ValueError:
127
+ console.print("\n[red]Input non numerico ricevuto dalla tabella.")
128
+ # sys.exit(0)
129
+ return None