StreamingCommunity 1.7.6__py3-none-any.whl → 1.9.1__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 (101) hide show
  1. StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/js_parser.py +4 -1
  2. StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/util.py +166 -166
  3. StreamingCommunity/{Src/Api → Api}/Player/ddl.py +89 -89
  4. StreamingCommunity/{Src/Api → Api}/Player/maxstream.py +151 -151
  5. StreamingCommunity/{Src/Api → Api}/Player/supervideo.py +193 -193
  6. StreamingCommunity/{Src/Api → Api}/Player/vixcloud.py +224 -212
  7. StreamingCommunity/{Src/Api → Api}/Site/1337xx/__init__.py +50 -50
  8. StreamingCommunity/{Src/Api → Api}/Site/1337xx/costant.py +15 -15
  9. StreamingCommunity/{Src/Api → Api}/Site/1337xx/site.py +83 -83
  10. StreamingCommunity/{Src/Api → Api}/Site/1337xx/title.py +66 -66
  11. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/__init__.py +50 -50
  12. StreamingCommunity/{Src/Api/Site/mostraguarda → Api/Site/altadefinizione}/costant.py +15 -15
  13. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/film.py +69 -69
  14. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/site.py +86 -86
  15. StreamingCommunity/{Src/Api → Api}/Site/animeunity/__init__.py +50 -50
  16. StreamingCommunity/{Src/Api/Site/altadefinizione → Api/Site/animeunity}/costant.py +15 -15
  17. StreamingCommunity/{Src/Api → Api}/Site/animeunity/film_serie.py +130 -131
  18. StreamingCommunity/{Src/Api → Api}/Site/animeunity/site.py +164 -164
  19. StreamingCommunity/{Src/Api → Api}/Site/animeunity/util/ScrapeSerie.py +3 -3
  20. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/__init__.py +51 -51
  21. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/costant.py +15 -15
  22. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/site.py +84 -84
  23. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/title.py +47 -47
  24. StreamingCommunity/{Src/Api → Api}/Site/cb01new/__init__.py +51 -51
  25. StreamingCommunity/{Src/Api → Api}/Site/cb01new/costant.py +15 -15
  26. StreamingCommunity/{Src/Api → Api}/Site/cb01new/film.py +69 -69
  27. StreamingCommunity/{Src/Api → Api}/Site/cb01new/site.py +74 -74
  28. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/__init__.py +57 -57
  29. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/costant.py +16 -16
  30. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/series.py +141 -142
  31. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/site.py +92 -92
  32. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/util/ScrapeSerie.py +84 -82
  33. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/__init__.py +52 -52
  34. StreamingCommunity/{Src/Api/Site/piratebays → Api/Site/guardaserie}/costant.py +15 -15
  35. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/series.py +195 -195
  36. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/site.py +84 -84
  37. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/util/ScrapeSerie.py +110 -110
  38. StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/__init__.py +48 -48
  39. StreamingCommunity/{Src/Api/Site/animeunity → Api/Site/mostraguarda}/costant.py +15 -15
  40. StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/film.py +94 -94
  41. StreamingCommunity/{Src/Api → Api}/Site/piratebays/__init__.py +50 -50
  42. StreamingCommunity/{Src/Api/Site/guardaserie → Api/Site/piratebays}/costant.py +15 -15
  43. StreamingCommunity/{Src/Api → Api}/Site/piratebays/site.py +88 -88
  44. StreamingCommunity/{Src/Api → Api}/Site/piratebays/title.py +45 -45
  45. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/__init__.py +55 -55
  46. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/costant.py +15 -15
  47. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/film.py +70 -70
  48. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/series.py +205 -203
  49. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/site.py +125 -125
  50. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/util/ScrapeSerie.py +3 -3
  51. StreamingCommunity/{Src/Api → Api}/Template/Class/SearchType.py +101 -101
  52. StreamingCommunity/{Src/Api → Api}/Template/Util/__init__.py +4 -4
  53. StreamingCommunity/{Src/Api → Api}/Template/Util/get_domain.py +137 -137
  54. StreamingCommunity/{Src/Api → Api}/Template/Util/manage_ep.py +153 -153
  55. StreamingCommunity/{Src/Api → Api}/Template/Util/recall_search.py +37 -37
  56. StreamingCommunity/Api/Template/__init__.py +3 -0
  57. StreamingCommunity/{Src/Api → Api}/Template/site.py +87 -87
  58. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/downloader.py +968 -968
  59. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/proxyes.py +110 -110
  60. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/segments.py +538 -540
  61. StreamingCommunity/{Src/Lib → Lib}/Downloader/MP4/downloader.py +156 -156
  62. StreamingCommunity/{Src/Lib → Lib}/Downloader/TOR/downloader.py +222 -222
  63. StreamingCommunity/{Src/Lib → Lib}/Downloader/__init__.py +4 -4
  64. StreamingCommunity/{Src/Lib → Lib}/Driver/driver_1.py +76 -76
  65. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/__init__.py +4 -4
  66. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/capture.py +170 -170
  67. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/command.py +292 -292
  68. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/util.py +241 -241
  69. StreamingCommunity/{Src/Lib → Lib}/M3U8/__init__.py +5 -5
  70. StreamingCommunity/{Src/Lib → Lib}/M3U8/decryptor.py +164 -129
  71. StreamingCommunity/{Src/Lib → Lib}/M3U8/estimator.py +175 -172
  72. StreamingCommunity/{Src/Lib → Lib}/M3U8/parser.py +666 -666
  73. StreamingCommunity/{Src/Lib → Lib}/M3U8/url_fixer.py +51 -51
  74. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  75. StreamingCommunity/{Src/Lib → Lib}/TMBD/obj_tmbd.py +39 -39
  76. StreamingCommunity/{Src/Lib → Lib}/TMBD/tmdb.py +345 -345
  77. StreamingCommunity/{Src/Upload → Upload}/update.py +68 -64
  78. StreamingCommunity/{Src/Upload → Upload}/version.py +5 -5
  79. StreamingCommunity/{Src/Util → Util}/_jsonConfig.py +204 -204
  80. StreamingCommunity/{Src/Util → Util}/call_stack.py +42 -42
  81. StreamingCommunity/{Src/Util → Util}/color.py +20 -20
  82. StreamingCommunity/{Src/Util → Util}/console.py +12 -12
  83. StreamingCommunity/Util/ffmpeg_installer.py +275 -0
  84. StreamingCommunity/{Src/Util → Util}/headers.py +147 -147
  85. StreamingCommunity/{Src/Util → Util}/logger.py +53 -53
  86. StreamingCommunity/{Src/Util → Util}/message.py +46 -46
  87. StreamingCommunity/{Src/Util → Util}/os.py +514 -417
  88. StreamingCommunity/{Src/Util → Util}/table.py +163 -163
  89. StreamingCommunity/run.py +202 -196
  90. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/METADATA +126 -60
  91. StreamingCommunity-1.9.1.dist-info/RECORD +95 -0
  92. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/WHEEL +1 -1
  93. StreamingCommunity/Src/Api/Site/animeunity/anime.py +0 -126
  94. StreamingCommunity/Src/Api/Site/ddlstreamitaly/Player/ScrapeSerie.py +0 -83
  95. StreamingCommunity/Src/Api/Site/guardaserie/Player/ScrapeSerie.py +0 -110
  96. StreamingCommunity/Src/Api/Template/__init__.py +0 -3
  97. StreamingCommunity/Src/Lib/TMBD/__init__.py +0 -2
  98. StreamingCommunity-1.7.6.dist-info/RECORD +0 -97
  99. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/LICENSE +0 -0
  100. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/entry_points.txt +0 -0
  101. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,20 @@
1
- # 24.05.24
2
-
3
- class Colors:
4
- BLACK = "\033[30m"
5
- RED = "\033[31m"
6
- GREEN = "\033[32m"
7
- YELLOW = "\033[33m"
8
- BLUE = "\033[34m"
9
- MAGENTA = "\033[35m"
10
- CYAN = "\033[36m"
11
- LIGHT_GRAY = "\033[37m"
12
- DARK_GRAY = "\033[90m"
13
- LIGHT_RED = "\033[91m"
14
- LIGHT_GREEN = "\033[92m"
15
- LIGHT_YELLOW = "\033[93m"
16
- LIGHT_BLUE = "\033[94m"
17
- LIGHT_MAGENTA = "\033[95m"
18
- LIGHT_CYAN = "\033[96m"
19
- WHITE = "\033[97m"
20
- RESET = "\033[0m"
1
+ # 24.05.24
2
+
3
+ class Colors:
4
+ BLACK = "\033[30m"
5
+ RED = "\033[31m"
6
+ GREEN = "\033[32m"
7
+ YELLOW = "\033[33m"
8
+ BLUE = "\033[34m"
9
+ MAGENTA = "\033[35m"
10
+ CYAN = "\033[36m"
11
+ LIGHT_GRAY = "\033[37m"
12
+ DARK_GRAY = "\033[90m"
13
+ LIGHT_RED = "\033[91m"
14
+ LIGHT_GREEN = "\033[92m"
15
+ LIGHT_YELLOW = "\033[93m"
16
+ LIGHT_BLUE = "\033[94m"
17
+ LIGHT_MAGENTA = "\033[95m"
18
+ LIGHT_CYAN = "\033[96m"
19
+ WHITE = "\033[97m"
20
+ RESET = "\033[0m"
@@ -1,12 +1,12 @@
1
- # 24.02.24
2
-
3
- from rich.console import Console
4
- from rich.prompt import Prompt, Confirm
5
- from rich.panel import Panel
6
- from rich.table import Table
7
- from rich.text import Text
8
-
9
-
10
- # Variable
11
- msg = Prompt()
12
- console = Console()
1
+ # 24.02.24
2
+
3
+ from rich.console import Console
4
+ from rich.prompt import Prompt, Confirm
5
+ from rich.panel import Panel
6
+ from rich.table import Table
7
+ from rich.text import Text
8
+
9
+
10
+ # Variable
11
+ msg = Prompt()
12
+ console = Console()
@@ -0,0 +1,275 @@
1
+ # 24.01.2024
2
+
3
+ import os
4
+ import platform
5
+ import subprocess
6
+ import zipfile
7
+ import tarfile
8
+ import logging
9
+ import requests
10
+ import shutil
11
+ import glob
12
+ from typing import Optional, Tuple
13
+
14
+
15
+ # External library
16
+ from rich.console import Console
17
+ from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn, TimeRemainingColumn
18
+
19
+
20
+ # Variable
21
+ console = Console()
22
+ FFMPEG_CONFIGURATION = {
23
+ 'windows': {
24
+ 'base_dir': lambda home: os.path.join(os.path.splitdrive(home)[0] + os.path.sep, 'binary'),
25
+ 'download_url': 'https://github.com/GyanD/codexffmpeg/releases/download/{version}/ffmpeg-{version}-full_build.zip',
26
+ 'file_extension': '.zip',
27
+ 'executables': ['ffmpeg.exe', 'ffprobe.exe', 'ffplay.exe']
28
+ },
29
+ 'darwin': {
30
+ 'base_dir': lambda home: os.path.join(home, 'Applications', 'binary'),
31
+ 'download_url': 'https://evermeet.cx/ffmpeg/ffmpeg-{version}.zip',
32
+ 'file_extension': '.zip',
33
+ 'executables': ['ffmpeg', 'ffprobe', 'ffplay']
34
+ },
35
+ 'linux': {
36
+ 'base_dir': lambda home: os.path.join(home, '.local', 'bin', 'binary'),
37
+ 'download_url': 'https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-{arch}-static.tar.xz',
38
+ 'file_extension': '.tar.xz',
39
+ 'executables': ['ffmpeg', 'ffprobe', 'ffplay']
40
+ }
41
+ }
42
+
43
+
44
+
45
+ class FFMPEGDownloader:
46
+ def __init__(self):
47
+ self.os_name = self._detect_system()
48
+ self.arch = self._detect_arch()
49
+ self.home_dir = os.path.expanduser('~')
50
+ self.base_dir = self._get_base_directory()
51
+
52
+ def _detect_system(self) -> str:
53
+ """Detect and normalize operating system name."""
54
+ system = platform.system().lower()
55
+
56
+ if system in FFMPEG_CONFIGURATION:
57
+ return system
58
+
59
+ raise ValueError(f"Unsupported operating system: {system}")
60
+
61
+ def _detect_arch(self) -> str:
62
+ """
63
+ Detect system architecture
64
+ """
65
+ machine = platform.machine().lower()
66
+
67
+ arch_map = {
68
+ 'amd64': 'x86_64',
69
+ 'x86_64': 'x86_64',
70
+ 'x64': 'x86_64',
71
+ 'arm64': 'arm64',
72
+ 'aarch64': 'arm64'
73
+ }
74
+
75
+ return arch_map.get(machine, machine)
76
+
77
+ def _get_base_directory(self) -> str:
78
+ """
79
+ Get base directory for binaries
80
+ """
81
+ base_dir = FFMPEG_CONFIGURATION[self.os_name]['base_dir'](self.home_dir)
82
+ os.makedirs(base_dir, exist_ok=True)
83
+
84
+ return base_dir
85
+
86
+ def _check_existing_binaries(self) -> Tuple[Optional[str], Optional[str]]:
87
+ """
88
+ Check if FFmpeg binaries already exist in the base directory
89
+ """
90
+ config = FFMPEG_CONFIGURATION[self.os_name]
91
+ executables = config['executables']
92
+
93
+ found_executables = []
94
+ for executable in executables:
95
+
96
+ # Search for exact executable in base directory
97
+ exe_paths = glob.glob(os.path.join(self.base_dir, executable))
98
+ if exe_paths:
99
+ found_executables.append(exe_paths[0])
100
+
101
+ # Return paths if both executables are found
102
+ if len(found_executables) == len(executables):
103
+ return tuple(found_executables)
104
+
105
+ return None, None
106
+
107
+ def _get_latest_version(self) -> str:
108
+ """
109
+ Get the latest FFmpeg version
110
+ """
111
+ try:
112
+ version_url = 'https://www.gyan.dev/ffmpeg/builds/release-version'
113
+ return requests.get(version_url).text.strip()
114
+
115
+ except Exception as e:
116
+ logging.error(f"Unable to get version: {e}")
117
+ return None
118
+
119
+ def _download_file(self, url: str, destination: str) -> bool:
120
+ """
121
+ Download with Rich progress bar
122
+ """
123
+ try:
124
+ response = requests.get(url, stream=True)
125
+ response.raise_for_status()
126
+
127
+ total_size = int(response.headers.get('content-length', 0))
128
+
129
+ with open(destination, 'wb') as file, \
130
+ Progress(
131
+ SpinnerColumn(),
132
+ TextColumn("[progress.description]{task.description}"),
133
+ BarColumn(),
134
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
135
+ TimeRemainingColumn()
136
+ ) as progress:
137
+
138
+ download_task = progress.add_task("[green]Downloading FFmpeg", total=total_size)
139
+
140
+ for chunk in response.iter_content(chunk_size=8192):
141
+ size = file.write(chunk)
142
+ progress.update(download_task, advance=size)
143
+
144
+ return True
145
+
146
+ except Exception as e:
147
+ logging.error(f"Download error: {e}")
148
+ return False
149
+
150
+ def _extract_and_copy_binaries(self, archive_path: str) -> Tuple[Optional[str], Optional[str]]:
151
+ """
152
+ Extract archive and copy executables to base directory
153
+ """
154
+ try:
155
+ # Temporary extraction path
156
+ extraction_path = os.path.join(self.base_dir, 'temp_extract')
157
+ os.makedirs(extraction_path, exist_ok=True)
158
+
159
+ # Extract based on file type
160
+ if archive_path.endswith('.zip'):
161
+ with zipfile.ZipFile(archive_path, 'r') as zip_ref:
162
+ zip_ref.extractall(extraction_path)
163
+ elif archive_path.endswith('.tar.xz'):
164
+ import lzma
165
+ with lzma.open(archive_path, 'rb') as xz_file:
166
+ with tarfile.open(fileobj=xz_file) as tar_ref:
167
+ tar_ref.extractall(extraction_path)
168
+
169
+ # Find and copy executables
170
+ config = FFMPEG_CONFIGURATION[self.os_name]
171
+ executables = config['executables']
172
+
173
+ found_paths = []
174
+ for executable in executables:
175
+ # Find executable in extracted files
176
+ exe_paths = glob.glob(os.path.join(extraction_path, '**', executable), recursive=True)
177
+
178
+ if exe_paths:
179
+ # Copy to base directory
180
+ dest_path = os.path.join(self.base_dir, executable)
181
+ shutil.copy2(exe_paths[0], dest_path)
182
+
183
+ # Set execution permissions for Unix-like systems
184
+ if self.os_name != 'windows':
185
+ os.chmod(dest_path, 0o755)
186
+
187
+ found_paths.append(dest_path)
188
+
189
+ # Clean up temporary extraction directory
190
+ shutil.rmtree(extraction_path, ignore_errors=True)
191
+
192
+ # Remove downloaded archive
193
+ os.remove(archive_path)
194
+
195
+ # Return paths if both executables found
196
+ if len(found_paths) == len(executables):
197
+ return tuple(found_paths)
198
+
199
+ return None, None
200
+
201
+ except Exception as e:
202
+ logging.error(f"Extraction/copy error: {e}")
203
+ return None, None
204
+
205
+ def download(self) -> Tuple[Optional[str], Optional[str]]:
206
+ """
207
+ Main download procedure
208
+ Returns paths of ffmpeg and ffprobe
209
+ """
210
+ # First, check if binaries already exist in base directory
211
+ existing_ffmpeg, existing_ffprobe, existing_ffplay = self._check_existing_binaries()
212
+ if existing_ffmpeg and existing_ffprobe:
213
+ return existing_ffmpeg, existing_ffprobe
214
+
215
+ # Get latest version
216
+ version = self._get_latest_version()
217
+ if not version:
218
+ logging.error("Cannot proceed: version not found")
219
+ return None, None
220
+
221
+ # Prepare configurations
222
+ config = FFMPEG_CONFIGURATION[self.os_name]
223
+
224
+ # Build download URL
225
+ download_url = config['download_url'].format(
226
+ version=version,
227
+ arch=self.arch
228
+ )
229
+
230
+ # Download path
231
+ download_path = os.path.join(
232
+ self.base_dir,
233
+ f'ffmpeg-{version}{config["file_extension"]}'
234
+ )
235
+
236
+ # Download
237
+ console.print(
238
+ f"[bold blue]Downloading FFmpeg from:[/] {download_url}",
239
+ )
240
+ if not self._download_file(download_url, download_path):
241
+ return None, None
242
+
243
+ # Extract and copy binaries
244
+ ffmpeg_path, ffprobe_path = self._extract_and_copy_binaries(download_path)
245
+
246
+ if ffmpeg_path and ffprobe_path:
247
+ return ffmpeg_path, ffprobe_path
248
+
249
+ logging.error("FFmpeg executables not found")
250
+ return None, None
251
+
252
+
253
+ def check_ffmpeg():
254
+ try:
255
+ # First, use 'where' command to check existing binaries on Windows
256
+ if platform.system().lower() == 'windows':
257
+ ffmpeg_path = subprocess.check_output(['where', 'ffmpeg'], text=True).strip().split('\n')[0] if subprocess.call(['where', 'ffmpeg'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 else None
258
+ ffprobe_path = subprocess.check_output(['where', 'ffprobe'], text=True).strip().split('\n')[0] if subprocess.call(['where', 'ffprobe'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 else None
259
+
260
+ if ffmpeg_path and ffprobe_path:
261
+ return ffmpeg_path, ffprobe_path
262
+
263
+ # Fallback to which/shutil method for Unix-like systems
264
+ ffmpeg_path = shutil.which('ffmpeg')
265
+ ffprobe_path = shutil.which('ffprobe')
266
+
267
+ if ffmpeg_path and ffprobe_path:
268
+ return ffmpeg_path, ffprobe_path
269
+
270
+ downloader = FFMPEGDownloader()
271
+ return downloader.download()
272
+
273
+ except Exception as e:
274
+ logging.error(f"Error checking FFmpeg: {e}")
275
+ return None, None
@@ -1,147 +1,147 @@
1
- # 4.04.24
2
-
3
- import re
4
- import random
5
-
6
-
7
- # External library
8
- from fake_useragent import UserAgent
9
-
10
-
11
- # Variable
12
- ua = UserAgent()
13
-
14
-
15
- def extract_versions(user_agent):
16
- """
17
- Extract browser versions from the user agent.
18
-
19
- Parameters:
20
- user_agent (str): User agent of the browser.
21
-
22
- Returns:
23
- list: List of browser versions.
24
- """
25
-
26
- # Patterns to extract versions from various user agents
27
- patterns = {
28
- 'chrome': re.compile(r'Chrome/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
29
- 'firefox': re.compile(r'Firefox/(\d+)\.?(\d+)?\.?(\d+)?'),
30
- 'safari': re.compile(r'Version/(\d+)\.(\d+)\.(\d+) Safari/(\d+)\.(\d+)\.(\d+)'),
31
- 'edge': re.compile(r'Edg/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
32
- 'edgios': re.compile(r'EdgiOS/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
33
- 'crios': re.compile(r'CriOS/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
34
- }
35
-
36
- for key, pattern in patterns.items():
37
- match = pattern.search(user_agent)
38
- if match:
39
- return [match.group(i+1) for i in range(match.lastindex)]
40
-
41
- # Fallback values if specific versions are not found
42
- return ['99', '0', '0', '0']
43
-
44
- def get_platform(user_agent):
45
- """
46
- Determine the device platform from the user agent.
47
-
48
- Parameters:
49
- user_agent (str): User agent of the browser.
50
-
51
- Returns:
52
- str: Device platform.
53
- """
54
- if 'Windows' in user_agent:
55
- return '"Windows"'
56
- elif 'Mac OS X' in user_agent:
57
- return '"macOS"'
58
- elif 'Android' in user_agent:
59
- return '"Android"'
60
- elif 'iPhone' in user_agent or 'iPad' in user_agent:
61
- return '"iOS"'
62
- elif 'Linux' in user_agent:
63
- return '"Linux"'
64
- return '"Unknown"'
65
-
66
- def get_model(user_agent):
67
- """
68
- Determine the device model from the user agent.
69
-
70
- Parameters:
71
- user_agent (str): User agent of the browser.
72
-
73
- Returns:
74
- str: Device model.
75
- """
76
- if 'iPhone' in user_agent:
77
- return '"iPhone"'
78
- elif 'iPad' in user_agent:
79
- return '"iPad"'
80
- elif 'Android' in user_agent:
81
- return '"Android"'
82
- elif 'Windows' in user_agent:
83
- return '"PC"'
84
- elif 'Mac OS X' in user_agent:
85
- return '"Mac"'
86
- elif 'Linux' in user_agent:
87
- return '"Linux"'
88
- return '"Unknown"'
89
-
90
- def random_headers(referer: str = None):
91
- """
92
- Generate random HTTP headers to simulate human-like behavior.
93
-
94
- Returns:
95
- dict: Generated HTTP headers.
96
- """
97
- user_agent = ua.random
98
- versions = extract_versions(user_agent)
99
- platform = get_platform(user_agent)
100
- model = get_model(user_agent)
101
- is_mobile = 'Mobi' in user_agent or 'Android' in user_agent
102
-
103
- # Generate sec-ch-ua string based on the browser
104
- if 'Chrome' in user_agent or 'CriOS' in user_agent:
105
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Chromium";v="{versions[0]}", "Google Chrome";v="{versions[0]}"'
106
- elif 'Edg' in user_agent or 'EdgiOS' in user_agent:
107
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Chromium";v="{versions[0]}", "Microsoft Edge";v="{versions[0]}"'
108
- elif 'Firefox' in user_agent:
109
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Firefox";v="{versions[0]}"'
110
- elif 'Safari' in user_agent:
111
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Safari";v="{versions[0]}"'
112
- else:
113
- sec_ch_ua = f'" Not;A Brand";v="{versions[0]}"'
114
-
115
- headers = {
116
- 'User-Agent': user_agent,
117
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
118
- 'Accept-Language': random.choice(['en-US', 'en-GB', 'fr-FR', 'es-ES', 'de-DE']),
119
- 'Accept-Encoding': 'gzip, deflate, br',
120
- 'Connection': 'keep-alive',
121
- 'Upgrade-Insecure-Requests': '1',
122
- 'Sec-Fetch-Dest': 'document',
123
- 'Sec-Fetch-Mode': 'navigate',
124
- 'Sec-Fetch-Site': 'none',
125
- 'Sec-Fetch-User': '?1',
126
- 'sec-ch-ua-mobile': '?1' if is_mobile else '?0',
127
- 'sec-ch-ua-platform': platform,
128
- 'sec-ch-ua': sec_ch_ua,
129
- 'sec-ch-ua-model': model
130
- }
131
-
132
- if referer:
133
- headers['Origin'] = referer
134
- headers['Referer'] = referer
135
-
136
- return headers
137
-
138
- def get_headers() -> str:
139
- """
140
- Generate a random user agent to use in HTTP requests.
141
-
142
- Returns:
143
- - str: A random user agent string.
144
- """
145
-
146
- # Get a random user agent string from the user agent rotator
147
- return str(ua.chrome)
1
+ # 4.04.24
2
+
3
+ import re
4
+ import random
5
+
6
+
7
+ # External library
8
+ from fake_useragent import UserAgent
9
+
10
+
11
+ # Variable
12
+ ua = UserAgent(use_external_data=True)
13
+
14
+
15
+ def extract_versions(user_agent):
16
+ """
17
+ Extract browser versions from the user agent.
18
+
19
+ Parameters:
20
+ user_agent (str): User agent of the browser.
21
+
22
+ Returns:
23
+ list: List of browser versions.
24
+ """
25
+
26
+ # Patterns to extract versions from various user agents
27
+ patterns = {
28
+ 'chrome': re.compile(r'Chrome/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
29
+ 'firefox': re.compile(r'Firefox/(\d+)\.?(\d+)?\.?(\d+)?'),
30
+ 'safari': re.compile(r'Version/(\d+)\.(\d+)\.(\d+) Safari/(\d+)\.(\d+)\.(\d+)'),
31
+ 'edge': re.compile(r'Edg/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
32
+ 'edgios': re.compile(r'EdgiOS/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
33
+ 'crios': re.compile(r'CriOS/(\d+)\.(\d+)\.(\d+)\.(\d+)'),
34
+ }
35
+
36
+ for key, pattern in patterns.items():
37
+ match = pattern.search(user_agent)
38
+ if match:
39
+ return [match.group(i+1) for i in range(match.lastindex)]
40
+
41
+ # Fallback values if specific versions are not found
42
+ return ['99', '0', '0', '0']
43
+
44
+ def get_platform(user_agent):
45
+ """
46
+ Determine the device platform from the user agent.
47
+
48
+ Parameters:
49
+ user_agent (str): User agent of the browser.
50
+
51
+ Returns:
52
+ str: Device platform.
53
+ """
54
+ if 'Windows' in user_agent:
55
+ return '"Windows"'
56
+ elif 'Mac OS X' in user_agent:
57
+ return '"macOS"'
58
+ elif 'Android' in user_agent:
59
+ return '"Android"'
60
+ elif 'iPhone' in user_agent or 'iPad' in user_agent:
61
+ return '"iOS"'
62
+ elif 'Linux' in user_agent:
63
+ return '"Linux"'
64
+ return '"Unknown"'
65
+
66
+ def get_model(user_agent):
67
+ """
68
+ Determine the device model from the user agent.
69
+
70
+ Parameters:
71
+ user_agent (str): User agent of the browser.
72
+
73
+ Returns:
74
+ str: Device model.
75
+ """
76
+ if 'iPhone' in user_agent:
77
+ return '"iPhone"'
78
+ elif 'iPad' in user_agent:
79
+ return '"iPad"'
80
+ elif 'Android' in user_agent:
81
+ return '"Android"'
82
+ elif 'Windows' in user_agent:
83
+ return '"PC"'
84
+ elif 'Mac OS X' in user_agent:
85
+ return '"Mac"'
86
+ elif 'Linux' in user_agent:
87
+ return '"Linux"'
88
+ return '"Unknown"'
89
+
90
+ def random_headers(referer: str = None):
91
+ """
92
+ Generate random HTTP headers to simulate human-like behavior.
93
+
94
+ Returns:
95
+ dict: Generated HTTP headers.
96
+ """
97
+ user_agent = ua.random
98
+ versions = extract_versions(user_agent)
99
+ platform = get_platform(user_agent)
100
+ model = get_model(user_agent)
101
+ is_mobile = 'Mobi' in user_agent or 'Android' in user_agent
102
+
103
+ # Generate sec-ch-ua string based on the browser
104
+ if 'Chrome' in user_agent or 'CriOS' in user_agent:
105
+ sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Chromium";v="{versions[0]}", "Google Chrome";v="{versions[0]}"'
106
+ elif 'Edg' in user_agent or 'EdgiOS' in user_agent:
107
+ sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Chromium";v="{versions[0]}", "Microsoft Edge";v="{versions[0]}"'
108
+ elif 'Firefox' in user_agent:
109
+ sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Firefox";v="{versions[0]}"'
110
+ elif 'Safari' in user_agent:
111
+ sec_ch_ua = f'" Not;A Brand";v="{versions[0]}", "Safari";v="{versions[0]}"'
112
+ else:
113
+ sec_ch_ua = f'" Not;A Brand";v="{versions[0]}"'
114
+
115
+ headers = {
116
+ 'User-Agent': user_agent,
117
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
118
+ 'Accept-Language': random.choice(['en-US', 'en-GB', 'fr-FR', 'es-ES', 'de-DE']),
119
+ 'Accept-Encoding': 'gzip, deflate, br',
120
+ 'Connection': 'keep-alive',
121
+ 'Upgrade-Insecure-Requests': '1',
122
+ 'Sec-Fetch-Dest': 'document',
123
+ 'Sec-Fetch-Mode': 'navigate',
124
+ 'Sec-Fetch-Site': 'none',
125
+ 'Sec-Fetch-User': '?1',
126
+ 'sec-ch-ua-mobile': '?1' if is_mobile else '?0',
127
+ 'sec-ch-ua-platform': platform,
128
+ 'sec-ch-ua': sec_ch_ua,
129
+ 'sec-ch-ua-model': model
130
+ }
131
+
132
+ if referer:
133
+ headers['Origin'] = referer
134
+ headers['Referer'] = referer
135
+
136
+ return headers
137
+
138
+ def get_headers() -> str:
139
+ """
140
+ Generate a random user agent to use in HTTP requests.
141
+
142
+ Returns:
143
+ - str: A random user agent string.
144
+ """
145
+
146
+ # Get a random user agent string from the user agent rotator
147
+ return str(ua.chrome)