StreamingCommunity 3.2.1__py3-none-any.whl → 3.2.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 (67) hide show
  1. StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +4 -0
  2. StreamingCommunity/Api/Player/hdplayer.py +2 -2
  3. StreamingCommunity/Api/Player/mixdrop.py +1 -1
  4. StreamingCommunity/Api/Player/vixcloud.py +4 -5
  5. StreamingCommunity/Api/Site/altadefinizione/film.py +2 -2
  6. StreamingCommunity/Api/Site/altadefinizione/series.py +1 -1
  7. StreamingCommunity/Api/Site/animeunity/serie.py +1 -1
  8. StreamingCommunity/Api/Site/animeworld/film.py +1 -1
  9. StreamingCommunity/Api/Site/animeworld/serie.py +1 -2
  10. StreamingCommunity/Api/Site/cb01new/film.py +1 -1
  11. StreamingCommunity/Api/Site/crunchyroll/__init__.py +103 -0
  12. StreamingCommunity/Api/Site/crunchyroll/film.py +82 -0
  13. StreamingCommunity/Api/Site/crunchyroll/series.py +186 -0
  14. StreamingCommunity/Api/Site/crunchyroll/site.py +113 -0
  15. StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +238 -0
  16. StreamingCommunity/Api/Site/crunchyroll/util/get_license.py +227 -0
  17. StreamingCommunity/Api/Site/guardaserie/series.py +1 -2
  18. StreamingCommunity/Api/Site/guardaserie/site.py +1 -2
  19. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +9 -8
  20. StreamingCommunity/Api/Site/mediasetinfinity/__init__.py +96 -0
  21. StreamingCommunity/Api/Site/mediasetinfinity/film.py +85 -0
  22. StreamingCommunity/Api/Site/mediasetinfinity/series.py +185 -0
  23. StreamingCommunity/Api/Site/mediasetinfinity/site.py +112 -0
  24. StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +259 -0
  25. StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py +64 -0
  26. StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +214 -0
  27. StreamingCommunity/Api/Site/raiplay/film.py +2 -2
  28. StreamingCommunity/Api/Site/raiplay/series.py +2 -1
  29. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +6 -17
  30. StreamingCommunity/Api/Site/streamingcommunity/film.py +3 -3
  31. StreamingCommunity/Api/Site/streamingcommunity/series.py +11 -11
  32. StreamingCommunity/Api/Site/streamingcommunity/site.py +2 -4
  33. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +3 -6
  34. StreamingCommunity/Api/Site/streamingwatch/__init__.py +6 -14
  35. StreamingCommunity/Api/Site/streamingwatch/film.py +3 -3
  36. StreamingCommunity/Api/Site/streamingwatch/series.py +9 -9
  37. StreamingCommunity/Api/Site/streamingwatch/site.py +5 -7
  38. StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +2 -2
  39. StreamingCommunity/Lib/Downloader/DASH/cdm_helpher.py +131 -0
  40. StreamingCommunity/Lib/Downloader/DASH/decrypt.py +79 -0
  41. StreamingCommunity/Lib/Downloader/DASH/downloader.py +218 -0
  42. StreamingCommunity/Lib/Downloader/DASH/parser.py +249 -0
  43. StreamingCommunity/Lib/Downloader/DASH/segments.py +332 -0
  44. StreamingCommunity/Lib/Downloader/HLS/downloader.py +10 -30
  45. StreamingCommunity/Lib/Downloader/HLS/segments.py +146 -263
  46. StreamingCommunity/Lib/Downloader/MP4/downloader.py +0 -5
  47. StreamingCommunity/Lib/FFmpeg/capture.py +3 -3
  48. StreamingCommunity/Lib/FFmpeg/command.py +1 -1
  49. StreamingCommunity/TelegramHelp/config.json +3 -7
  50. StreamingCommunity/Upload/version.py +1 -1
  51. StreamingCommunity/Util/bento4_installer.py +191 -0
  52. StreamingCommunity/Util/config_json.py +1 -1
  53. StreamingCommunity/Util/headers.py +0 -3
  54. StreamingCommunity/Util/os.py +36 -46
  55. StreamingCommunity/__init__.py +2 -1
  56. StreamingCommunity/run.py +11 -10
  57. {streamingcommunity-3.2.1.dist-info → streamingcommunity-3.2.7.dist-info}/METADATA +7 -9
  58. streamingcommunity-3.2.7.dist-info/RECORD +111 -0
  59. StreamingCommunity/Api/Site/1337xx/__init__.py +0 -72
  60. StreamingCommunity/Api/Site/1337xx/site.py +0 -82
  61. StreamingCommunity/Api/Site/1337xx/title.py +0 -61
  62. StreamingCommunity/Lib/Proxies/proxy.py +0 -72
  63. streamingcommunity-3.2.1.dist-info/RECORD +0 -96
  64. {streamingcommunity-3.2.1.dist-info → streamingcommunity-3.2.7.dist-info}/WHEEL +0 -0
  65. {streamingcommunity-3.2.1.dist-info → streamingcommunity-3.2.7.dist-info}/entry_points.txt +0 -0
  66. {streamingcommunity-3.2.1.dist-info → streamingcommunity-3.2.7.dist-info}/licenses/LICENSE +0 -0
  67. {streamingcommunity-3.2.1.dist-info → streamingcommunity-3.2.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,64 @@
1
+ # 16.03.25
2
+
3
+ from urllib.parse import urlparse, urlunparse
4
+
5
+
6
+ # External library
7
+ import httpx
8
+
9
+
10
+ def try_mpd(url, qualities):
11
+ """
12
+ Given a url containing one of the qualities (hd/hr/sd), try to replace it with the others and check which manifest exists.
13
+ """
14
+ parsed = urlparse(url)
15
+ path_parts = parsed.path.rsplit('/', 1)
16
+
17
+ if len(path_parts) != 2:
18
+ return None
19
+
20
+ dir_path, filename = path_parts
21
+
22
+ # Find the current quality in the filename
23
+ def replace_quality(filename, old_q, new_q):
24
+ if f"{old_q}_" in filename:
25
+ return filename.replace(f"{old_q}_", f"{new_q}_", 1)
26
+ elif filename.startswith(f"{old_q}_"):
27
+ return f"{new_q}_" + filename[len(f"{old_q}_") :]
28
+ return filename
29
+
30
+ for q in qualities:
31
+
32
+ # Search for which quality is present in the filename
33
+ for old_q in qualities:
34
+ if f"{old_q}_" in filename or filename.startswith(f"{old_q}_"):
35
+ new_filename = replace_quality(filename, old_q, q)
36
+ break
37
+
38
+ else:
39
+ new_filename = filename # No quality found, use original filename
40
+
41
+ new_path = f"{dir_path}/{new_filename}"
42
+ mpd_url = urlunparse(parsed._replace(path=new_path)).strip()
43
+
44
+ try:
45
+ r = httpx.head(mpd_url, timeout=5)
46
+ if r.status_code == 200:
47
+ return mpd_url
48
+
49
+ except Exception:
50
+ pass
51
+
52
+ return None
53
+
54
+ def get_manifest(base):
55
+ """
56
+ Try to get the manifest URL by checking different qualities.
57
+ """
58
+ manifest_qualities = ["hd", "hr", "sd"]
59
+
60
+ mpd_url = try_mpd(base, manifest_qualities)
61
+ if not mpd_url:
62
+ exit(1)
63
+
64
+ return mpd_url
@@ -0,0 +1,214 @@
1
+ # 16.03.25
2
+
3
+ from urllib.parse import urlencode
4
+ import xml.etree.ElementTree as ET
5
+
6
+
7
+ # External library
8
+ import httpx
9
+
10
+
11
+ # Internal utilities
12
+ from StreamingCommunity.Util.config_json import config_manager
13
+ from StreamingCommunity.Util.headers import get_headers, get_userAgent
14
+
15
+
16
+ # Variable
17
+ MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
18
+ bearer_token = None
19
+ playback_json = None
20
+
21
+
22
+ def get_bearer_token():
23
+ """
24
+ Gets the BEARER_TOKEN for authentication.
25
+
26
+ Returns:
27
+ str: The bearer token string.
28
+ """
29
+ global bearer_token
30
+
31
+ if bearer_token:
32
+ return bearer_token
33
+
34
+ LOGIN_URL = "https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0"
35
+
36
+ try:
37
+ response = httpx.post(
38
+ LOGIN_URL,
39
+ json={'client_id': 'client_id', 'appName': 'embed//mediasetplay-embed'},
40
+ follow_redirects=True,
41
+ timeout=MAX_TIMEOUT
42
+ )
43
+ response.raise_for_status()
44
+
45
+ # Extract the bearer token from the response
46
+ data = response.json()
47
+ bearer_token = data["response"]["beToken"]
48
+ return bearer_token
49
+
50
+ except Exception as e:
51
+ raise RuntimeError(f"Failed to get bearer token: {e}")
52
+
53
+ def get_playback_url(BEARER_TOKEN, CONTENT_ID):
54
+ """
55
+ Gets the playback URL for the specified content.
56
+
57
+ Args:
58
+ BEARER_TOKEN (str): The authentication token.
59
+ CONTENT_ID (str): The content identifier.
60
+
61
+ Returns:
62
+ dict: The playback JSON object.
63
+ """
64
+ global playback_json
65
+
66
+ if playback_json is not None:
67
+ return playback_json
68
+
69
+ headers = get_headers()
70
+ headers['authorization'] = f'Bearer {BEARER_TOKEN}'
71
+
72
+ json_data = {
73
+ 'contentId': CONTENT_ID,
74
+ 'streamType': 'VOD'
75
+ }
76
+
77
+ try:
78
+ response = httpx.post(
79
+ 'https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0',
80
+ headers=headers,
81
+ json=json_data,
82
+ follow_redirects=True,
83
+ timeout=MAX_TIMEOUT
84
+ )
85
+ response.raise_for_status()
86
+ resp_json = response.json()
87
+
88
+ # Check for PL022 error (Infinity+ rights)
89
+ if 'error' in resp_json and resp_json['error'].get('code') == 'PL022':
90
+ raise RuntimeError("Infinity+ required for this content.")
91
+
92
+ # Check for PL402 error (TVOD not purchased)
93
+ if 'error' in resp_json and resp_json['error'].get('code') == 'PL402':
94
+ raise RuntimeError("Content available for rental: you must rent it first.")
95
+
96
+ playback_json = resp_json['response']['mediaSelector']
97
+ return playback_json
98
+
99
+ except Exception as e:
100
+ raise RuntimeError(f"Failed to get playback URL: {e}")
101
+
102
+ def parse_tracking_data(tracking_value):
103
+ """
104
+ Parses the trackingData string into a dictionary.
105
+
106
+ Args:
107
+ tracking_value (str): The tracking data string.
108
+
109
+ Returns:
110
+ dict: Parsed tracking data.
111
+ """
112
+ return dict(item.split('=', 1) for item in tracking_value.split('|') if '=' in item)
113
+
114
+ def parse_smil_for_tracking_and_video(smil_xml):
115
+ """
116
+ Extracts all video_src and trackingData pairs from the SMIL.
117
+
118
+ Args:
119
+ smil_xml (str): The SMIL XML as a string.
120
+
121
+ Returns:
122
+ list: A list of dicts: {'video_src': ..., 'tracking_info': ...}
123
+ """
124
+ results = []
125
+ root = ET.fromstring(smil_xml)
126
+ ns = {'smil': root.tag.split('}')[0].strip('{')}
127
+
128
+ # Search all <par>
129
+ for par in root.findall('.//smil:par', ns):
130
+ video_src = None
131
+ tracking_info = None
132
+
133
+ # Search <video> inside <par>
134
+ video_elem = par.find('.//smil:video', ns)
135
+ if video_elem is not None:
136
+ video_src = video_elem.attrib.get('src')
137
+
138
+ # Search <ref> inside <par>
139
+ ref_elem = par.find('.//smil:ref', ns)
140
+ if ref_elem is not None:
141
+ # Search <param name="trackingData">
142
+ for param in ref_elem.findall('.//smil:param', ns):
143
+ if param.attrib.get('name') == 'trackingData':
144
+ tracking_value = param.attrib.get('value')
145
+ if tracking_value:
146
+ tracking_info = parse_tracking_data(tracking_value)
147
+ break
148
+
149
+ if video_src and tracking_info:
150
+ results.append({'video_src': video_src, 'tracking_info': tracking_info})
151
+
152
+ return results
153
+
154
+ def get_tracking_info(BEARER_TOKEN, PLAYBACK_JSON):
155
+ """
156
+ Retrieves tracking information from the playback JSON.
157
+
158
+ Args:
159
+ BEARER_TOKEN (str): The authentication token.
160
+ PLAYBACK_JSON (dict): The playback JSON object.
161
+
162
+ Returns:
163
+ list or None: List of tracking info dicts, or None if request fails.
164
+ """
165
+ params = {
166
+ "format": "SMIL",
167
+ "auth": BEARER_TOKEN,
168
+ "formats": "MPEG-DASH",
169
+ "assetTypes": "HR,browser,widevine,geoIT|geoNo:HR,browser,geoIT|geoNo:SD,browser,widevine,geoIT|geoNo:SD,browser,geoIT|geoNo:SS,browser,widevine,geoIT|geoNo:SS,browser,geoIT|geoNo",
170
+ "balance": "true",
171
+ "auto": "true",
172
+ "tracking": "true",
173
+ "delivery": "Streaming"
174
+ }
175
+
176
+ if 'publicUrl' in PLAYBACK_JSON:
177
+ params['publicUrl'] = PLAYBACK_JSON['publicUrl']
178
+
179
+ try:
180
+ response = httpx.get(
181
+ PLAYBACK_JSON['url'],
182
+ headers={'user-agent': get_userAgent()},
183
+ params=params,
184
+ follow_redirects=True,
185
+ timeout=MAX_TIMEOUT
186
+ )
187
+ response.raise_for_status()
188
+
189
+ smil_xml = response.text
190
+ results = parse_smil_for_tracking_and_video(smil_xml)
191
+ return results
192
+
193
+ except Exception as e:
194
+ return None
195
+
196
+ def generate_license_url(BEARER_TOKEN, tracking_info):
197
+ """
198
+ Generates the URL to obtain the Widevine license.
199
+
200
+ Args:
201
+ BEARER_TOKEN (str): The authentication token.
202
+ tracking_info (dict): The tracking info dictionary.
203
+
204
+ Returns:
205
+ str: The full license URL.
206
+ """
207
+ params = {
208
+ 'releasePid': tracking_info['tracking_info'].get('pid'),
209
+ 'account': f"http://access.auth.theplatform.com/data/Account/{tracking_info['tracking_info'].get('aid')}",
210
+ 'schema': '1.0',
211
+ 'token': BEARER_TOKEN,
212
+ }
213
+
214
+ return f"{'https://widevine.entitlement.theplatform.eu/wv/web/ModularDrm/getRawWidevineLicense'}?{urlencode(params)}"
@@ -11,9 +11,8 @@ from rich.console import Console
11
11
 
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.os import os_manager
14
- from StreamingCommunity.Util.message import start_message
15
- from StreamingCommunity.Lib.Downloader import HLS_Downloader
16
14
  from StreamingCommunity.Util.headers import get_headers
15
+ from StreamingCommunity.Util.message import start_message
17
16
 
18
17
 
19
18
  # Logic class
@@ -22,6 +21,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
22
21
 
23
22
 
24
23
  # Player
24
+ from StreamingCommunity import HLS_Downloader
25
25
  from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
26
26
 
27
27
 
@@ -11,7 +11,7 @@ from rich.prompt import Prompt
11
11
 
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.message import start_message
14
- from StreamingCommunity.Lib.Downloader import HLS_Downloader
14
+
15
15
 
16
16
  # Logic class
17
17
  from .util.ScrapeSerie import GetSerieInfo
@@ -27,6 +27,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
27
27
 
28
28
 
29
29
  # Player
30
+ from StreamingCommunity import HLS_Downloader
30
31
  from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
31
32
 
32
33
 
@@ -12,7 +12,6 @@ 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
16
15
  from StreamingCommunity.Api.Template.config_loader import site_constant
17
16
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
18
17
  from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
@@ -33,7 +32,6 @@ _deprecate = False
33
32
 
34
33
  msg = Prompt()
35
34
  console = Console()
36
- proxy = None
37
35
 
38
36
 
39
37
  def get_user_input(string_to_search: str = None):
@@ -74,7 +72,7 @@ def get_user_input(string_to_search: str = None):
74
72
  else:
75
73
  return msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
76
74
 
77
- def process_search_result(select_title, selections=None, proxy=None):
75
+ def process_search_result(select_title, selections=None):
78
76
  """
79
77
  Handles the search result and initiates the download for either a film or series.
80
78
 
@@ -82,7 +80,6 @@ def process_search_result(select_title, selections=None, proxy=None):
82
80
  select_title (MediaItem): The selected media item. Can be None if selection fails.
83
81
  selections (dict, optional): Dictionary containing selection inputs that bypass manual input
84
82
  e.g., {'season': season_selection, 'episode': episode_selection}
85
- proxy (str, optional): The proxy to use for downloads.
86
83
  """
87
84
  if not select_title:
88
85
  if site_constant.TELEGRAM_BOT:
@@ -100,10 +97,10 @@ def process_search_result(select_title, selections=None, proxy=None):
100
97
  season_selection = selections.get('season')
101
98
  episode_selection = selections.get('episode')
102
99
 
103
- download_series(select_title, season_selection, episode_selection, proxy)
100
+ download_series(select_title, season_selection, episode_selection)
104
101
 
105
102
  else:
106
- download_film(select_title, proxy)
103
+ download_film(select_title)
107
104
 
108
105
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
109
106
  """
@@ -121,17 +118,11 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
121
118
  if site_constant.TELEGRAM_BOT:
122
119
  bot = get_bot_instance()
123
120
 
124
- # Check proxy if not already set
125
- finder = ProxyFinder(site_constant.FULL_URL)
126
- proxy = finder.find_fast_proxy()
127
-
128
121
  if direct_item:
129
122
  select_title_obj = MediaItem(**direct_item)
130
- process_search_result(select_title_obj, selections, proxy)
123
+ process_search_result(select_title_obj, selections)
131
124
  return
132
125
 
133
-
134
-
135
126
  actual_search_query = get_user_input(string_to_search)
136
127
 
137
128
  # Handle cases where user input is empty, or 'back' was handled (sys.exit or None return)
@@ -142,9 +133,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
142
133
  return
143
134
 
144
135
  # Perform search on the database using the obtained query
145
- finder = ProxyFinder(site_constant.FULL_URL)
146
- proxy = finder.find_fast_proxy()
147
- len_database = title_search(actual_search_query, proxy)
136
+ len_database = title_search(actual_search_query)
148
137
 
149
138
  # If only the database object (media_search_manager populated by title_search) is needed
150
139
  if get_onlyDatabase:
@@ -152,7 +141,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
152
141
 
153
142
  if len_database > 0:
154
143
  select_title = get_select_title(table_show_manager, media_search_manager, len_database)
155
- process_search_result(select_title, selections, proxy)
144
+ process_search_result(select_title, selections)
156
145
 
157
146
  else:
158
147
  no_results_message = f"No results found for: '{actual_search_query}'"
@@ -10,7 +10,6 @@ from rich.console import Console
10
10
  # Internal utilities
11
11
  from StreamingCommunity.Util.os import os_manager
12
12
  from StreamingCommunity.Util.message import start_message
13
- from StreamingCommunity.Lib.Downloader import HLS_Downloader
14
13
  from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
15
14
 
16
15
 
@@ -20,6 +19,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
20
19
 
21
20
 
22
21
  # Player
22
+ from StreamingCommunity import HLS_Downloader
23
23
  from StreamingCommunity.Api.Player.vixcloud import VideoSource
24
24
 
25
25
 
@@ -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, proxy: str = None) -> str:
30
+ def download_film(select_title: MediaItem) -> 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, proxy: str = None) -> 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(f"{site_constant.FULL_URL}/it", False, select_title.id, proxy)
58
+ video_source = VideoSource(f"{site_constant.FULL_URL}/it", False, select_title.id)
59
59
 
60
60
  # Retrieve scws and if available master playlist
61
61
  video_source.get_iframe(select_title.id)
@@ -11,15 +11,14 @@ from rich.prompt import Prompt
11
11
 
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.message import start_message
14
- from StreamingCommunity.Lib.Downloader import HLS_Downloader
15
14
  from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
16
15
 
16
+
17
17
  # Logic class
18
18
  from .util.ScrapeSerie import GetSerieInfo
19
19
  from StreamingCommunity.Api.Template.Util import (
20
20
  manage_selection,
21
21
  map_episode_title,
22
- dynamic_format_number,
23
22
  validate_selection,
24
23
  validate_episode_selection,
25
24
  display_episodes_list
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
29
28
 
30
29
 
31
30
  # Player
31
+ from StreamingCommunity import HLS_Downloader
32
32
  from StreamingCommunity.Api.Player.vixcloud import VideoSource
33
33
 
34
34
 
@@ -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, proxy = None) -> None:
145
+ def download_series(select_season: MediaItem, season_selection: str = None, episode_selection: str = 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(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)
157
+ video_source = VideoSource(f"{site_constant.FULL_URL}/it", True, select_season.id)
158
+ scrape_serie = GetSerieInfo(f"{site_constant.FULL_URL}/it", select_season.id, select_season.slug)
159
159
 
160
160
  # Collect information about season
161
161
  scrape_serie.getNumberSeason()
@@ -200,11 +200,11 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis
200
200
 
201
201
  # Loop through the selected seasons and download episodes
202
202
  for i_season in list_season_select:
203
- season = None
204
- for s in scrape_serie.seasons_manager.seasons:
205
- if s.number == i_season:
206
- season = s
207
- break
203
+ try:
204
+ season = scrape_serie.seasons_manager.seasons[i_season - 1]
205
+ except IndexError:
206
+ console.print(f"[red]Season index {i_season} not found! Available seasons: {[s.number for s in scrape_serie.seasons_manager.seasons]}")
207
+ continue
208
208
  season_number = season.number
209
209
 
210
210
  if len(list_season_select) > 1 or index_season_selected == "*":
@@ -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, proxy: str) -> int:
31
+ def title_search(query: str) -> int:
32
32
  """
33
33
  Search for titles based on a search query.
34
34
 
@@ -49,7 +49,6 @@ def title_search(query: str, proxy: str) -> int:
49
49
  f"{site_constant.FULL_URL}/it",
50
50
  headers={'user-agent': get_userAgent()},
51
51
  timeout=max_timeout,
52
- proxy=proxy,
53
52
  follow_redirects=True
54
53
  )
55
54
  response.raise_for_status()
@@ -74,8 +73,7 @@ def title_search(query: str, proxy: str) -> int:
74
73
  'x-inertia': 'true',
75
74
  'x-inertia-version': version
76
75
  },
77
- timeout=max_timeout,
78
- proxy=proxy
76
+ timeout=max_timeout
79
77
  )
80
78
  response.raise_for_status()
81
79
 
@@ -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, proxy = None):
23
+ def __init__(self, url, media_id: int = None, series_name: str = None):
24
24
  """
25
25
  Initialize the GetSerieInfo class for scraping TV series information.
26
26
 
@@ -32,7 +32,6 @@ 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
36
35
  self.media_id = media_id
37
36
  self.seasons_manager = SeasonManager()
38
37
 
@@ -51,8 +50,7 @@ class GetSerieInfo:
51
50
  response = httpx.get(
52
51
  url=f"{self.url}/titles/{self.media_id}-{self.series_name}",
53
52
  headers=self.headers,
54
- timeout=max_timeout,
55
- proxy=self.proxy
53
+ timeout=max_timeout
56
54
  )
57
55
  response.raise_for_status()
58
56
 
@@ -106,8 +104,7 @@ class GetSerieInfo:
106
104
  'x-inertia': 'true',
107
105
  'x-inertia-version': self.version,
108
106
  },
109
- timeout=max_timeout,
110
- proxy=self.proxy
107
+ timeout=max_timeout
111
108
  )
112
109
 
113
110
  # Extract episodes from JSON response
@@ -7,7 +7,6 @@ from rich.prompt import Prompt
7
7
 
8
8
  # Internal utilities
9
9
  from StreamingCommunity.Api.Template import get_select_title
10
- from StreamingCommunity.Lib.Proxies.proxy import ProxyFinder
11
10
  from StreamingCommunity.Api.Template.config_loader import site_constant
12
11
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
13
12
 
@@ -27,7 +26,6 @@ _deprecate = False
27
26
 
28
27
  msg = Prompt()
29
28
  console = Console()
30
- proxy = None
31
29
 
32
30
 
33
31
  def get_user_input(string_to_search: str = None):
@@ -38,7 +36,7 @@ def get_user_input(string_to_search: str = None):
38
36
  string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
39
37
  return string_to_search
40
38
 
41
- def process_search_result(select_title, selections=None, proxy=None):
39
+ def process_search_result(select_title, selections=None):
42
40
  """
43
41
  Handles the search result and initiates the download for either a film or series.
44
42
 
@@ -55,10 +53,10 @@ def process_search_result(select_title, selections=None, proxy=None):
55
53
  season_selection = selections.get('season')
56
54
  episode_selection = selections.get('episode')
57
55
 
58
- download_series(select_title, season_selection, episode_selection, proxy)
56
+ download_series(select_title, season_selection, episode_selection)
59
57
 
60
58
  else:
61
- download_film(select_title, proxy)
59
+ download_film(select_title)
62
60
 
63
61
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
64
62
  """
@@ -73,20 +71,14 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
73
71
  """
74
72
  if direct_item:
75
73
  select_title = MediaItem(**direct_item)
76
- process_search_result(select_title, selections) # DONT SUPPORT PROXY FOR NOW
74
+ process_search_result(select_title, selections)
77
75
  return
78
76
 
79
- # Check proxy if not already set
80
- finder = ProxyFinder(site_constant.FULL_URL)
81
- proxy = finder.find_fast_proxy()
82
-
83
77
  if string_to_search is None:
84
78
  string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
85
79
 
86
80
  # Perform search on the database using the obtained query
87
- finder = ProxyFinder(url=f"{site_constant.FULL_URL}/serie/euphoria/")
88
- proxy = finder.find_fast_proxy()
89
- len_database = title_search(string_to_search, proxy)
81
+ len_database = title_search(string_to_search)
90
82
 
91
83
  # If only the database is needed, return the manager
92
84
  if get_onlyDatabase:
@@ -94,7 +86,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
94
86
 
95
87
  if len_database > 0:
96
88
  select_title = get_select_title(table_show_manager, media_search_manager,len_database)
97
- process_search_result(select_title, selections, proxy)
89
+ process_search_result(select_title, selections)
98
90
 
99
91
  else:
100
92
  # If no results are found, ask again
@@ -10,7 +10,6 @@ from rich.console import Console
10
10
  # Internal utilities
11
11
  from StreamingCommunity.Util.os import os_manager
12
12
  from StreamingCommunity.Util.message import start_message
13
- from StreamingCommunity.Lib.Downloader import HLS_Downloader
14
13
 
15
14
 
16
15
  # Logic class
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
19
18
 
20
19
 
21
20
  # Player
21
+ from StreamingCommunity import HLS_Downloader
22
22
  from StreamingCommunity.Api.Player.hdplayer import VideoSource
23
23
 
24
24
 
@@ -26,7 +26,7 @@ from StreamingCommunity.Api.Player.hdplayer import VideoSource
26
26
  console = Console()
27
27
 
28
28
 
29
- def download_film(select_title: MediaItem, proxy) -> str:
29
+ def download_film(select_title: MediaItem) -> str:
30
30
  """
31
31
  Downloads a film using the provided film ID, title name, and domain.
32
32
 
@@ -41,7 +41,7 @@ def download_film(select_title: MediaItem, proxy) -> str:
41
41
  console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
42
42
 
43
43
  # Get master playlists
44
- video_source = VideoSource(proxy)
44
+ video_source = VideoSource()
45
45
  master_playlist = video_source.get_m3u8_url(select_title.url)
46
46
 
47
47
  # Define the filename and path for the downloaded film