StreamingCommunity 2.9.7__py3-none-any.whl → 2.9.9__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 (61) hide show
  1. StreamingCommunity/Api/Player/ddl.py +2 -10
  2. StreamingCommunity/Api/Player/mediapolisvod.py +64 -0
  3. StreamingCommunity/Api/Player/sweetpixel.py +3 -3
  4. StreamingCommunity/Api/Player/vixcloud.py +4 -9
  5. StreamingCommunity/Api/Site/1337xx/__init__.py +1 -1
  6. StreamingCommunity/Api/Site/altadefinizione/__init__.py +23 -7
  7. StreamingCommunity/Api/Site/altadefinizione/film.py +0 -1
  8. StreamingCommunity/Api/Site/altadefinizione/series.py +66 -70
  9. StreamingCommunity/Api/Site/altadefinizione/site.py +2 -1
  10. StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +37 -2
  11. StreamingCommunity/Api/Site/animeunity/__init__.py +29 -10
  12. StreamingCommunity/Api/Site/animeunity/film.py +40 -0
  13. StreamingCommunity/Api/Site/animeunity/serie.py +153 -0
  14. StreamingCommunity/Api/Site/animeunity/site.py +1 -2
  15. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +15 -0
  16. StreamingCommunity/Api/Site/animeworld/__init__.py +25 -12
  17. StreamingCommunity/Api/Site/animeworld/film.py +63 -0
  18. StreamingCommunity/Api/Site/animeworld/serie.py +25 -22
  19. StreamingCommunity/Api/Site/animeworld/site.py +2 -1
  20. StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +32 -5
  21. StreamingCommunity/Api/Site/cb01new/__init__.py +1 -1
  22. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +1 -1
  23. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +31 -32
  24. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +2 -2
  25. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +30 -2
  26. StreamingCommunity/Api/Site/guardaserie/__init__.py +21 -7
  27. StreamingCommunity/Api/Site/guardaserie/series.py +55 -53
  28. StreamingCommunity/Api/Site/guardaserie/site.py +3 -2
  29. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +27 -1
  30. StreamingCommunity/Api/Site/raiplay/__init__.py +93 -0
  31. StreamingCommunity/Api/Site/raiplay/film.py +65 -0
  32. StreamingCommunity/Api/Site/raiplay/series.py +162 -0
  33. StreamingCommunity/Api/Site/raiplay/site.py +166 -0
  34. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +127 -0
  35. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +29 -22
  36. StreamingCommunity/Api/Site/streamingcommunity/film.py +1 -2
  37. StreamingCommunity/Api/Site/streamingcommunity/series.py +76 -90
  38. StreamingCommunity/Api/Site/streamingcommunity/site.py +1 -3
  39. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +41 -15
  40. StreamingCommunity/Api/Template/site.py +2 -2
  41. StreamingCommunity/Lib/Downloader/HLS/downloader.py +1 -1
  42. StreamingCommunity/Lib/Downloader/HLS/segments.py +2 -3
  43. StreamingCommunity/Lib/Downloader/MP4/downloader.py +2 -1
  44. StreamingCommunity/Lib/FFmpeg/util.py +47 -17
  45. StreamingCommunity/Lib/M3U8/estimator.py +50 -21
  46. StreamingCommunity/Lib/M3U8/parser.py +26 -6
  47. StreamingCommunity/Upload/update.py +22 -3
  48. StreamingCommunity/Upload/version.py +1 -1
  49. StreamingCommunity/Util/config_json.py +425 -274
  50. StreamingCommunity/Util/table.py +4 -2
  51. StreamingCommunity/run.py +1 -1
  52. {streamingcommunity-2.9.7.dist-info → streamingcommunity-2.9.9.dist-info}/METADATA +1 -1
  53. streamingcommunity-2.9.9.dist-info/RECORD +91 -0
  54. {streamingcommunity-2.9.7.dist-info → streamingcommunity-2.9.9.dist-info}/WHEEL +1 -1
  55. StreamingCommunity/Api/Site/animeunity/film_serie.py +0 -181
  56. StreamingCommunity/Api/Site/mostraguarda/__init__.py +0 -73
  57. StreamingCommunity/Api/Site/mostraguarda/film.py +0 -93
  58. streamingcommunity-2.9.7.dist-info/RECORD +0 -85
  59. {streamingcommunity-2.9.7.dist-info → streamingcommunity-2.9.9.dist-info}/entry_points.txt +0 -0
  60. {streamingcommunity-2.9.7.dist-info → streamingcommunity-2.9.9.dist-info}/licenses/LICENSE +0 -0
  61. {streamingcommunity-2.9.7.dist-info → streamingcommunity-2.9.9.dist-info}/top_level.txt +0 -0
@@ -18,21 +18,13 @@ max_timeout = config_manager.get_int("REQUESTS", "timeout")
18
18
 
19
19
 
20
20
  class VideoSource:
21
- def __init__(self, cookie) -> None:
21
+ def __init__(self, url, cookie) -> None:
22
22
  """
23
23
  Initializes the VideoSource object with default values.
24
24
  """
25
25
  self.headers = {'user-agent': get_userAgent()}
26
- self.cookie = cookie
27
-
28
- def setup(self, url: str) -> None:
29
- """
30
- Sets up the video source with the provided URL.
31
-
32
- Parameters:
33
- - url (str): The URL of the video source.
34
- """
35
26
  self.url = url
27
+ self.cookie = cookie
36
28
 
37
29
  def make_request(self, url: str) -> str:
38
30
  """
@@ -0,0 +1,64 @@
1
+ # 11.04.25
2
+
3
+
4
+ # External libraries
5
+ import httpx
6
+
7
+
8
+ # Internal utilities
9
+ from StreamingCommunity.Util.config_json import config_manager
10
+ from StreamingCommunity.Util.headers import get_headers
11
+
12
+
13
+ # Variable
14
+ MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
15
+
16
+
17
+ class VideoSource:
18
+
19
+ @staticmethod
20
+ def extract_m3u8_url(video_url: str) -> str:
21
+ """Extract the m3u8 streaming URL from a RaiPlay video URL."""
22
+ if not video_url.endswith('.json'):
23
+ if '/video/' in video_url:
24
+ video_id = video_url.split('/')[-1].split('.')[0]
25
+ video_path = '/'.join(video_url.split('/')[:-1])
26
+ video_url = f"{video_path}/{video_id}.json"
27
+
28
+ else:
29
+ return "Error: Unable to determine video JSON URL"
30
+
31
+ try:
32
+ response = httpx.get(video_url, headers=get_headers(), timeout=MAX_TIMEOUT)
33
+ if response.status_code != 200:
34
+ return f"Error: Failed to fetch video data (Status: {response.status_code})"
35
+
36
+ video_data = response.json()
37
+ content_url = video_data.get("video").get("content_url")
38
+
39
+ if not content_url:
40
+ return "Error: No content URL found in video data"
41
+
42
+ # Extract the element key
43
+ if "=" in content_url:
44
+ element_key = content_url.split("=")[1]
45
+ else:
46
+ return "Error: Unable to extract element key"
47
+
48
+ # Request the stream URL
49
+ params = {
50
+ 'cont': element_key,
51
+ 'output': '62',
52
+ }
53
+ stream_response = httpx.get('https://mediapolisvod.rai.it/relinker/relinkerServlet.htm', params=params, headers=get_headers(), timeout=MAX_TIMEOUT)
54
+
55
+ if stream_response.status_code != 200:
56
+ return f"Error: Failed to fetch stream URL (Status: {stream_response.status_code})"
57
+
58
+ # Extract the m3u8 URL
59
+ stream_data = stream_response.json()
60
+ m3u8_url = stream_data.get("video")[0] if "video" in stream_data else None
61
+ return m3u8_url
62
+
63
+ except Exception as e:
64
+ return f"Error: {str(e)}"
@@ -16,9 +16,9 @@ from StreamingCommunity.Util.headers import get_userAgent
16
16
  MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
17
17
 
18
18
 
19
- class AnimeWorldPlayer:
19
+ class VideoSource:
20
20
  def __init__(self, full_url, episode_data, session_id, csrf_token):
21
- """Initialize the AnimeWorldPlayer with session details, episode data, and URL."""
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
@@ -33,7 +33,7 @@ class AnimeWorldPlayer:
33
33
  timeout=MAX_TIMEOUT
34
34
  )
35
35
 
36
- def get_download_link(self):
36
+ def get_playlist(self):
37
37
  """Fetch the download link from AnimeWorld using the episode link."""
38
38
  try:
39
39
  # Make a POST request to the episode link and follow any redirects
@@ -24,26 +24,20 @@ console = Console()
24
24
 
25
25
 
26
26
  class VideoSource:
27
- def __init__(self, url: str, is_series: bool):
27
+ def __init__(self, url: str, is_series: bool, media_id: int = None):
28
28
  """
29
29
  Initialize video source for streaming site.
30
30
 
31
31
  Args:
32
32
  - url (str): The URL of the streaming site.
33
33
  - is_series (bool): Flag for series or movie content
34
+ - media_id (int, optional): Unique identifier for media item
34
35
  """
35
36
  self.headers = {'user-agent': get_userAgent()}
36
37
  self.url = url
37
38
  self.is_series = is_series
38
-
39
- def setup(self, media_id: int):
40
- """
41
- Configure media-specific context.
42
-
43
- Args:
44
- media_id (int): Unique identifier for media item
45
- """
46
39
  self.media_id = media_id
40
+ self.iframe_src = None
47
41
 
48
42
  def get_iframe(self, episode_id: int) -> None:
49
43
  """
@@ -164,6 +158,7 @@ class VideoSourceAnime(VideoSource):
164
158
  self.headers = {'user-agent': get_userAgent()}
165
159
  self.url = url
166
160
  self.src_mp4 = None
161
+ self.iframe_src = None
167
162
 
168
163
  def get_embed(self, episode_id: int):
169
164
  """
@@ -39,7 +39,7 @@ def process_search_result(select_title):
39
39
 
40
40
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
41
41
  """
42
- Main function of the application for search film, series and anime.
42
+ Main function of the application for search.
43
43
 
44
44
  Parameters:
45
45
  string_to_search (str, optional): String to search for
@@ -57,27 +57,43 @@ def get_user_input(string_to_search: str = None):
57
57
 
58
58
  return string_to_search
59
59
 
60
- def process_search_result(select_title):
60
+ def process_search_result(select_title, selections=None):
61
61
  """
62
62
  Handles the search result and initiates the download for either a film or series.
63
+
64
+ Parameters:
65
+ select_title (MediaItem): The selected media item
66
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
67
+ {'season': season_selection, 'episode': episode_selection}
63
68
  """
64
69
  if select_title.type == 'tv':
65
- download_series(select_title)
70
+ season_selection = None
71
+ episode_selection = None
72
+
73
+ if selections:
74
+ season_selection = selections.get('season')
75
+ episode_selection = selections.get('episode')
76
+
77
+ download_series(select_title, season_selection, episode_selection)
78
+
66
79
  else:
67
80
  download_film(select_title)
68
81
 
69
- def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
82
+ # search("Game of Thrones", selections={"season": "1", "episode": "1-3"})
83
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
70
84
  """
71
- Main function of the application for search film, series and anime.
85
+ Main function of the application for search.
72
86
 
73
87
  Parameters:
74
88
  string_to_search (str, optional): String to search for
75
89
  get_onylDatabase (bool, optional): If True, return only the database object
76
90
  direct_item (dict, optional): Direct item to process (bypass search)
91
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
92
+ {'season': season_selection, 'episode': episode_selection}
77
93
  """
78
94
  if direct_item:
79
95
  select_title = MediaItem(**direct_item)
80
- process_search_result(select_title)
96
+ process_search_result(select_title, selections)
81
97
  return
82
98
 
83
99
  # Get the user input for the search term
@@ -95,7 +111,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
95
111
 
96
112
  if len_database > 0:
97
113
  select_title = get_select_title(table_show_manager, media_search_manager)
98
- process_search_result(select_title)
114
+ process_search_result(select_title, selections)
99
115
 
100
116
  else:
101
117
  console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
@@ -105,4 +121,4 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
105
121
 
106
122
  # If no results are found, ask again
107
123
  string_to_search = get_user_input()
108
- search()
124
+ search(string_to_search, get_onlyDatabase, None, selections)
@@ -42,7 +42,6 @@ def download_film(select_title: MediaItem) -> str:
42
42
  Return:
43
43
  - str: output path if successful, otherwise None
44
44
  """
45
-
46
45
  if site_constant.TELEGRAM_BOT:
47
46
  bot = get_bot_instance()
48
47
  bot.send_message(f"Download in corso:\n{select_title.name}", None)
@@ -19,8 +19,7 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, Teleg
19
19
  from .util.ScrapeSerie import GetSerieInfo
20
20
  from StreamingCommunity.Api.Template.Util import (
21
21
  manage_selection,
22
- map_episode_title,
23
- dynamic_format_number,
22
+ map_episode_title,
24
23
  validate_selection,
25
24
  validate_episode_selection,
26
25
  display_episodes_list
@@ -40,23 +39,24 @@ console = Console()
40
39
 
41
40
  def download_video(index_season_selected: int, index_episode_selected: int, scrape_serie: GetSerieInfo) -> Tuple[str,bool]:
42
41
  """
43
- Download a single episode video.
42
+ Downloads a specific episode from a specified season.
44
43
 
45
44
  Parameters:
46
- - index_season_selected (int): Index of the selected season.
47
- - index_episode_selected (int): Index of the selected episode.
45
+ - index_season_selected (int): Season number
46
+ - index_episode_selected (int): Episode index
47
+ - scrape_serie (GetSerieInfo): Scraper object with series information
48
48
 
49
- Return:
50
- - str: output path
51
- - bool: kill handler status
49
+ Returns:
50
+ - str: Path to downloaded file
51
+ - bool: Whether download was stopped
52
52
  """
53
53
  start_message()
54
- index_season_selected = dynamic_format_number(str(index_season_selected))
55
54
 
56
- # Get info about episode
57
- obj_episode = scrape_serie.seasons_manager.get_season_by_number(int(index_season_selected)).episodes.get(index_episode_selected-1)
55
+ # Get episode information
56
+ obj_episode = scrape_serie.selectEpisode(index_season_selected, index_episode_selected-1)
58
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")
59
58
 
59
+ # Telegram integration
60
60
  if site_constant.TELEGRAM_BOT:
61
61
  bot = get_bot_instance()
62
62
 
@@ -93,21 +93,21 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
93
93
  return r_proc['path'], r_proc['stopped']
94
94
 
95
95
 
96
- def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, download_all: bool = False) -> None:
96
+ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, download_all: bool = False, episode_selection: str = None) -> None:
97
97
  """
98
- Download episodes of a selected season.
98
+ Handle downloading episodes for a specific season.
99
99
 
100
100
  Parameters:
101
- - index_season_selected (int): Index of the selected season.
102
- - download_all (bool): Download all episodes in the season.
101
+ - index_season_selected (int): Season number
102
+ - scrape_serie (GetSerieInfo): Scraper object with series information
103
+ - download_all (bool): Whether to download all episodes
104
+ - episode_selection (str, optional): Pre-defined episode selection that bypasses manual input
103
105
  """
104
- start_message()
105
- obj_episodes = scrape_serie.seasons_manager.get_season_by_number(index_season_selected).episodes
106
- episodes_count = len(obj_episodes.episodes)
106
+ # Get episodes for the selected season
107
+ episodes = scrape_serie.getEpisodeSeasons(index_season_selected)
108
+ episodes_count = len(episodes)
107
109
 
108
110
  if download_all:
109
-
110
- # Download all episodes without asking
111
111
  for i_episode in range(1, episodes_count + 1):
112
112
  path, stopped = download_video(index_season_selected, i_episode, scrape_serie)
113
113
 
@@ -117,16 +117,16 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, dow
117
117
  console.print(f"\n[red]End downloaded [yellow]season: [red]{index_season_selected}.")
118
118
 
119
119
  else:
120
+ if episode_selection is not None:
121
+ last_command = episode_selection
122
+ console.print(f"\n[cyan]Using provided episode selection: [yellow]{episode_selection}")
120
123
 
121
- # Display episodes list and manage user selection
122
- last_command = display_episodes_list(obj_episodes.episodes)
124
+ else:
125
+ last_command = display_episodes_list(episodes)
126
+
127
+ # Prompt user for episode selection
123
128
  list_episode_select = manage_selection(last_command, episodes_count)
124
-
125
- try:
126
- list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
127
- except ValueError as e:
128
- console.print(f"[red]{str(e)}")
129
- return
129
+ list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
130
130
 
131
131
  # Download selected episodes if not stopped
132
132
  for i_episode in list_episode_select:
@@ -135,69 +135,65 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, dow
135
135
  if stopped:
136
136
  break
137
137
 
138
- def download_series(select_season: MediaItem) -> None:
138
+ def download_series(select_season: MediaItem, season_selection: str = None, episode_selection: str = None) -> None:
139
139
  """
140
- Download episodes of a TV series based on user selection.
140
+ Handle downloading a complete series.
141
141
 
142
142
  Parameters:
143
- - select_season (MediaItem): Selected media item (TV series).
143
+ - select_season (MediaItem): Series metadata from search
144
+ - season_selection (str, optional): Pre-defined season selection that bypasses manual input
145
+ - episode_selection (str, optional): Pre-defined episode selection that bypasses manual input
144
146
  """
145
- if site_constant.TELEGRAM_BOT:
146
- bot = get_bot_instance()
147
-
148
- start_message()
149
-
150
- # Init class
151
147
  scrape_serie = GetSerieInfo(select_season.url)
152
148
 
153
- # Collect information about seasons
154
- scrape_serie.collect_season()
155
- seasons_count = len(scrape_serie.seasons_manager)
149
+ # Get total number of seasons
150
+ seasons_count = scrape_serie.getNumberSeason()
151
+
152
+ if site_constant.TELEGRAM_BOT:
153
+ bot = get_bot_instance()
156
154
 
157
155
  # Prompt user for season selection and download episodes
158
156
  console.print(f"\n[green]Seasons found: [red]{seasons_count}")
159
157
 
160
- if site_constant.TELEGRAM_BOT:
161
- console.print("\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
162
- "[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")
163
-
164
- bot.send_message(f"Stagioni trovate: {seasons_count}", None)
165
-
166
- index_season_selected = bot.ask(
167
- "select_title_episode",
168
- "Menu di selezione delle stagioni\n\n"
169
- "- Inserisci il numero della stagione (ad esempio, 1)\n"
170
- "- Inserisci * per scaricare tutte le stagioni\n"
171
- "- Inserisci un intervallo di stagioni (ad esempio, 1-2) per scaricare da una stagione all'altra\n"
172
- "- Inserisci (ad esempio, 3-*) per scaricare dalla stagione specificata fino alla fine della serie",
173
- None
174
- )
158
+ # If season_selection is provided, use it instead of asking for input
159
+ if season_selection is None:
160
+ if site_constant.TELEGRAM_BOT:
161
+ console.print("\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
162
+ "[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")
163
+
164
+ bot.send_message(f"Stagioni trovate: {seasons_count}", None)
165
+
166
+ index_season_selected = bot.ask(
167
+ "select_title_episode",
168
+ "Menu di selezione delle stagioni\n\n"
169
+ "- Inserisci il numero della stagione (ad esempio, 1)\n"
170
+ "- Inserisci * per scaricare tutte le stagioni\n"
171
+ "- Inserisci un intervallo di stagioni (ad esempio, 1-2) per scaricare da una stagione all'altra\n"
172
+ "- Inserisci (ad esempio, 3-*) per scaricare dalla stagione specificata fino alla fine della serie",
173
+ None
174
+ )
175
175
 
176
+ else:
177
+ index_season_selected = msg.ask(
178
+ "\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
179
+ "[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"
180
+ )
176
181
  else:
177
- index_season_selected = msg.ask(
178
- "\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
179
- "[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"
180
- )
182
+ index_season_selected = season_selection
183
+ console.print(f"\n[cyan]Using provided season selection: [yellow]{season_selection}")
181
184
 
182
- # Manage and validate the selection
185
+ # Validate the selection
183
186
  list_season_select = manage_selection(index_season_selected, seasons_count)
184
-
185
- try:
186
- list_season_select = validate_selection(list_season_select, seasons_count)
187
- except ValueError as e:
188
- console.print(f"[red]{str(e)}")
189
- return
187
+ list_season_select = validate_selection(list_season_select, seasons_count)
190
188
 
191
189
  # Loop through the selected seasons and download episodes
192
190
  for i_season in list_season_select:
193
191
  if len(list_season_select) > 1 or index_season_selected == "*":
194
-
195
192
  # Download all episodes if multiple seasons are selected or if '*' is used
196
193
  download_episode(i_season, scrape_serie, download_all=True)
197
194
  else:
198
-
199
195
  # Otherwise, let the user select specific episodes for the single season
200
- download_episode(i_season, scrape_serie, download_all=False)
196
+ download_episode(i_season, scrape_serie, download_all=False, episode_selection=episode_selection)
201
197
 
202
198
  if site_constant.TELEGRAM_BOT:
203
199
  bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
@@ -205,4 +201,4 @@ def download_series(select_season: MediaItem) -> None:
205
201
  # Get script_id
206
202
  script_id = TelegramSession.get_session()
207
203
  if script_id != "unknown":
208
- TelegramSession.deleteScriptId(script_id)
204
+ TelegramSession.deleteScriptId(script_id)
@@ -78,7 +78,8 @@ def title_search(query: str) -> int:
78
78
  media_search_manager.add_media({
79
79
  'url': url,
80
80
  'name': title,
81
- 'type': tipo
81
+ 'type': tipo,
82
+ 'image': f"{site_constant.FULL_URL}{movie_div.find('img', class_='layer-image').get('data-src')}"
82
83
  })
83
84
 
84
85
  if site_constant.TELEGRAM_BOT:
@@ -1,5 +1,8 @@
1
1
  # 16.03.25
2
2
 
3
+ import logging
4
+
5
+
3
6
  # External libraries
4
7
  import httpx
5
8
  from bs4 import BeautifulSoup
@@ -15,7 +18,6 @@ from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
15
18
  max_timeout = config_manager.get_int("REQUESTS", "timeout")
16
19
 
17
20
 
18
-
19
21
  class GetSerieInfo:
20
22
  def __init__(self, url):
21
23
  """
@@ -69,4 +71,37 @@ class GetSerieInfo:
69
71
  'number': ep_idx,
70
72
  'name': episode_name,
71
73
  'url': episode_url
72
- })
74
+ })
75
+
76
+
77
+ # ------------- FOR GUI -------------
78
+ def getNumberSeason(self) -> int:
79
+ """
80
+ Get the total number of seasons available for the series.
81
+ """
82
+ if not self.seasons_manager.seasons:
83
+ self.collect_season()
84
+
85
+ return len(self.seasons_manager.seasons)
86
+
87
+ def getEpisodeSeasons(self, season_number: int) -> list:
88
+ """
89
+ Get all episodes for a specific season.
90
+ """
91
+ if not self.seasons_manager.seasons:
92
+ self.collect_season()
93
+
94
+ # Get season directly by its number
95
+ season = self.seasons_manager.get_season_by_number(season_number)
96
+ return season.episodes.episodes if season else []
97
+
98
+ def selectEpisode(self, season_number: int, episode_index: int) -> dict:
99
+ """
100
+ Get information for a specific episode in a specific season.
101
+ """
102
+ episodes = self.getEpisodeSeasons(season_number)
103
+ if not episodes or episode_index < 0 or episode_index >= len(episodes):
104
+ logging.error(f"Episode index {episode_index} is out of range for season {season_number}")
105
+ return None
106
+
107
+ return episodes[episode_index]
@@ -18,7 +18,8 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
18
18
 
19
19
  # Logic class
20
20
  from .site import title_search, media_search_manager, table_show_manager
21
- from .film_serie import download_film, download_series
21
+ from .film import download_film
22
+ from .serie import download_series
22
23
 
23
24
 
24
25
  # Variable
@@ -56,24 +57,42 @@ def get_user_input(string_to_search: str = None):
56
57
 
57
58
  return string_to_search
58
59
 
59
- def process_search_result(select_title):
60
+ def process_search_result(select_title, selections=None):
60
61
  """
61
62
  Handles the search result and initiates the download for either a film or series.
63
+
64
+ Parameters:
65
+ select_title (MediaItem): The selected media item
66
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
67
+ {'season': season_selection, 'episode': episode_selection}
62
68
  """
63
- download_series(select_title)
69
+ if select_title.type == 'Movie' or select_title.type == 'OVA':
70
+ download_film(select_title)
71
+
72
+ else:
73
+ season_selection = None
74
+ episode_selection = None
64
75
 
65
- def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
76
+ if selections:
77
+ season_selection = selections.get('season')
78
+ episode_selection = selections.get('episode')
79
+
80
+ download_series(select_title, season_selection, episode_selection)
81
+
82
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
66
83
  """
67
- Main function of the application for search film, series and anime.
84
+ Main function of the application for search.
68
85
 
69
86
  Parameters:
70
87
  string_to_search (str, optional): String to search for
71
88
  get_onlyDatabase (bool, optional): If True, return only the database object
72
89
  direct_item (dict, optional): Direct item to process (bypass search)
90
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
91
+ {'season': season_selection, 'episode': episode_selection}
73
92
  """
74
93
  if direct_item:
75
94
  select_title = MediaItem(**direct_item)
76
- process_search_result(select_title)
95
+ process_search_result(select_title, selections)
77
96
  return
78
97
 
79
98
  # Get the user input for the search term
@@ -82,7 +101,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
82
101
  # Perform the database search
83
102
  len_database = title_search(string_to_search)
84
103
 
85
- ##If only the database is needed, return the manager
104
+ # If only the database is needed, return the manager
86
105
  if get_onlyDatabase:
87
106
  return media_search_manager
88
107
 
@@ -91,8 +110,8 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
91
110
 
92
111
  if len_database > 0:
93
112
  select_title = get_select_title(table_show_manager, media_search_manager)
94
- process_search_result(select_title)
95
-
113
+ process_search_result(select_title, selections)
114
+
96
115
  else:
97
116
  console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
98
117
 
@@ -101,4 +120,4 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
101
120
 
102
121
  # If no results are found, ask again
103
122
  string_to_search = get_user_input()
104
- search()
123
+ search(string_to_search, get_onlyDatabase, None, selections)
@@ -0,0 +1,40 @@
1
+ # 11.03.24
2
+
3
+ # External library
4
+ from rich.console import Console
5
+
6
+
7
+ # Logic class
8
+ from .serie import download_episode
9
+ from .util.ScrapeSerie import ScrapeSerieAnime
10
+ from StreamingCommunity.Api.Template.config_loader import site_constant
11
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
12
+
13
+
14
+ # Player
15
+ from StreamingCommunity.Api.Player.vixcloud import VideoSourceAnime
16
+
17
+
18
+ # Variable
19
+ console = Console()
20
+
21
+
22
+ def download_film(select_title: MediaItem):
23
+ """
24
+ Function to download a film.
25
+
26
+ Parameters:
27
+ - id_film (int): The ID of the film.
28
+ - title_name (str): The title of the film.
29
+ """
30
+
31
+ # Init class
32
+ scrape_serie = ScrapeSerieAnime(site_constant.FULL_URL)
33
+ video_source = VideoSourceAnime(site_constant.FULL_URL)
34
+
35
+ # Set up video source (only configure scrape_serie now)
36
+ scrape_serie.setup(None, select_title.id, select_title.slug)
37
+ scrape_serie.is_series = False
38
+
39
+ # Start download
40
+ download_episode(0, scrape_serie, video_source)