StreamingCommunity 2.9.8__py3-none-any.whl → 3.0.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 (67) 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 +2 -3
  6. StreamingCommunity/Api/Site/1337xx/site.py +6 -1
  7. StreamingCommunity/Api/Site/altadefinizione/__init__.py +24 -9
  8. StreamingCommunity/Api/Site/altadefinizione/film.py +0 -1
  9. StreamingCommunity/Api/Site/altadefinizione/series.py +66 -70
  10. StreamingCommunity/Api/Site/altadefinizione/site.py +8 -2
  11. StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +37 -2
  12. StreamingCommunity/Api/Site/animeunity/__init__.py +30 -12
  13. StreamingCommunity/Api/Site/animeunity/film.py +40 -0
  14. StreamingCommunity/Api/Site/animeunity/serie.py +153 -0
  15. StreamingCommunity/Api/Site/animeunity/site.py +64 -37
  16. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +41 -22
  17. StreamingCommunity/Api/Site/animeworld/__init__.py +26 -14
  18. StreamingCommunity/Api/Site/animeworld/film.py +63 -0
  19. StreamingCommunity/Api/Site/animeworld/serie.py +25 -22
  20. StreamingCommunity/Api/Site/animeworld/site.py +8 -2
  21. StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +32 -5
  22. StreamingCommunity/Api/Site/cb01new/__init__.py +2 -3
  23. StreamingCommunity/Api/Site/cb01new/site.py +7 -1
  24. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +2 -3
  25. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +31 -32
  26. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +8 -3
  27. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +30 -2
  28. StreamingCommunity/Api/Site/guardaserie/__init__.py +22 -9
  29. StreamingCommunity/Api/Site/guardaserie/series.py +55 -53
  30. StreamingCommunity/Api/Site/guardaserie/site.py +10 -3
  31. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +27 -1
  32. StreamingCommunity/Api/Site/raiplay/__init__.py +92 -0
  33. StreamingCommunity/Api/Site/raiplay/film.py +65 -0
  34. StreamingCommunity/Api/Site/raiplay/series.py +162 -0
  35. StreamingCommunity/Api/Site/raiplay/site.py +173 -0
  36. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +127 -0
  37. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +30 -24
  38. StreamingCommunity/Api/Site/streamingcommunity/film.py +1 -2
  39. StreamingCommunity/Api/Site/streamingcommunity/series.py +76 -90
  40. StreamingCommunity/Api/Site/streamingcommunity/site.py +8 -4
  41. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +41 -15
  42. StreamingCommunity/Api/Template/site.py +2 -2
  43. StreamingCommunity/Lib/Downloader/HLS/downloader.py +1 -1
  44. StreamingCommunity/Lib/Downloader/HLS/segments.py +9 -18
  45. StreamingCommunity/Lib/Downloader/MP4/downloader.py +2 -1
  46. StreamingCommunity/Lib/Downloader/TOR/downloader.py +7 -14
  47. StreamingCommunity/Lib/FFmpeg/capture.py +1 -5
  48. StreamingCommunity/Lib/FFmpeg/util.py +57 -19
  49. StreamingCommunity/Lib/M3U8/estimator.py +57 -41
  50. StreamingCommunity/Lib/M3U8/parser.py +26 -6
  51. StreamingCommunity/Upload/update.py +22 -3
  52. StreamingCommunity/Upload/version.py +1 -1
  53. StreamingCommunity/Util/ffmpeg_installer.py +26 -1
  54. StreamingCommunity/Util/os.py +13 -15
  55. StreamingCommunity/Util/table.py +4 -2
  56. StreamingCommunity/global_search.py +1 -4
  57. StreamingCommunity/run.py +1 -4
  58. {streamingcommunity-2.9.8.dist-info → streamingcommunity-3.0.0.dist-info}/METADATA +1 -1
  59. streamingcommunity-3.0.0.dist-info/RECORD +91 -0
  60. {streamingcommunity-2.9.8.dist-info → streamingcommunity-3.0.0.dist-info}/WHEEL +1 -1
  61. StreamingCommunity/Api/Site/animeunity/film_serie.py +0 -181
  62. StreamingCommunity/Api/Site/mostraguarda/__init__.py +0 -73
  63. StreamingCommunity/Api/Site/mostraguarda/film.py +0 -93
  64. streamingcommunity-2.9.8.dist-info/RECORD +0 -85
  65. {streamingcommunity-2.9.8.dist-info → streamingcommunity-3.0.0.dist-info}/entry_points.txt +0 -0
  66. {streamingcommunity-2.9.8.dist-info → streamingcommunity-3.0.0.dist-info}/licenses/LICENSE +0 -0
  67. {streamingcommunity-2.9.8.dist-info → streamingcommunity-3.0.0.dist-info}/top_level.txt +0 -0
@@ -19,12 +19,12 @@ from StreamingCommunity.Lib.Downloader import MP4_downloader
19
19
  # Logic class
20
20
  from .util.ScrapeSerie import ScrapSerie
21
21
  from StreamingCommunity.Api.Template.config_loader import site_constant
22
- from StreamingCommunity.Api.Template.Util import manage_selection, dynamic_format_number, map_episode_title
22
+ from StreamingCommunity.Api.Template.Util import manage_selection, dynamic_format_number
23
23
  from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
24
24
 
25
25
 
26
26
  # Player
27
- from StreamingCommunity.Api.Player.sweetpixel import AnimeWorldPlayer
27
+ from StreamingCommunity.Api.Player.sweetpixel import VideoSource
28
28
 
29
29
 
30
30
  # Variable
@@ -33,8 +33,7 @@ msg = Prompt()
33
33
  KILL_HANDLER = bool(False)
34
34
 
35
35
 
36
-
37
- def download_episode(index_select: int, scrape_serie: ScrapSerie, episodes) -> Tuple[str,bool]:
36
+ def download_episode(index_select: int, scrape_serie: ScrapSerie) -> Tuple[str,bool]:
38
37
  """
39
38
  Downloads the selected episode.
40
39
 
@@ -47,7 +46,8 @@ def download_episode(index_select: int, scrape_serie: ScrapSerie, episodes) -> T
47
46
  """
48
47
  start_message()
49
48
 
50
- # Get information about the selected episode
49
+ # Get episode information
50
+ episode_data = scrape_serie.selectEpisode(1, index_select)
51
51
  console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] ([cyan]E{index_select+1}[/cyan]) \n")
52
52
 
53
53
  # Define filename and path for the downloaded video
@@ -57,9 +57,9 @@ def download_episode(index_select: int, scrape_serie: ScrapSerie, episodes) -> T
57
57
  # Create output folder
58
58
  os_manager.create_path(mp4_path)
59
59
 
60
- # Collect mp4 link
61
- video_source = AnimeWorldPlayer(site_constant.FULL_URL, episodes[index_select], scrape_serie.session_id, scrape_serie.csrf_token)
62
- mp4_link = video_source.get_download_link()
60
+ # Get video source for the episode
61
+ video_source = VideoSource(site_constant.FULL_URL, episode_data, scrape_serie.session_id, scrape_serie.csrf_token)
62
+ mp4_link = video_source.get_playlist()
63
63
 
64
64
  # Start downloading
65
65
  path, kill_handler = MP4_downloader(
@@ -70,38 +70,41 @@ def download_episode(index_select: int, scrape_serie: ScrapSerie, episodes) -> T
70
70
  return path, kill_handler
71
71
 
72
72
 
73
- def download_series(select_title: MediaItem):
73
+ def download_series(select_title: MediaItem, episode_selection: str = None):
74
74
  """
75
75
  Function to download episodes of a TV series.
76
76
 
77
77
  Parameters:
78
- - tv_id (int): The ID of the TV series.
79
- - tv_name (str): The name of the TV series.
78
+ - select_title (MediaItem): The selected media item
79
+ - episode_selection (str, optional): Episode selection input that bypasses manual input
80
80
  """
81
81
  start_message()
82
82
 
83
+ # Create scrap instance
83
84
  scrape_serie = ScrapSerie(select_title.url, site_constant.FULL_URL)
85
+ episodes = scrape_serie.get_episodes()
84
86
 
85
- # Get the count of episodes for the TV series
86
- episodes = scrape_serie.get_episodes()
87
- episoded_count = len(episodes)
88
- console.print(f"[cyan]Episodes find: [red]{episoded_count}")
87
+ # Get episode count
88
+ console.print(f"[green]Episodes found:[/green] [red]{len(episodes)}[/red]")
89
89
 
90
- # Prompt user to select an episode index
91
- last_command = msg.ask("\n[cyan]Insert media [red]index [yellow]or [red]* [cyan]to download all media [yellow]or [red]1-2 [cyan]or [red]3-* [cyan]for a range of media")
90
+ # Display episodes list and get user selection
91
+ if episode_selection is None:
92
+ last_command = msg.ask("\n[cyan]Insert media [red]index [yellow]or [red]* [cyan]to download all media [yellow]or [red]1-2 [cyan]or [red]3-* [cyan]for a range of media")
93
+ else:
94
+ last_command = episode_selection
95
+ console.print(f"\n[cyan]Using provided episode selection: [yellow]{episode_selection}")
92
96
 
93
- # Manage user selection
94
- list_episode_select = manage_selection(last_command, episoded_count)
97
+ list_episode_select = manage_selection(last_command, len(episodes))
95
98
 
96
99
  # Download selected episodes
97
100
  if len(list_episode_select) == 1 and last_command != "*":
98
- path, _ = download_episode(list_episode_select[0]-1, scrape_serie, episodes)
101
+ path, _ = download_episode(list_episode_select[0]-1, scrape_serie)
99
102
  return path
100
103
 
101
- # Download all other episodes selecter
104
+ # Download all selected episodes
102
105
  else:
103
106
  kill_handler = False
104
107
  for i_episode in list_episode_select:
105
108
  if kill_handler:
106
109
  break
107
- _, kill_handler = download_episode(i_episode-1, scrape_serie, episodes)
110
+ _, kill_handler = download_episode(i_episode-1, scrape_serie)
@@ -70,7 +70,12 @@ def title_search(query: str) -> int:
70
70
 
71
71
  # Make the GET request
72
72
  try:
73
- response = httpx.get(search_url, headers={'User-Agent': get_userAgent()})
73
+ response = httpx.get(
74
+ search_url,
75
+ headers={'User-Agent': get_userAgent()},
76
+ timeout=max_timeout,
77
+ verify=False
78
+ )
74
79
 
75
80
  except Exception as e:
76
81
  console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
@@ -101,7 +106,8 @@ def title_search(query: str) -> int:
101
106
  'name': title,
102
107
  'type': anime_type,
103
108
  'DUB': is_dubbed,
104
- 'url': url
109
+ 'url': url,
110
+ 'image': element.find('img').get('src')
105
111
  })
106
112
 
107
113
  except Exception as e:
@@ -1,5 +1,6 @@
1
1
  # 21.03.25
2
2
 
3
+ import logging
3
4
 
4
5
  # External libraries
5
6
  import httpx
@@ -14,7 +15,7 @@ from StreamingCommunity.Util.os import os_manager
14
15
 
15
16
  # Player
16
17
  from ..site import get_session_and_csrf
17
- from StreamingCommunity.Api.Player.sweetpixel import AnimeWorldPlayer
18
+ from StreamingCommunity.Api.Player.sweetpixel import VideoSource
18
19
 
19
20
 
20
21
  # Variable
@@ -40,7 +41,6 @@ class ScrapSerie:
40
41
  except:
41
42
  raise Exception(f"Failed to retrieve anime page.")
42
43
 
43
-
44
44
  def get_name(self):
45
45
  """Extract and return the name of the anime series."""
46
46
  soup = BeautifulSoup(self.response.content, "html.parser")
@@ -68,12 +68,39 @@ class ScrapSerie:
68
68
  return episodes
69
69
 
70
70
  def get_episode(self, index):
71
- """Fetch a specific episode based on the index, and return an AnimeWorldPlayer instance."""
71
+ """Fetch a specific episode based on the index, and return an VideoSource instance."""
72
72
  episodes = self.get_episodes()
73
73
 
74
74
  if 0 <= index < len(episodes):
75
75
  episode_data = episodes[index]
76
- return AnimeWorldPlayer(episode_data, self.session_id, self.csrf_token)
76
+ return VideoSource(episode_data, self.session_id, self.csrf_token)
77
77
 
78
78
  else:
79
- raise IndexError("Episode index out of range")
79
+ raise IndexError("Episode index out of range")
80
+
81
+
82
+ # ------------- FOR GUI -------------
83
+ def getNumberSeason(self) -> int:
84
+ """
85
+ Get the total number of seasons available for the anime.
86
+ Note: AnimeWorld typically doesn't have seasons, so returns 1.
87
+ """
88
+ return 1
89
+
90
+ def getEpisodeSeasons(self, season_number: int = 1) -> list:
91
+ """
92
+ Get all episodes for a specific season.
93
+ Note: For AnimeWorld, this returns all episodes as they're typically in one season.
94
+ """
95
+ return self.get_episodes()
96
+
97
+ def selectEpisode(self, season_number: int = 1, episode_index: int = 0) -> dict:
98
+ """
99
+ Get information for a specific episode.
100
+ """
101
+ episodes = self.get_episodes()
102
+ if not episodes or episode_index < 0 or episode_index >= len(episodes):
103
+ logging.error(f"Episode index {episode_index} is out of range")
104
+ return None
105
+
106
+ return episodes[episode_index]
@@ -22,8 +22,7 @@ from .film import download_film
22
22
  # Variable
23
23
  indice = 4
24
24
  _useFor = "film"
25
- _deprecate = False
26
- _priority = 2
25
+ _priority = 0
27
26
  _engineDownload = "mp4"
28
27
 
29
28
  msg = Prompt()
@@ -39,7 +38,7 @@ def process_search_result(select_title):
39
38
 
40
39
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
41
40
  """
42
- Main function of the application for search film, series and anime.
41
+ Main function of the application for search.
43
42
 
44
43
  Parameters:
45
44
  string_to_search (str, optional): String to search for
@@ -44,7 +44,13 @@ def title_search(query: str) -> int:
44
44
  console.print(f"[cyan]Search url: [yellow]{search_url}")
45
45
 
46
46
  try:
47
- response = httpx.get(url=search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
47
+ response = httpx.get(
48
+ search_url,
49
+ headers={'user-agent': get_userAgent()},
50
+ timeout=max_timeout,
51
+ follow_redirects=True,
52
+ verify=False
53
+ )
48
54
  response.raise_for_status()
49
55
 
50
56
  except Exception as e:
@@ -23,8 +23,7 @@ from .series import download_thread
23
23
  # Variable
24
24
  indice = 6
25
25
  _useFor = "serie"
26
- _deprecate = False
27
- _priority = 2
26
+ _priority = 0
28
27
  _engineDownload = "mp4"
29
28
 
30
29
  msg = Prompt()
@@ -42,7 +41,7 @@ def process_search_result(select_title):
42
41
 
43
42
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
44
43
  """
45
- Main function of the application for search film, series and anime.
44
+ Main function of the application for search.
46
45
 
47
46
  Parameters:
48
47
  string_to_search (str, optional): String to search for
@@ -35,22 +35,22 @@ from StreamingCommunity.Api.Player.ddl import VideoSource
35
35
  console = Console()
36
36
 
37
37
 
38
- def download_video(index_episode_selected: int, scape_info_serie: GetSerieInfo, video_source: VideoSource) -> Tuple[str,bool]:
38
+ def download_video(index_episode_selected: int, scape_info_serie: GetSerieInfo) -> Tuple[str,bool]:
39
39
  """
40
- Download a single episode video.
40
+ Downloads a specific episode.
41
41
 
42
42
  Parameters:
43
- - tv_name (str): Name of the TV series.
44
- - index_episode_selected (int): Index of the selected episode.
43
+ - index_episode_selected (int): Episode index
44
+ - scape_info_serie (GetSerieInfo): Scraper object with series information
45
45
 
46
- Return:
47
- - str: output path
48
- - bool: kill handler status
46
+ Returns:
47
+ - str: Path to downloaded file
48
+ - bool: Whether download was stopped
49
49
  """
50
50
  start_message()
51
51
 
52
- # Get info about episode
53
- obj_episode = scape_info_serie.list_episodes[index_episode_selected - 1]
52
+ # Get episode information
53
+ obj_episode = scape_info_serie.selectEpisode(1, index_episode_selected-1)
54
54
  console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [bold magenta]{obj_episode.get('name')}[/bold magenta] ([cyan]E{index_episode_selected}[/cyan]) \n")
55
55
 
56
56
  # Define filename and path for the downloaded video
@@ -63,7 +63,7 @@ def download_video(index_episode_selected: int, scape_info_serie: GetSerieInfo,
63
63
  os_manager.create_path(mp4_path)
64
64
 
65
65
  # Setup video source
66
- video_source.setup(obj_episode.get('url'))
66
+ video_source = VideoSource(site_constant.COOKIE, obj_episode.get('url'))
67
67
 
68
68
  # Get m3u8 master playlist
69
69
  master_playlist = video_source.get_playlist()
@@ -82,38 +82,37 @@ def download_video(index_episode_selected: int, scape_info_serie: GetSerieInfo,
82
82
  console.print("[green]Result: ")
83
83
  console.print(r_proc)
84
84
 
85
- return os.path.join(mp4_path, title_name)
85
+ return os.path.join(mp4_path, title_name), False
86
86
 
87
87
 
88
- def download_thread(dict_serie: MediaItem):
88
+ def download_thread(dict_serie: MediaItem, episode_selection: str = None):
89
89
  """
90
90
  Download all episode of a thread
91
+
92
+ Parameters:
93
+ dict_serie (MediaItem): The selected media item
94
+ episode_selection (str, optional): Episode selection input that bypasses manual input
91
95
  """
92
- start_message()
93
-
94
- # Init class
95
- scape_info_serie = GetSerieInfo(dict_serie, site_constant.COOKIE)
96
- video_source = VideoSource(site_constant.COOKIE)
97
-
98
- # Collect information about thread
99
- list_dict_episode = scape_info_serie.get_episode_number()
100
- episodes_count = len(list_dict_episode)
101
-
96
+ scrape_serie = GetSerieInfo(dict_serie, site_constant.COOKIE)
97
+
98
+ # Get episode list
99
+ episodes = scrape_serie.getEpisodeSeasons()
100
+ episodes_count = len(episodes)
101
+
102
102
  # Display episodes list and manage user selection
103
- last_command = display_episodes_list(scape_info_serie.list_episodes)
103
+ if episode_selection is None:
104
+ last_command = display_episodes_list(scrape_serie.list_episodes)
105
+ else:
106
+ last_command = episode_selection
107
+ console.print(f"\n[cyan]Using provided episode selection: [yellow]{episode_selection}")
108
+
109
+ # Validate episode selection
104
110
  list_episode_select = manage_selection(last_command, episodes_count)
105
-
106
- try:
107
- list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
108
-
109
- except ValueError as e:
110
- console.print(f"[red]{str(e)}")
111
- return
111
+ list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
112
112
 
113
113
  # Download selected episodes
114
114
  kill_handler = bool(False)
115
115
  for i_episode in list_episode_select:
116
116
  if kill_handler:
117
117
  break
118
-
119
- kill_handler = download_video(i_episode, scape_info_serie, video_source)[1]
118
+ kill_handler = download_video(i_episode, scrape_serie)[1]
@@ -1,6 +1,5 @@
1
1
  # 09.06.24
2
2
 
3
- import sys
4
3
  import logging
5
4
 
6
5
 
@@ -45,7 +44,12 @@ def title_search(query: str) -> int:
45
44
  console.print(f"[cyan]Search url: [yellow]{search_url}")
46
45
 
47
46
  try:
48
- response = httpx.get(search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
47
+ response = httpx.get(
48
+ search_url,
49
+ headers={'user-agent': get_userAgent()},
50
+ timeout=max_timeout,
51
+ follow_redirects=True
52
+ )
49
53
  response.raise_for_status()
50
54
 
51
55
  except Exception as e:
@@ -67,7 +71,8 @@ def title_search(query: str) -> int:
67
71
  title_info = {
68
72
  'name': name,
69
73
  'url': link,
70
- 'type': title_type
74
+ 'type': title_type,
75
+ 'image': title_div.find("div", class_="ipsColumn").find("img").get("src")
71
76
  }
72
77
 
73
78
  media_search_manager.add_media(title_info)
@@ -47,7 +47,6 @@ class GetSerieInfo:
47
47
  Returns:
48
48
  List[Dict[str, str]]: List of dictionaries containing episode information.
49
49
  """
50
-
51
50
  try:
52
51
  response = httpx.get(f"{self.url}?area=online", cookies=self.cookies, headers=self.headers, timeout=max_timeout)
53
52
  response.raise_for_status()
@@ -81,4 +80,33 @@ class GetSerieInfo:
81
80
 
82
81
  self.list_episodes = list_dict_episode
83
82
  return list_dict_episode
84
-
83
+
84
+
85
+ # ------------- FOR GUI -------------
86
+ def getNumberSeason(self) -> int:
87
+ """
88
+ Get the total number of seasons available for the series.
89
+ Note: DDLStreamItaly typically provides content organized as threads, not seasons.
90
+ """
91
+ return 1
92
+
93
+ def getEpisodeSeasons(self, season_number: int = 1) -> list:
94
+ """
95
+ Get all episodes for a specific season.
96
+ Note: For DDLStreamItaly, this returns all episodes as they're typically in one list.
97
+ """
98
+ if not self.list_episodes:
99
+ self.list_episodes = self.get_episode_number()
100
+
101
+ return self.list_episodes
102
+
103
+ def selectEpisode(self, season_number: int = 1, episode_index: int = 0) -> dict:
104
+ """
105
+ Get information for a specific episode.
106
+ """
107
+ episodes = self.getEpisodeSeasons()
108
+ if not episodes or episode_index < 0 or episode_index >= len(episodes):
109
+ logging.error(f"Episode index {episode_index} is out of range")
110
+ return None
111
+
112
+ return episodes[episode_index]
@@ -22,32 +22,45 @@ from .series import download_series
22
22
  # Variable
23
23
  indice = 5
24
24
  _useFor = "serie"
25
- _deprecate = False
26
- _priority = 2
25
+ _priority = 0
27
26
  _engineDownload = "hls"
28
27
 
29
28
  msg = Prompt()
30
29
  console = Console()
31
30
 
32
31
 
33
- def process_search_result(select_title):
32
+ def process_search_result(select_title, selections=None):
34
33
  """
35
34
  Handles the search result and initiates the download for either a film or series.
35
+
36
+ Parameters:
37
+ select_title (MediaItem): The selected media item
38
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
39
+ {'season': season_selection, 'episode': episode_selection}
36
40
  """
37
- download_series(select_title)
41
+ season_selection = None
42
+ episode_selection = None
43
+
44
+ if selections:
45
+ season_selection = selections.get('season')
46
+ episode_selection = selections.get('episode')
47
+
48
+ download_series(select_title, season_selection, episode_selection)
38
49
 
39
- def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
50
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
40
51
  """
41
- Main function of the application for search film, series and anime.
52
+ Main function of the application for search.
42
53
 
43
54
  Parameters:
44
55
  string_to_search (str, optional): String to search for
45
- get_onylDatabase (bool, optional): If True, return only the database object
56
+ get_onlyDatabase (bool, optional): If True, return only the database object
46
57
  direct_item (dict, optional): Direct item to process (bypass search)
58
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
59
+ {'season': season_selection, 'episode': episode_selection}
47
60
  """
48
61
  if direct_item:
49
62
  select_title = MediaItem(**direct_item)
50
- process_search_result(select_title)
63
+ process_search_result(select_title, selections)
51
64
  return
52
65
 
53
66
  if string_to_search is None:
@@ -62,7 +75,7 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
62
75
 
63
76
  if len_database > 0:
64
77
  select_title = get_select_title(table_show_manager, media_search_manager)
65
- process_search_result(select_title)
78
+ process_search_result(select_title, selections)
66
79
 
67
80
  else:
68
81
 
@@ -1,6 +1,7 @@
1
1
  # 13.06.24
2
2
 
3
3
  import os
4
+ import logging
4
5
  from typing import Tuple
5
6
 
6
7
 
@@ -39,22 +40,22 @@ console = Console()
39
40
 
40
41
  def download_video(index_season_selected: int, index_episode_selected: int, scape_info_serie: GetSerieInfo) -> Tuple[str,bool]:
41
42
  """
42
- Download a single episode video.
43
+ Downloads a specific episode from a specified season.
43
44
 
44
45
  Parameters:
45
- - tv_name (str): Name of the TV series.
46
- - index_season_selected (int): Index of the selected season.
47
- - index_episode_selected (int): Index of the selected episode.
46
+ - index_season_selected (int): Season number
47
+ - index_episode_selected (int): Episode index
48
+ - scape_info_serie (GetSerieInfo): Scraper object with series information
48
49
 
49
- Return:
50
- - str: output path
51
- - bool: kill handler status
50
+ Returns:
51
+ - str: Path to downloaded file
52
+ - bool: Whether download was stopped
52
53
  """
53
54
  start_message()
54
- index_season_selected = dynamic_format_number(str(index_season_selected))
55
55
 
56
- # Get info about episode
57
- obj_episode = scape_info_serie.list_episodes[index_episode_selected - 1]
56
+ # Get episode information
57
+ obj_episode = scape_info_serie.selectEpisode(index_season_selected, index_episode_selected-1)
58
+ index_season_selected = dynamic_format_number(str(index_season_selected))
58
59
  console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [bold magenta]{obj_episode.get('name')}[/bold magenta] ([cyan]S{index_season_selected}E{index_episode_selected}[/cyan]) \n")
59
60
 
60
61
  # Define filename and path for the downloaded video
@@ -80,24 +81,23 @@ def download_video(index_season_selected: int, index_episode_selected: int, scap
80
81
  return r_proc['path'], r_proc['stopped']
81
82
 
82
83
 
83
- def download_episode(scape_info_serie: GetSerieInfo, index_season_selected: int, download_all: bool = False) -> None:
84
+ def download_episode(scape_info_serie: GetSerieInfo, index_season_selected: int, download_all: bool = False, episode_selection: str = None) -> None:
84
85
  """
85
- Download all episodes of a season.
86
+ Handle downloading episodes for a specific season.
86
87
 
87
88
  Parameters:
88
- - tv_name (str): Name of the TV series.
89
- - index_season_selected (int): Index of the selected season.
90
- - download_all (bool): Download all seasons episodes
89
+ - scape_info_serie (GetSerieInfo): Scraper object with series information
90
+ - index_season_selected (int): Season number
91
+ - download_all (bool): Whether to download all episodes
92
+ - episode_selection (str, optional): Pre-defined episode selection that bypasses manual input
91
93
  """
92
-
93
- # Start message and collect information about episodes
94
- start_message()
95
- list_dict_episode = scape_info_serie.get_episode_number(index_season_selected)
96
- episodes_count = len(list_dict_episode)
94
+ # Get episodes for the selected season
95
+ episodes = scape_info_serie.get_episode_number(index_season_selected)
96
+ episodes_count = len(episodes)
97
97
 
98
98
  if download_all:
99
-
100
- # Download all episodes without asking
99
+
100
+ # Download all episodes in the season
101
101
  for i_episode in range(1, episodes_count + 1):
102
102
  path, stopped = download_video(index_season_selected, i_episode, scape_info_serie)
103
103
 
@@ -109,14 +109,15 @@ def download_episode(scape_info_serie: GetSerieInfo, index_season_selected: int,
109
109
  else:
110
110
 
111
111
  # Display episodes list and manage user selection
112
- last_command = display_episodes_list(scape_info_serie.list_episodes)
112
+ if episode_selection is None:
113
+ last_command = display_episodes_list(scape_info_serie.list_episodes)
114
+ else:
115
+ last_command = episode_selection
116
+ console.print(f"\n[cyan]Using provided episode selection: [yellow]{episode_selection}")
117
+
118
+ # Validate the selection
113
119
  list_episode_select = manage_selection(last_command, episodes_count)
114
-
115
- try:
116
- list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
117
- except ValueError as e:
118
- console.print(f"[red]{str(e)}")
119
- return
120
+ list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
120
121
 
121
122
  # Download selected episodes
122
123
  for i_episode in list_episode_select:
@@ -126,46 +127,47 @@ def download_episode(scape_info_serie: GetSerieInfo, index_season_selected: int,
126
127
  break
127
128
 
128
129
 
129
- def download_series(dict_serie: MediaItem) -> None:
130
+ def download_series(dict_serie: MediaItem, season_selection: str = None, episode_selection: str = None) -> None:
130
131
  """
131
- Download all episodes of a TV series.
132
+ Handle downloading a complete series.
132
133
 
133
134
  Parameters:
134
- - dict_serie (MediaItem): obj with url name type and score
135
+ - dict_serie (MediaItem): Series metadata from search
136
+ - season_selection (str, optional): Pre-defined season selection that bypasses manual input
137
+ - episode_selection (str, optional): Pre-defined episode selection that bypasses manual input
135
138
  """
136
-
137
- # Start message and set up video source
138
139
  start_message()
139
140
 
140
- # Init class
141
- scape_info_serie = GetSerieInfo(dict_serie)
142
-
143
- # Collect information about seasons
144
- seasons_count = scape_info_serie.get_seasons_number()
141
+ # Create class
142
+ scrape_serie = GetSerieInfo(dict_serie)
145
143
 
144
+ # Get season count
145
+ seasons_count = scrape_serie.get_seasons_number()
146
+
146
147
  # Prompt user for season selection and download episodes
147
148
  console.print(f"\n[green]Seasons found: [red]{seasons_count}")
148
- index_season_selected = msg.ask(
149
- "\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
150
- "[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"
151
- )
152
-
153
- # Manage and validate the selection
154
- list_season_select = manage_selection(index_season_selected, seasons_count)
155
149
 
156
- try:
157
- list_season_select = validate_selection(list_season_select, seasons_count)
158
- except ValueError as e:
159
- console.print(f"[red]{str(e)}")
160
- return
150
+ # If season_selection is provided, use it instead of asking for input
151
+ if season_selection is None:
152
+ index_season_selected = msg.ask(
153
+ "\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
154
+ "[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"
155
+ )
156
+ else:
157
+ index_season_selected = season_selection
158
+ console.print(f"\n[cyan]Using provided season selection: [yellow]{season_selection}")
159
+
160
+ # Validate the selection
161
+ list_season_select = manage_selection(index_season_selected, seasons_count)
162
+ list_season_select = validate_selection(list_season_select, seasons_count)
161
163
 
162
164
  # Loop through the selected seasons and download episodes
163
165
  for i_season in list_season_select:
164
166
  if len(list_season_select) > 1 or index_season_selected == "*":
165
167
 
166
168
  # Download all episodes if multiple seasons are selected or if '*' is used
167
- download_episode(scape_info_serie, i_season, download_all=True)
169
+ download_episode(scrape_serie, i_season, download_all=True)
168
170
  else:
169
171
 
170
172
  # Otherwise, let the user select specific episodes for the single season
171
- download_episode(scape_info_serie, i_season, download_all=False)
173
+ download_episode(scrape_serie, i_season, download_all=False, episode_selection=episode_selection)