StreamingCommunity 2.9.3__py3-none-any.whl → 2.9.4__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 (33) hide show
  1. StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +40 -38
  2. StreamingCommunity/Api/Player/maxstream.py +3 -11
  3. StreamingCommunity/Api/Site/1337xx/site.py +1 -9
  4. StreamingCommunity/Api/Site/altadefinizione/__init__.py +61 -0
  5. StreamingCommunity/Api/Site/altadefinizione/film.py +98 -0
  6. StreamingCommunity/Api/Site/altadefinizione/series.py +164 -0
  7. StreamingCommunity/Api/Site/altadefinizione/site.py +75 -0
  8. StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +72 -0
  9. StreamingCommunity/Api/Site/animeunity/film_serie.py +1 -1
  10. StreamingCommunity/Api/Site/animeunity/site.py +1 -9
  11. StreamingCommunity/Api/Site/cb01new/site.py +5 -16
  12. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +1 -9
  13. StreamingCommunity/Api/Site/guardaserie/site.py +1 -9
  14. StreamingCommunity/Api/Site/streamingcommunity/series.py +29 -11
  15. StreamingCommunity/Api/Site/streamingcommunity/site.py +10 -10
  16. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +38 -17
  17. StreamingCommunity/Api/Template/Class/SearchType.py +1 -1
  18. StreamingCommunity/Api/Template/Util/__init__.py +0 -1
  19. StreamingCommunity/Api/Template/Util/manage_ep.py +1 -0
  20. StreamingCommunity/Api/Template/config_loader.py +0 -4
  21. StreamingCommunity/Lib/Downloader/HLS/downloader.py +2 -2
  22. StreamingCommunity/Lib/Downloader/MP4/downloader.py +3 -2
  23. StreamingCommunity/Lib/M3U8/estimator.py +3 -3
  24. StreamingCommunity/Upload/version.py +1 -1
  25. StreamingCommunity/Util/config_json.py +0 -3
  26. StreamingCommunity/__init__.py +6 -0
  27. {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.4.dist-info}/METADATA +90 -7
  28. {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.4.dist-info}/RECORD +32 -28
  29. {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.4.dist-info}/WHEEL +1 -1
  30. StreamingCommunity/Api/Template/Util/get_domain.py +0 -100
  31. {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.4.dist-info}/LICENSE +0 -0
  32. {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.4.dist-info}/entry_points.txt +0 -0
  33. {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.4.dist-info}/top_level.txt +0 -0
@@ -17,7 +17,6 @@ from StreamingCommunity.Util.table import TVShowManager
17
17
 
18
18
  # Logic class
19
19
  from StreamingCommunity.Api.Template.config_loader import site_constant
20
- from StreamingCommunity.Api.Template.Util import search_domain
21
20
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
22
21
 
23
22
 
@@ -41,15 +40,7 @@ def title_search(word_to_search: str) -> int:
41
40
  media_search_manager.clear()
42
41
  table_show_manager.clear()
43
42
 
44
- # Check if domain is working
45
- domain_to_use, base_url = search_domain(site_constant.FULL_URL)
46
-
47
- if domain_to_use is None or base_url is None:
48
- console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
49
- console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
50
- sys.exit(1)
51
-
52
- search_url = f"{site_constant.FULL_URL}/?s={word_to_search}"
43
+ search_url = f"{site_constant.FULL_URL}/?story={word_to_search}&do=search&subaction=search"
53
44
  console.print(f"[cyan]Search url: [yellow]{search_url}")
54
45
 
55
46
  try:
@@ -58,20 +49,18 @@ def title_search(word_to_search: str) -> int:
58
49
 
59
50
  except Exception as e:
60
51
  console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
52
+ return 0
61
53
 
62
54
  # Create soup and find table
63
55
  soup = BeautifulSoup(response.text, "html.parser")
64
56
 
65
- for div in soup.find_all("div", class_ = "card-content"):
57
+ for div in soup.find_all("div", class_ = "short-main"):
66
58
  try:
67
-
68
- url = div.find("h3").find("a").get("href")
69
- title = div.find("h3").find("a").get_text(strip=True)
70
- desc = div.find("p").find("strong").text
59
+ url = div.find("a").get("href")
60
+ title = div.find("a").get_text(strip=True)
71
61
 
72
62
  title_info = {
73
63
  'name': title,
74
- 'desc': desc,
75
64
  'url': url
76
65
  }
77
66
 
@@ -18,7 +18,6 @@ from StreamingCommunity.Util.table import TVShowManager
18
18
 
19
19
  # Logic class
20
20
  from StreamingCommunity.Api.Template.config_loader import site_constant
21
- from StreamingCommunity.Api.Template.Util import search_domain
22
21
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
23
22
 
24
23
 
@@ -42,14 +41,6 @@ def title_search(word_to_search: str) -> int:
42
41
  media_search_manager.clear()
43
42
  table_show_manager.clear()
44
43
 
45
- # Check if domain is working
46
- domain_to_use, base_url = search_domain(site_constant.FULL_URL)
47
-
48
- if domain_to_use is None or base_url is None:
49
- console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
50
- console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
51
- sys.exit(1)
52
-
53
44
  search_url = f"{site_constant.FULL_URL}/search/?&q={word_to_search}&quick=1&type=videobox_video&nodes=11"
54
45
  console.print(f"[cyan]Search url: [yellow]{search_url}")
55
46
 
@@ -59,6 +50,7 @@ def title_search(word_to_search: str) -> int:
59
50
 
60
51
  except Exception as e:
61
52
  console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
53
+ return 0
62
54
 
63
55
  # Create soup and find table
64
56
  soup = BeautifulSoup(response.text, "html.parser")
@@ -16,7 +16,6 @@ from StreamingCommunity.Util.table import TVShowManager
16
16
 
17
17
  # Logic class
18
18
  from StreamingCommunity.Api.Template.config_loader import site_constant
19
- from StreamingCommunity.Api.Template.Util import search_domain
20
19
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
21
20
 
22
21
 
@@ -41,14 +40,6 @@ def title_search(word_to_search: str) -> int:
41
40
  media_search_manager.clear()
42
41
  table_show_manager.clear()
43
42
 
44
- # Check if domain is working
45
- domain_to_use, base_url = search_domain(site_constant.FULL_URL)
46
-
47
- if domain_to_use is None or base_url is None:
48
- console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
49
- console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
50
- sys.exit(1)
51
-
52
43
  search_url = f"{site_constant.FULL_URL}/?story={word_to_search}&do=search&subaction=search"
53
44
  console.print(f"[cyan]Search url: [yellow]{search_url}")
54
45
 
@@ -58,6 +49,7 @@ def title_search(word_to_search: str) -> int:
58
49
 
59
50
  except Exception as e:
60
51
  console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
52
+ return 0
61
53
 
62
54
  # Create soup and find table
63
55
  soup = BeautifulSoup(response.text, "html.parser")
@@ -52,8 +52,15 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
52
52
  start_message()
53
53
  index_season_selected = dynamic_format_number(str(index_season_selected))
54
54
 
55
+ # SPECIAL: Get season number
56
+ season = None
57
+ for s in scrape_serie.seasons_manager.seasons:
58
+ if s.number == int(index_season_selected):
59
+ season = s
60
+ break
61
+
55
62
  # Get info about episode
56
- obj_episode = scrape_serie.episode_manager.get(index_episode_selected - 1)
63
+ obj_episode = season.episodes.get(index_episode_selected - 1)
57
64
  console.print(f"[yellow]Download: [red]{index_season_selected}:{index_episode_selected} {obj_episode.name}")
58
65
  print()
59
66
 
@@ -100,14 +107,16 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, vid
100
107
  - index_season_selected (int): Index of the selected season.
101
108
  - download_all (bool): Download all episodes in the season.
102
109
  """
103
-
104
- # Clean memory of all episodes and get the number of the season
105
- scrape_serie.episode_manager.clear()
106
-
107
- # Start message and collect information about episodes
108
110
  start_message()
109
111
  scrape_serie.collect_info_season(index_season_selected)
110
- episodes_count = scrape_serie.episode_manager.length()
112
+
113
+ # SPECIAL: Get season number
114
+ season = None
115
+ for s in scrape_serie.seasons_manager.seasons:
116
+ if s.number == index_season_selected:
117
+ season = s
118
+ break
119
+ episodes_count = len(season.episodes.episodes)
111
120
 
112
121
  if download_all:
113
122
 
@@ -123,7 +132,7 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, vid
123
132
  else:
124
133
 
125
134
  # Display episodes list and manage user selection
126
- last_command = display_episodes_list(scrape_serie.episode_manager.episodes)
135
+ last_command = display_episodes_list(season.episodes.episodes)
127
136
  list_episode_select = manage_selection(last_command, episodes_count)
128
137
 
129
138
  try:
@@ -163,7 +172,7 @@ def download_series(select_season: MediaItem) -> None:
163
172
 
164
173
  # Collect information about seasons
165
174
  scrape_serie.collect_info_title()
166
- seasons_count = scrape_serie.season_manager.seasons_count
175
+ seasons_count = len(scrape_serie.seasons_manager)
167
176
 
168
177
  # Prompt user for season selection and download episodes
169
178
  console.print(f"\n[green]Seasons found: [red]{seasons_count}")
@@ -197,14 +206,23 @@ def download_series(select_season: MediaItem) -> None:
197
206
 
198
207
  # Loop through the selected seasons and download episodes
199
208
  for i_season in list_season_select:
209
+
210
+ # SPECIAL: Get season number
211
+ season = None
212
+ for s in scrape_serie.seasons_manager.seasons:
213
+ if s.number == i_season:
214
+ season = s
215
+ break
216
+ season_number = season.number
217
+
200
218
  if len(list_season_select) > 1 or index_season_selected == "*":
201
219
 
202
220
  # Download all episodes if multiple seasons are selected or if '*' is used
203
- download_episode(scrape_serie.season_manager.seasonsData.get_season_by_number(i_season-1).number, scrape_serie, video_source, download_all=True)
221
+ download_episode(season_number, scrape_serie, video_source, download_all=True)
204
222
  else:
205
223
 
206
224
  # Otherwise, let the user select specific episodes for the single season
207
- download_episode(scrape_serie.season_manager.seasonsData.get_season_by_number(i_season-1).number, scrape_serie, video_source, download_all=False)
225
+ download_episode(season_number, scrape_serie, video_source, download_all=False)
208
226
 
209
227
  if site_constant.TELEGRAM_BOT:
210
228
  bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
@@ -17,7 +17,6 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
17
17
 
18
18
  # Logic class
19
19
  from StreamingCommunity.Api.Template.config_loader import site_constant
20
- from StreamingCommunity.Api.Template.Util import search_domain
21
20
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
22
21
 
23
22
 
@@ -38,13 +37,6 @@ def title_search(title_search: str) -> int:
38
37
  Returns:
39
38
  int: The number of titles found.
40
39
  """
41
- domain_to_use, base_url = search_domain(site_constant.FULL_URL)
42
-
43
- if domain_to_use is None or base_url is None:
44
- console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
45
- console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
46
- sys.exit(1)
47
-
48
40
  if site_constant.TELEGRAM_BOT:
49
41
  bot = get_bot_instance()
50
42
 
@@ -60,12 +52,20 @@ def title_search(title_search: str) -> int:
60
52
 
61
53
  except Exception as e:
62
54
  console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
55
+ return 0
63
56
 
64
57
  # Prepara le scelte per l'utente
65
58
  if site_constant.TELEGRAM_BOT:
66
59
  choices = []
67
-
68
- for i, dict_title in enumerate(response.json()['data']):
60
+
61
+ # Collect json data
62
+ try:
63
+ data = response.json().get('data', [])
64
+ except Exception as e:
65
+ console.log(f"Error parsing JSON response: {e}")
66
+ return 0
67
+
68
+ for i, dict_title in enumerate(data):
69
69
  try:
70
70
  media_search_manager.add_media({
71
71
  'id': dict_title.get('id'),
@@ -12,7 +12,7 @@ from bs4 import BeautifulSoup
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.headers import get_userAgent
14
14
  from StreamingCommunity.Util.config_json import config_manager
15
- from StreamingCommunity.Api.Player.Helper.Vixcloud.util import Season, EpisodeManager
15
+ from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
16
16
 
17
17
 
18
18
  # Variable
@@ -22,7 +22,7 @@ max_timeout = config_manager.get_int("REQUESTS", "timeout")
22
22
  class GetSerieInfo:
23
23
  def __init__(self, url):
24
24
  """
25
- Initialize the ScrapeSerie class for scraping TV series information.
25
+ Initialize the GetSerieInfo class for scraping TV series information.
26
26
 
27
27
  Args:
28
28
  - url (str): The URL of the streaming site.
@@ -31,6 +31,9 @@ class GetSerieInfo:
31
31
  self.headers = {'user-agent': get_userAgent()}
32
32
  self.url = url
33
33
 
34
+ # Initialize the SeasonManager
35
+ self.seasons_manager = SeasonManager()
36
+
34
37
  def setup(self, media_id: int = None, series_name: str = None):
35
38
  """
36
39
  Set up the scraper with specific media details.
@@ -41,19 +44,17 @@ class GetSerieInfo:
41
44
  """
42
45
  self.media_id = media_id
43
46
 
44
- # If series name is provided, initialize series-specific managers
47
+ # If series name is provided, initialize series-specific properties
45
48
  if series_name is not None:
46
49
  self.is_series = True
47
50
  self.series_name = series_name
48
- self.season_manager = None
49
- self.episode_manager: EpisodeManager = EpisodeManager()
50
51
 
51
52
  def collect_info_title(self) -> None:
52
53
  """
53
- Retrieve season information for a TV series from the streaming site.
54
+ Retrieve general information about the TV series from the streaming site.
54
55
 
55
56
  Raises:
56
- Exception: If there's an error fetching season information
57
+ Exception: If there's an error fetching series information
57
58
  """
58
59
  try:
59
60
  response = httpx.get(
@@ -63,16 +64,30 @@ class GetSerieInfo:
63
64
  )
64
65
  response.raise_for_status()
65
66
 
66
- # Extract seasons from JSON response
67
+ # Extract series info from JSON response
67
68
  soup = BeautifulSoup(response.text, "html.parser")
68
69
  json_response = json.loads(soup.find("div", {"id": "app"}).get("data-page"))
69
70
  self.version = json_response['version']
70
-
71
- # Collect info about season
72
- self.season_manager = Season(json_response.get("props").get("title"))
71
+
72
+ # Extract information about available seasons
73
+ title_data = json_response.get("props", {}).get("title", {})
74
+
75
+ # Save general series information
76
+ self.title_info = title_data
77
+
78
+ # Extract available seasons and add them to SeasonManager
79
+ seasons_data = title_data.get("seasons", [])
80
+ for season_data in seasons_data:
81
+ self.seasons_manager.add_season({
82
+ 'id': season_data.get('id', 0),
83
+ 'number': season_data.get('number', 0),
84
+ 'name': f"Season {season_data.get('number', 0)}",
85
+ 'slug': season_data.get('slug', ''),
86
+ 'type': title_data.get('type', '')
87
+ })
73
88
 
74
89
  except Exception as e:
75
- logging.error(f"Error collecting season info: {e}")
90
+ logging.error(f"Error collecting series info: {e}")
76
91
  raise
77
92
 
78
93
  def collect_info_season(self, number_season: int) -> None:
@@ -86,6 +101,12 @@ class GetSerieInfo:
86
101
  Exception: If there's an error fetching episode information
87
102
  """
88
103
  try:
104
+ # Get the season object from SeasonManager
105
+ season = self.seasons_manager.get_season_by_number(number_season)
106
+ if not season:
107
+ logging.error(f"Season {number_season} not found")
108
+ return
109
+
89
110
  response = httpx.get(
90
111
  url=f'{self.url}/titles/{self.media_id}-{self.series_name}/stagione-{number_season}',
91
112
  headers={
@@ -98,12 +119,12 @@ class GetSerieInfo:
98
119
  response.raise_for_status()
99
120
 
100
121
  # Extract episodes from JSON response
101
- json_response = response.json().get('props').get('loadedSeason').get('episodes')
122
+ json_response = response.json().get('props', {}).get('loadedSeason', {}).get('episodes', [])
102
123
 
103
- # Add each episode to the episode manager
124
+ # Add each episode to the corresponding season's episode manager
104
125
  for dict_episode in json_response:
105
- self.episode_manager.add(dict_episode)
126
+ season.episodes.add(dict_episode)
106
127
 
107
128
  except Exception as e:
108
- logging.error(f"Error collecting title season info: {e}")
109
- raise
129
+ logging.error(f"Error collecting episodes for season {number_season}: {e}")
130
+ raise
@@ -98,4 +98,4 @@ class MediaManager:
98
98
  self.media_list.clear()
99
99
 
100
100
  def __str__(self):
101
- return f"MediaManager(num_media={len(self.media_list)})"
101
+ return f"MediaManager(num_media={len(self.media_list)})"
@@ -1,6 +1,5 @@
1
1
  # 23.11.24
2
2
 
3
- from .get_domain import search_domain
4
3
  from .manage_ep import (
5
4
  manage_selection,
6
5
  map_episode_title,
@@ -218,6 +218,7 @@ def validate_episode_selection(list_episode_select: List[int], episodes_count: i
218
218
  input_episodes = input(f"Enter valid episode numbers (1-{episodes_count}): ")
219
219
  list_episode_select = list(map(int, input_episodes.split(',')))
220
220
 
221
+
221
222
  def display_episodes_list(episodes_manager) -> str:
222
223
  """
223
224
  Display episodes list and handle user input.
@@ -31,10 +31,6 @@ class SiteConstant:
31
31
  def ROOT_PATH(self):
32
32
  return config_manager.get('OUT_FOLDER', 'root_path')
33
33
 
34
- @property
35
- def DOMAIN_NOW(self):
36
- return config_manager.get_site(self.SITE_NAME, 'domain')
37
-
38
34
  @property
39
35
  def FULL_URL(self):
40
36
  return config_manager.get_site(self.SITE_NAME, 'full_url').rstrip('/')
@@ -438,13 +438,13 @@ class HLS_Downloader:
438
438
  return response
439
439
 
440
440
  if GET_ONLY_LINK:
441
- console.print(f"URL: {self.m3u8_url}[/bold red]")
441
+ console.print(f"URL: [bold red]{self.m3u8_url}[/bold red]")
442
442
  return {
443
443
  'path': None,
444
444
  'url': self.m3u8_url,
445
445
  'is_master': getattr(self.m3u8_manager, 'is_master', None),
446
446
  'msg': None,
447
- 'error': error_msg,
447
+ 'error': None,
448
448
  'stopped': True
449
449
  }
450
450
 
@@ -30,7 +30,8 @@ from ...FFmpeg import print_duration_table
30
30
 
31
31
 
32
32
  # Config
33
- REQUEST_VERIFY = config_manager.get_int('REQUESTS', 'verify')
33
+ REQUEST_VERIFY = config_manager.get_bool('REQUESTS', 'verify')
34
+ REQUEST_HTTP2 = config_manager.get_bool('REQUESTS', 'http2')
34
35
  GET_ONLY_LINK = config_manager.get_bool('M3U8_PARSER', 'get_only_link')
35
36
  REQUEST_TIMEOUT = config_manager.get_float('REQUESTS', 'timeout')
36
37
  TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
@@ -111,7 +112,7 @@ def MP4_downloader(url: str, path: str, referer: str = None, headers_: dict = No
111
112
  original_handler = signal.signal(signal.SIGINT, partial(signal_handler, interrupt_handler=interrupt_handler, original_handler=signal.getsignal(signal.SIGINT)))
112
113
 
113
114
  try:
114
- transport = httpx.HTTPTransport(verify=REQUEST_VERIFY, http2=True)
115
+ transport = httpx.HTTPTransport(verify=REQUEST_VERIFY, http2=REQUEST_HTTP2)
115
116
 
116
117
  with httpx.Client(transport=transport, timeout=httpx.Timeout(60)) as client:
117
118
  with client.stream("GET", url, headers=headers, timeout=REQUEST_TIMEOUT) as response:
@@ -119,15 +119,15 @@ class M3U8_Ts_Estimator:
119
119
 
120
120
  retry_count = self.segments_instance.active_retries if self.segments_instance else 0
121
121
  progress_str = (
122
- f"{Colors.GREEN}{number_file_total_size} {Colors.WHITE}< {Colors.RED}{units_file_total_size}"
123
- f"{Colors.WHITE} {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit}"
122
+ f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
123
+ f"{Colors.WHITE}, {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit}"
124
124
  f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
125
125
  )
126
126
 
127
127
  else:
128
128
  retry_count = self.segments_instance.active_retries if self.segments_instance else 0
129
129
  progress_str = (
130
- f"{Colors.GREEN}{number_file_total_size} {Colors.WHITE}< {Colors.RED}{units_file_total_size}"
130
+ f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
131
131
  f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
132
132
  )
133
133
 
@@ -1,5 +1,5 @@
1
1
  __title__ = 'StreamingCommunity'
2
- __version__ = '2.9.3'
2
+ __version__ = '2.9.4'
3
3
  __author__ = 'Arrowar'
4
4
  __description__ = 'A command-line program to download film'
5
5
  __copyright__ = 'Copyright 2024'
@@ -421,9 +421,6 @@ class ConfigManager:
421
421
  config_manager = ConfigManager()
422
422
  config_manager.read_config()
423
423
 
424
-
425
- import sys
426
-
427
424
  def get_use_large_bar():
428
425
  """
429
426
  Determines whether the large bar feature should be enabled.
@@ -0,0 +1,6 @@
1
+ # 11.03.25
2
+
3
+ from .run import main
4
+ from .Lib.Downloader.HLS.downloader import HLS_Downloader
5
+ from .Lib.Downloader.MP4.downloader import MP4_downloader
6
+ from .Lib.Downloader.TOR.downloader import TOR_downloader
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: StreamingCommunity
3
- Version: 2.9.3
3
+ Version: 2.9.4
4
4
  Home-page: https://github.com/Lovi-0/StreamingCommunity
5
5
  Author: Lovi-0
6
6
  Project-URL: Bug Reports, https://github.com/Lovi-0/StreamingCommunity/issues
@@ -23,6 +23,14 @@ Requires-Dist: pycryptodomex
23
23
  Requires-Dist: ua-generator
24
24
  Requires-Dist: qbittorrent-api
25
25
  Requires-Dist: pyTelegramBotAPI
26
+ Dynamic: author
27
+ Dynamic: description
28
+ Dynamic: description-content-type
29
+ Dynamic: home-page
30
+ Dynamic: keywords
31
+ Dynamic: project-url
32
+ Dynamic: requires-dist
33
+ Dynamic: requires-python
26
34
 
27
35
  <p align="center">
28
36
  <img src="https://i.ibb.co/v6RnT0wY/s2.jpg" alt="Project Logo" width="700"/>
@@ -105,9 +113,15 @@ Install directly from PyPI:
105
113
  pip install StreamingCommunity
106
114
  ```
107
115
 
108
- ### Creating a Run Script
116
+ Update to the latest version:
109
117
 
110
- Create `run_streaming.py`:
118
+ ```bash
119
+ pip install --upgrade StreamingCommunity
120
+ ```
121
+
122
+ ## Quick Start
123
+
124
+ Create a simple script (`run_streaming.py`) to launch the main application:
111
125
 
112
126
  ```python
113
127
  from StreamingCommunity.run import main
@@ -117,16 +131,85 @@ if __name__ == "__main__":
117
131
  ```
118
132
 
119
133
  Run the script:
134
+
120
135
  ```bash
121
136
  python run_streaming.py
122
137
  ```
123
138
 
124
- ### Updating via PyPI
139
+ ## Modules
125
140
 
126
- ```bash
127
- pip install --upgrade StreamingCommunity
141
+ ### HLS Downloader
142
+
143
+ Download HTTP Live Streaming (HLS) content from m3u8 URLs.
144
+
145
+ ```python
146
+ from StreamingCommunity.Download import HLS_Downloader
147
+
148
+ # Initialize with m3u8 URL and optional output path
149
+ downloader = HLS_Downloader(
150
+ m3u8_url="https://example.com/stream.m3u8",
151
+ output_path="/downloads/video.mp4" # Optional
152
+ )
153
+
154
+ # Start the download
155
+ downloader.download()
128
156
  ```
129
157
 
158
+ See [HLS example](./Test/Download/HLS.py) for complete usage.
159
+
160
+ ### MP4 Downloader
161
+
162
+ Direct MP4 file downloader with support for custom headers and referrer.
163
+
164
+ ```python
165
+ from StreamingCommunity.Download import MP4_downloader
166
+
167
+ # Basic usage
168
+ downloader = MP4_downloader(
169
+ url="https://example.com/video.mp4",
170
+ path="/downloads/saved_video.mp4"
171
+ )
172
+
173
+ # Advanced usage with custom headers and referrer
174
+ headers = {
175
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
176
+ }
177
+ downloader = MP4_downloader(
178
+ url="https://example.com/video.mp4",
179
+ path="/downloads/saved_video.mp4",
180
+ referer="https://example.com",
181
+ headers_=headers
182
+ )
183
+
184
+ # Start download
185
+ downloader.download()
186
+ ```
187
+
188
+ See [MP4 example](./Test/Download/MP4.py) for complete usage.
189
+
190
+ ### Torrent Client
191
+
192
+ Download content via torrent magnet links.
193
+
194
+ ```python
195
+ from StreamingCommunity.Download import TOR_downloader
196
+
197
+ # Initialize torrent client
198
+ client = TOR_downloader()
199
+
200
+ # Add magnet link
201
+ client.add_magnet_link("magnet:?xt=urn:btih:example_hash&dn=example_name")
202
+
203
+ # Start download
204
+ client.start_download()
205
+
206
+ # Move downloaded files to specific location
207
+ client.move_downloaded_files("/downloads/torrents/")
208
+ ```
209
+
210
+ See [Torrent example](./Test/Download/TOR.py) for complete usage.
211
+
212
+
130
213
  ## 2. Automatic Installation
131
214
 
132
215
  ### Supported Operating Systems 💿