tokenade 3.5.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.
Files changed (150) hide show
  1. tokenade/__init__.py +84 -0
  2. tokenade/cli/__init__.py +306 -0
  3. tokenade/cli/__main__.py +5 -0
  4. tokenade/cli/advanced.py +458 -0
  5. tokenade/cli/completions.py +73 -0
  6. tokenade/cli/config.py +47 -0
  7. tokenade/cli/management.py +264 -0
  8. tokenade/cli/output.py +31 -0
  9. tokenade/cli/proxy.py +118 -0
  10. tokenade/cli/security.py +156 -0
  11. tokenade/cli/session.py +471 -0
  12. tokenade/core/__init__.py +0 -0
  13. tokenade/core/antidetection/__init__.py +4 -0
  14. tokenade/core/antidetection/behavioral.py +140 -0
  15. tokenade/core/antidetection/cdp_cleaner.py +60 -0
  16. tokenade/core/api/__init__.py +3 -0
  17. tokenade/core/api/server.py +251 -0
  18. tokenade/core/batch/__init__.py +23 -0
  19. tokenade/core/batch/operations.py +399 -0
  20. tokenade/core/browser/__init__.py +0 -0
  21. tokenade/core/browser/manager.py +311 -0
  22. tokenade/core/crypto/__init__.py +19 -0
  23. tokenade/core/crypto/cookie_crypto.py +506 -0
  24. tokenade/core/crypto/encryptor.py +299 -0
  25. tokenade/core/extractor/__init__.py +0 -0
  26. tokenade/core/fingerprint/__init__.py +0 -0
  27. tokenade/core/fingerprint/collectors/__init__.py +30 -0
  28. tokenade/core/fingerprint/collectors/audio.py +124 -0
  29. tokenade/core/fingerprint/collectors/base.py +69 -0
  30. tokenade/core/fingerprint/collectors/battery.py +59 -0
  31. tokenade/core/fingerprint/collectors/canvas.py +81 -0
  32. tokenade/core/fingerprint/collectors/fonts.py +52 -0
  33. tokenade/core/fingerprint/collectors/navigator.py +99 -0
  34. tokenade/core/fingerprint/collectors/plugins.py +92 -0
  35. tokenade/core/fingerprint/collectors/screen.py +81 -0
  36. tokenade/core/fingerprint/collectors/webgl.py +104 -0
  37. tokenade/core/fingerprint/collectors/webrtc.py +91 -0
  38. tokenade/core/fingerprint/injector.py +94 -0
  39. tokenade/core/fingerprint/manager.py +278 -0
  40. tokenade/core/fingerprint/stealth.py +357 -0
  41. tokenade/core/importer/__init__.py +23 -0
  42. tokenade/core/importer/adb_extractor.py +261 -0
  43. tokenade/core/importer/advanced_validator.py +666 -0
  44. tokenade/core/importer/browser_discovery.py +314 -0
  45. tokenade/core/importer/chromium_forks.py +175 -0
  46. tokenade/core/importer/cookie_extractor.py +517 -0
  47. tokenade/core/importer/db_utils.py +66 -0
  48. tokenade/core/importer/format_exporter.py +213 -0
  49. tokenade/core/importer/format_importer.py +278 -0
  50. tokenade/core/importer/local_storage_extractor.py +272 -0
  51. tokenade/core/importer/mobile_extractor.py +264 -0
  52. tokenade/core/importer/safari_extractor.py +318 -0
  53. tokenade/core/importer/session_comparator.py +124 -0
  54. tokenade/core/importer/session_loader.py +470 -0
  55. tokenade/core/importer/session_manager.py +295 -0
  56. tokenade/core/importer/session_packager.py +354 -0
  57. tokenade/core/importer/session_refresher.py +354 -0
  58. tokenade/core/importer/session_rotation.py +150 -0
  59. tokenade/core/importer/session_sharer.py +692 -0
  60. tokenade/core/importer/session_vault.py +282 -0
  61. tokenade/core/importer/tor_extractor.py +138 -0
  62. tokenade/core/importer/validator.py +498 -0
  63. tokenade/core/injector/__init__.py +15 -0
  64. tokenade/core/injector/profile_manager.py +375 -0
  65. tokenade/core/integration/__init__.py +8 -0
  66. tokenade/core/integration/docker_manager.py +349 -0
  67. tokenade/core/integration/kubernetes.py +395 -0
  68. tokenade/core/integration/plugin_registry.py +250 -0
  69. tokenade/core/integration/webhooks.py +219 -0
  70. tokenade/core/proxy/__init__.py +11 -0
  71. tokenade/core/proxy/cdp_proxy.py +1301 -0
  72. tokenade/core/proxy/extension_bridge.py +132 -0
  73. tokenade/core/proxy/forward_proxy.py +151 -0
  74. tokenade/core/proxy/multi_site_proxy.py +257 -0
  75. tokenade/core/proxy/server.py +1295 -0
  76. tokenade/core/refresh/__init__.py +19 -0
  77. tokenade/core/refresh/health_checker.py +356 -0
  78. tokenade/core/refresh/health_scorer.py +292 -0
  79. tokenade/core/runtime/__init__.py +30 -0
  80. tokenade/core/runtime/engine.py +786 -0
  81. tokenade/core/runtime/tls_matcher.py +251 -0
  82. tokenade/core/security/__init__.py +27 -0
  83. tokenade/core/security/audit.py +577 -0
  84. tokenade/core/security/credentials.py +418 -0
  85. tokenade/core/utils/__init__.py +0 -0
  86. tokenade/core/utils/performance.py +444 -0
  87. tokenade/handlers/__init__.py +0 -0
  88. tokenade/handlers/base.py +294 -0
  89. tokenade/handlers/generic_oauth.py +594 -0
  90. tokenade/handlers/github.py +349 -0
  91. tokenade/handlers/google.py +302 -0
  92. tokenade/sdk/__init__.py +257 -0
  93. tokenade/tests/__init__.py +0 -0
  94. tokenade/tests/portability.py +309 -0
  95. tokenade/tests/test_advanced_validator.py +237 -0
  96. tokenade/tests/test_antidetection.py +147 -0
  97. tokenade/tests/test_api_sdk.py +264 -0
  98. tokenade/tests/test_benchmarks.py +157 -0
  99. tokenade/tests/test_browser.py +351 -0
  100. tokenade/tests/test_browser_discovery.py +59 -0
  101. tokenade/tests/test_browser_improvements.py +276 -0
  102. tokenade/tests/test_browser_support.py +732 -0
  103. tokenade/tests/test_cli.py +204 -0
  104. tokenade/tests/test_cli_helpers.py +102 -0
  105. tokenade/tests/test_cli_refactor.py +458 -0
  106. tokenade/tests/test_collectors.py +286 -0
  107. tokenade/tests/test_comprehensive.py +314 -0
  108. tokenade/tests/test_cookie_extractor.py +156 -0
  109. tokenade/tests/test_crypto.py +189 -0
  110. tokenade/tests/test_db_utils.py +93 -0
  111. tokenade/tests/test_encryptor.py +126 -0
  112. tokenade/tests/test_encryptor_edge.py +66 -0
  113. tokenade/tests/test_enterprise.py +819 -0
  114. tokenade/tests/test_fingerprint.py +67 -0
  115. tokenade/tests/test_format_export.py +415 -0
  116. tokenade/tests/test_forward_proxy.py +52 -0
  117. tokenade/tests/test_handlers.py +523 -0
  118. tokenade/tests/test_health_scorer.py +538 -0
  119. tokenade/tests/test_importer_integration.py +273 -0
  120. tokenade/tests/test_integration.py +660 -0
  121. tokenade/tests/test_local_storage.py +57 -0
  122. tokenade/tests/test_local_storage_extractor.py +175 -0
  123. tokenade/tests/test_mac_crypto.py +74 -0
  124. tokenade/tests/test_multi_site_proxy.py +51 -0
  125. tokenade/tests/test_performance.py +302 -0
  126. tokenade/tests/test_property_based.py +215 -0
  127. tokenade/tests/test_proxy.py +645 -0
  128. tokenade/tests/test_proxy_config.py +86 -0
  129. tokenade/tests/test_proxy_gui.py +81 -0
  130. tokenade/tests/test_runtime.py +473 -0
  131. tokenade/tests/test_security.py +349 -0
  132. tokenade/tests/test_session_comparator.py +110 -0
  133. tokenade/tests/test_session_loader.py +53 -0
  134. tokenade/tests/test_session_manager.py +135 -0
  135. tokenade/tests/test_session_packager.py +104 -0
  136. tokenade/tests/test_session_refresher.py +558 -0
  137. tokenade/tests/test_session_rotation.py +408 -0
  138. tokenade/tests/test_session_sharer.py +588 -0
  139. tokenade/tests/test_session_vault.py +418 -0
  140. tokenade/tests/test_site_filter.py +66 -0
  141. tokenade/tests/test_ssrf.py +55 -0
  142. tokenade/tests/test_stealth.py +148 -0
  143. tokenade/tests/test_tls.py +40 -0
  144. tokenade/tests/test_tls_matcher.py +131 -0
  145. tokenade/utils/__init__.py +0 -0
  146. tokenade-3.5.0.dist-info/METADATA +567 -0
  147. tokenade-3.5.0.dist-info/RECORD +150 -0
  148. tokenade-3.5.0.dist-info/WHEEL +5 -0
  149. tokenade-3.5.0.dist-info/entry_points.txt +2 -0
  150. tokenade-3.5.0.dist-info/top_level.txt +1 -0
tokenade/__init__.py ADDED
@@ -0,0 +1,84 @@
1
+ """
2
+ Tokenade - Production-grade token shifting tool.
3
+
4
+ A secure, structured tool for extracting, transferring, and testing
5
+ browser sessions and authentication tokens across devices.
6
+
7
+ Modules:
8
+ core.browser: Browser automation abstractions
9
+ core.crypto: Cross-platform cookie encryption/decryption
10
+ core.fingerprint: Browser fingerprint collection and matching
11
+ core.extractor: Token extraction utilities
12
+ handlers: Site-specific handlers (Google, etc.)
13
+ tests: Portability testing framework
14
+ utils: Helper utilities
15
+
16
+ Usage:
17
+ from tokenade.cli import main
18
+ main()
19
+ """
20
+
21
+ __version__ = "3.5.0"
22
+ __author__ = "Tokenade Team"
23
+ __license__ = "MIT"
24
+
25
+ from tokenade.core.browser.manager import BrowserManager, BrowserConfig, BrowserFactory
26
+ from tokenade.core.crypto.cookie_crypto import (
27
+ CookieCrypto, WindowsCookieCrypto, LinuxCookieCrypto, CookieCryptoFactory,
28
+ DecryptedCookie,
29
+ )
30
+ from tokenade.core.fingerprint.manager import (
31
+ BrowserFingerprint, FingerprintCollector, FingerprintManager,
32
+ )
33
+ from tokenade.core.security.credentials import (
34
+ AccountCredentials, CredentialManager, SecureSessionStorage,
35
+ )
36
+ from tokenade.core.runtime.engine import (
37
+ RuntimeConfig, RuntimeEngine, SessionValidator, create_engine_from_session,
38
+ )
39
+ from tokenade.handlers.base import (
40
+ SiteHandler, HandlerRegistry, SessionData, ExtractedToken,
41
+ AuthStatus, TokenType,
42
+ )
43
+ from tokenade.core.importer.browser_discovery import (
44
+ BrowserProfileDiscovery, BrowserProfile,
45
+ )
46
+ from tokenade.core.importer.cookie_extractor import (
47
+ CookieExtractor, SiteFilter, SITE_DETECTION,
48
+ )
49
+ from tokenade.core.importer.session_packager import SessionPackager
50
+ from tokenade.core.importer.session_loader import SessionLoader
51
+
52
+ __all__ = [
53
+ "BrowserManager",
54
+ "BrowserConfig",
55
+ "BrowserFactory",
56
+ "CookieCrypto",
57
+ "WindowsCookieCrypto",
58
+ "LinuxCookieCrypto",
59
+ "CookieCryptoFactory",
60
+ "DecryptedCookie",
61
+ "BrowserFingerprint",
62
+ "FingerprintCollector",
63
+ "FingerprintManager",
64
+ "AccountCredentials",
65
+ "CredentialManager",
66
+ "SecureSessionStorage",
67
+ "RuntimeConfig",
68
+ "RuntimeEngine",
69
+ "SessionValidator",
70
+ "create_engine_from_session",
71
+ "SiteHandler",
72
+ "HandlerRegistry",
73
+ "SessionData",
74
+ "ExtractedToken",
75
+ "AuthStatus",
76
+ "TokenType",
77
+ "BrowserProfileDiscovery",
78
+ "BrowserProfile",
79
+ "CookieExtractor",
80
+ "SiteFilter",
81
+ "SITE_DETECTION",
82
+ "SessionPackager",
83
+ "SessionLoader",
84
+ ]
@@ -0,0 +1,306 @@
1
+ """Tokenade CLI - Main entry point and argument parser."""
2
+ import argparse
3
+ import logging
4
+ import sys
5
+
6
+ from tokenade.cli.session import cmd_extract, cmd_export, cmd_load, cmd_transfer, cmd_inject_profile
7
+ from tokenade.cli.security import cmd_encrypt, cmd_decrypt, cmd_rekey
8
+ from tokenade.cli.proxy import cmd_proxy
9
+ from tokenade.cli.management import cmd_sessions, cmd_health, cmd_refresh, cmd_share, cmd_unshare
10
+ from tokenade.cli.advanced import (
11
+ cmd_batch_export, cmd_batch_load, cmd_validate, cmd_validate_rules,
12
+ cmd_diff, cmd_fingerprint, cmd_test, cmd_setup,
13
+ )
14
+
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
18
+ )
19
+ logger = logging.getLogger("tokenade")
20
+
21
+
22
+ def setup_logging(verbose: bool = False):
23
+ """Configure logging level."""
24
+ level = logging.DEBUG if verbose else logging.INFO
25
+ logging.getLogger("tokenade").setLevel(level)
26
+
27
+
28
+ def main():
29
+ """Main CLI entry point."""
30
+ from tokenade import __version__
31
+ parser = argparse.ArgumentParser(
32
+ description="Tokenade - Browser session portability tool",
33
+ formatter_class=argparse.RawDescriptionHelpFormatter,
34
+ epilog="""
35
+ Quick Start:
36
+ 1. Export: tokenade export --browser-name firefox --domains "google.com,accounts.google.com" -o my_session.tokenade
37
+ 2. Proxy: tokenade proxy -s my_session.tokenade
38
+ 3. Browse: Open http://127.0.0.1:9222 and enter the target URL
39
+
40
+ Commands:
41
+ export Extract cookies from browser to .tokenade file
42
+ proxy Start CDP proxy server with donor session
43
+ load Load .tokenade session into a browser
44
+ inject-profile Inject cookies directly into browser profile
45
+ encrypt Encrypt a .tokenade file
46
+ decrypt Decrypt a .tokenade file
47
+ health Check session health
48
+ batch-export Export multiple sites at once
49
+ """,
50
+ )
51
+
52
+ parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
53
+ parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose logging")
54
+
55
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
56
+
57
+ # Setup
58
+ setup_parser = subparsers.add_parser("setup", help="Setup accounts")
59
+
60
+ # Extract
61
+ extract_parser = subparsers.add_parser("extract", help="Extract tokens")
62
+ extract_parser.add_argument("--visible", action="store_true", help="Show browser window")
63
+
64
+ # Transfer
65
+ transfer_parser = subparsers.add_parser("transfer", help="Transfer session")
66
+ transfer_parser.add_argument("-s", "--session", required=True, help="Session file path")
67
+ transfer_parser.add_argument("-f", "--fingerprint", help="Target fingerprint name")
68
+ transfer_parser.add_argument("-p", "--profile-dir", default="browser_data/transfer", help="Profile directory")
69
+ transfer_parser.add_argument("--visible", action="store_true", help="Show browser window")
70
+ transfer_parser.add_argument("--stealth-level", choices=["basic", "advanced", "maximum"], default="maximum", help="Stealth injection level")
71
+ transfer_parser.add_argument("--validate-stealth", action="store_true", help="Validate stealth injection after launch")
72
+
73
+ # Test
74
+ test_parser = subparsers.add_parser("test", help="Test portability")
75
+ test_parser.add_argument("-s", "--session", required=True, help="Session file path")
76
+ test_parser.add_argument("--source-fp", default="default", help="Source fingerprint")
77
+ test_parser.add_argument("--target-fp", default="default", help="Target fingerprint")
78
+ test_parser.add_argument("--variations", action="store_true", help="Test fingerprint variations")
79
+ test_parser.add_argument("--test-api", action="store_true", help="Test API calls")
80
+ test_parser.add_argument("--stealth-level", choices=["basic", "advanced", "maximum"], default="maximum", help="Stealth injection level")
81
+ test_parser.add_argument("--validate-stealth", action="store_true", help="Validate stealth injection")
82
+ test_parser.add_argument("-o", "--output", help="Output report path")
83
+
84
+ # Fingerprint
85
+ fp_parser = subparsers.add_parser("fingerprint", help="Manage fingerprints")
86
+ fp_parser.add_argument("action", choices=["list", "collect", "show", "delete"], help="Action")
87
+ fp_parser.add_argument("-n", "--name", help="Fingerprint name")
88
+ fp_parser.add_argument("-p", "--profile-dir", help="Browser profile directory")
89
+
90
+ # Validate
91
+ validate_parser = subparsers.add_parser("validate", help="Validate sessions")
92
+ validate_parser.add_argument("-d", "--sessions-dir", default="sessions", help="Sessions directory")
93
+
94
+ # Export
95
+ export_parser = subparsers.add_parser("export", help="Export session from existing browser")
96
+ export_parser.add_argument("--browser-name", choices=["chrome", "firefox", "edge", "brave"], help="Browser name")
97
+ export_parser.add_argument("--browser-path", help="Custom path to browser profile")
98
+ export_parser.add_argument("--profile", help="Profile name within browser")
99
+ export_parser.add_argument("--site-config", help="Path to JSON site config file for filtering")
100
+ export_parser.add_argument("--domains", help="Comma-separated domains to filter (e.g. 'google.com,accounts.google.com')")
101
+ export_parser.add_argument("--file-path", help="Export from cookies file")
102
+ export_parser.add_argument("--format", choices=["netscape", "json", "curl"], default="netscape", help="File format")
103
+ export_parser.add_argument("--collect-fingerprint", action="store_true", help="Collect source browser fingerprint")
104
+ export_parser.add_argument("--output", "-o", help="Output file path (any extension)")
105
+ export_parser.add_argument("--list-profiles", action="store_true", help="List available profiles")
106
+ export_parser.add_argument("--decrypt", action="store_true", help="Decrypt cookies (auto-detected)")
107
+ export_parser.add_argument("--extract-local-storage", action="store_true", help="Also extract localStorage data")
108
+ export_parser.add_argument("--local-storage-origin", help="Origin to extract localStorage from")
109
+
110
+ # Load
111
+ load_parser = subparsers.add_parser("load", help="Load session file into browser")
112
+ load_parser.add_argument("--file", "-f", required=True, help="Path to session file")
113
+ load_parser.add_argument("--site-config", help="Path to JSON site config file for validation")
114
+ load_parser.add_argument("--fingerprint", help="Target fingerprint name")
115
+ load_parser.add_argument("--stealth-level", choices=["basic", "advanced", "maximum"], default="maximum", help="Stealth level")
116
+ load_parser.add_argument("--validate", action="store_true", help="Validate session after injection")
117
+ load_parser.add_argument("--runtime", action="store_true", help="Load into RuntimeEngine")
118
+ load_parser.add_argument("--test-api", action="store_true", help="Test API after loading")
119
+ load_parser.add_argument("--visible", action="store_true", help="Show browser window")
120
+ load_parser.add_argument("--profile-dir", help="Browser profile directory")
121
+ load_parser.add_argument("--no-local-storage", action="store_true", help="Skip localStorage injection if present")
122
+
123
+ # Inject Profile
124
+ inject_parser = subparsers.add_parser("inject-profile", help="Inject cookies directly into browser profile")
125
+ inject_parser.add_argument("--session", "-s", required=True, help="Path to session file")
126
+ inject_parser.add_argument("--profile", "-p", required=True, help="Browser profile path")
127
+ inject_parser.add_argument("--browser", "-b", choices=["chrome", "brave", "edge", "firefox", "opera", "vivaldi"],
128
+ default="chrome", help="Browser name")
129
+ inject_parser.add_argument("--no-backup", action="store_true", help="Skip backup creation")
130
+ inject_parser.add_argument("--dry-run", action="store_true", help="Show what would be injected without making changes")
131
+
132
+ # Encrypt
133
+ encrypt_parser = subparsers.add_parser("encrypt", help="Encrypt session file")
134
+ encrypt_parser.add_argument("--input", "-i", required=True, help="Input file path")
135
+ encrypt_parser.add_argument("--output", "-o", help="Output file path")
136
+ encrypt_parser.add_argument("--password", "-p", help="Encryption password")
137
+ encrypt_parser.add_argument("--key-file", "-k", help="Password file")
138
+
139
+ # Decrypt
140
+ decrypt_parser = subparsers.add_parser("decrypt", help="Decrypt session file")
141
+ decrypt_parser.add_argument("--input", "-i", required=True, help="Encrypted file path")
142
+ decrypt_parser.add_argument("--output", "-o", help="Output file path")
143
+ decrypt_parser.add_argument("--password", "-p", help="Decryption password")
144
+ decrypt_parser.add_argument("--key-file", "-k", help="Password file")
145
+
146
+ # Rekey
147
+ rekey_parser = subparsers.add_parser("rekey", help="Change encryption password")
148
+ rekey_parser.add_argument("--input", "-i", required=True, help="Encrypted file path")
149
+ rekey_parser.add_argument("--output", "-o", help="Output file path")
150
+ rekey_parser.add_argument("--old-password", help="Old password")
151
+ rekey_parser.add_argument("--new-password", help="New password")
152
+ rekey_parser.add_argument("--old-key-file", help="Old password file")
153
+ rekey_parser.add_argument("--new-key-file", help="New password file")
154
+
155
+ # Batch Export
156
+ batch_export_parser = subparsers.add_parser("batch-export", help="Batch export multiple sites")
157
+ batch_export_parser.add_argument("--site-config", "-s", required=True, help="Site config JSON file")
158
+ batch_export_parser.add_argument("--browser", "-b", choices=["chrome", "firefox", "edge", "brave"],
159
+ default="firefox", help="Browser name")
160
+ batch_export_parser.add_argument("--browser-path", help="Custom browser profile path")
161
+ batch_export_parser.add_argument("--profile", "-p", help="Profile name")
162
+ batch_export_parser.add_argument("--output", "-o", help="Output directory")
163
+ batch_export_parser.add_argument("--extract-local-storage", action="store_true", help="Extract localStorage")
164
+
165
+ # Batch Load
166
+ batch_load_parser = subparsers.add_parser("batch-load", help="Batch load multiple sessions")
167
+ batch_load_parser.add_argument("--sessions-dir", "-d", required=True, help="Sessions directory")
168
+ batch_load_parser.add_argument("--target-browser", "-t", choices=["chrome", "firefox", "edge", "brave"],
169
+ default="chrome", help="Target browser")
170
+ batch_load_parser.add_argument("--site-config", "-s", help="Site config JSON file for validation")
171
+ batch_load_parser.add_argument("--profile-dir", help="Target profile directory")
172
+ batch_load_parser.add_argument("--validate", action="store_true", help="Validate sessions")
173
+ batch_load_parser.add_argument("--visible", action="store_true", help="Show browser window")
174
+
175
+ # Health Check
176
+ health_parser = subparsers.add_parser("health", help="Check session health")
177
+ health_parser.add_argument("--session", "-s", help="Single session file to check")
178
+ health_parser.add_argument("--sessions-dir", "-d", help="Directory of sessions to check")
179
+
180
+ # Refresh
181
+ refresh_parser = subparsers.add_parser("refresh", help="Refresh session from source browser")
182
+ refresh_parser.add_argument("--session", "-s", required=True, help="Session file to refresh")
183
+ refresh_parser.add_argument("--source-browser", "-b", choices=["chrome", "firefox", "edge", "brave"],
184
+ required=True, help="Source browser name")
185
+ refresh_parser.add_argument("--source-browser-path", help="Custom source browser profile path")
186
+ refresh_parser.add_argument("--source-profile", help="Source profile name")
187
+ refresh_parser.add_argument("--site-config", help="Site config JSON file for filtering")
188
+
189
+ # Proxy
190
+ proxy_parser = subparsers.add_parser("proxy", help="Start fingerprint-matched proxy server")
191
+ proxy_parser.add_argument("--session", "-s", help="Path to .tokenade session file (single mode)")
192
+ proxy_parser.add_argument("--all", action="store_true", help="Serve all sessions (multi-site mode)")
193
+ proxy_parser.add_argument("--sessions-dir", "-d", help="Directory of .tokenade files (for --all)")
194
+ proxy_parser.add_argument("--mode", choices=["gui", "forward"], default="gui",
195
+ help="Proxy mode: gui (browser GUI) or forward (HTTP_PROXY)")
196
+ proxy_parser.add_argument("--port", "-p", type=int, default=9222, help="Port to listen on (default: 9222)")
197
+ proxy_parser.add_argument("--host", default="127.0.0.1", help="Host to bind to (default: 127.0.0.1)")
198
+ proxy_parser.add_argument("--legacy", action="store_true", help="Use legacy service-worker proxy (default: CDP)")
199
+ proxy_parser.add_argument("--visible", action="store_true", help="Show browser window (CDP mode only)")
200
+ proxy_parser.add_argument("--fingerprint", action="store_true", help="Enable TLS fingerprint matching via curl-cffi (breaks cf_clearance)")
201
+ proxy_parser.add_argument("--no-open-browser", action="store_true", help="Don't open browser automatically")
202
+ proxy_parser.add_argument("--no-gui", action="store_true", help="Disable GUI mode (legacy proxy only)")
203
+ proxy_parser.add_argument("--timeout", type=int, default=30, help="Request timeout in seconds (default: 30)")
204
+ proxy_parser.add_argument("--auto-refresh", action="store_true", help="Auto-refresh session from source browser when cookies expire")
205
+ proxy_parser.add_argument("--source-browser", help="Source browser for auto-refresh (e.g., firefox, chrome)")
206
+ proxy_parser.add_argument("--source-profile", help="Source profile for auto-refresh (e.g., default, Profile 1)")
207
+
208
+ # Sessions (subcommand group)
209
+ sessions_parser = subparsers.add_parser("sessions", help="Manage multiple sessions")
210
+ sessions_sub = sessions_parser.add_subparsers(dest="sessions_command", help="Session management commands")
211
+
212
+ # sessions list
213
+ sessions_list_parser = sessions_sub.add_parser("list", help="List all sessions")
214
+ sessions_list_parser.add_argument("--dir", "-d", default=".", help="Directory to search")
215
+ sessions_list_parser.add_argument("--pattern", "-p", default="*.tokenade", help="File pattern")
216
+ sessions_list_parser.add_argument("--recursive", "-r", action="store_true", help="Search subdirectories")
217
+ sessions_list_parser.add_argument("--site", "-s", help="Filter by site name")
218
+ sessions_list_parser.add_argument("--browser", "-b", help="Filter by source browser")
219
+
220
+ # sessions merge
221
+ sessions_merge_parser = sessions_sub.add_parser("merge", help="Merge multiple sessions")
222
+ sessions_merge_parser.add_argument("files", nargs="+", help="Session files to merge")
223
+ sessions_merge_parser.add_argument("--output", "-o", required=True, help="Output file path")
224
+ sessions_merge_parser.add_argument("--site-name", help="Site name for merged session")
225
+
226
+ # sessions rotate
227
+ sessions_rotate_parser = sessions_sub.add_parser("rotate", help="Select next session (rotation)")
228
+ sessions_rotate_parser.add_argument("files", nargs="+", help="Session files to rotate through")
229
+ sessions_rotate_parser.add_argument("--strategy", choices=["round-robin", "random"], default="round-robin",
230
+ help="Rotation strategy")
231
+ sessions_rotate_parser.add_argument("--state-file", help="State file for round-robin")
232
+
233
+ # sessions stats
234
+ sessions_stats_parser = sessions_sub.add_parser("stats", help="Show aggregate session statistics")
235
+ sessions_stats_parser.add_argument("files", nargs="+", help="Session files to analyze")
236
+
237
+ # Share
238
+ share_parser = subparsers.add_parser("share", help="Create shareable session link or QR code")
239
+ share_parser.add_argument("--session", "-s", required=True, help="Session file to share")
240
+ share_parser.add_argument("--output", "-o", help="Output file path (HTML or QR image)")
241
+ share_parser.add_argument("--format", choices=["url", "html", "qr"], default="url",
242
+ help="Output format: url (default), html, qr")
243
+ share_parser.add_argument("--expiry", type=int, default=24, help="Link expiry in hours (default: 24)")
244
+ share_parser.add_argument("--max-uses", type=int, default=0, help="Max uses (0 = unlimited)")
245
+ share_parser.add_argument("--password", "-p", help="Password protect the link")
246
+
247
+ # Unshare
248
+ unshare_parser = subparsers.add_parser("unshare", help="Revoke a shared session")
249
+ unshare_parser.add_argument("session_id", help="Session ID to revoke")
250
+ unshare_parser.add_argument("--list", action="store_true", help="List all active shares")
251
+
252
+ # Validate Rules
253
+ validate_rules_parser = subparsers.add_parser("validate-rules", help="Validate session with custom rules")
254
+ validate_rules_parser.add_argument("--session", "-s", required=True, help="Session file to validate")
255
+ validate_rules_parser.add_argument("--rules", "-r", required=True, help="Validation rules JSON file")
256
+ validate_rules_parser.add_argument("--url", "-u", help="Target site URL")
257
+ validate_rules_parser.add_argument("--update-baselines", action="store_true", help="Update screenshot baselines")
258
+
259
+ # Diff
260
+ diff_parser = subparsers.add_parser("diff", help="Compare two session files")
261
+ diff_parser.add_argument("session_a", help="First .tokenade file")
262
+ diff_parser.add_argument("session_b", help="Second .tokenade file")
263
+ diff_parser.add_argument("--verbose", "-v", action="store_true", help="Show detailed differences")
264
+
265
+ args = parser.parse_args()
266
+
267
+ if not args.command:
268
+ parser.print_help()
269
+ sys.exit(1)
270
+
271
+ setup_logging(args.verbose)
272
+
273
+ commands = {
274
+ "setup": cmd_setup,
275
+ "extract": cmd_extract,
276
+ "transfer": cmd_transfer,
277
+ "test": cmd_test,
278
+ "fingerprint": cmd_fingerprint,
279
+ "validate": cmd_validate,
280
+ "export": cmd_export,
281
+ "load": cmd_load,
282
+ "inject-profile": cmd_inject_profile,
283
+ "encrypt": cmd_encrypt,
284
+ "decrypt": cmd_decrypt,
285
+ "rekey": cmd_rekey,
286
+ "batch-export": cmd_batch_export,
287
+ "batch-load": cmd_batch_load,
288
+ "health": cmd_health,
289
+ "refresh": cmd_refresh,
290
+ "proxy": cmd_proxy,
291
+ "sessions": cmd_sessions,
292
+ "share": cmd_share,
293
+ "unshare": cmd_unshare,
294
+ "validate-rules": cmd_validate_rules,
295
+ "diff": cmd_diff,
296
+ }
297
+
298
+ try:
299
+ commands[args.command](args)
300
+ except KeyboardInterrupt:
301
+ print("\n\n⚠️ Interrupted by user")
302
+ sys.exit(130)
303
+ except Exception as e:
304
+ logger.exception("Command failed")
305
+ print(f"\n❌ Error: {e}")
306
+ sys.exit(1)
@@ -0,0 +1,5 @@
1
+ """Allow running: python -m tokenade.cli"""
2
+ from tokenade.cli import main
3
+
4
+ if __name__ == "__main__":
5
+ main()