aiptx 2.0.7__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.
Files changed (187) hide show
  1. aipt_v2/__init__.py +110 -0
  2. aipt_v2/__main__.py +24 -0
  3. aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
  4. aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
  5. aipt_v2/agents/__init__.py +46 -0
  6. aipt_v2/agents/base.py +520 -0
  7. aipt_v2/agents/exploit_agent.py +688 -0
  8. aipt_v2/agents/ptt.py +406 -0
  9. aipt_v2/agents/state.py +168 -0
  10. aipt_v2/app.py +957 -0
  11. aipt_v2/browser/__init__.py +31 -0
  12. aipt_v2/browser/automation.py +458 -0
  13. aipt_v2/browser/crawler.py +453 -0
  14. aipt_v2/cli.py +2933 -0
  15. aipt_v2/compliance/__init__.py +71 -0
  16. aipt_v2/compliance/compliance_report.py +449 -0
  17. aipt_v2/compliance/framework_mapper.py +424 -0
  18. aipt_v2/compliance/nist_mapping.py +345 -0
  19. aipt_v2/compliance/owasp_mapping.py +330 -0
  20. aipt_v2/compliance/pci_mapping.py +297 -0
  21. aipt_v2/config.py +341 -0
  22. aipt_v2/core/__init__.py +43 -0
  23. aipt_v2/core/agent.py +630 -0
  24. aipt_v2/core/llm.py +395 -0
  25. aipt_v2/core/memory.py +305 -0
  26. aipt_v2/core/ptt.py +329 -0
  27. aipt_v2/database/__init__.py +14 -0
  28. aipt_v2/database/models.py +232 -0
  29. aipt_v2/database/repository.py +384 -0
  30. aipt_v2/docker/__init__.py +23 -0
  31. aipt_v2/docker/builder.py +260 -0
  32. aipt_v2/docker/manager.py +222 -0
  33. aipt_v2/docker/sandbox.py +371 -0
  34. aipt_v2/evasion/__init__.py +58 -0
  35. aipt_v2/evasion/request_obfuscator.py +272 -0
  36. aipt_v2/evasion/tls_fingerprint.py +285 -0
  37. aipt_v2/evasion/ua_rotator.py +301 -0
  38. aipt_v2/evasion/waf_bypass.py +439 -0
  39. aipt_v2/execution/__init__.py +23 -0
  40. aipt_v2/execution/executor.py +302 -0
  41. aipt_v2/execution/parser.py +544 -0
  42. aipt_v2/execution/terminal.py +337 -0
  43. aipt_v2/health.py +437 -0
  44. aipt_v2/intelligence/__init__.py +194 -0
  45. aipt_v2/intelligence/adaptation.py +474 -0
  46. aipt_v2/intelligence/auth.py +520 -0
  47. aipt_v2/intelligence/chaining.py +775 -0
  48. aipt_v2/intelligence/correlation.py +536 -0
  49. aipt_v2/intelligence/cve_aipt.py +334 -0
  50. aipt_v2/intelligence/cve_info.py +1111 -0
  51. aipt_v2/intelligence/knowledge_graph.py +590 -0
  52. aipt_v2/intelligence/learning.py +626 -0
  53. aipt_v2/intelligence/llm_analyzer.py +502 -0
  54. aipt_v2/intelligence/llm_tool_selector.py +518 -0
  55. aipt_v2/intelligence/payload_generator.py +562 -0
  56. aipt_v2/intelligence/rag.py +239 -0
  57. aipt_v2/intelligence/scope.py +442 -0
  58. aipt_v2/intelligence/searchers/__init__.py +5 -0
  59. aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
  60. aipt_v2/intelligence/searchers/github_searcher.py +467 -0
  61. aipt_v2/intelligence/searchers/google_searcher.py +281 -0
  62. aipt_v2/intelligence/tools.json +443 -0
  63. aipt_v2/intelligence/triage.py +670 -0
  64. aipt_v2/interactive_shell.py +559 -0
  65. aipt_v2/interface/__init__.py +5 -0
  66. aipt_v2/interface/cli.py +230 -0
  67. aipt_v2/interface/main.py +501 -0
  68. aipt_v2/interface/tui.py +1276 -0
  69. aipt_v2/interface/utils.py +583 -0
  70. aipt_v2/llm/__init__.py +39 -0
  71. aipt_v2/llm/config.py +26 -0
  72. aipt_v2/llm/llm.py +514 -0
  73. aipt_v2/llm/memory.py +214 -0
  74. aipt_v2/llm/request_queue.py +89 -0
  75. aipt_v2/llm/utils.py +89 -0
  76. aipt_v2/local_tool_installer.py +1467 -0
  77. aipt_v2/models/__init__.py +15 -0
  78. aipt_v2/models/findings.py +295 -0
  79. aipt_v2/models/phase_result.py +224 -0
  80. aipt_v2/models/scan_config.py +207 -0
  81. aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
  82. aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
  83. aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
  84. aipt_v2/monitoring/prometheus.yml +60 -0
  85. aipt_v2/orchestration/__init__.py +52 -0
  86. aipt_v2/orchestration/pipeline.py +398 -0
  87. aipt_v2/orchestration/progress.py +300 -0
  88. aipt_v2/orchestration/scheduler.py +296 -0
  89. aipt_v2/orchestrator.py +2427 -0
  90. aipt_v2/payloads/__init__.py +27 -0
  91. aipt_v2/payloads/cmdi.py +150 -0
  92. aipt_v2/payloads/sqli.py +263 -0
  93. aipt_v2/payloads/ssrf.py +204 -0
  94. aipt_v2/payloads/templates.py +222 -0
  95. aipt_v2/payloads/traversal.py +166 -0
  96. aipt_v2/payloads/xss.py +204 -0
  97. aipt_v2/prompts/__init__.py +60 -0
  98. aipt_v2/proxy/__init__.py +29 -0
  99. aipt_v2/proxy/history.py +352 -0
  100. aipt_v2/proxy/interceptor.py +452 -0
  101. aipt_v2/recon/__init__.py +44 -0
  102. aipt_v2/recon/dns.py +241 -0
  103. aipt_v2/recon/osint.py +367 -0
  104. aipt_v2/recon/subdomain.py +372 -0
  105. aipt_v2/recon/tech_detect.py +311 -0
  106. aipt_v2/reports/__init__.py +17 -0
  107. aipt_v2/reports/generator.py +313 -0
  108. aipt_v2/reports/html_report.py +378 -0
  109. aipt_v2/runtime/__init__.py +53 -0
  110. aipt_v2/runtime/base.py +30 -0
  111. aipt_v2/runtime/docker.py +401 -0
  112. aipt_v2/runtime/local.py +346 -0
  113. aipt_v2/runtime/tool_server.py +205 -0
  114. aipt_v2/runtime/vps.py +830 -0
  115. aipt_v2/scanners/__init__.py +28 -0
  116. aipt_v2/scanners/base.py +273 -0
  117. aipt_v2/scanners/nikto.py +244 -0
  118. aipt_v2/scanners/nmap.py +402 -0
  119. aipt_v2/scanners/nuclei.py +273 -0
  120. aipt_v2/scanners/web.py +454 -0
  121. aipt_v2/scripts/security_audit.py +366 -0
  122. aipt_v2/setup_wizard.py +941 -0
  123. aipt_v2/skills/__init__.py +80 -0
  124. aipt_v2/skills/agents/__init__.py +14 -0
  125. aipt_v2/skills/agents/api_tester.py +706 -0
  126. aipt_v2/skills/agents/base.py +477 -0
  127. aipt_v2/skills/agents/code_review.py +459 -0
  128. aipt_v2/skills/agents/security_agent.py +336 -0
  129. aipt_v2/skills/agents/web_pentest.py +818 -0
  130. aipt_v2/skills/prompts/__init__.py +647 -0
  131. aipt_v2/system_detector.py +539 -0
  132. aipt_v2/telemetry/__init__.py +7 -0
  133. aipt_v2/telemetry/tracer.py +347 -0
  134. aipt_v2/terminal/__init__.py +28 -0
  135. aipt_v2/terminal/executor.py +400 -0
  136. aipt_v2/terminal/sandbox.py +350 -0
  137. aipt_v2/tools/__init__.py +44 -0
  138. aipt_v2/tools/active_directory/__init__.py +78 -0
  139. aipt_v2/tools/active_directory/ad_config.py +238 -0
  140. aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
  141. aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
  142. aipt_v2/tools/active_directory/ldap_enum.py +533 -0
  143. aipt_v2/tools/active_directory/smb_attacks.py +505 -0
  144. aipt_v2/tools/agents_graph/__init__.py +19 -0
  145. aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
  146. aipt_v2/tools/api_security/__init__.py +76 -0
  147. aipt_v2/tools/api_security/api_discovery.py +608 -0
  148. aipt_v2/tools/api_security/graphql_scanner.py +622 -0
  149. aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
  150. aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
  151. aipt_v2/tools/browser/__init__.py +5 -0
  152. aipt_v2/tools/browser/browser_actions.py +238 -0
  153. aipt_v2/tools/browser/browser_instance.py +535 -0
  154. aipt_v2/tools/browser/tab_manager.py +344 -0
  155. aipt_v2/tools/cloud/__init__.py +70 -0
  156. aipt_v2/tools/cloud/cloud_config.py +273 -0
  157. aipt_v2/tools/cloud/cloud_scanner.py +639 -0
  158. aipt_v2/tools/cloud/prowler_tool.py +571 -0
  159. aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
  160. aipt_v2/tools/executor.py +307 -0
  161. aipt_v2/tools/parser.py +408 -0
  162. aipt_v2/tools/proxy/__init__.py +5 -0
  163. aipt_v2/tools/proxy/proxy_actions.py +103 -0
  164. aipt_v2/tools/proxy/proxy_manager.py +789 -0
  165. aipt_v2/tools/registry.py +196 -0
  166. aipt_v2/tools/scanners/__init__.py +343 -0
  167. aipt_v2/tools/scanners/acunetix_tool.py +712 -0
  168. aipt_v2/tools/scanners/burp_tool.py +631 -0
  169. aipt_v2/tools/scanners/config.py +156 -0
  170. aipt_v2/tools/scanners/nessus_tool.py +588 -0
  171. aipt_v2/tools/scanners/zap_tool.py +612 -0
  172. aipt_v2/tools/terminal/__init__.py +5 -0
  173. aipt_v2/tools/terminal/terminal_actions.py +37 -0
  174. aipt_v2/tools/terminal/terminal_manager.py +153 -0
  175. aipt_v2/tools/terminal/terminal_session.py +449 -0
  176. aipt_v2/tools/tool_processing.py +108 -0
  177. aipt_v2/utils/__init__.py +17 -0
  178. aipt_v2/utils/logging.py +202 -0
  179. aipt_v2/utils/model_manager.py +187 -0
  180. aipt_v2/utils/searchers/__init__.py +269 -0
  181. aipt_v2/verify_install.py +793 -0
  182. aiptx-2.0.7.dist-info/METADATA +345 -0
  183. aiptx-2.0.7.dist-info/RECORD +187 -0
  184. aiptx-2.0.7.dist-info/WHEEL +5 -0
  185. aiptx-2.0.7.dist-info/entry_points.txt +7 -0
  186. aiptx-2.0.7.dist-info/licenses/LICENSE +21 -0
  187. aiptx-2.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,301 @@
1
+ """
2
+ User-Agent Rotator
3
+
4
+ Provides realistic User-Agent strings for request rotation:
5
+ - Chrome, Firefox, Safari, Edge user agents
6
+ - Mobile user agents
7
+ - Bot/crawler user agents
8
+ - Custom user agent generation
9
+
10
+ Usage:
11
+ from aipt_v2.evasion import UARotator, get_random_ua
12
+
13
+ rotator = UARotator()
14
+ ua = rotator.get_random()
15
+ """
16
+
17
+ import random
18
+ from dataclasses import dataclass
19
+ from typing import List, Optional
20
+ from enum import Enum
21
+
22
+
23
+ class UACategory(Enum):
24
+ """User-Agent categories."""
25
+ CHROME = "chrome"
26
+ FIREFOX = "firefox"
27
+ SAFARI = "safari"
28
+ EDGE = "edge"
29
+ MOBILE = "mobile"
30
+ BOT = "bot"
31
+
32
+
33
+ @dataclass
34
+ class UserAgent:
35
+ """User-Agent information."""
36
+ string: str
37
+ browser: str
38
+ version: str
39
+ os: str
40
+ category: str
41
+
42
+
43
+ class UARotator:
44
+ """
45
+ User-Agent String Rotator.
46
+
47
+ Provides realistic user agent strings for
48
+ request rotation to avoid fingerprinting.
49
+ """
50
+
51
+ # Chrome User-Agents (Windows, Mac, Linux)
52
+ CHROME_UA = [
53
+ # Windows
54
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
55
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
56
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
57
+ "Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
58
+ # Mac
59
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
60
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
61
+ # Linux
62
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
63
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
64
+ ]
65
+
66
+ # Firefox User-Agents
67
+ FIREFOX_UA = [
68
+ # Windows
69
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
70
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0",
71
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:119.0) Gecko/20100101 Firefox/119.0",
72
+ # Mac
73
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0",
74
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:120.0) Gecko/20100101 Firefox/120.0",
75
+ # Linux
76
+ "Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0",
77
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
78
+ ]
79
+
80
+ # Safari User-Agents
81
+ SAFARI_UA = [
82
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
83
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
84
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Safari/605.1.15",
85
+ ]
86
+
87
+ # Edge User-Agents
88
+ EDGE_UA = [
89
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
90
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
91
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
92
+ ]
93
+
94
+ # Mobile User-Agents
95
+ MOBILE_UA = [
96
+ # iOS Safari
97
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
98
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
99
+ "Mozilla/5.0 (iPad; CPU OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
100
+ # Android Chrome
101
+ "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
102
+ "Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
103
+ "Mozilla/5.0 (Linux; Android 14; SM-A546B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36",
104
+ ]
105
+
106
+ # Bot/Crawler User-Agents
107
+ BOT_UA = [
108
+ "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
109
+ "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
110
+ "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)",
111
+ "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.0; +https://openai.com/gptbot)",
112
+ "curl/8.4.0",
113
+ "Wget/1.21",
114
+ "Python-urllib/3.11",
115
+ "python-requests/2.31.0",
116
+ ]
117
+
118
+ def __init__(self):
119
+ """Initialize UA rotator."""
120
+ self.all_uas = (
121
+ self.CHROME_UA + self.FIREFOX_UA +
122
+ self.SAFARI_UA + self.EDGE_UA + self.MOBILE_UA
123
+ )
124
+ self._current_index = 0
125
+
126
+ def get_random(self, category: Optional[str] = None) -> UserAgent:
127
+ """
128
+ Get random user agent.
129
+
130
+ Args:
131
+ category: Optional category filter
132
+
133
+ Returns:
134
+ UserAgent
135
+ """
136
+ if category == "chrome":
137
+ ua_list = self.CHROME_UA
138
+ elif category == "firefox":
139
+ ua_list = self.FIREFOX_UA
140
+ elif category == "safari":
141
+ ua_list = self.SAFARI_UA
142
+ elif category == "edge":
143
+ ua_list = self.EDGE_UA
144
+ elif category == "mobile":
145
+ ua_list = self.MOBILE_UA
146
+ elif category == "bot":
147
+ ua_list = self.BOT_UA
148
+ else:
149
+ ua_list = self.all_uas
150
+
151
+ ua_string = random.choice(ua_list)
152
+ return self._parse_ua(ua_string)
153
+
154
+ def get_next(self) -> UserAgent:
155
+ """
156
+ Get next user agent (round-robin).
157
+
158
+ Returns:
159
+ UserAgent
160
+ """
161
+ ua_string = self.all_uas[self._current_index]
162
+ self._current_index = (self._current_index + 1) % len(self.all_uas)
163
+ return self._parse_ua(ua_string)
164
+
165
+ def get_all(self, category: Optional[str] = None) -> List[UserAgent]:
166
+ """
167
+ Get all user agents.
168
+
169
+ Args:
170
+ category: Optional category filter
171
+
172
+ Returns:
173
+ List of UserAgent
174
+ """
175
+ if category == "chrome":
176
+ ua_list = self.CHROME_UA
177
+ elif category == "firefox":
178
+ ua_list = self.FIREFOX_UA
179
+ elif category == "safari":
180
+ ua_list = self.SAFARI_UA
181
+ elif category == "edge":
182
+ ua_list = self.EDGE_UA
183
+ elif category == "mobile":
184
+ ua_list = self.MOBILE_UA
185
+ elif category == "bot":
186
+ ua_list = self.BOT_UA
187
+ else:
188
+ ua_list = self.all_uas
189
+
190
+ return [self._parse_ua(ua) for ua in ua_list]
191
+
192
+ def _parse_ua(self, ua_string: str) -> UserAgent:
193
+ """Parse user agent string into components."""
194
+ browser = "Unknown"
195
+ version = "Unknown"
196
+ os = "Unknown"
197
+ category = "desktop"
198
+
199
+ # Detect browser
200
+ if "Chrome/" in ua_string and "Edg/" not in ua_string:
201
+ browser = "Chrome"
202
+ version = ua_string.split("Chrome/")[1].split(" ")[0]
203
+ elif "Firefox/" in ua_string:
204
+ browser = "Firefox"
205
+ version = ua_string.split("Firefox/")[1].split(" ")[0]
206
+ elif "Safari/" in ua_string and "Chrome" not in ua_string:
207
+ browser = "Safari"
208
+ if "Version/" in ua_string:
209
+ version = ua_string.split("Version/")[1].split(" ")[0]
210
+ elif "Edg/" in ua_string:
211
+ browser = "Edge"
212
+ version = ua_string.split("Edg/")[1].split(" ")[0]
213
+ elif "Googlebot" in ua_string:
214
+ browser = "Googlebot"
215
+ category = "bot"
216
+ elif "bingbot" in ua_string:
217
+ browser = "Bingbot"
218
+ category = "bot"
219
+ elif "curl" in ua_string:
220
+ browser = "curl"
221
+ category = "bot"
222
+
223
+ # Detect OS
224
+ if "Windows NT 10" in ua_string:
225
+ os = "Windows 10"
226
+ elif "Windows NT 11" in ua_string:
227
+ os = "Windows 11"
228
+ elif "Macintosh" in ua_string:
229
+ os = "macOS"
230
+ elif "Linux" in ua_string:
231
+ os = "Linux"
232
+ elif "iPhone" in ua_string:
233
+ os = "iOS"
234
+ category = "mobile"
235
+ elif "iPad" in ua_string:
236
+ os = "iPadOS"
237
+ category = "mobile"
238
+ elif "Android" in ua_string:
239
+ os = "Android"
240
+ category = "mobile"
241
+
242
+ return UserAgent(
243
+ string=ua_string,
244
+ browser=browser,
245
+ version=version,
246
+ os=os,
247
+ category=category
248
+ )
249
+
250
+ def generate_custom(
251
+ self,
252
+ browser: str = "Chrome",
253
+ version: str = "120.0.0.0",
254
+ os: str = "Windows"
255
+ ) -> str:
256
+ """
257
+ Generate custom user agent string.
258
+
259
+ Args:
260
+ browser: Browser name
261
+ version: Browser version
262
+ os: Operating system
263
+
264
+ Returns:
265
+ Custom user agent string
266
+ """
267
+ os_strings = {
268
+ "Windows": "Windows NT 10.0; Win64; x64",
269
+ "Mac": "Macintosh; Intel Mac OS X 10_15_7",
270
+ "Linux": "X11; Linux x86_64",
271
+ "iOS": "iPhone; CPU iPhone OS 17_0 like Mac OS X",
272
+ "Android": "Linux; Android 14; Pixel 8"
273
+ }
274
+
275
+ os_str = os_strings.get(os, os_strings["Windows"])
276
+
277
+ if browser == "Chrome":
278
+ return f"Mozilla/5.0 ({os_str}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{version} Safari/537.36"
279
+ elif browser == "Firefox":
280
+ return f"Mozilla/5.0 ({os_str}; rv:{version}) Gecko/20100101 Firefox/{version}"
281
+ elif browser == "Safari":
282
+ return f"Mozilla/5.0 ({os_str}) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{version} Safari/605.1.15"
283
+ elif browser == "Edge":
284
+ return f"Mozilla/5.0 ({os_str}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{version} Safari/537.36 Edg/{version}"
285
+
286
+ return f"Mozilla/5.0 ({os_str})"
287
+
288
+
289
+ # Convenience function
290
+ def get_random_ua(category: Optional[str] = None) -> str:
291
+ """
292
+ Get random user agent string.
293
+
294
+ Args:
295
+ category: Optional category (chrome, firefox, safari, edge, mobile, bot)
296
+
297
+ Returns:
298
+ User agent string
299
+ """
300
+ rotator = UARotator()
301
+ return rotator.get_random(category).string