StreamingCommunity 3.3.9__py3-none-any.whl → 3.4.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 (60) hide show
  1. StreamingCommunity/Api/Player/hdplayer.py +0 -5
  2. StreamingCommunity/Api/Player/mediapolisvod.py +4 -13
  3. StreamingCommunity/Api/Player/supervideo.py +3 -8
  4. StreamingCommunity/Api/Player/sweetpixel.py +1 -9
  5. StreamingCommunity/Api/Player/vixcloud.py +5 -16
  6. StreamingCommunity/Api/Site/altadefinizione/film.py +4 -15
  7. StreamingCommunity/Api/Site/altadefinizione/site.py +2 -7
  8. StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +2 -7
  9. StreamingCommunity/Api/Site/animeunity/site.py +9 -24
  10. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +11 -27
  11. StreamingCommunity/Api/Site/animeworld/film.py +4 -2
  12. StreamingCommunity/Api/Site/animeworld/site.py +3 -11
  13. StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +1 -4
  14. StreamingCommunity/Api/Site/crunchyroll/film.py +4 -5
  15. StreamingCommunity/Api/Site/crunchyroll/series.py +2 -3
  16. StreamingCommunity/Api/Site/crunchyroll/site.py +2 -9
  17. StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +5 -27
  18. StreamingCommunity/Api/Site/crunchyroll/util/get_license.py +11 -26
  19. StreamingCommunity/Api/Site/guardaserie/site.py +4 -12
  20. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +3 -10
  21. StreamingCommunity/Api/Site/mediasetinfinity/film.py +11 -12
  22. StreamingCommunity/Api/Site/mediasetinfinity/series.py +1 -2
  23. StreamingCommunity/Api/Site/mediasetinfinity/site.py +3 -11
  24. StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +39 -50
  25. StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py +3 -3
  26. StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +7 -25
  27. StreamingCommunity/Api/Site/raiplay/film.py +6 -7
  28. StreamingCommunity/Api/Site/raiplay/series.py +0 -2
  29. StreamingCommunity/Api/Site/raiplay/site.py +3 -11
  30. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +4 -11
  31. StreamingCommunity/Api/Site/raiplay/util/get_license.py +3 -12
  32. StreamingCommunity/Api/Site/streamingcommunity/film.py +5 -16
  33. StreamingCommunity/Api/Site/streamingcommunity/site.py +3 -22
  34. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +11 -26
  35. StreamingCommunity/Api/Site/streamingwatch/__init__.py +1 -0
  36. StreamingCommunity/Api/Site/streamingwatch/film.py +4 -2
  37. StreamingCommunity/Api/Site/streamingwatch/series.py +1 -1
  38. StreamingCommunity/Api/Site/streamingwatch/site.py +4 -18
  39. StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +0 -3
  40. StreamingCommunity/Api/Template/config_loader.py +0 -7
  41. StreamingCommunity/Lib/Downloader/DASH/decrypt.py +54 -1
  42. StreamingCommunity/Lib/Downloader/DASH/downloader.py +131 -54
  43. StreamingCommunity/Lib/Downloader/DASH/parser.py +2 -3
  44. StreamingCommunity/Lib/Downloader/DASH/segments.py +66 -54
  45. StreamingCommunity/Lib/Downloader/HLS/downloader.py +31 -50
  46. StreamingCommunity/Lib/Downloader/HLS/segments.py +23 -28
  47. StreamingCommunity/Lib/FFmpeg/capture.py +37 -5
  48. StreamingCommunity/Lib/FFmpeg/command.py +32 -90
  49. StreamingCommunity/Lib/TMBD/tmdb.py +2 -4
  50. StreamingCommunity/TelegramHelp/config.json +0 -1
  51. StreamingCommunity/Upload/version.py +1 -1
  52. StreamingCommunity/Util/config_json.py +28 -21
  53. StreamingCommunity/Util/http_client.py +28 -0
  54. StreamingCommunity/Util/os.py +16 -6
  55. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/METADATA +1 -3
  56. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/RECORD +60 -60
  57. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/WHEEL +0 -0
  58. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/entry_points.txt +0 -0
  59. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/licenses/LICENSE +0 -0
  60. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/top_level.txt +0 -0
@@ -3,31 +3,18 @@
3
3
  import logging
4
4
 
5
5
 
6
- # External libraries
7
- from curl_cffi import requests
8
-
9
-
10
6
  # Internal utilities
11
- from StreamingCommunity.Util.config_json import config_manager
12
7
  from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
8
+ from StreamingCommunity.Util.http_client import create_client_curl
13
9
  from .get_license import CrunchyrollClient
14
10
 
15
11
 
16
- # Variable
17
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
18
-
19
-
20
12
  def get_series_seasons(series_id, headers, params):
21
13
  """
22
14
  Fetches the seasons for a given series ID from Crunchyroll.
23
15
  """
24
16
  url = f'https://www.crunchyroll.com/content/v2/cms/series/{series_id}/seasons'
25
- response = requests.get(
26
- url,
27
- params=params,
28
- headers=headers,
29
- impersonate="chrome136"
30
- )
17
+ response = create_client_curl(headers=headers).get(url, params=params)
31
18
  return response
32
19
 
33
20
 
@@ -36,12 +23,7 @@ def get_season_episodes(season_id, headers, params):
36
23
  Fetches the episodes for a given season ID from Crunchyroll.
37
24
  """
38
25
  url = f'https://www.crunchyroll.com/content/v2/cms/seasons/{season_id}/episodes'
39
- response = requests.get(
40
- url,
41
- params=params,
42
- headers=headers,
43
- impersonate="chrome136"
44
- )
26
+ response = create_client_curl(headers=headers).get(url, params=params)
45
27
  return response
46
28
 
47
29
 
@@ -137,12 +119,8 @@ class GetSerieInfo:
137
119
  'ratings': 'true',
138
120
  'locale': 'it-IT',
139
121
  }
140
- response = requests.get(
141
- url,
142
- params=params,
143
- headers=headers,
144
- impersonate="chrome136"
145
- )
122
+
123
+ response = create_client_curl(headers=headers).get(url, params=params)
146
124
 
147
125
  if response.status_code != 200:
148
126
  logging.warning(f"Failed to fetch audio locales for episode {episode_id}")
@@ -1,11 +1,11 @@
1
1
  # 28.07.25
2
2
 
3
3
  from typing import Tuple, List, Dict
4
- from curl_cffi import requests
5
4
 
6
5
 
7
6
  # Internal utilities
8
7
  from StreamingCommunity.Util.config_json import config_manager
8
+ from StreamingCommunity.Util.http_client import create_client_curl
9
9
  from StreamingCommunity.Util.headers import get_userAgent
10
10
 
11
11
 
@@ -44,17 +44,13 @@ class CrunchyrollClient:
44
44
  headers['authorization'] = f'Basic {PUBLIC_TOKEN}'
45
45
  headers['content-type'] = 'application/x-www-form-urlencoded'
46
46
 
47
- response = requests.post(
48
- 'https://www.crunchyroll.com/auth/v1/token',
49
- cookies=self._get_cookies(),
50
- headers=headers,
51
- data={
52
- 'device_id': self.device_id,
53
- 'device_type': 'Chrome on Windows',
54
- 'grant_type': 'etp_rt_cookie',
55
- },
56
- impersonate="chrome136"
57
- )
47
+ data = {
48
+ 'device_id': self.device_id,
49
+ 'device_type': 'Chrome on Windows',
50
+ 'grant_type': 'etp_rt_cookie',
51
+ }
52
+
53
+ response = create_client_curl(headers=headers).post('https://www.crunchyroll.com/auth/v1/token', cookies=self._get_cookies(), data=data)
58
54
 
59
55
  if response.status_code == 400:
60
56
  print("Error 400: Please enter a correct 'etp_rt' value in config.json. You can find the value in the request headers.")
@@ -69,14 +65,8 @@ class CrunchyrollClient:
69
65
 
70
66
  def get_streams(self, media_id: str) -> Dict:
71
67
  """Ottieni gli stream disponibili"""
72
- response = requests.get(
73
- f'https://www.crunchyroll.com/playback/v3/{media_id}/web/chrome/play',
74
- cookies=self._get_cookies(),
75
- headers=self._get_headers(),
76
- params={'locale': self.locale},
77
- impersonate="chrome136"
78
- )
79
-
68
+ response = create_client_curl(headers=self._get_headers()).get(f'https://www.crunchyroll.com/playback/v3/{media_id}/web/chrome/play', cookies=self._get_cookies(), params={'locale': self.locale})
69
+
80
70
  if response.status_code == 403:
81
71
  raise Exception("Playback is Rejected: The current subscription does not have access to this content")
82
72
 
@@ -94,12 +84,7 @@ class CrunchyrollClient:
94
84
 
95
85
  def delete_active_stream(self, media_id: str, token: str) -> bool:
96
86
  """Elimina uno stream attivo"""
97
- response = requests.delete(
98
- f'https://www.crunchyroll.com/playback/v1/token/{media_id}/{token}',
99
- cookies=self._get_cookies(),
100
- headers=self._get_headers(),
101
- impersonate="chrome136"
102
- )
87
+ response = create_client_curl(headers=self._get_headers()).delete(f'https://www.crunchyroll.com/playback/v1/token/{media_id}/{token}', cookies=self._get_cookies())
103
88
  response.raise_for_status()
104
89
  return response.status_code in [200, 204]
105
90
 
@@ -1,13 +1,14 @@
1
1
  # 09.06.24
2
2
 
3
+
3
4
  # External libraries
4
- import httpx
5
5
  from bs4 import BeautifulSoup
6
6
  from rich.console import Console
7
7
 
8
+
8
9
  # Internal utilities
9
- from StreamingCommunity.Util.config_json import config_manager
10
10
  from StreamingCommunity.Util.headers import get_userAgent
11
+ from StreamingCommunity.Util.http_client import create_client
11
12
  from StreamingCommunity.Util.table import TVShowManager
12
13
 
13
14
 
@@ -20,8 +21,6 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
20
21
  console = Console()
21
22
  media_search_manager = MediaManager()
22
23
  table_show_manager = TVShowManager()
23
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
24
-
25
24
 
26
25
 
27
26
  def title_search(query: str) -> int:
@@ -41,15 +40,8 @@ def title_search(query: str) -> int:
41
40
  console.print(f"[cyan]Search url: [yellow]{search_url}")
42
41
 
43
42
  try:
44
- response = httpx.get(
45
- search_url,
46
- headers={'user-agent': get_userAgent()},
47
- timeout=max_timeout,
48
- follow_redirects=True,
49
- verify=False
50
- )
43
+ response = create_client(headers={'user-agent': get_userAgent()}).get(search_url)
51
44
  response.raise_for_status()
52
-
53
45
  except Exception as e:
54
46
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
55
47
  return 0
@@ -5,22 +5,18 @@ from typing import List, Dict
5
5
 
6
6
 
7
7
  # External libraries
8
- import httpx
9
8
  from bs4 import BeautifulSoup
10
9
 
11
10
 
12
11
  # Internal utilities
13
12
  from StreamingCommunity.Util.headers import get_userAgent
14
- from StreamingCommunity.Util.config_json import config_manager
13
+ from StreamingCommunity.Util.http_client import create_client
15
14
 
16
15
 
17
16
  # Logic class
18
17
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
19
18
 
20
19
 
21
- # Variable
22
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
23
-
24
20
 
25
21
  class GetSerieInfo:
26
22
  def __init__(self, dict_serie: MediaItem) -> None:
@@ -43,8 +39,7 @@ class GetSerieInfo:
43
39
  int: Number of seasons of the TV series. Returns -1 if parsing fails.
44
40
  """
45
41
  try:
46
- # Make an HTTP request to the series URL
47
- response = httpx.get(self.url, headers=self.headers, timeout=max_timeout, follow_redirects=True)
42
+ response = create_client(headers=self.headers).get(self.url)
48
43
  response.raise_for_status()
49
44
 
50
45
  # Find the seasons container
@@ -72,9 +67,7 @@ class GetSerieInfo:
72
67
  List[Dict[str, str]]: List of dictionaries containing episode information.
73
68
  """
74
69
  try:
75
-
76
- # Make an HTTP request to the series URL
77
- response = httpx.get(self.url, headers=self.headers, timeout=max_timeout, follow_redirects=True)
70
+ response = create_client(headers=self.headers).get(self.url)
78
71
  response.raise_for_status()
79
72
 
80
73
  # Parse HTML content of the page
@@ -9,7 +9,8 @@ from rich.console import Console
9
9
 
10
10
 
11
11
  # Internal utilities
12
- from StreamingCommunity.Util.os import os_manager, get_wvd_path
12
+ from StreamingCommunity.Util.config_json import config_manager
13
+ from StreamingCommunity.Util.os import os_manager
13
14
  from StreamingCommunity.Util.message import start_message
14
15
  from StreamingCommunity.Util.headers import get_headers
15
16
 
@@ -22,11 +23,12 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
22
23
  # Player
23
24
  from .util.fix_mpd import get_manifest
24
25
  from StreamingCommunity import DASH_Downloader
25
- from .util.get_license import get_bearer_token, get_playback_url, get_tracking_info, generate_license_url
26
+ from .util.get_license import get_playback_url, get_tracking_info, generate_license_url
26
27
 
27
28
 
28
29
  # Variable
29
30
  console = Console()
31
+ extension_output = config_manager.get("M3U8_CONVERSION", "extension")
30
32
 
31
33
 
32
34
  def download_film(select_title: MediaItem) -> Tuple[str, bool]:
@@ -43,21 +45,18 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
43
45
  console.print(f"\n[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
44
46
 
45
47
  # Define the filename and path for the downloaded film
46
- title_name = os_manager.get_sanitize_file(select_title.name) + ".mp4"
47
- mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(".mp4", ""))
48
+ title_name = os_manager.get_sanitize_file(select_title.name, select_title.date) + extension_output
49
+ mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(extension_output, ""))
48
50
 
49
- # Generate mpd and license URLs
50
- bearer = get_bearer_token()
51
+ # Get playback URL and tracking info
52
+ playback_json = get_playback_url(select_title.id)
53
+ tracking_info = get_tracking_info(playback_json)['videos'][0]
51
54
 
52
- playback_json = get_playback_url(bearer, select_title.id)
53
- tracking_info = get_tracking_info(bearer, playback_json)[0]
54
-
55
- license_url = generate_license_url(bearer, tracking_info)
56
- mpd_url = get_manifest(tracking_info['video_src'])
55
+ license_url = generate_license_url(tracking_info)
56
+ mpd_url = get_manifest(tracking_info['url'])
57
57
 
58
58
  # Download the episode
59
59
  dash_process = DASH_Downloader(
60
- cdm_device=get_wvd_path(),
61
60
  license_url=license_url,
62
61
  mpd_url=mpd_url,
63
62
  output_path=os.path.join(mp4_path, title_name),
@@ -12,7 +12,7 @@ from rich.prompt import Prompt
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.headers import get_headers
14
14
  from StreamingCommunity.Util.message import start_message
15
- from StreamingCommunity.Util.os import os_manager, get_wvd_path
15
+ from StreamingCommunity.Util.os import os_manager
16
16
 
17
17
 
18
18
  # Logic class
@@ -70,7 +70,6 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
70
70
 
71
71
  # Download the episode
72
72
  dash_process = DASH_Downloader(
73
- cdm_device=get_wvd_path(),
74
73
  license_url=license_url,
75
74
  mpd_url=mpd_url,
76
75
  mpd_sub_list=tracking_info['subtitles'],
@@ -4,12 +4,11 @@ from datetime import datetime
4
4
 
5
5
 
6
6
  # External libraries
7
- import httpx
8
7
  from rich.console import Console
9
8
 
10
9
 
11
10
  # Internal utilities
12
- from StreamingCommunity.Util.config_json import config_manager
11
+ from StreamingCommunity.Util.http_client import create_client
13
12
  from StreamingCommunity.Util.table import TVShowManager
14
13
  from StreamingCommunity.Api.Template.config_loader import site_constant
15
14
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
@@ -23,7 +22,6 @@ from .util.get_license import get_bearer_token
23
22
  console = Console()
24
23
  media_search_manager = MediaManager()
25
24
  table_show_manager = TVShowManager()
26
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
27
25
 
28
26
 
29
27
  def title_search(query: str) -> int:
@@ -46,15 +44,9 @@ def title_search(query: str) -> int:
46
44
  'extensions': f'{{"persistedQuery":{{"version":1,"sha256Hash":"{class_mediaset_api.getHash256()}"}}}}',
47
45
  'variables': f'{{"first":10,"property":"search","query":"{query}","uxReference":"filteredSearch"}}',
48
46
  }
47
+
49
48
  try:
50
- response = httpx.get(
51
- search_url,
52
- headers=class_mediaset_api.generate_request_headers(),
53
- params=params,
54
- timeout=max_timeout,
55
- follow_redirects=True
56
- )
57
-
49
+ response = create_client(headers=class_mediaset_api.generate_request_headers()).get(search_url, params=params)
58
50
  response.raise_for_status()
59
51
  except Exception as e:
60
52
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
@@ -5,18 +5,14 @@ from urllib.parse import urlparse
5
5
 
6
6
 
7
7
  # External libraries
8
- import httpx
9
8
  from bs4 import BeautifulSoup
10
9
 
11
10
 
12
11
  # Internal utilities
13
- from StreamingCommunity.Util.config_json import config_manager
14
12
  from StreamingCommunity.Util.headers import get_headers, get_userAgent
13
+ from StreamingCommunity.Util.http_client import create_client
15
14
  from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
16
15
 
17
- # Variable
18
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
19
-
20
16
 
21
17
  class GetSerieInfo:
22
18
  def __init__(self, url):
@@ -46,20 +42,14 @@ class GetSerieInfo:
46
42
 
47
43
  def _get_series_data(self):
48
44
  """Get series data through the API"""
49
- headers = {'User-Agent': get_userAgent()}
50
- params = {'byGuid': self.serie_id}
51
-
52
- with httpx.Client(timeout=max_timeout, follow_redirects=True) as client:
53
- response = client.get(
54
- f'https://feed.entertainment.tv.theplatform.eu/f/{self.public_id}/mediaset-prod-all-series-v2',
55
- params=params,
56
- headers=headers
57
- )
58
-
59
- if response.status_code == 200:
45
+ try:
46
+ params = {'byGuid': self.serie_id}
47
+ response = create_client(headers=self.headers).get(f'https://feed.entertainment.tv.theplatform.eu/f/{self.public_id}/mediaset-prod-all-series-v2', params=params)
48
+ response.raise_for_status()
60
49
  return response.json()
61
- else:
62
- logging.error(f"Failed to get series data: {response.status_code}")
50
+
51
+ except Exception as e:
52
+ logging.error(f"Failed to get series data with error: {e}")
63
53
  return None
64
54
 
65
55
  def _process_available_seasons(self, data):
@@ -106,32 +96,30 @@ class GetSerieInfo:
106
96
 
107
97
  def _extract_season_sb_ids(self, stagioni_disponibili):
108
98
  """Extract sb IDs from season pages"""
109
- with httpx.Client(timeout=max_timeout, follow_redirects=True) as client:
110
- for season in stagioni_disponibili:
111
- response_page = client.get(
112
- season['page_url'],
113
- headers={'User-Agent': get_userAgent()}
114
- )
115
-
116
- print("Response for _extract_season_sb_ids:", response_page.status_code, " season index:", season['tvSeasonNumber'])
117
- soup = BeautifulSoup(response_page.text, 'html.parser')
118
-
119
- # Try first with 'Episodi', then with 'Puntate intere'
120
- link = soup.find('a', string='Episodi')
121
- if not link:
122
- #print("Using word: Puntate intere")
123
- link = soup.find('a', string='Puntate intere')
124
-
125
- if link is None:
126
- link = soup.find('a', class_ = 'titleCarousel')
127
-
128
- if link and link.has_attr('href'):
129
- if not link.string == 'Puntate intere':
130
- print("Using word: Episodi")
131
-
132
- season['sb'] = link['href'].split(',')[-1]
133
- else:
134
- logging.warning(f"Link 'Episodi' or 'Puntate intere' not found for season {season['tvSeasonNumber']}")
99
+ client = create_client()
100
+
101
+ for season in stagioni_disponibili:
102
+ response_page = client.get(season['page_url'], headers={'User-Agent': get_userAgent()})
103
+
104
+ print("Response for _extract_season_sb_ids:", response_page.status_code, " season index:", season['tvSeasonNumber'])
105
+ soup = BeautifulSoup(response_page.text, 'html.parser')
106
+
107
+ # Try first with 'Episodi', then with 'Puntate intere'
108
+ link = soup.find('a', string='Episodi')
109
+ if not link:
110
+ #print("Using word: Puntate intere")
111
+ link = soup.find('a', string='Puntate intere')
112
+
113
+ if link is None:
114
+ link = soup.find('a', class_ = 'titleCarousel')
115
+
116
+ if link and link.has_attr('href'):
117
+ if not link.string == 'Puntate intere':
118
+ print("Using word: Episodi")
119
+
120
+ season['sb'] = link['href'].split(',')[-1]
121
+ else:
122
+ logging.warning(f"Link 'Episodi' or 'Puntate intere' not found for season {season['tvSeasonNumber']}")
135
123
 
136
124
  def _get_season_episodes(self, season):
137
125
  """Get episodes for a specific season"""
@@ -147,11 +135,11 @@ class GetSerieInfo:
147
135
  'range': '0-100',
148
136
  }
149
137
  episode_url = f"https://feed.entertainment.tv.theplatform.eu/f/{self.public_id}/mediaset-prod-all-programs-v2"
150
-
151
- with httpx.Client(timeout=max_timeout, follow_redirects=True) as client:
152
- episode_response = client.get(episode_url, headers=episode_headers, params=params)
153
138
 
154
- if episode_response.status_code == 200:
139
+ try:
140
+ episode_response = create_client(headers=episode_headers).get(episode_url, params=params)
141
+ episode_response.raise_for_status()
142
+
155
143
  episode_data = episode_response.json()
156
144
  season['episodes'] = []
157
145
 
@@ -166,8 +154,9 @@ class GetSerieInfo:
166
154
  season['episodes'].append(episode_info)
167
155
 
168
156
  print(f"Found {len(season['episodes'])} episodes for season {season['tvSeasonNumber']}")
169
- else:
170
- logging.error(f"Failed to get episodes for season {season['tvSeasonNumber']}: {episode_response.status_code}")
157
+
158
+ except Exception as e:
159
+ logging.error(f"Failed to get episodes for season {season['tvSeasonNumber']} with error: {e}")
171
160
 
172
161
  def collect_season(self) -> None:
173
162
  """
@@ -3,8 +3,8 @@
3
3
  from urllib.parse import urlparse, urlunparse
4
4
 
5
5
 
6
- # External library
7
- import httpx
6
+ # Internal utilities
7
+ from StreamingCommunity.Util.http_client import create_client
8
8
 
9
9
 
10
10
  def try_mpd(url, qualities):
@@ -42,7 +42,7 @@ def try_mpd(url, qualities):
42
42
  mpd_url = urlunparse(parsed._replace(path=new_path)).strip()
43
43
 
44
44
  try:
45
- r = httpx.head(mpd_url, timeout=5)
45
+ r = create_client().head(mpd_url)
46
46
  if r.status_code == 200:
47
47
  return mpd_url
48
48
 
@@ -7,19 +7,17 @@ import xml.etree.ElementTree as ET
7
7
 
8
8
 
9
9
  # External library
10
- import httpx
11
10
  from bs4 import BeautifulSoup
12
11
  from rich.console import Console
13
12
 
14
13
 
15
14
  # Internal utilities
16
- from StreamingCommunity.Util.config_json import config_manager
15
+ from StreamingCommunity.Util.http_client import create_client
17
16
  from StreamingCommunity.Util.headers import get_headers, get_userAgent
18
17
 
19
18
 
20
19
  # Variable
21
20
  console = Console()
22
- MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
23
21
  network_data = []
24
22
  class_mediaset_api = None
25
23
 
@@ -51,17 +49,13 @@ class MediasetAPI:
51
49
  'appName': self.app_name,
52
50
  'client_id': self.client_id,
53
51
  }
54
- response = httpx.post(
55
- 'https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0',
56
- headers=self.headers,
57
- json=json_data,
58
- )
52
+ response = create_client(headers=self.headers).post('https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0', json=json_data)
59
53
  return response.json()['response']['beToken']
60
54
 
61
55
  def fetch_html(self, timeout=10):
62
- r = httpx.get("https://mediasetinfinity.mediaset.it/", timeout=timeout, headers=self.headers)
63
- r.raise_for_status()
64
- return r.text
56
+ response = create_client(headers=self.headers).get("https://mediasetinfinity.mediaset.it/")
57
+ response.raise_for_status()
58
+ return response.text
65
59
 
66
60
  def find_relevant_script(self, html):
67
61
  soup = BeautifulSoup(html, "html.parser")
@@ -124,13 +118,7 @@ def get_playback_url(CONTENT_ID):
124
118
  }
125
119
 
126
120
  try:
127
- response = httpx.post(
128
- 'https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0',
129
- headers=headers,
130
- json=json_data,
131
- follow_redirects=True,
132
- timeout=MAX_TIMEOUT
133
- )
121
+ response = create_client(headers=headers).post('https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0', json=json_data)
134
122
  response.raise_for_status()
135
123
  resp_json = response.json()
136
124
 
@@ -255,13 +243,7 @@ def get_tracking_info(PLAYBACK_JSON):
255
243
  params['publicUrl'] = PLAYBACK_JSON['publicUrl']
256
244
 
257
245
  try:
258
- response = httpx.get(
259
- PLAYBACK_JSON['url'],
260
- headers={'user-agent': get_userAgent()},
261
- params=params,
262
- follow_redirects=True,
263
- timeout=MAX_TIMEOUT
264
- )
246
+ response = create_client(headers={'user-agent': get_userAgent()}).get(PLAYBACK_JSON['url'], params=params)
265
247
  response.raise_for_status()
266
248
 
267
249
  results = parse_smil_for_media_info(response.text)
@@ -5,17 +5,16 @@ from typing import Tuple
5
5
 
6
6
 
7
7
  # External library
8
- import httpx
9
8
  from rich.console import Console
10
9
 
11
10
 
12
11
  # Internal utilities
13
12
  from StreamingCommunity.Util.os import os_manager
13
+ from StreamingCommunity.Util.config_json import config_manager
14
14
  from StreamingCommunity.Util.headers import get_headers
15
- from StreamingCommunity.Util.os import get_wvd_path
15
+ from StreamingCommunity.Util.http_client import create_client
16
16
  from StreamingCommunity.Util.message import start_message
17
17
 
18
-
19
18
  # Logic class
20
19
  from .util.get_license import generate_license_url
21
20
  from StreamingCommunity.Api.Template.config_loader import site_constant
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
29
28
 
30
29
  # Variable
31
30
  console = Console()
31
+ extension_output = config_manager.get("M3U8_CONVERSION", "extension")
32
32
 
33
33
 
34
34
  def download_film(select_title: MediaItem) -> Tuple[str, bool]:
@@ -46,13 +46,13 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
46
46
  console.print(f"\n[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
47
47
 
48
48
  # Extract m3u8 URL from the film's URL
49
- response = httpx.get(select_title.url + ".json", headers=get_headers(), timeout=10)
49
+ response = create_client(headers=get_headers()).get(select_title.url + ".json")
50
50
  first_item_path = "https://www.raiplay.it" + response.json().get("first_item_path")
51
51
  master_playlist = VideoSource.extract_m3u8_url(first_item_path)
52
52
 
53
53
  # Define the filename and path for the downloaded film
54
- mp4_name = os_manager.get_sanitize_file(select_title.name) + ".mp4"
55
- mp4_path = os.path.join(site_constant.MOVIE_FOLDER, mp4_name.replace(".mp4", ""))
54
+ mp4_name = os_manager.get_sanitize_file(select_title.name, select_title.date) + extension_output
55
+ mp4_path = os.path.join(site_constant.MOVIE_FOLDER, mp4_name.replace(extension_output, ""))
56
56
 
57
57
  # HLS
58
58
  if ".mpd" not in master_playlist:
@@ -66,7 +66,6 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
66
66
  license_url = generate_license_url(select_title.mpd_id)
67
67
 
68
68
  dash_process = DASH_Downloader(
69
- cdm_device=get_wvd_path(),
70
69
  license_url=license_url,
71
70
  mpd_url=master_playlist,
72
71
  output_path=os.path.join(mp4_path, mp4_name),
@@ -11,7 +11,6 @@ from rich.prompt import Prompt
11
11
 
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.headers import get_headers, get_userAgent
14
- from StreamingCommunity.Util.os import get_wvd_path
15
14
  from StreamingCommunity.Util.message import start_message
16
15
 
17
16
 
@@ -91,7 +90,6 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
91
90
  }
92
91
 
93
92
  dash_process = DASH_Downloader(
94
- cdm_device=get_wvd_path(),
95
93
  license_url=full_license_url.split("?")[0],
96
94
  mpd_url=master_playlist,
97
95
  output_path=os.path.join(mp4_path, mp4_name),
@@ -1,13 +1,12 @@
1
1
  # 21.05.24
2
2
 
3
3
  # External libraries
4
- import httpx
5
4
  from rich.console import Console
6
5
 
7
6
 
8
7
  # Internal utilities
9
- from StreamingCommunity.Util.config_json import config_manager
10
- from StreamingCommunity.Util.headers import get_userAgent
8
+ from StreamingCommunity.Util.headers import get_headers
9
+ from StreamingCommunity.Util.http_client import create_client
11
10
  from StreamingCommunity.Util.table import TVShowManager
12
11
  from StreamingCommunity.Api.Template.config_loader import site_constant
13
12
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
@@ -21,7 +20,6 @@ from .util.ScrapeSerie import GetSerieInfo
21
20
  console = Console()
22
21
  media_search_manager = MediaManager()
23
22
  table_show_manager = TVShowManager()
24
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
25
23
 
26
24
 
27
25
  def determine_media_type(item):
@@ -67,13 +65,7 @@ def title_search(query: str) -> int:
67
65
  }
68
66
 
69
67
  try:
70
- response = httpx.post(
71
- search_url,
72
- headers={'user-agent': get_userAgent()},
73
- json=json_data,
74
- timeout=max_timeout,
75
- follow_redirects=True
76
- )
68
+ response = create_client(headers=get_headers()).post(search_url, json=json_data)
77
69
  response.raise_for_status()
78
70
 
79
71
  except Exception as e: