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
@@ -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)
@@ -0,0 +1,153 @@
1
+ # 11.03.24
2
+
3
+ import os
4
+ from typing import Tuple
5
+
6
+
7
+ # External library
8
+ from rich.console import Console
9
+ from rich.prompt import Prompt
10
+
11
+
12
+ # Internal utilities
13
+ from StreamingCommunity.Util.os import os_manager
14
+ from StreamingCommunity.Util.message import start_message
15
+ from StreamingCommunity.Lib.Downloader import MP4_downloader
16
+ from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
17
+
18
+
19
+ # Logic class
20
+ from .util.ScrapeSerie import ScrapeSerieAnime
21
+ from StreamingCommunity.Api.Template.config_loader import site_constant
22
+ from StreamingCommunity.Api.Template.Util import manage_selection, dynamic_format_number
23
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
24
+
25
+
26
+ # Player
27
+ from StreamingCommunity.Api.Player.vixcloud import VideoSourceAnime
28
+
29
+
30
+ # Variable
31
+ console = Console()
32
+ msg = Prompt()
33
+ KILL_HANDLER = bool(False)
34
+
35
+
36
+ def download_episode(index_select: int, scrape_serie: ScrapeSerieAnime, video_source: VideoSourceAnime) -> Tuple[str,bool]:
37
+ """
38
+ Downloads the selected episode.
39
+
40
+ Parameters:
41
+ - index_select (int): Index of the episode to download.
42
+
43
+ Return:
44
+ - str: output path
45
+ - bool: kill handler status
46
+ """
47
+ start_message()
48
+
49
+ # Get episode information
50
+ obj_episode = scrape_serie.selectEpisode(1, index_select)
51
+ console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] ([cyan]E{obj_episode.number}[/cyan]) \n")
52
+
53
+ if site_constant.TELEGRAM_BOT:
54
+ bot = get_bot_instance()
55
+ bot.send_message(f"Download in corso\nAnime: {scrape_serie.series_name}\nEpisodio: {obj_episode.number}", None)
56
+
57
+ # Get script_id and update it
58
+ script_id = TelegramSession.get_session()
59
+ if script_id != "unknown":
60
+ TelegramSession.updateScriptId(script_id, f"{scrape_serie.series_name} - E{obj_episode.number}")
61
+
62
+ # Collect mp4 url
63
+ video_source.get_embed(obj_episode.id)
64
+
65
+ # Create output path
66
+ mp4_name = f"{scrape_serie.series_name}_EP_{dynamic_format_number(str(obj_episode.number))}.mp4"
67
+
68
+ if scrape_serie.is_series:
69
+ mp4_path = os_manager.get_sanitize_path(os.path.join(site_constant.ANIME_FOLDER, scrape_serie.series_name))
70
+ else:
71
+ mp4_path = os_manager.get_sanitize_path(os.path.join(site_constant.MOVIE_FOLDER, scrape_serie.series_name))
72
+
73
+ # Create output folder
74
+ os_manager.create_path(mp4_path)
75
+
76
+ # Start downloading
77
+ path, kill_handler = MP4_downloader(
78
+ url=str(video_source.src_mp4).strip(),
79
+ path=os.path.join(mp4_path, mp4_name)
80
+ )
81
+
82
+ return path, kill_handler
83
+
84
+
85
+ def download_series(select_title: MediaItem, season_selection: str = None, episode_selection: str = None):
86
+ """
87
+ Function to download episodes of a TV series.
88
+
89
+ Parameters:
90
+ - select_title (MediaItem): The selected media item
91
+ - season_selection (str, optional): Season selection input that bypasses manual input (usually '1' for anime)
92
+ - episode_selection (str, optional): Episode selection input that bypasses manual input
93
+ """
94
+ start_message()
95
+
96
+ if site_constant.TELEGRAM_BOT:
97
+ bot = get_bot_instance()
98
+
99
+ scrape_serie = ScrapeSerieAnime(site_constant.FULL_URL)
100
+ video_source = VideoSourceAnime(site_constant.FULL_URL)
101
+
102
+ # Set up video source (only configure scrape_serie now)
103
+ scrape_serie.setup(None, select_title.id, select_title.slug)
104
+
105
+ # Get episode information
106
+ episoded_count = scrape_serie.get_count_episodes()
107
+ console.print(f"[green]Episodes count:[/green] [red]{episoded_count}[/red]")
108
+
109
+ # Telegram bot integration
110
+ if episode_selection is None:
111
+ if site_constant.TELEGRAM_BOT:
112
+ console.print(f"\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")
113
+ bot.send_message(f"Episodi trovati: {episoded_count}", None)
114
+
115
+ last_command = bot.ask(
116
+ "select_title",
117
+ "Menu di selezione degli episodi: \n\n"
118
+ "- Inserisci il numero dell'episodio (ad esempio, 1)\n"
119
+ "- Inserisci * per scaricare tutti gli episodi\n"
120
+ "- Inserisci un intervallo di episodi (ad esempio, 1-2) per scaricare da un episodio all'altro\n"
121
+ "- Inserisci (ad esempio, 3-*) per scaricare dall'episodio specificato fino alla fine della serie",
122
+ None
123
+ )
124
+ else:
125
+ # Prompt user to select an episode index
126
+ 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")
127
+ else:
128
+ last_command = episode_selection
129
+ console.print(f"\n[cyan]Using provided episode selection: [yellow]{episode_selection}")
130
+
131
+ # Manage user selection
132
+ list_episode_select = manage_selection(last_command, episoded_count)
133
+
134
+ # Download selected episodes
135
+ if len(list_episode_select) == 1 and last_command != "*":
136
+ path, _ = download_episode(list_episode_select[0]-1, scrape_serie, video_source)
137
+ return path
138
+
139
+ # Download all other episodes selected
140
+ else:
141
+ kill_handler = False
142
+ for i_episode in list_episode_select:
143
+ if kill_handler:
144
+ break
145
+ _, kill_handler = download_episode(i_episode-1, scrape_serie, video_source)
146
+
147
+ if site_constant.TELEGRAM_BOT:
148
+ bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
149
+
150
+ # Get script_id
151
+ script_id = TelegramSession.get_session()
152
+ if script_id != "unknown":
153
+ TelegramSession.deleteScriptId(script_id)
@@ -1,6 +1,5 @@
1
1
  # 10.12.23
2
2
 
3
- import sys
4
3
  import logging
5
4
 
6
5
 
@@ -52,10 +51,8 @@ def get_token() -> dict:
52
51
 
53
52
  for html_meta in soup.find_all("meta"):
54
53
  if html_meta.get('name') == "csrf-token":
55
-
56
54
  find_csrf_token = html_meta.get('content')
57
55
 
58
- logging.info(f"Extract: ('animeunity_session': {response.cookies['animeunity_session']}, 'csrf_token': {find_csrf_token})")
59
56
  return {
60
57
  'animeunity_session': response.cookies['animeunity_session'],
61
58
  'csrf_token': find_csrf_token
@@ -65,9 +62,6 @@ def get_token() -> dict:
65
62
  def get_real_title(record):
66
63
  """
67
64
  Get the real title from a record.
68
-
69
- This function takes a record, which is assumed to be a dictionary representing a row of JSON data.
70
- It looks for a title in the record, prioritizing English over Italian titles if available.
71
65
 
72
66
  Parameters:
73
67
  - record (dict): A dictionary representing a row of JSON data.
@@ -85,7 +79,7 @@ def get_real_title(record):
85
79
 
86
80
  def title_search(query: str) -> int:
87
81
  """
88
- Function to perform an anime search using a provided query.
82
+ Function to perform an anime search using both APIs and combine results.
89
83
 
90
84
  Parameters:
91
85
  - query (str): The query to search for.
@@ -98,63 +92,96 @@ def title_search(query: str) -> int:
98
92
 
99
93
  media_search_manager.clear()
100
94
  table_show_manager.clear()
95
+ seen_titles = set()
96
+ choices = [] if site_constant.TELEGRAM_BOT else None
101
97
 
102
98
  # Create parameter for request
103
99
  data = get_token()
104
- cookies = {'animeunity_session': data.get('animeunity_session')}
100
+ cookies = {
101
+ 'animeunity_session': data.get('animeunity_session')
102
+ }
105
103
  headers = {
106
104
  'user-agent': get_userAgent(),
107
105
  'x-csrf-token': data.get('csrf_token')
108
106
  }
109
- json_data = {'title': query}
110
107
 
111
- # Send a POST request to the API endpoint for live search
108
+ # First API call - livesearch
109
+ try:
110
+ response1 = httpx.post(
111
+ f'{site_constant.FULL_URL}/livesearch',
112
+ cookies=cookies,
113
+ headers=headers,
114
+ json={'title': query},
115
+ timeout=max_timeout
116
+ )
117
+
118
+ response1.raise_for_status()
119
+ process_results(response1.json()['records'], seen_titles, media_search_manager, choices)
120
+
121
+ except Exception as e:
122
+ console.print(f"Site: {site_constant.SITE_NAME}, livesearch error: {e}")
123
+
124
+ # Second API call - archivio
112
125
  try:
113
- response = httpx.post(
114
- f'{site_constant.FULL_URL}/livesearch',
115
- cookies=cookies,
116
- headers=headers,
126
+ json_data = {
127
+ 'title': query,
128
+ 'type': False,
129
+ 'year': False,
130
+ 'order': 'Lista A-Z',
131
+ 'status': False,
132
+ 'genres': False,
133
+ 'offset': 0,
134
+ 'dubbed': False,
135
+ 'season': False
136
+ }
137
+
138
+ response2 = httpx.post(
139
+ f'{site_constant.FULL_URL}/archivio/get-animes',
140
+ cookies=cookies,
141
+ headers=headers,
117
142
  json=json_data,
118
143
  timeout=max_timeout
119
144
  )
120
- response.raise_for_status()
145
+
146
+ response2.raise_for_status()
147
+ process_results(response2.json()['records'], seen_titles, media_search_manager, choices)
121
148
 
122
149
  except Exception as e:
123
- console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
124
- return 0
150
+ console.print(f"Site: {site_constant.SITE_NAME}, archivio search error: {e}")
125
151
 
126
- # Inizializza la lista delle scelte
127
- if site_constant.TELEGRAM_BOT:
128
- choices = []
152
+ if site_constant.TELEGRAM_BOT and choices and len(choices) > 0:
153
+ bot.send_message(f"Lista dei risultati:", choices)
154
+
155
+ result_count = media_search_manager.get_length()
156
+ if result_count == 0:
157
+ console.print(f"Nothing matching was found for: {query}")
158
+
159
+ return result_count
129
160
 
130
- for dict_title in response.json()['records']:
161
+ def process_results(records: list, seen_titles: set, media_manager: MediaManager, choices: list = None) -> None:
162
+ """Helper function to process search results and add unique entries."""
163
+ for dict_title in records:
131
164
  try:
132
-
133
- # Rename keys for consistency
165
+ title_id = dict_title.get('id')
166
+ if title_id in seen_titles:
167
+ continue
168
+
169
+ seen_titles.add(title_id)
134
170
  dict_title['name'] = get_real_title(dict_title)
135
171
 
136
- media_search_manager.add_media({
137
- 'id': dict_title.get('id'),
172
+ media_manager.add_media({
173
+ 'id': title_id,
138
174
  'slug': dict_title.get('slug'),
139
175
  'name': dict_title.get('name'),
140
176
  'type': dict_title.get('type'),
141
177
  'status': dict_title.get('status'),
142
178
  'episodes_count': dict_title.get('episodes_count'),
143
- 'plot': ' '.join((words := str(dict_title.get('plot', '')).split())[:10]) + ('...' if len(words) > 10 else '')
179
+ 'image': dict_title.get('imageurl')
144
180
  })
145
181
 
146
- if site_constant.TELEGRAM_BOT:
147
-
148
- # Crea una stringa formattata per ogni scelta con numero
182
+ if choices is not None:
149
183
  choice_text = f"{len(choices)} - {dict_title.get('name')} ({dict_title.get('type')}) - Episodi: {dict_title.get('episodes_count')}"
150
184
  choices.append(choice_text)
151
185
 
152
186
  except Exception as e:
153
- print(f"Error parsing a film entry: {e}")
154
-
155
- if site_constant.TELEGRAM_BOT:
156
- if choices:
157
- bot.send_message(f"Lista dei risultati:", choices)
158
-
159
- # Return the length of media search manager
160
- return media_search_manager.get_length()
187
+ print(f"Error parsing a title entry: {e}")
@@ -29,6 +29,7 @@ class ScrapeSerieAnime:
29
29
  self.is_series = False
30
30
  self.headers = {'user-agent': get_userAgent()}
31
31
  self.url = url
32
+ self.episodes_cache = None
32
33
 
33
34
  def setup(self, version: str = None, media_id: int = None, series_name: str = None):
34
35
  self.version = version
@@ -62,35 +63,53 @@ class ScrapeSerieAnime:
62
63
  logging.error(f"Error fetching episode count: {e}")
63
64
  return None
64
65
 
65
- def get_info_episode(self, index_ep: int) -> Episode:
66
+ def _fetch_all_episodes(self):
66
67
  """
67
- Fetch detailed information for a specific episode.
68
-
69
- Args:
70
- index_ep (int): Zero-based index of the target episode
71
-
72
- Returns:
73
- Episode: Detailed episode information
68
+ Fetch all episodes data at once and cache it
74
69
  """
75
70
  try:
76
-
77
- params = {
78
- "start_range": index_ep,
79
- "end_range": index_ep + 1
80
- }
71
+ count = self.get_count_episodes()
72
+ if not count:
73
+ return
81
74
 
82
75
  response = httpx.get(
83
- url=f"{self.url}/info_api/{self.media_id}/{index_ep}",
84
- headers=self.headers,
85
- params=params,
76
+ url=f"{self.url}/info_api/{self.media_id}/1",
77
+ params={
78
+ "start_range": 1,
79
+ "end_range": count
80
+ },
81
+ headers=self.headers,
86
82
  timeout=max_timeout
87
83
  )
88
84
  response.raise_for_status()
85
+
86
+ self.episodes_cache = response.json()["episodes"]
87
+ except Exception as e:
88
+ logging.error(f"Error fetching all episodes: {e}")
89
+ self.episodes_cache = None
89
90
 
90
- # Return information about the episode
91
- json_data = response.json()["episodes"][-1]
92
- return Episode(json_data)
91
+ def get_info_episode(self, index_ep: int) -> Episode:
92
+ """
93
+ Get episode info from cache
94
+ """
95
+ if self.episodes_cache is None:
96
+ self._fetch_all_episodes()
97
+
98
+ if self.episodes_cache and 0 <= index_ep < len(self.episodes_cache):
99
+ return Episode(self.episodes_cache[index_ep])
100
+ return None
101
+
102
+
103
+ # ------------- FOR GUI -------------
104
+ def getNumberSeason(self) -> int:
105
+ """
106
+ Get the total number of seasons available for the anime.
107
+ Note: AnimeUnity typically doesn't have seasons, so returns 1.
108
+ """
109
+ return 1
93
110
 
94
- except Exception as e:
95
- logging.error(f"Error fetching episode information: {e}")
96
- return None
111
+ def selectEpisode(self, season_number: int = 1, episode_index: int = 0) -> Episode:
112
+ """
113
+ Get information for a specific episode.
114
+ """
115
+ return self.get_info_episode(episode_index)
@@ -14,13 +14,13 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
14
14
  # Logic class
15
15
  from .site import title_search, media_search_manager, table_show_manager
16
16
  from .serie import download_series
17
+ from .film import download_film
17
18
 
18
19
 
19
20
  # Variable
20
21
  indice = 8
21
22
  _useFor = "anime"
22
- _deprecate = False
23
- _priority = 2
23
+ _priority = 0
24
24
  _engineDownload = "mp4"
25
25
 
26
26
  msg = Prompt()
@@ -28,44 +28,56 @@ console = Console()
28
28
 
29
29
 
30
30
 
31
- def process_search_result(select_title):
31
+ def process_search_result(select_title, selections=None):
32
32
  """
33
33
  Handles the search result and initiates the download for either a film or series.
34
+
35
+ Parameters:
36
+ select_title (MediaItem): The selected media item
37
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
38
+ {'season': season_selection, 'episode': episode_selection}
34
39
  """
35
40
  if select_title.type == "TV":
36
- download_series(select_title)
41
+ episode_selection = None
42
+ if selections:
43
+ episode_selection = selections.get('episode')
44
+ download_series(select_title, episode_selection)
45
+
46
+ else:
47
+ download_film(select_title)
37
48
 
38
- def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
49
+ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
39
50
  """
40
- Main function of the application for search film, series and anime.
51
+ Main function of the application for search.
41
52
 
42
53
  Parameters:
43
54
  string_to_search (str, optional): String to search for
44
55
  get_onlyDatabase (bool, optional): If True, return only the database object
45
56
  direct_item (dict, optional): Direct item to process (bypass search)
57
+ selections (dict, optional): Dictionary containing selection inputs that bypass manual input
58
+ {'season': season_selection, 'episode': episode_selection}
46
59
  """
47
60
  if direct_item:
48
61
  select_title = MediaItem(**direct_item)
49
- process_search_result(select_title)
62
+ process_search_result(select_title, selections)
50
63
  return
51
64
 
52
65
  # Get the user input for the search term
53
- string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
66
+ if string_to_search is None:
67
+ string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
54
68
 
55
69
  # Perform the database search
56
70
  len_database = title_search(string_to_search)
57
71
 
58
- ##If only the database is needed, return the manager
72
+ # If only the database is needed, return the manager
59
73
  if get_onlyDatabase:
60
74
  return media_search_manager
61
75
 
62
76
  if len_database > 0:
63
77
  select_title = get_select_title(table_show_manager, media_search_manager)
64
- process_search_result(select_title)
65
-
78
+ process_search_result(select_title, selections)
79
+
66
80
  else:
67
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
68
-
69
81
  # If no results are found, ask again
70
- string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
82
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
71
83
  search()
@@ -0,0 +1,63 @@
1
+ # 11.03.24
2
+
3
+ import os
4
+
5
+ # External library
6
+ from rich.console import Console
7
+
8
+
9
+ # Internal utilities
10
+ from StreamingCommunity.Util.os import os_manager
11
+ from StreamingCommunity.Util.message import start_message
12
+ from StreamingCommunity.Lib.Downloader import MP4_downloader
13
+
14
+
15
+ # Logic class
16
+ from .util.ScrapeSerie import ScrapSerie
17
+ from StreamingCommunity.Api.Template.config_loader import site_constant
18
+ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
19
+
20
+
21
+ # Player
22
+ from StreamingCommunity.Api.Player.sweetpixel import VideoSource
23
+
24
+
25
+ # Variable
26
+ console = Console()
27
+
28
+
29
+ def download_film(select_title: MediaItem):
30
+ """
31
+ Function to download a film.
32
+
33
+ Parameters:
34
+ - id_film (int): The ID of the film.
35
+ - title_name (str): The title of the film.
36
+ """
37
+ start_message()
38
+
39
+ scrape_serie = ScrapSerie(select_title.url, site_constant.FULL_URL)
40
+ episodes = scrape_serie.get_episodes()
41
+
42
+ # Get episode information
43
+ episode_data = episodes[0]
44
+ console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] ([cyan]{scrape_serie.get_name()}[/cyan]) \n")
45
+
46
+ # Define filename and path for the downloaded video
47
+ mp4_name = f"{scrape_serie.get_name()}.mp4"
48
+ mp4_path = os.path.join(site_constant.ANIME_FOLDER, scrape_serie.get_name())
49
+
50
+ # Create output folder
51
+ os_manager.create_path(mp4_path)
52
+
53
+ # Get video source for the episode
54
+ video_source = VideoSource(site_constant.FULL_URL, episode_data, scrape_serie.session_id, scrape_serie.csrf_token)
55
+ mp4_link = video_source.get_playlist()
56
+
57
+ # Start downloading
58
+ path, kill_handler = MP4_downloader(
59
+ url=str(mp4_link).strip(),
60
+ path=os.path.join(mp4_path, mp4_name)
61
+ )
62
+
63
+ return path, kill_handler