StreamingCommunity 2.9.8__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 (59) 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/table.py +4 -2
  50. {streamingcommunity-2.9.8.dist-info → streamingcommunity-2.9.9.dist-info}/METADATA +1 -1
  51. streamingcommunity-2.9.9.dist-info/RECORD +91 -0
  52. {streamingcommunity-2.9.8.dist-info → streamingcommunity-2.9.9.dist-info}/WHEEL +1 -1
  53. StreamingCommunity/Api/Site/animeunity/film_serie.py +0 -181
  54. StreamingCommunity/Api/Site/mostraguarda/__init__.py +0 -73
  55. StreamingCommunity/Api/Site/mostraguarda/film.py +0 -93
  56. streamingcommunity-2.9.8.dist-info/RECORD +0 -85
  57. {streamingcommunity-2.9.8.dist-info → streamingcommunity-2.9.9.dist-info}/entry_points.txt +0 -0
  58. {streamingcommunity-2.9.8.dist-info → streamingcommunity-2.9.9.dist-info}/licenses/LICENSE +0 -0
  59. {streamingcommunity-2.9.8.dist-info → streamingcommunity-2.9.9.dist-info}/top_level.txt +0 -0
@@ -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
 
@@ -140,7 +139,7 @@ def title_search(query: str) -> int:
140
139
  'type': dict_title.get('type'),
141
140
  'status': dict_title.get('status'),
142
141
  'episodes_count': dict_title.get('episodes_count'),
143
- 'plot': ' '.join((words := str(dict_title.get('plot', '')).split())[:10]) + ('...' if len(words) > 10 else '')
142
+ 'image': dict_title.get('imageurl')
144
143
  })
145
144
 
146
145
  if site_constant.TELEGRAM_BOT:
@@ -94,3 +94,18 @@ class ScrapeSerieAnime:
94
94
  except Exception as e:
95
95
  logging.error(f"Error fetching episode information: {e}")
96
96
  return None
97
+
98
+
99
+ # ------------- FOR GUI -------------
100
+ def getNumberSeason(self) -> int:
101
+ """
102
+ Get the total number of seasons available for the anime.
103
+ Note: AnimeUnity typically doesn't have seasons, so returns 1.
104
+ """
105
+ return 1
106
+
107
+ def selectEpisode(self, season_number: int = 1, episode_index: int = 0) -> Episode:
108
+ """
109
+ Get information for a specific episode.
110
+ """
111
+ return self.get_info_episode(episode_index)
@@ -14,6 +14,7 @@ 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
@@ -28,44 +29,56 @@ console = Console()
28
29
 
29
30
 
30
31
 
31
- def process_search_result(select_title):
32
+ def process_search_result(select_title, selections=None):
32
33
  """
33
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}
34
40
  """
35
41
  if select_title.type == "TV":
36
- download_series(select_title)
42
+ episode_selection = None
43
+ if selections:
44
+ episode_selection = selections.get('episode')
45
+ download_series(select_title, episode_selection)
46
+
47
+ else:
48
+ download_film(select_title)
37
49
 
38
- 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):
39
51
  """
40
- Main function of the application for search film, series and anime.
52
+ Main function of the application for search.
41
53
 
42
54
  Parameters:
43
55
  string_to_search (str, optional): String to search for
44
56
  get_onlyDatabase (bool, optional): If True, return only the database object
45
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}
46
60
  """
47
61
  if direct_item:
48
62
  select_title = MediaItem(**direct_item)
49
- process_search_result(select_title)
63
+ process_search_result(select_title, selections)
50
64
  return
51
65
 
52
66
  # 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()
67
+ if string_to_search is None:
68
+ string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
54
69
 
55
70
  # Perform the database search
56
71
  len_database = title_search(string_to_search)
57
72
 
58
- ##If only the database is needed, return the manager
73
+ # If only the database is needed, return the manager
59
74
  if get_onlyDatabase:
60
75
  return media_search_manager
61
76
 
62
77
  if len_database > 0:
63
78
  select_title = get_select_title(table_show_manager, media_search_manager)
64
- process_search_result(select_title)
65
-
79
+ process_search_result(select_title, selections)
80
+
66
81
  else:
67
- console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
68
-
69
82
  # 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()
83
+ console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
71
84
  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
@@ -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)
@@ -101,7 +101,8 @@ def title_search(query: str) -> int:
101
101
  'name': title,
102
102
  'type': anime_type,
103
103
  'DUB': is_dubbed,
104
- 'url': url
104
+ 'url': url,
105
+ 'image': element.find('img').get('src')
105
106
  })
106
107
 
107
108
  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]
@@ -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
@@ -42,7 +42,7 @@ def process_search_result(select_title):
42
42
 
43
43
  def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
44
44
  """
45
- Main function of the application for search film, series and anime.
45
+ Main function of the application for search.
46
46
 
47
47
  Parameters:
48
48
  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
 
@@ -67,7 +66,8 @@ def title_search(query: str) -> int:
67
66
  title_info = {
68
67
  'name': name,
69
68
  'url': link,
70
- 'type': title_type
69
+ 'type': title_type,
70
+ 'image': title_div.find("div", class_="ipsColumn").find("img").get("src")
71
71
  }
72
72
 
73
73
  media_search_manager.add_media(title_info)