StreamingCommunity 2.7.0__py3-none-any.whl → 2.9.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 (71) hide show
  1. StreamingCommunity/Api/Player/ddl.py +2 -2
  2. StreamingCommunity/Api/Player/maxstream.py +7 -13
  3. StreamingCommunity/Api/Player/supervideo.py +7 -33
  4. StreamingCommunity/Api/Player/vixcloud.py +8 -80
  5. StreamingCommunity/Api/Site/1337xx/__init__.py +8 -1
  6. StreamingCommunity/Api/Site/1337xx/site.py +10 -16
  7. StreamingCommunity/Api/Site/1337xx/title.py +4 -1
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +9 -2
  9. StreamingCommunity/Api/Site/animeunity/film_serie.py +7 -1
  10. StreamingCommunity/Api/Site/animeunity/site.py +8 -10
  11. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +1 -1
  12. StreamingCommunity/Api/Site/cb01new/__init__.py +8 -1
  13. StreamingCommunity/Api/Site/cb01new/film.py +10 -6
  14. StreamingCommunity/Api/Site/cb01new/site.py +16 -15
  15. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +9 -2
  16. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +7 -1
  17. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +10 -15
  18. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +1 -1
  19. StreamingCommunity/Api/Site/guardaserie/__init__.py +9 -2
  20. StreamingCommunity/Api/Site/guardaserie/series.py +13 -8
  21. StreamingCommunity/Api/Site/guardaserie/site.py +12 -17
  22. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +1 -1
  23. StreamingCommunity/Api/Site/mostraguarda/__init__.py +6 -2
  24. StreamingCommunity/Api/Site/mostraguarda/film.py +10 -8
  25. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +9 -2
  26. StreamingCommunity/Api/Site/streamingcommunity/film.py +11 -6
  27. StreamingCommunity/Api/Site/streamingcommunity/series.py +17 -10
  28. StreamingCommunity/Api/Site/streamingcommunity/site.py +10 -15
  29. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +2 -2
  30. StreamingCommunity/Api/Template/Util/__init__.py +0 -1
  31. StreamingCommunity/Api/Template/Util/get_domain.py +24 -66
  32. StreamingCommunity/Api/Template/Util/manage_ep.py +10 -5
  33. StreamingCommunity/Api/Template/config_loader.py +8 -8
  34. StreamingCommunity/Api/Template/site.py +3 -6
  35. StreamingCommunity/Lib/Downloader/HLS/downloader.py +15 -14
  36. StreamingCommunity/Lib/Downloader/HLS/segments.py +11 -31
  37. StreamingCommunity/Lib/Downloader/MP4/downloader.py +12 -9
  38. StreamingCommunity/Lib/Downloader/TOR/downloader.py +109 -101
  39. StreamingCommunity/Lib/FFmpeg/__init__.py +1 -1
  40. StreamingCommunity/Lib/FFmpeg/capture.py +10 -12
  41. StreamingCommunity/Lib/FFmpeg/command.py +15 -14
  42. StreamingCommunity/Lib/FFmpeg/util.py +9 -38
  43. StreamingCommunity/Lib/M3U8/decryptor.py +72 -146
  44. StreamingCommunity/Lib/M3U8/estimator.py +8 -16
  45. StreamingCommunity/Lib/M3U8/parser.py +25 -27
  46. StreamingCommunity/Lib/M3U8/url_fixer.py +1 -4
  47. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  48. StreamingCommunity/Lib/TMBD/obj_tmbd.py +3 -17
  49. StreamingCommunity/Lib/TMBD/tmdb.py +4 -9
  50. StreamingCommunity/TelegramHelp/telegram_bot.py +50 -50
  51. StreamingCommunity/Upload/update.py +3 -2
  52. StreamingCommunity/Upload/version.py +1 -1
  53. StreamingCommunity/Util/color.py +1 -1
  54. StreamingCommunity/Util/{_jsonConfig.py → config_json.py} +148 -54
  55. StreamingCommunity/Util/headers.py +2 -38
  56. StreamingCommunity/Util/logger.py +72 -42
  57. StreamingCommunity/Util/message.py +8 -3
  58. StreamingCommunity/Util/os.py +41 -93
  59. StreamingCommunity/Util/table.py +8 -17
  60. StreamingCommunity/run.py +26 -34
  61. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/METADATA +165 -92
  62. StreamingCommunity-2.9.0.dist-info/RECORD +75 -0
  63. StreamingCommunity/Api/Template/Util/recall_search.py +0 -37
  64. StreamingCommunity/Lib/Downloader/HLS/proxyes.py +0 -110
  65. StreamingCommunity/Util/call_stack.py +0 -42
  66. StreamingCommunity/Util/console.py +0 -12
  67. StreamingCommunity-2.7.0.dist-info/RECORD +0 -79
  68. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/LICENSE +0 -0
  69. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/WHEEL +0 -0
  70. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/entry_points.txt +0 -0
  71. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,24 @@
1
1
  # 18.06.24
2
2
 
3
- import ssl
4
- import time
3
+ import certifi
5
4
  from urllib.parse import urlparse, unquote
6
5
 
7
6
 
8
7
  # External libraries
9
8
  import httpx
9
+ from rich.console import Console
10
10
 
11
11
 
12
12
  # Internal utilities
13
13
  from StreamingCommunity.Util.headers import get_headers
14
- from StreamingCommunity.Util.console import console
15
- from StreamingCommunity.Util._jsonConfig import config_manager
14
+ from StreamingCommunity.Util.config_json import config_manager
16
15
 
17
16
 
17
+ # Variable
18
+ console = Console()
19
+ VERIFY = config_manager.get("REQUESTS", "verify")
20
+ MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
21
+
18
22
 
19
23
  def get_tld(url_str):
20
24
  """Extract the TLD (Top-Level Domain) from the URL."""
@@ -50,16 +54,7 @@ def get_base_domain(url_str):
50
54
  except Exception:
51
55
  return None
52
56
 
53
- def get_base_url(url_str):
54
- """Extract base URL including protocol and domain, removing path and query parameters."""
55
- try:
56
- parsed = urlparse(url_str)
57
- return f"{parsed.scheme}://{parsed.netloc}"
58
-
59
- except Exception:
60
- return None
61
-
62
- def validate_url(url, base_url, max_timeout, max_retries=2, sleep=1):
57
+ def validate_url(url, base_url):
63
58
  """Validate if URL is accessible and matches expected base domain."""
64
59
  console.print(f"\n[cyan]Starting validation for URL[white]: [yellow]{url}")
65
60
 
@@ -71,71 +66,34 @@ def validate_url(url, base_url, max_timeout, max_retries=2, sleep=1):
71
66
  console.print(f"[red]Domain structure mismatch: {url_domain} != {base_domain}")
72
67
  return False, None
73
68
 
74
- # Count dots to ensure we don't have extra subdomains
75
- base_dots = base_url.count('.')
76
- url_dots = url.count('.')
77
- if url_dots > base_dots + 1:
78
- console.print(f"[red]Too many subdomains in URL")
79
- return False, None
80
-
81
69
  client = httpx.Client(
82
- verify=False,
70
+ verify=VERIFY,
83
71
  headers=get_headers(),
84
- timeout=max_timeout
72
+ timeout=MAX_TIMEOUT
85
73
  )
86
74
 
87
- for retry in range(max_retries):
88
- try:
89
- time.sleep(sleep)
90
-
91
- # Initial check without redirects
92
- response = client.get(url, follow_redirects=False)
93
- if response.status_code == 403:
94
- console.print(f"[red]Check failed (403) - Attempt {retry + 1}/{max_retries}")
95
- continue
96
-
97
- if response.status_code >= 400:
98
- console.print(f"[red]Check failed: HTTP {response.status_code}")
99
- return False, None
100
-
101
- # Follow redirects and verify final domain
102
- final_response = client.get(url, follow_redirects=True)
103
- final_domain = get_base_domain(str(final_response.url))
104
- console.print(f"[cyan]Redirect url: [red]{final_response.url}")
105
-
106
- if final_domain != base_domain:
107
- console.print(f"[red]Final domain mismatch: {final_domain} != {base_domain}")
108
- return False, None
109
-
110
- new_tld = get_tld(str(final_response.url))
111
- if new_tld != get_tld(url):
112
- return True, new_tld
113
-
114
- return True, None
115
-
116
- except (httpx.RequestError, ssl.SSLError) as e:
117
- console.print(f"[red]Connection error: {str(e)}")
118
- time.sleep(sleep)
119
- continue
120
-
121
- return False, None
75
+ # Make request to web site
76
+ response = client.get(url, follow_redirects=False)
77
+
78
+ if response.status_code >= 400:
79
+ console.print(f"[red]Check failed: HTTP {response.status_code}")
80
+ console.print(f"[red]Response content: {response.text}")
81
+ return False, None
82
+
83
+ return True, base_domain
122
84
 
123
85
  def search_domain(site_name: str, base_url: str, get_first: bool = False):
124
- """Search for valid domain matching site name and base URL."""
125
- max_timeout = config_manager.get_int("REQUESTS", "timeout")
126
-
86
+ """Search for valid domain matching site name and base URL."""
127
87
  try:
128
- is_correct, redirect_tld = validate_url(base_url, base_url, max_timeout)
88
+ is_correct, redirect_tld = validate_url(base_url, base_url)
129
89
 
130
90
  if is_correct:
131
91
  tld = redirect_tld or get_tld(base_url)
132
- config_manager.configSite[site_name]['domain'] = tld
133
-
134
- console.print(f"[green]Successfully validated initial URL")
135
92
  return tld, base_url
136
93
 
137
94
  else:
138
95
  return None, None
139
96
 
140
97
  except Exception as e:
141
- console.print(f"[red]Error testing initial URL: {str(e)}")
98
+ console.print(f"[red]Error testing initial URL: {str(e)}")
99
+ return None, None
@@ -5,15 +5,21 @@ import logging
5
5
  from typing import List
6
6
 
7
7
 
8
+ # External library
9
+ from rich.console import Console
10
+ from rich.prompt import Prompt
11
+
12
+
8
13
  # Internal utilities
9
- from StreamingCommunity.Util.console import console, msg
10
14
  from StreamingCommunity.Util.os import os_manager
11
- from StreamingCommunity.Util._jsonConfig import config_manager
15
+ from StreamingCommunity.Util.config_json import config_manager
12
16
  from StreamingCommunity.Util.table import TVShowManager
13
17
 
14
18
 
15
- # Config
16
- MAP_EPISODE = config_manager.get('DEFAULT', 'map_episode_name')
19
+ # Variable
20
+ msg = Prompt()
21
+ console = Console()
22
+ MAP_EPISODE = config_manager.get('OUT_FOLDER', 'map_episode_name')
17
23
 
18
24
 
19
25
  def dynamic_format_number(n: int) -> str:
@@ -195,7 +201,6 @@ def display_episodes_list(episodes_manager) -> str:
195
201
  """
196
202
  # Set up table for displaying episodes
197
203
  table_show_manager = TVShowManager()
198
- table_show_manager.set_slice_end(10)
199
204
 
200
205
  # Add columns to the table
201
206
  column_info = {
@@ -5,7 +5,7 @@ import inspect
5
5
 
6
6
 
7
7
  # Internal utilities
8
- from StreamingCommunity.Util._jsonConfig import config_manager
8
+ from StreamingCommunity.Util.config_json import config_manager
9
9
 
10
10
 
11
11
  def get_site_name_from_stack():
@@ -29,7 +29,7 @@ class SiteConstant:
29
29
 
30
30
  @property
31
31
  def ROOT_PATH(self):
32
- return config_manager.get('DEFAULT', 'root_path')
32
+ return config_manager.get('OUT_FOLDER', 'root_path')
33
33
 
34
34
  @property
35
35
  def DOMAIN_NOW(self):
@@ -42,23 +42,23 @@ class SiteConstant:
42
42
  @property
43
43
  def SERIES_FOLDER(self):
44
44
  base_path = self.ROOT_PATH
45
- if config_manager.get_bool("DEFAULT", "add_siteName"):
45
+ if config_manager.get_bool("OUT_FOLDER", "add_siteName"):
46
46
  base_path = os.path.join(base_path, self.SITE_NAME)
47
- return os.path.join(base_path, config_manager.get('DEFAULT', 'serie_folder_name'))
47
+ return os.path.join(base_path, config_manager.get('OUT_FOLDER', 'serie_folder_name'))
48
48
 
49
49
  @property
50
50
  def MOVIE_FOLDER(self):
51
51
  base_path = self.ROOT_PATH
52
- if config_manager.get_bool("DEFAULT", "add_siteName"):
52
+ if config_manager.get_bool("OUT_FOLDER", "add_siteName"):
53
53
  base_path = os.path.join(base_path, self.SITE_NAME)
54
- return os.path.join(base_path, config_manager.get('DEFAULT', 'movie_folder_name'))
54
+ return os.path.join(base_path, config_manager.get('OUT_FOLDER', 'movie_folder_name'))
55
55
 
56
56
  @property
57
57
  def ANIME_FOLDER(self):
58
58
  base_path = self.ROOT_PATH
59
- if config_manager.get_bool("DEFAULT", "add_siteName"):
59
+ if config_manager.get_bool("OUT_FOLDER", "add_siteName"):
60
60
  base_path = os.path.join(base_path, self.SITE_NAME)
61
- return os.path.join(base_path, config_manager.get('DEFAULT', 'anime_folder_name'))
61
+ return os.path.join(base_path, config_manager.get('OUT_FOLDER', 'anime_folder_name'))
62
62
 
63
63
  @property
64
64
  def COOKIE(self):
@@ -3,11 +3,12 @@
3
3
  import sys
4
4
 
5
5
 
6
- # Internal utilities
7
- from StreamingCommunity.Util.console import console
6
+ # External library
7
+ from rich.console import Console
8
8
 
9
9
 
10
10
  # Variable
11
+ console = Console()
11
12
  available_colors = ['red', 'magenta', 'yellow', 'cyan', 'green', 'blue', 'white']
12
13
  column_to_hide = ['Slug', 'Sub_ita', 'Last_air_date', 'Seasons_count', 'Url']
13
14
 
@@ -19,10 +20,6 @@ def get_select_title(table_show_manager, media_search_manager):
19
20
  Returns:
20
21
  MediaItem: The selected media item.
21
22
  """
22
-
23
- # Set up table for displaying titles
24
- table_show_manager.set_slice_end(10)
25
-
26
23
  # Determine column_info dynamically for (search site)
27
24
  if not media_search_manager.media_list:
28
25
  console.print("\n[red]No media items available.")
@@ -10,17 +10,14 @@ from typing import Any, Dict, List, Optional
10
10
 
11
11
  # External libraries
12
12
  import httpx
13
+ from rich.console import Console
14
+ from rich.panel import Panel
13
15
 
14
16
 
15
17
  # Internal utilities
16
- from StreamingCommunity.Util._jsonConfig import config_manager
18
+ from StreamingCommunity.Util.config_json import config_manager
17
19
  from StreamingCommunity.Util.headers import get_userAgent
18
- from StreamingCommunity.Util.console import console, Panel
19
- from StreamingCommunity.Util.os import (
20
- compute_sha1_hash,
21
- os_manager,
22
- internet_manager
23
- )
20
+ from StreamingCommunity.Util.os import compute_sha1_hash, os_manager, internet_manager
24
21
  from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
25
22
 
26
23
 
@@ -47,9 +44,9 @@ FILTER_CUSTOM_REOLUTION = str(config_manager.get('M3U8_PARSER', 'force_resolutio
47
44
  GET_ONLY_LINK = config_manager.get_bool('M3U8_PARSER', 'get_only_link')
48
45
  RETRY_LIMIT = config_manager.get_int('REQUESTS', 'max_retry')
49
46
  MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
50
-
51
47
  TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
52
48
 
49
+ console = Console()
53
50
 
54
51
 
55
52
  class HLSClient:
@@ -100,7 +97,7 @@ class PathManager:
100
97
  Creates a hash-based filename if no path is provided.
101
98
  """
102
99
  if not path:
103
- root = config_manager.get('DEFAULT', 'root_path')
100
+ root = config_manager.get('OUT_FOLDER', 'root_path')
104
101
  hash_name = compute_sha1_hash(self.m3u8_url) + ".mp4"
105
102
  return os.path.join(root, "undefined", hash_name)
106
103
 
@@ -193,7 +190,7 @@ class M3U8Manager:
193
190
  list_available_resolution = [f"{r[0]}x{r[1]}" for r in tuple_available_resolution]
194
191
 
195
192
  console.print(
196
- f"[cyan bold]Video [/cyan bold] [green]Available:[/green] [purple]{', '.join(list_available_resolution)}[/purple] | "
193
+ f"[cyan bold]Video [/cyan bold] [green]Available:[/green] [purple]{', '.join(list_available_resolution)}[/purple] | "
197
194
  f"[red]Set:[/red] [purple]{FILTER_CUSTOM_REOLUTION}[/purple] | "
198
195
  f"[yellow]Downloadable:[/yellow] [purple]{self.video_res[0]}x{self.video_res[1]}[/purple]"
199
196
  )
@@ -208,7 +205,7 @@ class M3U8Manager:
208
205
  set_codec_info = available_codec_info if config_manager.get_bool("M3U8_CONVERSION", "use_codec") else "[purple]copy[/purple]"
209
206
 
210
207
  console.print(
211
- f"[bold cyan]Codec [/bold cyan] [green]Available:[/green] {available_codec_info} | "
208
+ f"[bold cyan]Codec [/bold cyan] [green]Available:[/green] {available_codec_info} | "
212
209
  f"[red]Set:[/red] {set_codec_info}"
213
210
  )
214
211
 
@@ -217,7 +214,7 @@ class M3U8Manager:
217
214
  downloadable_sub_languages = list(set(available_sub_languages) & set(DOWNLOAD_SPECIFIC_SUBTITLE))
218
215
  if available_sub_languages:
219
216
  console.print(
220
- f"[cyan bold]Subtitle [/cyan bold] [green]Available:[/green] [purple]{', '.join(available_sub_languages)}[/purple] | "
217
+ f"[cyan bold]Subtitle [/cyan bold] [green]Available:[/green] [purple]{', '.join(available_sub_languages)}[/purple] | "
221
218
  f"[red]Set:[/red] [purple]{', '.join(DOWNLOAD_SPECIFIC_SUBTITLE)}[/purple] | "
222
219
  f"[yellow]Downloadable:[/yellow] [purple]{', '.join(downloadable_sub_languages)}[/purple]"
223
220
  )
@@ -227,7 +224,7 @@ class M3U8Manager:
227
224
  downloadable_audio_languages = list(set(available_audio_languages) & set(DOWNLOAD_SPECIFIC_AUDIO))
228
225
  if available_audio_languages:
229
226
  console.print(
230
- f"[cyan bold]Audio [/cyan bold] [green]Available:[/green] [purple]{', '.join(available_audio_languages)}[/purple] | "
227
+ f"[cyan bold]Audio [/cyan bold] [green]Available:[/green] [purple]{', '.join(available_audio_languages)}[/purple] | "
231
228
  f"[red]Set:[/red] [purple]{', '.join(DOWNLOAD_SPECIFIC_AUDIO)}[/purple] | "
232
229
  f"[yellow]Downloadable:[/yellow] [purple]{', '.join(downloadable_audio_languages)}[/purple]"
233
230
  )
@@ -432,7 +429,8 @@ class HLS_Downloader:
432
429
  'path': self.path_manager.output_path,
433
430
  'url': self.m3u8_url,
434
431
  'is_master': False,
435
- 'error': 'File already exists',
432
+ 'msg': 'File already exists',
433
+ 'error': None,
436
434
  'stopped': False
437
435
  }
438
436
  if TELEGRAM_BOT:
@@ -476,6 +474,8 @@ class HLS_Downloader:
476
474
  'path': self.path_manager.output_path,
477
475
  'url': self.m3u8_url,
478
476
  'is_master': self.m3u8_manager.is_master,
477
+ 'msg': None,
478
+ 'error': None,
479
479
  'stopped': download_stopped
480
480
  }
481
481
 
@@ -488,6 +488,7 @@ class HLS_Downloader:
488
488
  'path': None,
489
489
  'url': self.m3u8_url,
490
490
  'is_master': getattr(self.m3u8_manager, 'is_master', None),
491
+ 'msg': None,
491
492
  'error': error_msg,
492
493
  'stopped': False
493
494
  }
@@ -17,14 +17,13 @@ from typing import Dict
17
17
  # External libraries
18
18
  import httpx
19
19
  from tqdm import tqdm
20
+ from rich.console import Console
20
21
 
21
22
 
22
23
  # Internal utilities
23
24
  from StreamingCommunity.Util.color import Colors
24
- from StreamingCommunity.Util.console import console
25
- from StreamingCommunity.Util.headers import get_userAgent, random_headers
26
- from StreamingCommunity.Util._jsonConfig import config_manager
27
- from StreamingCommunity.Util.os import os_manager
25
+ from StreamingCommunity.Util.headers import get_userAgent
26
+ from StreamingCommunity.Util.config_json import config_manager, get_use_large_bar
28
27
 
29
28
 
30
29
  # Logic class
@@ -34,16 +33,11 @@ from ...M3U8 import (
34
33
  M3U8_Parser,
35
34
  M3U8_UrlFix
36
35
  )
37
- from .proxyes import main_test_proxy
38
36
 
39
37
  # Config
40
38
  TQDM_DELAY_WORKER = config_manager.get_float('M3U8_DOWNLOAD', 'tqdm_delay')
41
- USE_LARGE_BAR = not ("android" in sys.platform or "ios" in sys.platform)
42
39
  REQUEST_MAX_RETRY = config_manager.get_int('REQUESTS', 'max_retry')
43
- REQUEST_VERIFY = False
44
- THERE_IS_PROXY_LIST = os_manager.check_file("list_proxy.txt")
45
- PROXY_START_MIN = config_manager.get_float('REQUESTS', 'proxy_start_min')
46
- PROXY_START_MAX = config_manager.get_float('REQUESTS', 'proxy_start_max')
40
+ REQUEST_VERIFY = config_manager.get_int('REQUESTS', 'verify')
47
41
  DEFAULT_VIDEO_WORKERS = config_manager.get_int('M3U8_DOWNLOAD', 'default_video_workser')
48
42
  DEFAULT_AUDIO_WORKERS = config_manager.get_int('M3U8_DOWNLOAD', 'default_audio_workser')
49
43
  MAX_TIMEOOUT = config_manager.get_int("REQUESTS", "timeout")
@@ -52,6 +46,9 @@ SEGMENT_MAX_TIMEOUT = config_manager.get_int("M3U8_DOWNLOAD", "segment_timeout")
52
46
  TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
53
47
 
54
48
 
49
+ # Variable
50
+ console = Console()
51
+
55
52
 
56
53
  class M3U8_Segments:
57
54
  def __init__(self, url: str, tmp_folder: str, is_index_url: bool = True):
@@ -133,15 +130,6 @@ class M3U8_Segments:
133
130
  ]
134
131
  self.class_ts_estimator.total_segments = len(self.segments)
135
132
 
136
- # Proxy
137
- if THERE_IS_PROXY_LIST:
138
- console.log("[red]Start validation proxy.")
139
- self.valid_proxy = main_test_proxy(self.segments[0])
140
- console.log(f"[cyan]N. Valid ip: [red]{len(self.valid_proxy)}")
141
-
142
- if len(self.valid_proxy) == 0:
143
- sys.exit(0)
144
-
145
133
  def get_info(self) -> None:
146
134
  if self.is_index_url:
147
135
  try:
@@ -184,18 +172,13 @@ class M3U8_Segments:
184
172
  else:
185
173
  print("Signal handler must be set in the main thread")
186
174
 
187
- def _get_http_client(self, index: int = None):
175
+ def _get_http_client(self):
188
176
  client_params = {
189
- #'headers': random_headers(self.key_base_url) if hasattr(self, 'key_base_url') else {'User-Agent': get_userAgent()},
190
177
  'headers': {'User-Agent': get_userAgent()},
191
178
  'timeout': SEGMENT_MAX_TIMEOUT,
192
179
  'follow_redirects': True,
193
180
  'http2': False
194
181
  }
195
-
196
- if THERE_IS_PROXY_LIST and index is not None and hasattr(self, 'valid_proxy'):
197
- client_params['proxies'] = self.valid_proxy[index % len(self.valid_proxy)]
198
-
199
182
  return httpx.Client(**client_params)
200
183
 
201
184
  def download_segment(self, ts_url: str, index: int, progress_bar: tqdm, backoff_factor: float = 1.1) -> None:
@@ -213,7 +196,7 @@ class M3U8_Segments:
213
196
  return
214
197
 
215
198
  try:
216
- with self._get_http_client(index) as client:
199
+ with self._get_http_client() as client:
217
200
  start_time = time.time()
218
201
  response = client.get(ts_url)
219
202
 
@@ -350,7 +333,6 @@ class M3U8_Segments:
350
333
 
351
334
  # Configure workers and delay
352
335
  max_workers = self._get_worker_count(type)
353
- delay = max(PROXY_START_MIN, min(PROXY_START_MAX, 1 / (len(self.valid_proxy) + 1))) if THERE_IS_PROXY_LIST else TQDM_DELAY_WORKER
354
336
 
355
337
  # Download segments with completion verification
356
338
  with ThreadPoolExecutor(max_workers=max_workers) as executor:
@@ -361,7 +343,7 @@ class M3U8_Segments:
361
343
  if self.interrupt_flag.is_set():
362
344
  break
363
345
 
364
- time.sleep(delay)
346
+ time.sleep(TQDM_DELAY_WORKER)
365
347
  futures.append(executor.submit(self.download_segment, segment_url, index, progress_bar))
366
348
 
367
349
  # Wait for futures with interrupt handling
@@ -405,7 +387,7 @@ class M3U8_Segments:
405
387
  """
406
388
  Generate platform-appropriate progress bar format.
407
389
  """
408
- if not USE_LARGE_BAR:
390
+ if not get_use_large_bar():
409
391
  return (
410
392
  f"{Colors.YELLOW}Proc{Colors.WHITE}: "
411
393
  f"{Colors.RED}{{percentage:.2f}}% "
@@ -429,8 +411,6 @@ class M3U8_Segments:
429
411
  'audio': DEFAULT_AUDIO_WORKERS
430
412
  }.get(stream_type.lower(), 1)
431
413
 
432
- if THERE_IS_PROXY_LIST:
433
- return min(len(self.valid_proxy), base_workers * 2)
434
414
  return base_workers
435
415
 
436
416
  def _generate_results(self, stream_type: str) -> Dict:
@@ -12,13 +12,15 @@ from functools import partial
12
12
  # External libraries
13
13
  import httpx
14
14
  from tqdm import tqdm
15
+ from rich.console import Console
16
+ from rich.prompt import Prompt
17
+ from rich.panel import Panel
15
18
 
16
19
 
17
20
  # Internal utilities
18
21
  from StreamingCommunity.Util.headers import get_userAgent
19
22
  from StreamingCommunity.Util.color import Colors
20
- from StreamingCommunity.Util.console import console, Panel
21
- from StreamingCommunity.Util._jsonConfig import config_manager
23
+ from StreamingCommunity.Util.config_json import config_manager
22
24
  from StreamingCommunity.Util.os import internet_manager
23
25
  from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
24
26
 
@@ -27,18 +29,17 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
27
29
  from ...FFmpeg import print_duration_table
28
30
 
29
31
 
30
- # Suppress SSL warnings
31
- import urllib3
32
- urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
33
-
34
-
35
32
  # Config
33
+ REQUEST_VERIFY = config_manager.get_int('REQUESTS', 'verify')
36
34
  GET_ONLY_LINK = config_manager.get_bool('M3U8_PARSER', 'get_only_link')
37
35
  REQUEST_TIMEOUT = config_manager.get_float('REQUESTS', 'timeout')
38
-
39
36
  TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
40
37
 
41
38
 
39
+ # Variable
40
+ msg = Prompt()
41
+ console = Console()
42
+
42
43
 
43
44
  class InterruptHandler:
44
45
  def __init__(self):
@@ -47,6 +48,7 @@ class InterruptHandler:
47
48
  self.kill_download = False
48
49
  self.force_quit = False
49
50
 
51
+
50
52
  def signal_handler(signum, frame, interrupt_handler, original_handler):
51
53
  """Enhanced signal handler for multiple interrupt scenarios"""
52
54
  current_time = time.time()
@@ -67,6 +69,7 @@ def signal_handler(signum, frame, interrupt_handler, original_handler):
67
69
  console.print("\n[bold red]Force quit activated. Saving partial download...[/bold red]")
68
70
  signal.signal(signum, original_handler)
69
71
 
72
+
70
73
  def MP4_downloader(url: str, path: str, referer: str = None, headers_: dict = None):
71
74
  """
72
75
  Downloads an MP4 video with enhanced interrupt handling.
@@ -111,7 +114,7 @@ def MP4_downloader(url: str, path: str, referer: str = None, headers_: dict = No
111
114
  original_handler = signal.signal(signal.SIGINT, partial(signal_handler, interrupt_handler=interrupt_handler, original_handler=signal.getsignal(signal.SIGINT)))
112
115
 
113
116
  try:
114
- transport = httpx.HTTPTransport(verify=False, http2=True)
117
+ transport = httpx.HTTPTransport(verify=REQUEST_VERIFY, http2=True)
115
118
 
116
119
  with httpx.Client(transport=transport, timeout=httpx.Timeout(60)) as client:
117
120
  with client.stream("GET", url, headers=headers, timeout=REQUEST_TIMEOUT) as response: