StreamingCommunity 2.5.6__py3-none-any.whl → 2.5.8__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 (65) hide show
  1. StreamingCommunity/Api/Player/ddl.py +2 -3
  2. StreamingCommunity/Api/Site/1337xx/__init__.py +5 -6
  3. StreamingCommunity/Api/Site/1337xx/site.py +7 -14
  4. StreamingCommunity/Api/Site/1337xx/title.py +3 -5
  5. StreamingCommunity/Api/Site/altadefinizionegratis/__init__.py +7 -6
  6. StreamingCommunity/Api/Site/altadefinizionegratis/film.py +14 -19
  7. StreamingCommunity/Api/Site/altadefinizionegratis/site.py +6 -14
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +7 -7
  9. StreamingCommunity/Api/Site/animeunity/film_serie.py +29 -31
  10. StreamingCommunity/Api/Site/animeunity/site.py +14 -22
  11. StreamingCommunity/Api/Site/cb01new/__init__.py +5 -4
  12. StreamingCommunity/Api/Site/cb01new/film.py +2 -5
  13. StreamingCommunity/Api/Site/cb01new/site.py +5 -13
  14. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +5 -4
  15. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +12 -49
  16. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +6 -16
  17. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +2 -3
  18. StreamingCommunity/Api/Site/guardaserie/__init__.py +5 -4
  19. StreamingCommunity/Api/Site/guardaserie/series.py +12 -46
  20. StreamingCommunity/Api/Site/guardaserie/site.py +5 -13
  21. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +10 -14
  22. StreamingCommunity/Api/Site/ilcorsaronero/__init__.py +5 -4
  23. StreamingCommunity/Api/Site/ilcorsaronero/site.py +5 -13
  24. StreamingCommunity/Api/Site/ilcorsaronero/title.py +3 -5
  25. StreamingCommunity/Api/Site/mostraguarda/__init__.py +2 -2
  26. StreamingCommunity/Api/Site/mostraguarda/film.py +4 -8
  27. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +8 -7
  28. StreamingCommunity/Api/Site/streamingcommunity/film.py +14 -18
  29. StreamingCommunity/Api/Site/streamingcommunity/series.py +25 -76
  30. StreamingCommunity/Api/Site/streamingcommunity/site.py +11 -23
  31. StreamingCommunity/Api/Template/Util/__init__.py +8 -1
  32. StreamingCommunity/Api/Template/Util/manage_ep.py +46 -2
  33. StreamingCommunity/Api/Template/config_loader.py +71 -0
  34. StreamingCommunity/Lib/Downloader/HLS/downloader.py +60 -60
  35. StreamingCommunity/Lib/Downloader/HLS/segments.py +40 -15
  36. StreamingCommunity/Lib/Downloader/MP4/downloader.py +47 -40
  37. StreamingCommunity/Lib/FFmpeg/command.py +59 -3
  38. StreamingCommunity/Lib/M3U8/estimator.py +10 -12
  39. StreamingCommunity/Lib/M3U8/parser.py +12 -51
  40. StreamingCommunity/Lib/TMBD/tmdb.py +66 -99
  41. StreamingCommunity/TelegramHelp/telegram_bot.py +222 -68
  42. StreamingCommunity/Util/_jsonConfig.py +14 -13
  43. StreamingCommunity/Util/ffmpeg_installer.py +70 -64
  44. StreamingCommunity/Util/headers.py +11 -122
  45. StreamingCommunity/Util/os.py +65 -56
  46. StreamingCommunity/Util/table.py +62 -108
  47. StreamingCommunity/run.py +16 -11
  48. {StreamingCommunity-2.5.6.dist-info → StreamingCommunity-2.5.8.dist-info}/METADATA +57 -23
  49. StreamingCommunity-2.5.8.dist-info/RECORD +86 -0
  50. StreamingCommunity/Api/Site/1337xx/costant.py +0 -15
  51. StreamingCommunity/Api/Site/altadefinizionegratis/costant.py +0 -21
  52. StreamingCommunity/Api/Site/animeunity/costant.py +0 -21
  53. StreamingCommunity/Api/Site/cb01new/costant.py +0 -19
  54. StreamingCommunity/Api/Site/ddlstreamitaly/costant.py +0 -20
  55. StreamingCommunity/Api/Site/guardaserie/costant.py +0 -19
  56. StreamingCommunity/Api/Site/ilcorsaronero/costant.py +0 -19
  57. StreamingCommunity/Api/Site/mostraguarda/costant.py +0 -19
  58. StreamingCommunity/Api/Site/streamingcommunity/costant.py +0 -21
  59. StreamingCommunity/TelegramHelp/request_manager.py +0 -82
  60. StreamingCommunity/TelegramHelp/session.py +0 -56
  61. StreamingCommunity-2.5.6.dist-info/RECORD +0 -96
  62. {StreamingCommunity-2.5.6.dist-info → StreamingCommunity-2.5.8.dist-info}/LICENSE +0 -0
  63. {StreamingCommunity-2.5.6.dist-info → StreamingCommunity-2.5.8.dist-info}/WHEEL +0 -0
  64. {StreamingCommunity-2.5.6.dist-info → StreamingCommunity-2.5.8.dist-info}/entry_points.txt +0 -0
  65. {StreamingCommunity-2.5.6.dist-info → StreamingCommunity-2.5.8.dist-info}/top_level.txt +0 -0
@@ -4,17 +4,18 @@ import os
4
4
  import sys
5
5
  import json
6
6
  import logging
7
+ from pathlib import Path
7
8
  from typing import Any, List
8
9
 
9
10
 
10
11
  class ConfigManager:
11
- def __init__(self, file_path: str = 'config.json') -> None:
12
+ def __init__(self, file_name: str = 'config.json') -> None:
12
13
  """Initialize the ConfigManager.
13
14
 
14
15
  Parameters:
15
16
  - file_path (str, optional): The path to the configuration file. Default is 'config.json'.
16
17
  """
17
- self.file_path = file_path
18
+ self.file_path = Path(__file__).parent.parent.parent / file_name
18
19
  self.config = {}
19
20
  self.cache = {}
20
21
 
@@ -50,17 +51,17 @@ class ConfigManager:
50
51
  def download_requirements(self, url: str, filename: str):
51
52
  """
52
53
  Download the requirements.txt file from the specified URL if not found locally using requests.
53
-
54
+
54
55
  Args:
55
56
  url (str): The URL to download the requirements file from.
56
57
  filename (str): The local filename to save the requirements file as.
57
58
  """
58
59
  try:
59
60
  import requests
60
-
61
+
61
62
  logging.info(f"{filename} not found locally. Downloading from {url}...")
62
63
  response = requests.get(url)
63
-
64
+
64
65
  if response.status_code == 200:
65
66
  with open(filename, 'wb') as f:
66
67
  f.write(response.content)
@@ -68,7 +69,7 @@ class ConfigManager:
68
69
  else:
69
70
  logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
70
71
  sys.exit(0)
71
-
72
+
72
73
  except Exception as e:
73
74
  logging.error(f"Failed to download {filename}: {e}")
74
75
  sys.exit(0)
@@ -89,15 +90,15 @@ class ConfigManager:
89
90
 
90
91
  if cache_key in self.cache:
91
92
  return self.cache[cache_key]
92
-
93
+
93
94
  if section in self.config and key in self.config[section]:
94
95
  value = self.config[section][key]
95
96
  else:
96
97
  raise ValueError(f"Key '{key}' not found in section '{section}'")
97
-
98
+
98
99
  value = self._convert_to_data_type(value, data_type)
99
100
  self.cache[cache_key] = value
100
-
101
+
101
102
  return value
102
103
 
103
104
  def _convert_to_data_type(self, value: str, data_type: type) -> Any:
@@ -120,7 +121,7 @@ class ConfigManager:
120
121
  return None
121
122
  else:
122
123
  return value
123
-
124
+
124
125
  def get(self, section: str, key: str) -> Any:
125
126
  """Read a value from the configuration file.
126
127
 
@@ -144,7 +145,7 @@ class ConfigManager:
144
145
  int: The integer value.
145
146
  """
146
147
  return self.read_key(section, key, int)
147
-
148
+
148
149
  def get_float(self, section: str, key: str) -> int:
149
150
  """Read an float value from the configuration file.
150
151
 
@@ -180,7 +181,7 @@ class ConfigManager:
180
181
  list: The list value.
181
182
  """
182
183
  return self.read_key(section, key, list)
183
-
184
+
184
185
  def get_dict(self, section: str, key: str) -> dict:
185
186
  """Read a dictionary value from the configuration file.
186
187
 
@@ -220,7 +221,7 @@ class ConfigManager:
220
221
  json.dump(self.config, f, indent=4)
221
222
  except Exception as e:
222
223
  print(f"Error writing configuration file: {e}")
223
-
224
+
224
225
 
225
226
  # Initialize
226
227
  config_manager = ConfigManager()
@@ -4,8 +4,6 @@ import os
4
4
  import glob
5
5
  import gzip
6
6
  import shutil
7
- import tarfile
8
- import zipfile
9
7
  import logging
10
8
  import platform
11
9
  import subprocess
@@ -179,64 +177,59 @@ class FFMPEGDownloader:
179
177
  size = file.write(chunk)
180
178
  progress.update(download_task, advance=size)
181
179
  return True
180
+
182
181
  except Exception as e:
183
182
  logging.error(f"Download error: {e}")
184
183
  return False
185
184
 
186
- def _extract_and_copy_binaries(self, archive_path: str) -> Tuple[Optional[str], Optional[str], Optional[str]]:
185
+ def _extract_file(self, gz_path: str, final_path: str) -> bool:
187
186
  """
188
- Extract FFmpeg binaries from the downloaded archive and copy them to the base directory.
187
+ Extract a gzipped file and set proper permissions.
189
188
 
190
189
  Parameters:
191
- archive_path (str): Path to the downloaded archive file
190
+ gz_path (str): Path to the gzipped file
191
+ final_path (str): Path where the extracted file should be saved
192
192
 
193
193
  Returns:
194
- Tuple[Optional[str], Optional[str], Optional[str]]: Paths to the extracted ffmpeg,
195
- ffprobe, and ffplay executables. Returns None for each executable that couldn't be extracted.
194
+ bool: True if extraction was successful, False otherwise
196
195
  """
197
196
  try:
198
- extraction_path = os.path.join(self.base_dir, 'temp_extract')
199
- os.makedirs(extraction_path, exist_ok=True)
200
-
201
- if archive_path.endswith('.zip'):
202
- with zipfile.ZipFile(archive_path, 'r') as zip_ref:
203
- zip_ref.extractall(extraction_path)
204
- elif archive_path.endswith('.tar.xz'):
205
- with tarfile.open(archive_path) as tar_ref:
206
- tar_ref.extractall(extraction_path)
207
- elif archive_path.endswith('.gz'):
208
- file_name = os.path.basename(archive_path)[:-3] # Remove extension .gz
209
- output_path = os.path.join(extraction_path, file_name)
210
- with gzip.open(archive_path, 'rb') as f_in, open(output_path, 'wb') as f_out:
197
+ logging.info(f"Attempting to extract {gz_path} to {final_path}")
198
+
199
+ # Check if source file exists and is readable
200
+ if not os.path.exists(gz_path):
201
+ logging.error(f"Source file {gz_path} does not exist")
202
+ return False
203
+
204
+ if not os.access(gz_path, os.R_OK):
205
+ logging.error(f"Source file {gz_path} is not readable")
206
+ return False
207
+
208
+ # Extract the file
209
+ with gzip.open(gz_path, 'rb') as f_in:
210
+ # Test if the gzip file is valid
211
+ try:
212
+ f_in.read(1)
213
+ f_in.seek(0)
214
+ except Exception as e:
215
+ logging.error(f"Invalid gzip file {gz_path}: {e}")
216
+ return False
217
+
218
+ # Extract the file
219
+ with open(final_path, 'wb') as f_out:
211
220
  shutil.copyfileobj(f_in, f_out)
212
- else:
213
- raise ValueError("Unsupported archive format")
214
-
215
- config = FFMPEG_CONFIGURATION[self.os_name]
216
- executables = config['executables']
217
- found_paths = []
218
-
219
- for executable in executables:
220
- exe_paths = glob.glob(os.path.join(extraction_path, '**', executable), recursive=True)
221
- if exe_paths:
222
- dest_path = os.path.join(self.base_dir, executable)
223
- shutil.copy2(exe_paths[0], dest_path)
224
-
225
- if self.os_name != 'windows':
226
- os.chmod(dest_path, 0o755)
227
-
228
- found_paths.append(dest_path)
229
- else:
230
- found_paths.append(None)
231
221
 
232
- shutil.rmtree(extraction_path, ignore_errors=True)
233
- os.remove(archive_path)
234
-
235
- return tuple(found_paths) if len(found_paths) == 3 else (None, None, None)
222
+ # Set executable permissions
223
+ os.chmod(final_path, 0o755)
224
+ logging.info(f"Successfully extracted {gz_path} to {final_path}")
225
+
226
+ # Remove the gzip file
227
+ os.remove(gz_path)
228
+ return True
236
229
 
237
230
  except Exception as e:
238
- logging.error(f"Extraction/copy error: {e}")
239
- return None, None, None
231
+ logging.error(f"Extraction error for {gz_path}: {e}")
232
+ return False
240
233
 
241
234
  def download(self) -> Tuple[Optional[str], Optional[str], Optional[str]]:
242
235
  """
@@ -244,30 +237,43 @@ class FFMPEGDownloader:
244
237
 
245
238
  Returns:
246
239
  Tuple[Optional[str], Optional[str], Optional[str]]: Paths to ffmpeg, ffprobe, and ffplay executables.
247
- Returns None for each executable that couldn't be downloaded or set up.
248
240
  """
249
241
  config = FFMPEG_CONFIGURATION[self.os_name]
250
242
  executables = [exe.format(arch=self.arch) for exe in config['executables']]
251
-
243
+ successful_extractions = []
244
+
252
245
  for executable in executables:
253
- download_url = f"https://github.com/eugeneware/ffmpeg-static/releases/latest/download/{executable}.gz"
254
- download_path = os.path.join(self.base_dir, f"{executable}.gz")
255
- final_path = os.path.join(self.base_dir, executable)
256
-
257
- console.print(f"[bold blue]Downloading {executable} from GitHub[/]")
258
- if not self._download_file(download_url, download_path):
259
- return None, None, None
260
-
261
- with gzip.open(download_path, 'rb') as f_in, open(final_path, 'wb') as f_out:
262
- shutil.copyfileobj(f_in, f_out)
263
-
264
- os.chmod(final_path, 0o755)
265
- os.remove(download_path)
266
-
246
+ try:
247
+ download_url = f"https://github.com/eugeneware/ffmpeg-static/releases/latest/download/{executable}.gz"
248
+ download_path = os.path.join(self.base_dir, f"{executable}.gz")
249
+ final_path = os.path.join(self.base_dir, executable)
250
+
251
+ # Log the current operation
252
+ logging.info(f"Processing {executable}")
253
+ console.print(f"[bold blue]Downloading {executable} from GitHub[/]")
254
+
255
+ # Download the file
256
+ if not self._download_file(download_url, download_path):
257
+ console.print(f"[bold red]Failed to download {executable}[/]")
258
+ continue
259
+
260
+ # Extract the file
261
+ if self._extract_file(download_path, final_path):
262
+ successful_extractions.append(final_path)
263
+ console.print(f"[bold green]Successfully installed {executable}[/]")
264
+ else:
265
+ console.print(f"[bold red]Failed to extract {executable}[/]")
266
+
267
+ except Exception as e:
268
+ logging.error(f"Error processing {executable}: {e}")
269
+ console.print(f"[bold red]Error processing {executable}: {str(e)}[/]")
270
+ continue
271
+
272
+ # Return the results based on successful extractions
267
273
  return (
268
- os.path.join(self.base_dir, executables[0]),
269
- os.path.join(self.base_dir, executables[1]),
270
- None
274
+ successful_extractions[0] if len(successful_extractions) > 0 else None,
275
+ successful_extractions[1] if len(successful_extractions) > 1 else None,
276
+ None # ffplay is not included in the current implementation
271
277
  )
272
278
 
273
279
  def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
@@ -1,104 +1,24 @@
1
1
  # 4.04.24
2
2
 
3
- import re
4
- import sys
5
3
  import random
6
- from importlib.metadata import version, PackageNotFoundError
7
4
 
8
5
 
9
6
  # External library
10
- from fake_useragent import UserAgent
7
+ import ua_generator
11
8
 
12
9
 
13
- # Variable
14
- try:
15
- ua_version = version('fake-useragent')
16
- except PackageNotFoundError:
17
- ua_version = None
18
-
19
- if not getattr(sys, 'frozen', False):
20
- if ua_version == '1.1.3':
21
- ua = UserAgent(use_external_data=True)
22
- else:
23
- ua = UserAgent()
24
- else:
25
- ua = UserAgent()
26
-
27
-
28
- def extract_versions(user_agent):
29
- """
30
- Extract browser versions from the user agent.
31
-
32
- Parameters:
33
- user_agent (str): User agent of the browser.
34
-
35
- Returns:
36
- list: List of browser versions.
37
- """
38
-
39
- # Patterns to extract versions from various user agents
40
- patterns = {
41
- 'chrome': re.compile(r'Chrome/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
42
- 'firefox': re.compile(r'Firefox/(\d+)\.?(\d+)?\.?(\d+)?'),
43
- 'safari': re.compile(r'Version/(\d+)\.(\d+)\.(\d+) Safari/(\d+)\.(\d+)\.(\d+)'),
44
- 'edge': re.compile(r'Edg/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
45
- 'edgios': re.compile(r'EdgiOS/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
46
- 'crios': re.compile(r'CriOS/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
47
- }
48
-
49
- for key, pattern in patterns.items():
50
- match = pattern.search(user_agent)
51
- if match:
52
- return [match.group(i+1) for i in range(match.lastindex)]
53
-
54
- # Fallback values if specific versions are not found
55
- return ['99', '0', '0', '0']
56
-
57
- def get_platform(user_agent):
10
+ def get_headers() -> str:
58
11
  """
59
- Determine the device platform from the user agent.
60
-
61
- Parameters:
62
- user_agent (str): User agent of the browser.
12
+ Generate a random user agent to use in HTTP requests.
63
13
 
64
14
  Returns:
65
- str: Device platform.
66
- """
67
- if 'Windows' in user_agent:
68
- return '"Windows"'
69
- elif 'Mac OS X' in user_agent:
70
- return '"macOS"'
71
- elif 'Android' in user_agent:
72
- return '"Android"'
73
- elif 'iPhone' in user_agent or 'iPad' in user_agent:
74
- return '"iOS"'
75
- elif 'Linux' in user_agent:
76
- return '"Linux"'
77
- return '"Unknown"'
78
-
79
- def get_model(user_agent):
15
+ - str: A random user agent string.
80
16
  """
81
- Determine the device model from the user agent.
17
+
18
+ # Get a random user agent string from the user agent rotator
19
+ user_agent = ua_generator.generate().text
20
+ return user_agent
82
21
 
83
- Parameters:
84
- user_agent (str): User agent of the browser.
85
-
86
- Returns:
87
- str: Device model.
88
- """
89
- if 'iPhone' in user_agent:
90
- return '"iPhone"'
91
- elif 'iPad' in user_agent:
92
- return '"iPad"'
93
- elif 'Android' in user_agent:
94
- return '"Android"'
95
- elif 'Windows' in user_agent:
96
- return '"PC"'
97
- elif 'Mac OS X' in user_agent:
98
- return '"Mac"'
99
- elif 'Linux' in user_agent:
100
- return '"Linux"'
101
- return '"Unknown"'
102
22
 
103
23
  def random_headers(referer: str = None):
104
24
  """
@@ -107,26 +27,10 @@ def random_headers(referer: str = None):
107
27
  Returns:
108
28
  dict: Generated HTTP headers.
109
29
  """
110
- user_agent = ua.random
111
- versions = extract_versions(user_agent)
112
- platform = get_platform(user_agent)
113
- model = get_model(user_agent)
114
- is_mobile = 'Mobi' in user_agent or 'Android' in user_agent
115
-
116
- # Generate sec-ch-ua string based on the browser
117
- if 'Chrome' in user_agent or 'CriOS' in user_agent:
118
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Chromium";v="{versions[0]}", "Google Chrome";v="{versions[0]}"'
119
- elif 'Edg' in user_agent or 'EdgiOS' in user_agent:
120
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Chromium";v="{versions[0]}", "Microsoft Edge";v="{versions[0]}"'
121
- elif 'Firefox' in user_agent:
122
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Firefox";v="{versions[0]}"'
123
- elif 'Safari' in user_agent:
124
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Safari";v="{versions[0]}"'
125
- else:
126
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}"'
30
+ ua = ua_generator.generate()
127
31
 
128
32
  headers = {
129
- 'User-Agent': user_agent,
33
+ 'User-Agent': ua.text,
130
34
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
131
35
  'Accept-Language': random.choice(['en-US', 'en-GB', 'fr-FR', 'es-ES', 'de-DE']),
132
36
  'Accept-Encoding': 'gzip, deflate, br',
@@ -136,25 +40,10 @@ def random_headers(referer: str = None):
136
40
  'Sec-Fetch-Mode': 'navigate',
137
41
  'Sec-Fetch-Site': 'none',
138
42
  'Sec-Fetch-User': '?1',
139
- 'sec-ch-ua-mobile': '?1' if is_mobile else '?0',
140
- 'sec-ch-ua-platform': platform,
141
- 'sec-ch-ua': sec_ch_ua,
142
- 'sec-ch-ua-model': model
143
43
  }
144
44
 
145
45
  if referer:
146
46
  headers['Origin'] = referer
147
47
  headers['Referer'] = referer
148
48
 
149
- return headers
150
-
151
- def get_headers() -> str:
152
- """
153
- Generate a random user agent to use in HTTP requests.
154
-
155
- Returns:
156
- - str: A random user agent string.
157
- """
158
-
159
- # Get a random user agent string from the user agent rotator
160
- return str(ua.chrome)
49
+ return headers