StreamingCommunity 3.3.9__py3-none-any.whl → 3.4.2__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 (70) 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 -16
  7. StreamingCommunity/Api/Site/altadefinizione/series.py +3 -12
  8. StreamingCommunity/Api/Site/altadefinizione/site.py +2 -9
  9. StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +2 -7
  10. StreamingCommunity/Api/Site/animeunity/site.py +9 -24
  11. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +11 -27
  12. StreamingCommunity/Api/Site/animeworld/film.py +4 -2
  13. StreamingCommunity/Api/Site/animeworld/site.py +3 -11
  14. StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +1 -4
  15. StreamingCommunity/Api/Site/crunchyroll/film.py +4 -5
  16. StreamingCommunity/Api/Site/crunchyroll/series.py +5 -17
  17. StreamingCommunity/Api/Site/crunchyroll/site.py +4 -13
  18. StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +5 -27
  19. StreamingCommunity/Api/Site/crunchyroll/util/get_license.py +11 -26
  20. StreamingCommunity/Api/Site/guardaserie/series.py +3 -14
  21. StreamingCommunity/Api/Site/guardaserie/site.py +4 -12
  22. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +3 -10
  23. StreamingCommunity/Api/Site/mediasetinfinity/film.py +11 -12
  24. StreamingCommunity/Api/Site/mediasetinfinity/series.py +4 -15
  25. StreamingCommunity/Api/Site/mediasetinfinity/site.py +16 -32
  26. StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +39 -50
  27. StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py +3 -3
  28. StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +7 -25
  29. StreamingCommunity/Api/Site/raiplay/film.py +6 -8
  30. StreamingCommunity/Api/Site/raiplay/series.py +5 -20
  31. StreamingCommunity/Api/Site/raiplay/site.py +45 -47
  32. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +91 -55
  33. StreamingCommunity/Api/Site/raiplay/util/get_license.py +3 -12
  34. StreamingCommunity/Api/Site/streamingcommunity/film.py +5 -16
  35. StreamingCommunity/Api/Site/streamingcommunity/series.py +5 -10
  36. StreamingCommunity/Api/Site/streamingcommunity/site.py +3 -22
  37. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +11 -27
  38. StreamingCommunity/Api/Site/streamingwatch/__init__.py +1 -0
  39. StreamingCommunity/Api/Site/streamingwatch/film.py +4 -2
  40. StreamingCommunity/Api/Site/streamingwatch/series.py +4 -14
  41. StreamingCommunity/Api/Site/streamingwatch/site.py +4 -18
  42. StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +0 -3
  43. StreamingCommunity/Api/Template/Util/__init__.py +4 -2
  44. StreamingCommunity/Api/Template/Util/manage_ep.py +66 -0
  45. StreamingCommunity/Api/Template/config_loader.py +0 -7
  46. StreamingCommunity/Lib/Downloader/DASH/decrypt.py +54 -1
  47. StreamingCommunity/Lib/Downloader/DASH/downloader.py +186 -70
  48. StreamingCommunity/Lib/Downloader/DASH/parser.py +2 -3
  49. StreamingCommunity/Lib/Downloader/DASH/segments.py +109 -68
  50. StreamingCommunity/Lib/Downloader/HLS/downloader.py +100 -82
  51. StreamingCommunity/Lib/Downloader/HLS/segments.py +40 -28
  52. StreamingCommunity/Lib/Downloader/MP4/downloader.py +16 -4
  53. StreamingCommunity/Lib/FFmpeg/capture.py +37 -5
  54. StreamingCommunity/Lib/FFmpeg/command.py +32 -90
  55. StreamingCommunity/Lib/M3U8/estimator.py +47 -1
  56. StreamingCommunity/Lib/TMBD/tmdb.py +2 -4
  57. StreamingCommunity/TelegramHelp/config.json +0 -1
  58. StreamingCommunity/Upload/update.py +19 -6
  59. StreamingCommunity/Upload/version.py +1 -1
  60. StreamingCommunity/Util/config_json.py +28 -21
  61. StreamingCommunity/Util/http_client.py +28 -0
  62. StreamingCommunity/Util/os.py +16 -6
  63. StreamingCommunity/Util/table.py +50 -8
  64. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.2.dist-info}/METADATA +1 -3
  65. streamingcommunity-3.4.2.dist-info/RECORD +111 -0
  66. streamingcommunity-3.3.9.dist-info/RECORD +0 -111
  67. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.2.dist-info}/WHEEL +0 -0
  68. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.2.dist-info}/entry_points.txt +0 -0
  69. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.2.dist-info}/licenses/LICENSE +0 -0
  70. {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.2.dist-info}/top_level.txt +0 -0
@@ -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),
@@ -79,7 +78,6 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
79
78
  # Get final output path and status
80
79
  r_proc = dash_process.get_status()
81
80
 
82
-
83
81
  if r_proc['error'] is not None:
84
82
  try:
85
83
  os.remove(r_proc['path'])
@@ -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
 
@@ -24,7 +23,8 @@ from StreamingCommunity.Api.Template.Util import (
24
23
  map_episode_title,
25
24
  validate_selection,
26
25
  validate_episode_selection,
27
- display_episodes_list
26
+ display_episodes_list,
27
+ display_seasons_list
28
28
  )
29
29
  from StreamingCommunity.Api.Template.config_loader import site_constant
30
30
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
@@ -72,17 +72,8 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
72
72
  m3u8_url=master_playlist,
73
73
  output_path=os.path.join(mp4_path, mp4_name)
74
74
  ).start()
75
- # Get streaming URL
76
- master_playlist = VideoSource.extract_m3u8_url(obj_episode.url)
77
75
 
78
- # HLS
79
- if ".mpd" not in master_playlist:
80
- r_proc = HLS_Downloader(
81
- m3u8_url=master_playlist,
82
- output_path=os.path.join(mp4_path, mp4_name)
83
- ).start()
84
-
85
- # MPD
76
+ # MPD (DASH)
86
77
  else:
87
78
  full_license_url = generate_license_url(obj_episode.mpd_id)
88
79
  license_headers = {
@@ -91,7 +82,6 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
91
82
  }
92
83
 
93
84
  dash_process = DASH_Downloader(
94
- cdm_device=get_wvd_path(),
95
85
  license_url=full_license_url.split("?")[0],
96
86
  mpd_url=master_playlist,
97
87
  output_path=os.path.join(mp4_path, mp4_name),
@@ -171,15 +161,10 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis
171
161
  # Get seasons info
172
162
  scrape_serie.collect_info_title()
173
163
  seasons_count = len(scrape_serie.seasons_manager)
174
- console.print(f"\n[green]Seasons found: [red]{seasons_count}")
175
164
 
176
165
  # If season_selection is provided, use it instead of asking for input
177
166
  if season_selection is None:
178
- index_season_selected = msg.ask(
179
- "\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
180
- "[yellow](e.g., 1-2) [cyan]for a range of seasons, or [yellow](e.g., 3-*) [cyan]to download from a specific season to the end"
181
- )
182
-
167
+ index_season_selected = display_seasons_list(scrape_serie.seasons_manager)
183
168
  else:
184
169
  index_season_selected = season_selection
185
170
  console.print(f"\n[cyan]Using provided season selection: [yellow]{season_selection}")
@@ -193,4 +178,4 @@ def download_series(select_season: MediaItem, season_selection: str = None, epis
193
178
  if len(list_season_select) > 1 or index_season_selected == "*":
194
179
  download_episode(season_number, scrape_serie, download_all=True)
195
180
  else:
196
- download_episode(season_number, scrape_serie, download_all=False, episode_selection=episode_selection)
181
+ download_episode(season_number, scrape_serie, download_all=False, episode_selection=episode_selection)
@@ -1,42 +1,21 @@
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
14
13
 
15
14
 
16
- # Logic Import
17
- from .util.ScrapeSerie import GetSerieInfo
18
-
19
-
20
15
  # Variable
21
16
  console = Console()
22
17
  media_search_manager = MediaManager()
23
18
  table_show_manager = TVShowManager()
24
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
25
-
26
-
27
- def determine_media_type(item):
28
- """
29
- Determine if the item is a film or TV series by checking actual seasons count
30
- using GetSerieInfo.
31
- """
32
- try:
33
- scraper = GetSerieInfo(item.get('path_id'))
34
- scraper.collect_info_title()
35
- return scraper.prog_tipology, scraper.prog_description, scraper.prog_year
36
-
37
- except Exception as e:
38
- console.print(f"[red]Error determining media type: {e}[/red]")
39
- return None, None, None
40
19
 
41
20
 
42
21
  def title_search(query: str) -> int:
@@ -67,37 +46,56 @@ def title_search(query: str) -> int:
67
46
  }
68
47
 
69
48
  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
- )
49
+ response = create_client(headers=get_headers()).post(search_url, json=json_data)
77
50
  response.raise_for_status()
78
51
 
79
52
  except Exception as e:
80
53
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
81
54
  return 0
82
55
 
83
- # Limit to only 15 results for performance
84
- data = response.json().get('agg').get('titoli').get('cards')[:15]
56
+ try:
57
+ response_data = response.json()
58
+ cards = response_data.get('agg', {}).get('titoli', {}).get('cards', [])
59
+
60
+ # Limit to only 15 results for performance
61
+ data = cards[:15]
62
+ console.print(f"[cyan]Found {len(cards)} results, processing first {len(data)}...[/cyan]")
63
+
64
+ except Exception as e:
65
+ console.print(f"[red]Error parsing search results: {e}[/red]")
66
+ return 0
85
67
 
86
68
  # Process each item and add to media manager
87
- for item in data:
88
- media_type, prog_description, prog_year = determine_media_type(item)
89
- if media_type is None:
69
+ for idx, item in enumerate(data, 1):
70
+ try:
71
+ # Get path_id
72
+ path_id = item.get('path_id', '')
73
+ if not path_id:
74
+ console.print("[yellow]Skipping item due to missing path_id[/yellow]")
75
+ continue
76
+
77
+ # Get image URL - handle both relative and absolute URLs
78
+ image = item.get('immagine', '')
79
+ if image and not image.startswith('http'):
80
+ image = f"https://www.raiplay.it{image}"
81
+
82
+ # Get URL - handle both relative and absolute URLs
83
+ url = item.get('url', '')
84
+ if url and not url.startswith('http'):
85
+ url = f"https://www.raiplay.it{url}"
86
+
87
+ media_search_manager.add_media({
88
+ 'id': item.get('id', ''),
89
+ 'name': item.get('titolo', 'Unknown'),
90
+ 'type': "tv",
91
+ 'path_id': path_id,
92
+ 'url': url,
93
+ 'image': image,
94
+ 'year': image.split("/")[5]
95
+ })
96
+
97
+ except Exception as e:
98
+ console.print(f"[red]Error processing item '{item.get('titolo', 'Unknown')}': {e}[/red]")
90
99
  continue
91
-
92
- media_search_manager.add_media({
93
- 'id': item.get('id', ''),
94
- 'name': item.get('titolo', ''),
95
- 'type': media_type,
96
- 'path_id': item.get('path_id', ''),
97
- 'url': f"https://www.raiplay.it{item.get('url', '')}",
98
- 'image': f"https://www.raiplay.it{item.get('immagine', '')}",
99
- 'desc': prog_description,
100
- 'year': prog_year
101
- })
102
-
100
+
103
101
  return media_search_manager.get_length()