StreamingCommunity 2.9.4__py3-none-any.whl → 2.9.5__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 (32) hide show
  1. StreamingCommunity/Api/Site/1337xx/__init__.py +26 -12
  2. StreamingCommunity/Api/Site/1337xx/site.py +2 -1
  3. StreamingCommunity/Api/Site/altadefinizione/__init__.py +64 -17
  4. StreamingCommunity/Api/Site/altadefinizione/film.py +31 -1
  5. StreamingCommunity/Api/Site/altadefinizione/series.py +53 -8
  6. StreamingCommunity/Api/Site/altadefinizione/site.py +22 -4
  7. StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +2 -2
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +53 -32
  9. StreamingCommunity/Api/Site/animeunity/film_serie.py +5 -1
  10. StreamingCommunity/Api/Site/animeunity/site.py +0 -2
  11. StreamingCommunity/Api/Site/cb01new/__init__.py +26 -14
  12. StreamingCommunity/Api/Site/cb01new/site.py +7 -5
  13. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +26 -15
  14. StreamingCommunity/Api/Site/guardaserie/__init__.py +23 -11
  15. StreamingCommunity/Api/Site/guardaserie/site.py +2 -1
  16. StreamingCommunity/Api/Site/mostraguarda/__init__.py +27 -7
  17. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +50 -27
  18. StreamingCommunity/Api/Site/streamingcommunity/series.py +5 -1
  19. StreamingCommunity/Api/Site/streamingcommunity/site.py +4 -0
  20. StreamingCommunity/Lib/Downloader/HLS/segments.py +1 -1
  21. StreamingCommunity/Lib/Downloader/MP4/downloader.py +7 -6
  22. StreamingCommunity/Upload/version.py +1 -1
  23. StreamingCommunity/Util/config_json.py +2 -8
  24. StreamingCommunity/Util/table.py +12 -2
  25. StreamingCommunity/global_search.py +315 -0
  26. StreamingCommunity/run.py +27 -3
  27. {streamingcommunity-2.9.4.dist-info → streamingcommunity-2.9.5.dist-info}/METADATA +39 -10
  28. {streamingcommunity-2.9.4.dist-info → streamingcommunity-2.9.5.dist-info}/RECORD +32 -31
  29. {streamingcommunity-2.9.4.dist-info → streamingcommunity-2.9.5.dist-info}/LICENSE +0 -0
  30. {streamingcommunity-2.9.4.dist-info → streamingcommunity-2.9.5.dist-info}/WHEEL +0 -0
  31. {streamingcommunity-2.9.4.dist-info → streamingcommunity-2.9.5.dist-info}/entry_points.txt +0 -0
  32. {streamingcommunity-2.9.4.dist-info → streamingcommunity-2.9.5.dist-info}/top_level.txt +0 -0
@@ -40,7 +40,7 @@ def title_search(word_to_search: str) -> int:
40
40
  media_search_manager.clear()
41
41
  table_show_manager.clear()
42
42
 
43
- search_url = f"{site_constant.FULL_URL}/?story={word_to_search}&do=search&subaction=search"
43
+ search_url = f"{site_constant.FULL_URL}/?s={word_to_search}"
44
44
  console.print(f"[cyan]Search url: [yellow]{search_url}")
45
45
 
46
46
  try:
@@ -54,14 +54,16 @@ def title_search(word_to_search: str) -> int:
54
54
  # Create soup and find table
55
55
  soup = BeautifulSoup(response.text, "html.parser")
56
56
 
57
- for div in soup.find_all("div", class_ = "short-main"):
57
+ for card in soup.find_all("div", class_=["card", "mp-post", "horizontal"]):
58
58
  try:
59
- url = div.find("a").get("href")
60
- title = div.find("a").get_text(strip=True)
59
+ title_tag = card.find("h3", class_="card-title").find("a")
60
+ url = title_tag.get("href")
61
+ title = title_tag.get_text(strip=True)
61
62
 
62
63
  title_info = {
63
64
  'name': title,
64
- 'url': url
65
+ 'url': url,
66
+ 'type': 'film'
65
67
  }
66
68
 
67
69
  media_search_manager.add_media(title_info)
@@ -12,6 +12,7 @@ from rich.prompt import Prompt
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Api.Template import get_select_title
14
14
  from StreamingCommunity.Api.Template.config_loader import site_constant
15
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
15
16
 
16
17
 
17
18
  # Logic class
@@ -30,10 +31,28 @@ msg = Prompt()
30
31
  console = Console()
31
32
 
32
33
 
33
- def search(string_to_search: str = None, get_onylDatabase: bool = False):
34
+ def process_search_result(select_title):
34
35
  """
35
- Main function of the application for film and series.
36
+ Handles the search result and initiates the download for either a film or series.
36
37
  """
38
+ if "Serie TV" in str(select_title.type):
39
+ download_thread(select_title)
40
+ else:
41
+ logging.error(f"Not supported: {select_title.type}")
42
+
43
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
44
+ """
45
+ Main function of the application for search film, series and anime.
46
+
47
+ Parameters:
48
+ string_to_search (str, optional): String to search for
49
+ get_onylDatabase (bool, optional): If True, return only the database object
50
+ direct_item (dict, optional): Direct item to process (bypass search)
51
+ """
52
+ if direct_item:
53
+ select_title = MediaItem(**direct_item)
54
+ process_search_result(select_title)
55
+ return
37
56
 
38
57
  if string_to_search is None:
39
58
  string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
@@ -41,24 +60,16 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
41
60
  # Search on database
42
61
  len_database = title_search(quote_plus(string_to_search))
43
62
 
44
- # Return list of elements
45
- if get_onylDatabase:
63
+ # If only the database is needed, return the manager
64
+ if get_onlyDatabase:
46
65
  return media_search_manager
47
66
 
48
67
  if len_database > 0:
49
-
50
- # Select title from list
51
68
  select_title = get_select_title(table_show_manager, media_search_manager)
52
-
53
- # Download only film
54
- if "Serie TV" in str(select_title.type):
55
- download_thread(select_title)
56
-
57
- else:
58
- logging.error(f"Not supported: {select_title.type}")
69
+ process_search_result(select_title)
59
70
 
60
71
  else:
72
+
73
+ # If no results are found, ask again
61
74
  console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
62
-
63
- # Retry
64
75
  search()
@@ -11,6 +11,7 @@ from rich.prompt import Prompt
11
11
  # Internal utilities
12
12
  from StreamingCommunity.Api.Template import get_select_title
13
13
  from StreamingCommunity.Api.Template.config_loader import site_constant
14
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
14
15
 
15
16
 
16
17
  # Logic class
@@ -29,10 +30,25 @@ msg = Prompt()
29
30
  console = Console()
30
31
 
31
32
 
32
- def search(string_to_search: str = None, get_onylDatabase: bool = False):
33
+ def process_search_result(select_title):
33
34
  """
34
- Main function of the application for film and series.
35
+ Handles the search result and initiates the download for either a film or series.
35
36
  """
37
+ download_series(select_title)
38
+
39
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
40
+ """
41
+ Main function of the application for search film, series and anime.
42
+
43
+ Parameters:
44
+ string_to_search (str, optional): String to search for
45
+ get_onylDatabase (bool, optional): If True, return only the database object
46
+ direct_item (dict, optional): Direct item to process (bypass search)
47
+ """
48
+ if direct_item:
49
+ select_title = MediaItem(**direct_item)
50
+ process_search_result(select_title)
51
+ return
36
52
 
37
53
  if string_to_search is None:
38
54
  string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
@@ -40,20 +56,16 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
40
56
  # Search on database
41
57
  len_database = title_search(quote_plus(string_to_search))
42
58
 
43
- # Return list of elements
44
- if get_onylDatabase:
59
+ # If only the database is needed, return the manager
60
+ if get_onlyDatabase:
45
61
  return media_search_manager
46
62
 
47
63
  if len_database > 0:
48
-
49
- # Select title from list
50
64
  select_title = get_select_title(table_show_manager, media_search_manager)
51
-
52
- # Download only film
53
- download_series(select_title)
65
+ process_search_result(select_title)
54
66
 
55
67
  else:
56
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
57
68
 
58
- # Retry
69
+ # If no results are found, ask again
70
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
59
71
  search()
@@ -63,7 +63,8 @@ def title_search(word_to_search: str) -> int:
63
63
 
64
64
  serie_info = {
65
65
  'name': title,
66
- 'url': link
66
+ 'url': link,
67
+ 'type': 'tv'
67
68
  }
68
69
 
69
70
  media_search_manager.add_media(serie_info)
@@ -5,12 +5,16 @@ from urllib.parse import quote_plus
5
5
 
6
6
  # External library
7
7
  from rich.console import Console
8
- from rich.prompt import Prompt, Confirm
8
+ from rich.prompt import Prompt
9
9
 
10
10
 
11
- # Logic class
11
+ # Internal utilities
12
12
  from StreamingCommunity.Api.Template.config_loader import site_constant
13
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
13
14
  from StreamingCommunity.Lib.TMBD import tmdb, Json_film
15
+
16
+
17
+ # Logic class
14
18
  from .film import download_film
15
19
 
16
20
 
@@ -25,16 +29,32 @@ msg = Prompt()
25
29
  console = Console()
26
30
 
27
31
 
28
- def search(string_to_search: str = None, get_onylDatabase: bool = False):
32
+ def process_search_result(select_title):
29
33
  """
30
- Main function of the application for film and series.
34
+ Handles the search result and initiates the download for either a film or series.
31
35
  """
36
+ download_film(select_title)
37
+
38
+
39
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
40
+ """
41
+ Main function of the application for search film, series and anime.
42
+
43
+ Parameters:
44
+ string_to_search (str, optional): String to search for
45
+ get_onylDatabase (bool, optional): If True, return only the database object
46
+ direct_item (dict, optional): Direct item to process (bypass search)
47
+ """
48
+ if direct_item:
49
+ select_title = MediaItem(**direct_item)
50
+ process_search_result(select_title)
51
+ return
32
52
 
33
53
  if string_to_search is None:
34
54
  string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
35
55
 
36
56
  # Not available for the moment
37
- if get_onylDatabase:
57
+ if get_onlyDatabase:
38
58
  return 0
39
59
 
40
60
  # Search on database
@@ -47,7 +67,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
47
67
  download_film(movie_details)
48
68
 
49
69
  else:
50
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
51
70
 
52
- # Retry
71
+ # If no results are found, ask again
72
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
53
73
  search()
@@ -12,11 +12,12 @@ from rich.prompt import Prompt
12
12
 
13
13
  # Internal utilities
14
14
  from StreamingCommunity.Api.Template import get_select_title
15
+ from StreamingCommunity.Api.Template.config_loader import site_constant
16
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
15
17
  from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
16
18
 
17
19
 
18
20
  # Logic class
19
- from StreamingCommunity.Api.Template.config_loader import site_constant
20
21
  from .site import title_search, table_show_manager, media_search_manager
21
22
  from .film import download_film
22
23
  from .series import download_series
@@ -33,54 +34,76 @@ msg = Prompt()
33
34
  console = Console()
34
35
 
35
36
 
36
- def search(string_to_search: str = None, get_onylDatabase: bool = False):
37
+ def get_user_input(string_to_search: str = None):
37
38
  """
38
- Main function of the application for film and series.
39
+ Asks the user to input a search term.
40
+ Handles both Telegram bot input and direct input.
39
41
  """
40
- if site_constant.TELEGRAM_BOT:
41
- bot = get_bot_instance()
42
-
43
- if string_to_search is None:
44
-
45
- # Chiedi la scelta all'utente con il bot Telegram
42
+ if string_to_search is None:
43
+ if site_constant.TELEGRAM_BOT:
44
+ bot = get_bot_instance()
46
45
  string_to_search = bot.ask(
47
46
  "key_search",
48
- f"Inserisci la parola da cercare\noppure back per tornare alla scelta: ",
47
+ f"Enter the search term\nor type 'back' to return to the menu: ",
49
48
  None
50
49
  )
51
50
 
52
51
  if string_to_search == 'back':
53
- # Riavvia lo script
54
- # Chiude il processo attuale e avvia una nuova istanza dello script
52
+
53
+ # Restart the script
55
54
  subprocess.Popen([sys.executable] + sys.argv)
56
55
  sys.exit()
57
-
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
60
+
61
+ def process_search_result(select_title):
62
+ """
63
+ Handles the search result and initiates the download for either a film or series.
64
+ """
65
+ if select_title.type == 'tv':
66
+ download_series(select_title)
58
67
  else:
59
- if string_to_search is None:
60
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
68
+ download_film(select_title)
61
69
 
70
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
71
+ """
72
+ Main function of the application for search film, series and anime.
73
+
74
+ Parameters:
75
+ string_to_search (str, optional): String to search for
76
+ get_onylDatabase (bool, optional): If True, return only the database object
77
+ direct_item (dict, optional): Direct item to process (bypass search)
78
+ """
79
+ if direct_item:
80
+ select_title = MediaItem(**direct_item)
81
+ process_search_result(select_title)
82
+ return
83
+
84
+ # Get the user input for the search term
85
+ string_to_search = get_user_input(string_to_search)
86
+
87
+ # Perform the database search
62
88
  len_database = title_search(quote_plus(string_to_search))
63
89
 
64
- # Return list of elements
65
- if get_onylDatabase:
90
+ # If only the database is needed, return the manager
91
+ if get_onlyDatabase:
66
92
  return media_search_manager
67
93
 
94
+ if site_constant.TELEGRAM_BOT:
95
+ bot = get_bot_instance()
96
+
68
97
  if len_database > 0:
69
-
70
- # Select title from list
71
98
  select_title = get_select_title(table_show_manager, media_search_manager)
72
-
73
- if select_title.type == 'tv':
74
- download_series(select_title)
75
-
76
- else:
77
- download_film(select_title)
99
+ process_search_result(select_title)
78
100
 
79
101
  else:
80
102
  console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
81
103
 
82
104
  if site_constant.TELEGRAM_BOT:
83
- bot.send_message(f"Nessun risultato trovato riprova", None)
105
+ bot.send_message(f"No results found, please try again", None)
84
106
 
85
- # Retry
107
+ # If no results are found, ask again
108
+ string_to_search = get_user_input()
86
109
  search()
@@ -185,7 +185,11 @@ def download_series(select_season: MediaItem) -> None:
185
185
 
186
186
  index_season_selected = bot.ask(
187
187
  "select_title_episode",
188
- "Inserisci il numero della stagione (es. 1), * per scaricare tutte le stagioni, (es. 1-2) per un intervallo di stagioni, o (es. 3-*) per scaricare dalla stagione specificata fino alla fine",
188
+ "Menu di selezione delle stagioni\n\n"
189
+ "- Inserisci il numero della stagione (ad esempio, 1)\n"
190
+ "- Inserisci * per scaricare tutte le stagioni\n"
191
+ "- Inserisci un intervallo di stagioni (ad esempio, 1-2) per scaricare da una stagione all'altra\n"
192
+ "- Inserisci (ad esempio, 3-*) per scaricare dalla stagione specificata fino alla fine della serie",
189
193
  None
190
194
  )
191
195
 
@@ -52,6 +52,8 @@ def title_search(title_search: str) -> int:
52
52
 
53
53
  except Exception as e:
54
54
  console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
55
+ if site_constant.TELEGRAM_BOT:
56
+ bot.send_message(f"ERRORE\n\nErrore nella richiesta di ricerca:\n\n{e}", None)
55
57
  return 0
56
58
 
57
59
  # Prepara le scelte per l'utente
@@ -82,6 +84,8 @@ def title_search(title_search: str) -> int:
82
84
 
83
85
  except Exception as e:
84
86
  print(f"Error parsing a film entry: {e}")
87
+ if site_constant.TELEGRAM_BOT:
88
+ bot.send_message(f"ERRORE\n\nErrore nell'analisi del film:\n\n{e}", None)
85
89
 
86
90
  if site_constant.TELEGRAM_BOT:
87
91
  if choices:
@@ -37,7 +37,7 @@ from ...M3U8 import (
37
37
  # Config
38
38
  TQDM_DELAY_WORKER = config_manager.get_float('M3U8_DOWNLOAD', 'tqdm_delay')
39
39
  REQUEST_MAX_RETRY = config_manager.get_int('REQUESTS', 'max_retry')
40
- REQUEST_VERIFY = config_manager.get_int('REQUESTS', 'verify')
40
+ REQUEST_VERIFY = config_manager.get_bool('REQUESTS', 'verify')
41
41
  DEFAULT_VIDEO_WORKERS = config_manager.get_int('M3U8_DOWNLOAD', 'default_video_workser')
42
42
  DEFAULT_AUDIO_WORKERS = config_manager.get_int('M3U8_DOWNLOAD', 'default_audio_workser')
43
43
  MAX_TIMEOOUT = config_manager.get_int("REQUESTS", "timeout")
@@ -31,7 +31,6 @@ from ...FFmpeg import print_duration_table
31
31
 
32
32
  # Config
33
33
  REQUEST_VERIFY = config_manager.get_bool('REQUESTS', 'verify')
34
- REQUEST_HTTP2 = config_manager.get_bool('REQUESTS', 'http2')
35
34
  GET_ONLY_LINK = config_manager.get_bool('M3U8_PARSER', 'get_only_link')
36
35
  REQUEST_TIMEOUT = config_manager.get_float('REQUESTS', 'timeout')
37
36
  TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
@@ -111,11 +110,12 @@ def MP4_downloader(url: str, path: str, referer: str = None, headers_: dict = No
111
110
  interrupt_handler = InterruptHandler()
112
111
  original_handler = signal.signal(signal.SIGINT, partial(signal_handler, interrupt_handler=interrupt_handler, original_handler=signal.getsignal(signal.SIGINT)))
113
112
 
113
+ # Ensure the output directory exists
114
+ os.makedirs(os.path.dirname(path), exist_ok=True)
115
+
114
116
  try:
115
- transport = httpx.HTTPTransport(verify=REQUEST_VERIFY, http2=REQUEST_HTTP2)
116
-
117
- with httpx.Client(transport=transport, timeout=httpx.Timeout(60)) as client:
118
- with client.stream("GET", url, headers=headers, timeout=REQUEST_TIMEOUT) as response:
117
+ with httpx.Client() as client:
118
+ with client.stream("GET", url, headers=headers) as response:
119
119
  response.raise_for_status()
120
120
  total = int(response.headers.get('content-length', 0))
121
121
 
@@ -123,6 +123,7 @@ def MP4_downloader(url: str, path: str, referer: str = None, headers_: dict = No
123
123
  console.print("[bold red]No video stream found.[/bold red]")
124
124
  return None, False
125
125
 
126
+ # Create a fancy progress bar
126
127
  progress_bar = tqdm(
127
128
  total=total,
128
129
  ascii='░▒█',
@@ -135,7 +136,7 @@ def MP4_downloader(url: str, path: str, referer: str = None, headers_: dict = No
135
136
  unit_scale=True,
136
137
  desc='Downloading',
137
138
  mininterval=0.05,
138
- file=sys.stdout # Using file=sys.stdout to force in-place updates because sys.stderr may not support carriage returns in this environment.
139
+ file=sys.stdout # Using file=sys.stdout to force in-place updates because sys.stderr may not support carriage returns in this environment.
139
140
  )
140
141
 
141
142
  downloaded = 0
@@ -1,5 +1,5 @@
1
1
  __title__ = 'StreamingCommunity'
2
- __version__ = '2.9.4'
2
+ __version__ = '2.9.5'
3
3
  __author__ = 'Arrowar'
4
4
  __description__ = 'A command-line program to download film'
5
5
  __copyright__ = 'Copyright 2024'
@@ -196,6 +196,7 @@ class ConfigManager:
196
196
  except Exception as e:
197
197
  logging.error(f"Error reading configuration file: {e}")
198
198
  console.print(f"[bold red]Failed to read configuration:[/bold red] {str(e)}")
199
+ sys.exit(0)
199
200
 
200
201
  def download_requirements(self, url: str, filename: str) -> None:
201
202
  """
@@ -255,14 +256,7 @@ class ConfigManager:
255
256
  sites_info = []
256
257
  for site, info in examples:
257
258
  sites_info.append(f"[cyan]{site}[/cyan]: {info.get('full_url', 'N/A')}")
258
-
259
- console.print("[bold cyan]Sample sites:[/bold cyan]")
260
- for info in sites_info:
261
- console.print(f" {info}")
262
-
263
- if site_count > 3:
264
- console.print(f" ... and {site_count - 3} more")
265
-
259
+
266
260
  else:
267
261
  console.print("[bold yellow]API returned empty data set[/bold yellow]")
268
262
  else:
@@ -147,9 +147,14 @@ class TVShowManager:
147
147
  if not force_int_input:
148
148
  prompt_msg = ("\n[cyan]Insert media index [yellow](e.g., 1), [red]* [cyan]to download all media, "
149
149
  "[yellow](e.g., 1-2) [cyan]for a range of media, or [yellow](e.g., 3-*) [cyan]to download from a specific index to the end")
150
+ telegram_msg = "Menu di selezione degli episodi: \n\n" \
151
+ "- Inserisci il numero dell'episodio (ad esempio, 1)\n" \
152
+ "- Inserisci * per scaricare tutti gli episodi\n" \
153
+ "- Inserisci un intervallo di episodi (ad esempio, 1-2) per scaricare da un episodio all'altro\n" \
154
+ "- Inserisci (ad esempio, 3-*) per scaricare dall'episodio specificato fino alla fine della serie"
150
155
 
151
156
  if is_telegram:
152
- key = bot.ask("select_title_episode", prompt_msg, None)
157
+ key = bot.ask("select_title_episode", telegram_msg, None)
153
158
  else:
154
159
  key = Prompt.ask(prompt_msg)
155
160
  else:
@@ -183,9 +188,14 @@ class TVShowManager:
183
188
  if not force_int_input:
184
189
  prompt_msg = ("\n[cyan]Insert media index [yellow](e.g., 1), [red]* [cyan]to download all media, "
185
190
  "[yellow](e.g., 1-2) [cyan]for a range of media, or [yellow](e.g., 3-*) [cyan]to download from a specific index to the end")
191
+ telegram_msg = "Menu di selezione degli episodi: \n\n" \
192
+ "- Inserisci il numero dell'episodio (ad esempio, 1)\n" \
193
+ "- Inserisci * per scaricare tutti gli episodi\n" \
194
+ "- Inserisci un intervallo di episodi (ad esempio, 1-2) per scaricare da un episodio all'altro\n" \
195
+ "- Inserisci (ad esempio, 3-*) per scaricare dall'episodio specificato fino alla fine della serie"
186
196
 
187
197
  if is_telegram:
188
- key = bot.ask("select_title_episode", prompt_msg, None)
198
+ key = bot.ask("select_title_episode", telegram_msg, None)
189
199
  else:
190
200
  key = Prompt.ask(prompt_msg)
191
201
  else: