StreamingCommunity 3.2.8__py3-none-any.whl → 3.3.0__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 (86) hide show
  1. StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +2 -1
  2. StreamingCommunity/Api/Player/hdplayer.py +2 -2
  3. StreamingCommunity/Api/Player/sweetpixel.py +5 -8
  4. StreamingCommunity/Api/Site/altadefinizione/__init__.py +32 -15
  5. StreamingCommunity/Api/Site/altadefinizione/film.py +10 -8
  6. StreamingCommunity/Api/Site/altadefinizione/series.py +9 -7
  7. StreamingCommunity/Api/Site/altadefinizione/site.py +1 -1
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +31 -15
  9. StreamingCommunity/Api/Site/animeunity/serie.py +2 -2
  10. StreamingCommunity/Api/Site/animeworld/__init__.py +33 -7
  11. StreamingCommunity/Api/Site/animeworld/site.py +3 -5
  12. StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +8 -10
  13. StreamingCommunity/Api/Site/crunchyroll/__init__.py +44 -12
  14. StreamingCommunity/Api/Site/crunchyroll/film.py +9 -7
  15. StreamingCommunity/Api/Site/crunchyroll/series.py +9 -7
  16. StreamingCommunity/Api/Site/crunchyroll/site.py +16 -1
  17. StreamingCommunity/Api/Site/guardaserie/__init__.py +36 -10
  18. StreamingCommunity/Api/Site/guardaserie/series.py +8 -6
  19. StreamingCommunity/Api/Site/guardaserie/site.py +0 -3
  20. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +1 -2
  21. StreamingCommunity/Api/Site/mediasetinfinity/__init__.py +37 -12
  22. StreamingCommunity/Api/Site/mediasetinfinity/film.py +10 -16
  23. StreamingCommunity/Api/Site/mediasetinfinity/series.py +12 -18
  24. StreamingCommunity/Api/Site/mediasetinfinity/site.py +18 -3
  25. StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +214 -180
  26. StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +2 -31
  27. StreamingCommunity/Api/Site/raiplay/__init__.py +47 -12
  28. StreamingCommunity/Api/Site/raiplay/film.py +42 -10
  29. StreamingCommunity/Api/Site/raiplay/series.py +53 -11
  30. StreamingCommunity/Api/Site/raiplay/site.py +4 -1
  31. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +2 -1
  32. StreamingCommunity/Api/Site/raiplay/util/get_license.py +40 -0
  33. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +5 -8
  34. StreamingCommunity/Api/Site/streamingcommunity/film.py +7 -5
  35. StreamingCommunity/Api/Site/streamingcommunity/series.py +9 -7
  36. StreamingCommunity/Api/Site/streamingcommunity/site.py +8 -3
  37. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +5 -2
  38. StreamingCommunity/Api/Site/streamingwatch/__init__.py +43 -9
  39. StreamingCommunity/Api/Site/streamingwatch/film.py +7 -5
  40. StreamingCommunity/Api/Site/streamingwatch/series.py +8 -6
  41. StreamingCommunity/Api/Site/streamingwatch/site.py +3 -1
  42. StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +3 -3
  43. StreamingCommunity/Api/Template/Util/__init__.py +10 -1
  44. StreamingCommunity/Api/Template/Util/manage_ep.py +4 -4
  45. StreamingCommunity/Api/Template/__init__.py +5 -1
  46. StreamingCommunity/Api/Template/site.py +10 -6
  47. StreamingCommunity/Lib/Downloader/DASH/cdm_helpher.py +13 -12
  48. StreamingCommunity/Lib/Downloader/DASH/decrypt.py +1 -1
  49. StreamingCommunity/Lib/Downloader/DASH/downloader.py +24 -22
  50. StreamingCommunity/Lib/Downloader/DASH/parser.py +1 -1
  51. StreamingCommunity/Lib/Downloader/DASH/segments.py +4 -3
  52. StreamingCommunity/Lib/Downloader/HLS/downloader.py +11 -9
  53. StreamingCommunity/Lib/Downloader/HLS/segments.py +4 -9
  54. StreamingCommunity/Lib/Downloader/MP4/downloader.py +25 -6
  55. StreamingCommunity/Lib/Downloader/TOR/downloader.py +3 -5
  56. StreamingCommunity/Lib/Downloader/__init__.py +9 -1
  57. StreamingCommunity/Lib/FFmpeg/__init__.py +10 -1
  58. StreamingCommunity/Lib/FFmpeg/command.py +4 -6
  59. StreamingCommunity/Lib/FFmpeg/util.py +1 -1
  60. StreamingCommunity/Lib/M3U8/__init__.py +9 -1
  61. StreamingCommunity/Lib/M3U8/decryptor.py +8 -4
  62. StreamingCommunity/Lib/M3U8/estimator.py +0 -6
  63. StreamingCommunity/Lib/M3U8/parser.py +1 -1
  64. StreamingCommunity/Lib/M3U8/url_fixer.py +1 -1
  65. StreamingCommunity/Lib/TMBD/__init__.py +6 -1
  66. StreamingCommunity/TelegramHelp/config.json +1 -5
  67. StreamingCommunity/TelegramHelp/telegram_bot.py +9 -10
  68. StreamingCommunity/Upload/update.py +2 -2
  69. StreamingCommunity/Upload/version.py +1 -1
  70. StreamingCommunity/Util/config_json.py +139 -59
  71. StreamingCommunity/Util/http_client.py +201 -0
  72. StreamingCommunity/Util/message.py +1 -1
  73. StreamingCommunity/Util/os.py +8 -5
  74. StreamingCommunity/Util/table.py +3 -3
  75. StreamingCommunity/__init__.py +9 -1
  76. StreamingCommunity/run.py +394 -258
  77. {streamingcommunity-3.2.8.dist-info → streamingcommunity-3.3.0.dist-info}/METADATA +147 -45
  78. streamingcommunity-3.3.0.dist-info/RECORD +110 -0
  79. StreamingCommunity/Api/Site/cb01new/__init__.py +0 -72
  80. StreamingCommunity/Api/Site/cb01new/film.py +0 -62
  81. StreamingCommunity/Api/Site/cb01new/site.py +0 -78
  82. streamingcommunity-3.2.8.dist-info/RECORD +0 -111
  83. {streamingcommunity-3.2.8.dist-info → streamingcommunity-3.3.0.dist-info}/WHEEL +0 -0
  84. {streamingcommunity-3.2.8.dist-info → streamingcommunity-3.3.0.dist-info}/entry_points.txt +0 -0
  85. {streamingcommunity-3.2.8.dist-info → streamingcommunity-3.3.0.dist-info}/licenses/LICENSE +0 -0
  86. {streamingcommunity-3.2.8.dist-info → streamingcommunity-3.3.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  # 23.11.24
2
2
 
3
- from typing import Dict, Any, List, Union, List, Optional
3
+ from typing import Dict, Any, List, Optional
4
4
 
5
5
 
6
6
  class Episode:
@@ -12,6 +12,7 @@ class Episode:
12
12
  self.name: str = data.get('name', '')
13
13
  self.duration: int = data.get('duration', 0)
14
14
  self.url: str = data.get('url', '')
15
+ self.mpd_id: str = data.get('mpd_id', '')
15
16
 
16
17
  def __str__(self):
17
18
  return f"Episode(id={self.id}, number={self.number}, name='{self.name}', duration={self.duration} sec)"
@@ -3,12 +3,12 @@
3
3
  import re
4
4
 
5
5
  # External library
6
- import httpx
7
6
  from bs4 import BeautifulSoup
8
7
 
9
8
 
10
9
  # Internal utilities
11
10
  from StreamingCommunity.Util.headers import get_userAgent
11
+ from StreamingCommunity.Util.http_client import create_client
12
12
  from StreamingCommunity.Util.config_json import config_manager
13
13
 
14
14
 
@@ -19,7 +19,7 @@ REQUEST_VERIFY = config_manager.get_bool('REQUESTS', 'verify')
19
19
 
20
20
  class VideoSource:
21
21
  def __init__(self):
22
- self.client = httpx.Client(headers={'user-agent': get_userAgent()}, timeout=MAX_TIMEOUT, verify=REQUEST_VERIFY)
22
+ self.client = create_client(headers={'user-agent': get_userAgent()})
23
23
 
24
24
  def extractLinkHdPlayer(self, response):
25
25
  """Extract iframe source from the page."""
@@ -4,12 +4,12 @@ import logging
4
4
 
5
5
 
6
6
  # External libraries
7
- import httpx
8
7
 
9
8
 
10
9
  # Internal utilities
11
10
  from StreamingCommunity.Util.config_json import config_manager
12
11
  from StreamingCommunity.Util.headers import get_userAgent
12
+ from StreamingCommunity.Util.http_client import create_client
13
13
 
14
14
 
15
15
  # Variable
@@ -17,21 +17,18 @@ MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
17
17
  REQUEST_VERIFY = config_manager.get_bool('REQUESTS', 'verify')
18
18
 
19
19
  class VideoSource:
20
- def __init__(self, full_url, episode_data, session_id, csrf_token):
20
+ def __init__(self, site_url, episode_data, session_id, csrf_token):
21
21
  """Initialize the VideoSource with session details, episode data, and URL."""
22
22
  self.session_id = session_id
23
23
  self.csrf_token = csrf_token
24
24
  self.episode_data = episode_data
25
25
  self.number = episode_data['number']
26
- self.link = episode_data['link']
26
+ self.link = site_url + episode_data['link']
27
27
 
28
28
  # Create an HTTP client with session cookies, headers, and base URL.
29
- self.client = httpx.Client(
29
+ self.client = create_client(
30
30
  cookies={"sessionId": session_id},
31
- headers={"User-Agent": get_userAgent(), "csrf-token": csrf_token},
32
- base_url=full_url,
33
- timeout=MAX_TIMEOUT,
34
- verify=REQUEST_VERIFY
31
+ headers={"User-Agent": get_userAgent(), "csrf-token": csrf_token}
35
32
  )
36
33
 
37
34
  def get_playlist(self):
@@ -22,6 +22,7 @@ from .site import title_search, table_show_manager, media_search_manager
22
22
  from .film import download_film
23
23
  from .series import download_series
24
24
 
25
+
25
26
  # Variable
26
27
  indice = 2
27
28
  _useFor = "Film_&_Serie"
@@ -43,7 +44,7 @@ def get_user_input(string_to_search: str = None):
43
44
  bot = get_bot_instance()
44
45
  string_to_search = bot.ask(
45
46
  "key_search",
46
- f"Enter the search term\nor type 'back' to return to the menu: ",
47
+ "Enter the search term\nor type 'back' to return to the menu: ",
47
48
  None
48
49
  )
49
50
 
@@ -66,6 +67,14 @@ def process_search_result(select_title, selections=None):
66
67
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
67
68
  {'season': season_selection, 'episode': episode_selection}
68
69
  """
70
+ if not select_title:
71
+ if site_constant.TELEGRAM_BOT:
72
+ bot = get_bot_instance()
73
+ bot.send_message("No title selected or selection cancelled.", None)
74
+ else:
75
+ console.print("[yellow]No title selected or selection cancelled.")
76
+ return
77
+
69
78
  if select_title.type == 'tv':
70
79
  season_selection = None
71
80
  episode_selection = None
@@ -86,39 +95,47 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
86
95
 
87
96
  Parameters:
88
97
  string_to_search (str, optional): String to search for
89
- get_onylDatabase (bool, optional): If True, return only the database object
98
+ get_onlyDatabase (bool, optional): If True, return only the database object
90
99
  direct_item (dict, optional): Direct item to process (bypass search)
91
100
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
92
101
  {'season': season_selection, 'episode': episode_selection}
93
102
  """
103
+ bot = None
104
+ if site_constant.TELEGRAM_BOT:
105
+ bot = get_bot_instance()
106
+
94
107
  if direct_item:
95
108
  select_title = MediaItem(**direct_item)
96
109
  process_search_result(select_title, selections)
97
110
  return
98
111
 
99
112
  # Get the user input for the search term
100
- string_to_search = get_user_input(string_to_search)
113
+ actual_search_query = get_user_input(string_to_search)
114
+
115
+ # Handle cases where user input is empty, or 'back' was handled (sys.exit or None return)
116
+ if not actual_search_query:
117
+ if bot:
118
+ if actual_search_query is None: # Specifically for timeout from bot.ask or failed restart
119
+ bot.send_message("Search term not provided or operation cancelled. Returning.", None)
120
+ return
101
121
 
102
122
  # Perform the database search
103
- len_database = title_search(quote_plus(string_to_search))
123
+ len_database = title_search(quote_plus(actual_search_query))
104
124
 
105
125
  # If only the database is needed, return the manager
106
126
  if get_onlyDatabase:
107
127
  return media_search_manager
108
-
109
- if site_constant.TELEGRAM_BOT:
110
- bot = get_bot_instance()
111
-
128
+
112
129
  if len_database > 0:
113
130
  select_title = get_select_title(table_show_manager, media_search_manager, len_database)
114
131
  process_search_result(select_title, selections)
115
132
 
116
133
  else:
117
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
118
-
119
- if site_constant.TELEGRAM_BOT:
120
- bot.send_message(f"No results found, please try again", None)
134
+ if bot:
135
+ bot.send_message(f"No results found for: '{actual_search_query}'", None)
136
+ else:
137
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{actual_search_query}")
121
138
 
122
- # If no results are found, ask again
123
- string_to_search = get_user_input()
124
- search(string_to_search, get_onlyDatabase, None, selections)
139
+ # Do not call search() recursively here to avoid infinite loops on no results.
140
+ # The flow should return to the caller (e.g., main menu in run.py).
141
+ return
@@ -5,7 +5,6 @@ import re
5
5
 
6
6
 
7
7
  # External library
8
- import httpx
9
8
  from bs4 import BeautifulSoup
10
9
  from rich.console import Console
11
10
 
@@ -13,6 +12,7 @@ from rich.console import Console
13
12
  # Internal utilities
14
13
  from StreamingCommunity.Util.os import os_manager
15
14
  from StreamingCommunity.Util.headers import get_headers
15
+ from StreamingCommunity.Util.http_client import create_client
16
16
  from StreamingCommunity.Util.message import start_message
17
17
  from StreamingCommunity.Util.config_json import config_manager
18
18
  from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
@@ -60,7 +60,7 @@ def download_film(select_title: MediaItem) -> str:
60
60
 
61
61
  # Extract mostraguarda URL
62
62
  try:
63
- response = httpx.get(select_title.url, headers=get_headers(), timeout=10)
63
+ response = create_client(headers=get_headers()).get(select_title.url)
64
64
  response.raise_for_status()
65
65
 
66
66
  soup = BeautifulSoup(response.text, 'html.parser')
@@ -74,7 +74,7 @@ def download_film(select_title: MediaItem) -> str:
74
74
  # Extract supervideo URL
75
75
  supervideo_url = None
76
76
  try:
77
- response = httpx.get(mostraguarda, headers=get_headers(), timeout=10)
77
+ response = create_client(headers=get_headers()).get(mostraguarda)
78
78
  response.raise_for_status()
79
79
 
80
80
  soup = BeautifulSoup(response.text, 'html.parser')
@@ -96,7 +96,7 @@ def download_film(select_title: MediaItem) -> str:
96
96
  mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(".mp4", ""))
97
97
 
98
98
  # Download the film using the m3u8 playlist, and output filename
99
- r_proc = HLS_Downloader(
99
+ hls_process = HLS_Downloader(
100
100
  m3u8_url=master_playlist,
101
101
  output_path=os.path.join(mp4_path, title_name)
102
102
  ).start()
@@ -108,8 +108,10 @@ def download_film(select_title: MediaItem) -> str:
108
108
  if script_id != "unknown":
109
109
  TelegramSession.deleteScriptId(script_id)
110
110
 
111
- if r_proc['error'] is not None:
112
- try: os.remove(r_proc['path'])
113
- except: pass
111
+ if hls_process['error'] is not None:
112
+ try:
113
+ os.remove(hls_process['path'])
114
+ except Exception:
115
+ pass
114
116
 
115
- return r_proc['path']
117
+ return hls_process['path']
@@ -54,7 +54,7 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
54
54
 
55
55
  # Get episode information
56
56
  obj_episode = scrape_serie.selectEpisode(index_season_selected, index_episode_selected-1)
57
- console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [bold magenta]{obj_episode.name}[/bold magenta] ([cyan]S{index_season_selected}E{index_episode_selected}[/cyan]) \n")
57
+ console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{scrape_serie.series_name}[/cyan] \\ [bold magenta]{obj_episode.name}[/bold magenta] ([cyan]S{index_season_selected}E{index_episode_selected}[/cyan]) \n")
58
58
 
59
59
  # Telegram integration
60
60
  if site_constant.TELEGRAM_BOT:
@@ -81,16 +81,18 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
81
81
  master_playlist = video_source.get_playlist()
82
82
 
83
83
  # Download the episode
84
- r_proc = HLS_Downloader(
84
+ hls_process = HLS_Downloader(
85
85
  m3u8_url=master_playlist,
86
86
  output_path=os.path.join(mp4_path, mp4_name)
87
87
  ).start()
88
88
 
89
- if r_proc['error'] is not None:
90
- try: os.remove(r_proc['path'])
91
- except: pass
89
+ if hls_process['error'] is not None:
90
+ try:
91
+ os.remove(hls_process['path'])
92
+ except Exception:
93
+ pass
92
94
 
93
- return r_proc['path'], r_proc['stopped']
95
+ return hls_process['path'], hls_process['stopped']
94
96
 
95
97
 
96
98
  def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, download_all: bool = False, episode_selection: str = None) -> None:
@@ -196,7 +198,7 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis
196
198
  download_episode(i_season, scrape_serie, download_all=False, episode_selection=episode_selection)
197
199
 
198
200
  if site_constant.TELEGRAM_BOT:
199
- bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
201
+ bot.send_message("Finito di scaricare tutte le serie e episodi", None)
200
202
 
201
203
  # Get script_id
202
204
  script_id = TelegramSession.get_session()
@@ -93,7 +93,7 @@ def title_search(query: str) -> int:
93
93
 
94
94
  if site_constant.TELEGRAM_BOT:
95
95
  if choices:
96
- bot.send_message(f"Lista dei risultati:", choices)
96
+ bot.send_message("Lista dei risultati:", choices)
97
97
 
98
98
  # Return the number of titles found
99
99
  return media_search_manager.get_length()
@@ -43,7 +43,7 @@ def get_user_input(string_to_search: str = None):
43
43
  bot = get_bot_instance()
44
44
  string_to_search = bot.ask(
45
45
  "key_search",
46
- f"Enter the search term\nor type 'back' to return to the menu: ",
46
+ "Enter the search term\nor type 'back' to return to the menu: ",
47
47
  None
48
48
  )
49
49
 
@@ -66,6 +66,14 @@ def process_search_result(select_title, selections=None):
66
66
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
67
67
  {'season': season_selection, 'episode': episode_selection}
68
68
  """
69
+ if not select_title:
70
+ if site_constant.TELEGRAM_BOT:
71
+ bot = get_bot_instance()
72
+ bot.send_message("No title selected or selection cancelled.", None)
73
+ else:
74
+ console.print("[yellow]No title selected or selection cancelled.")
75
+ return
76
+
69
77
  if select_title.type == 'Movie':
70
78
  download_film(select_title)
71
79
 
@@ -90,34 +98,42 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
90
98
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
91
99
  {'season': season_selection, 'episode': episode_selection}
92
100
  """
101
+ bot = None
102
+ if site_constant.TELEGRAM_BOT:
103
+ bot = get_bot_instance()
104
+
93
105
  if direct_item:
94
106
  select_title = MediaItem(**direct_item)
95
107
  process_search_result(select_title, selections)
96
108
  return
97
-
109
+
98
110
  # Get the user input for the search term
99
- string_to_search = get_user_input(string_to_search)
111
+ actual_search_query = get_user_input(string_to_search)
100
112
 
113
+ # Handle cases where user input is empty, or 'back' was handled (sys.exit or None return)
114
+ if not actual_search_query:
115
+ if bot:
116
+ if actual_search_query is None: # Specifically for timeout from bot.ask or failed restart
117
+ bot.send_message("Search term not provided or operation cancelled. Returning.", None)
118
+ return
119
+
101
120
  # Perform the database search
102
- len_database = title_search(string_to_search)
121
+ len_database = title_search(actual_search_query)
103
122
 
104
123
  # If only the database is needed, return the manager
105
124
  if get_onlyDatabase:
106
125
  return media_search_manager
107
-
108
- if site_constant.TELEGRAM_BOT:
109
- bot = get_bot_instance()
110
126
 
111
127
  if len_database > 0:
112
- select_title = get_select_title(table_show_manager, media_search_manager,len_database)
128
+ select_title = get_select_title(table_show_manager, media_search_manager, len_database)
113
129
  process_search_result(select_title, selections)
114
130
 
115
131
  else:
116
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
117
-
118
- if site_constant.TELEGRAM_BOT:
119
- bot.send_message(f"No results found, please try again", None)
132
+ if bot:
133
+ bot.send_message(f"No results found for: '{actual_search_query}'", None)
134
+ else:
135
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{actual_search_query}")
120
136
 
121
- # If no results are found, ask again
122
- string_to_search = get_user_input()
123
- search(string_to_search, get_onlyDatabase, None, selections)
137
+ # Do not call search() recursively here to avoid infinite loops on no results.
138
+ # The flow should return to the caller (e.g., main menu in run.py).
139
+ return
@@ -109,7 +109,7 @@ def download_series(select_title: MediaItem, season_selection: str = None, episo
109
109
  # Telegram bot integration
110
110
  if episode_selection is None:
111
111
  if site_constant.TELEGRAM_BOT:
112
- console.print(f"\n[cyan]Insert media [red]index [yellow]or [red]* [cyan]to download all media [yellow]or [red]1-2 [cyan]or [red]3-* [cyan]for a range of media")
112
+ console.print("\n[cyan]Insert media [red]index [yellow]or [red]* [cyan]to download all media [yellow]or [red]1-2 [cyan]or [red]3-* [cyan]for a range of media")
113
113
  bot.send_message(f"Episodi trovati: {episoded_count}", None)
114
114
 
115
115
  last_command = bot.ask(
@@ -145,7 +145,7 @@ def download_series(select_title: MediaItem, season_selection: str = None, episo
145
145
  _, kill_handler = download_episode(i_episode-1, scrape_serie, video_source)
146
146
 
147
147
  if site_constant.TELEGRAM_BOT:
148
- bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
148
+ bot.send_message("Finito di scaricare tutte le serie e episodi", None)
149
149
 
150
150
  # Get script_id
151
151
  script_id = TelegramSession.get_session()
@@ -9,6 +9,7 @@ from rich.prompt import Prompt
9
9
  from StreamingCommunity.Api.Template import get_select_title
10
10
  from StreamingCommunity.Api.Template.config_loader import site_constant
11
11
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
12
+ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
12
13
 
13
14
 
14
15
  # Logic class
@@ -38,6 +39,14 @@ def process_search_result(select_title, selections=None):
38
39
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
39
40
  {'season': season_selection, 'episode': episode_selection}
40
41
  """
42
+ if not select_title:
43
+ if site_constant.TELEGRAM_BOT:
44
+ bot = get_bot_instance()
45
+ bot.send_message("No title selected or selection cancelled.", None)
46
+ else:
47
+ console.print("[yellow]No title selected or selection cancelled.")
48
+ return
49
+
41
50
  if select_title.type == "TV":
42
51
  episode_selection = None
43
52
  if selections:
@@ -58,6 +67,10 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
58
67
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
59
68
  {'season': season_selection, 'episode': episode_selection}
60
69
  """
70
+ bot = None
71
+ if site_constant.TELEGRAM_BOT:
72
+ bot = get_bot_instance()
73
+
61
74
  if direct_item:
62
75
  select_title = MediaItem(**direct_item)
63
76
  process_search_result(select_title, selections)
@@ -65,20 +78,33 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
65
78
 
66
79
  # Get the user input for the search term
67
80
  if string_to_search is None:
68
- string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
81
+ actual_search_query = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
82
+ else:
83
+ actual_search_query = string_to_search
69
84
 
70
85
  # Perform the database search
71
- len_database = title_search(string_to_search)
86
+ if not actual_search_query:
87
+ if bot:
88
+ if actual_search_query is None:
89
+ bot.send_message("Search term not provided or operation cancelled. Returning.", None)
90
+ return
91
+
92
+ len_database = title_search(actual_search_query)
72
93
 
73
94
  # If only the database is needed, return the manager
74
95
  if get_onlyDatabase:
75
96
  return media_search_manager
76
97
 
77
98
  if len_database > 0:
78
- select_title = get_select_title(table_show_manager, media_search_manager,len_database)
99
+ select_title = get_select_title(table_show_manager, media_search_manager, len_database)
79
100
  process_search_result(select_title, selections)
80
-
101
+
81
102
  else:
82
- # If no results are found, ask again
83
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
84
- search()
103
+ if bot:
104
+ bot.send_message(f"No results found for: '{actual_search_query}'", None)
105
+ else:
106
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{actual_search_query}")
107
+
108
+ # Do not call search() recursively here to avoid infinite loops on no results.
109
+ # The flow should return to the caller (e.g., main menu in run.py).
110
+ return
@@ -11,6 +11,7 @@ from rich.console import Console
11
11
  # Internal utilities
12
12
  from StreamingCommunity.Util.config_json import config_manager
13
13
  from StreamingCommunity.Util.headers import get_userAgent, get_headers
14
+ from StreamingCommunity.Util.http_client import create_client
14
15
  from StreamingCommunity.Util.table import TVShowManager
15
16
 
16
17
 
@@ -31,11 +32,8 @@ def get_session_and_csrf() -> dict:
31
32
  Get the session ID and CSRF token from the website's cookies and HTML meta data.
32
33
  """
33
34
  # Send an initial GET request to the website
34
- response = httpx.get(
35
- site_constant.FULL_URL,
36
- headers=get_headers(),
37
- verify=False
38
- )
35
+ client = create_client(headers=get_headers())
36
+ response = client.get(site_constant.FULL_URL)
39
37
 
40
38
  # Extract the sessionId from the cookies
41
39
  session_id = response.cookies.get('sessionId')
@@ -2,13 +2,14 @@
2
2
 
3
3
  import logging
4
4
 
5
+
5
6
  # External libraries
6
- import httpx
7
7
  from bs4 import BeautifulSoup
8
8
 
9
9
 
10
10
  # Internal utilities
11
11
  from StreamingCommunity.Util.headers import get_userAgent
12
+ from StreamingCommunity.Util.http_client import create_client
12
13
  from StreamingCommunity.Util.config_json import config_manager
13
14
  from StreamingCommunity.Util.os import os_manager
14
15
 
@@ -23,24 +24,21 @@ max_timeout = config_manager.get_int("REQUESTS", "timeout")
23
24
 
24
25
 
25
26
  class ScrapSerie:
26
- def __init__(self, url, full_url):
27
+ def __init__(self, url, site_url):
27
28
  """Initialize the ScrapSerie object with the provided URL and setup the HTTP client."""
28
29
  self.url = url
29
- self.link = httpx.URL(url).path
30
30
  self.session_id, self.csrf_token = get_session_and_csrf()
31
- self.client = httpx.Client(
31
+ self.client = create_client(
32
32
  cookies={"sessionId": self.session_id},
33
- headers={"User-Agent": get_userAgent(), "csrf-token": self.csrf_token},
34
- base_url=full_url,
35
- verify=False
33
+ headers={"User-Agent": get_userAgent(), "csrf-token": self.csrf_token}
36
34
  )
37
35
 
38
36
  try:
39
- self.response = self.client.get(self.link, timeout=max_timeout, follow_redirects=True)
37
+ self.response = self.client.get(self.url, timeout=max_timeout, follow_redirects=True)
40
38
  self.response.raise_for_status()
41
39
 
42
- except:
43
- raise Exception(f"Failed to retrieve anime page.")
40
+ except Exception as e:
41
+ raise Exception(f"Failed to retrieve anime page: {str(e)}")
44
42
 
45
43
  def get_name(self):
46
44
  """Extract and return the name of the anime series."""
@@ -1,7 +1,5 @@
1
1
  # 16.03.25
2
2
 
3
- import sys
4
- import subprocess
5
3
  from urllib.parse import quote_plus
6
4
 
7
5
 
@@ -14,6 +12,7 @@ from rich.prompt import Prompt
14
12
  from StreamingCommunity.Api.Template import get_select_title
15
13
  from StreamingCommunity.Api.Template.config_loader import site_constant
16
14
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
15
+ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
17
16
 
18
17
 
19
18
  # Logic class
@@ -21,11 +20,12 @@ from .site import title_search, table_show_manager, media_search_manager
21
20
  from .film import download_film
22
21
  from .series import download_series
23
22
 
23
+
24
24
  # Variable
25
25
  indice = 8
26
26
  _useFor = "Anime"
27
27
  _priority = 0
28
- _engineDownload = "hls"
28
+ _engineDownload = "dash"
29
29
  _deprecate = False
30
30
 
31
31
  msg = Prompt()
@@ -51,6 +51,14 @@ def process_search_result(select_title, selections=None):
51
51
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
52
52
  {'season': season_selection, 'episode': episode_selection}
53
53
  """
54
+ if not select_title:
55
+ if site_constant.TELEGRAM_BOT:
56
+ bot = get_bot_instance()
57
+ bot.send_message("No title selected or selection cancelled.", None)
58
+ else:
59
+ console.print("[yellow]No title selected or selection cancelled.")
60
+ return
61
+
54
62
  if select_title.type == 'tv':
55
63
  season_selection = None
56
64
  episode_selection = None
@@ -71,33 +79,57 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
71
79
 
72
80
  Parameters:
73
81
  string_to_search (str, optional): String to search for
74
- get_onylDatabase (bool, optional): If True, return only the database object
82
+ get_onlyDatabase (bool, optional): If True, return only the database object
83
+ direct_item (dict, optional): Direct item to process (bypass search)
84
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
85
+ {'season': season_selection, 'episode': episode_selection}
86
+ """
87
+ """
88
+ Main function of the application for search.
89
+
90
+ Parameters:
91
+ string_to_search (str, optional): String to search for
92
+ get_onlyDatabase (bool, optional): If True, return only the database object
75
93
  direct_item (dict, optional): Direct item to process (bypass search)
76
94
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
77
95
  {'season': season_selection, 'episode': episode_selection}
78
96
  """
97
+ bot = None
98
+ if site_constant.TELEGRAM_BOT:
99
+ bot = get_bot_instance()
100
+
79
101
  if direct_item:
80
102
  select_title = MediaItem(**direct_item)
81
103
  process_search_result(select_title, selections)
82
104
  return
83
105
 
84
106
  # Get the user input for the search term
85
- string_to_search = get_user_input(string_to_search)
107
+ actual_search_query = get_user_input(string_to_search)
108
+
109
+ # Handle cases where user input is empty, or 'back' was handled (sys.exit or None return)
110
+ if not actual_search_query:
111
+ if bot:
112
+ if actual_search_query is None: # Specifically for timeout from bot.ask or failed restart
113
+ bot.send_message("Search term not provided or operation cancelled. Returning.", None)
114
+ return
86
115
 
87
116
  # Perform the database search
88
- len_database = title_search(quote_plus(string_to_search))
117
+ len_database = title_search(quote_plus(actual_search_query))
89
118
 
90
119
  # If only the database is needed, return the manager
91
120
  if get_onlyDatabase:
92
121
  return media_search_manager
93
-
122
+
94
123
  if len_database > 0:
95
124
  select_title = get_select_title(table_show_manager, media_search_manager, len_database)
96
125
  process_search_result(select_title, selections)
97
126
 
98
127
  else:
99
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
100
-
101
- # If no results are found, ask again
102
- string_to_search = get_user_input()
103
- search(string_to_search, get_onlyDatabase, None, selections)
128
+ if bot:
129
+ bot.send_message(f"No results found for: '{actual_search_query}'", None)
130
+ else:
131
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{actual_search_query}")
132
+
133
+ # Do not call search() recursively here to avoid infinite loops on no results.
134
+ # The flow should return to the caller (e.g., main menu in run.py).
135
+ return