simplex 1.2.35__py3-none-any.whl → 1.2.36__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 simplex might be problematic. Click here for more details.
- simplex/cli.py +6 -7
- simplex/simplex.py +18 -132
- {simplex-1.2.35.dist-info → simplex-1.2.36.dist-info}/METADATA +12 -2
- simplex-1.2.36.dist-info/RECORD +11 -0
- {simplex-1.2.35.dist-info → simplex-1.2.36.dist-info}/WHEEL +1 -1
- simplex-1.2.35.dist-info/RECORD +0 -11
- {simplex-1.2.35.dist-info → simplex-1.2.36.dist-info}/LICENSE +0 -0
- {simplex-1.2.35.dist-info → simplex-1.2.36.dist-info}/entry_points.txt +0 -0
- {simplex-1.2.35.dist-info → simplex-1.2.36.dist-info}/top_level.txt +0 -0
simplex/cli.py
CHANGED
|
@@ -63,14 +63,13 @@ def login(website, proxies):
|
|
|
63
63
|
website = 'https://' + website
|
|
64
64
|
|
|
65
65
|
animated_print(f"[SIMPLEX] Creating login session for {website}")
|
|
66
|
-
|
|
67
|
-
fileName = simplex.create_login_session(website, proxies=proxies)
|
|
68
|
-
|
|
69
|
-
if fileName:
|
|
70
|
-
animated_print(f"[SIMPLEX] Login session created and saved to {fileName}")
|
|
71
|
-
else:
|
|
72
|
-
print(f"{Fore.YELLOW}[SIMPLEX] Warning: Session data could not be saved{Style.RESET_ALL}")
|
|
66
|
+
login_session_url = simplex.create_login_session(website, proxies=proxies)
|
|
73
67
|
|
|
68
|
+
if login_session_url:
|
|
69
|
+
animated_print("[SIMPLEX] Opening login page in your browser")
|
|
70
|
+
webbrowser.open_new_tab(login_session_url)
|
|
71
|
+
else:
|
|
72
|
+
print(f"{Fore.YELLOW}[SIMPLEX] Warning: No login URL returned from the server{Style.RESET_ALL}")
|
|
74
73
|
except Exception as e:
|
|
75
74
|
raise click.ClickException(str(e))
|
|
76
75
|
|
simplex/simplex.py
CHANGED
|
@@ -1,60 +1,9 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
import atexit
|
|
3
3
|
from typing import Optional
|
|
4
|
-
from playwright.sync_api import sync_playwright
|
|
5
|
-
import os
|
|
6
|
-
import json
|
|
7
|
-
|
|
8
4
|
BASE_URL = "https://api.simplex.sh"
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
def __init__(self, simplex_instance):
|
|
12
|
-
self.simplex = simplex_instance
|
|
13
|
-
|
|
14
|
-
def click(self, locator: str, locator_type: str, exact: Optional[bool] = False,
|
|
15
|
-
element_index: Optional[str] = None, nth_index: Optional[int] = None,
|
|
16
|
-
locator_options: Optional[dict] = None):
|
|
17
|
-
|
|
18
|
-
if element_index and element_index not in ["first", "last", "nth"]:
|
|
19
|
-
raise ValueError("element_index must be 'first', 'last', or 'nth'")
|
|
20
|
-
|
|
21
|
-
if element_index=="nth" and not nth_index:
|
|
22
|
-
raise ValueError("nth_index is required when element_index is 'nth'")
|
|
23
|
-
|
|
24
|
-
data = {
|
|
25
|
-
'session_id': self.simplex.session_id,
|
|
26
|
-
'locator': locator,
|
|
27
|
-
'locator_type': locator_type,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if element_index:
|
|
31
|
-
data['element_index'] = element_index
|
|
32
|
-
data['nth_index'] = nth_index
|
|
33
|
-
|
|
34
|
-
if exact:
|
|
35
|
-
data['exact'] = exact
|
|
36
|
-
|
|
37
|
-
if locator_options:
|
|
38
|
-
data['locator_options'] = json.dumps(locator_options)
|
|
39
|
-
|
|
40
|
-
response = requests.post(
|
|
41
|
-
f"{BASE_URL}/playwright/click",
|
|
42
|
-
headers={
|
|
43
|
-
'x-api-key': self.simplex.api_key
|
|
44
|
-
},
|
|
45
|
-
data=data
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
if 'succeeded' not in response.json():
|
|
49
|
-
print(response.json())
|
|
50
|
-
raise ValueError(f"It looks like the click action with playwright failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
51
|
-
|
|
52
|
-
if response.json()["succeeded"]:
|
|
53
|
-
return
|
|
54
|
-
else:
|
|
55
|
-
raise ValueError(f"Failed to click element: {response.json()['error']}")
|
|
56
|
-
|
|
57
|
-
|
|
6
|
+
import json
|
|
58
7
|
|
|
59
8
|
class Simplex:
|
|
60
9
|
def __init__(self, api_key: str):
|
|
@@ -62,8 +11,6 @@ class Simplex:
|
|
|
62
11
|
self.session_id = None
|
|
63
12
|
atexit.register(self.close_session)
|
|
64
13
|
|
|
65
|
-
self.playwright = Playwright(self)
|
|
66
|
-
|
|
67
14
|
def close_session(self):
|
|
68
15
|
if not self.session_id:
|
|
69
16
|
return
|
|
@@ -82,18 +29,18 @@ class Simplex:
|
|
|
82
29
|
else:
|
|
83
30
|
raise ValueError(f"Failed to close session: {response.json()['error']}")
|
|
84
31
|
|
|
85
|
-
def create_session(self, show_in_console: Optional[bool] = True, proxies: Optional[bool] = True):
|
|
32
|
+
def create_session(self, show_in_console: Optional[bool] = True, proxies: Optional[bool] = True, session_data: Optional[str] = None):
|
|
86
33
|
response = requests.post(
|
|
87
34
|
f"{BASE_URL}/create_session",
|
|
88
35
|
headers={
|
|
89
36
|
'x-api-key': self.api_key
|
|
90
37
|
},
|
|
91
|
-
data={'proxies': proxies}
|
|
38
|
+
data={'proxies': proxies, 'session_data': session_data}
|
|
92
39
|
)
|
|
93
40
|
# Check for non-200 status code
|
|
94
41
|
if response.status_code != 200:
|
|
95
42
|
raise ValueError(f"Create session request failed with status code {response.status_code}: {response.text}")
|
|
96
|
-
|
|
43
|
+
|
|
97
44
|
response_json = response.json()
|
|
98
45
|
if 'session_id' not in response_json:
|
|
99
46
|
raise ValueError(f"It looks like the session wasn't created successfully. Did you set your api_key when creating the Simplex class?")
|
|
@@ -382,81 +329,20 @@ class Simplex:
|
|
|
382
329
|
else:
|
|
383
330
|
raise ValueError(f"Failed to wait: {response.json()['error']}")
|
|
384
331
|
|
|
385
|
-
def create_login_session(self, url: str,
|
|
386
|
-
|
|
387
|
-
""
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
headless=False,
|
|
400
|
-
args=[
|
|
401
|
-
'--disable-blink-features=AutomationControlled',
|
|
402
|
-
'--disable-automation',
|
|
403
|
-
],
|
|
404
|
-
ignore_default_args=['--enable-automation']
|
|
405
|
-
)
|
|
406
|
-
|
|
407
|
-
# Close the default about:blank page
|
|
408
|
-
if len(browser.pages) > 0:
|
|
409
|
-
browser.pages[0].close()
|
|
410
|
-
|
|
411
|
-
# Create main page for login
|
|
412
|
-
main_page = browser.new_page()
|
|
413
|
-
main_page.goto(url)
|
|
414
|
-
|
|
415
|
-
# Create control page
|
|
416
|
-
control_page = browser.new_page()
|
|
417
|
-
control_page.set_content("""
|
|
418
|
-
<html>
|
|
419
|
-
<body style="display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f5f5f5;">
|
|
420
|
-
<button id="capture-btn" style="
|
|
421
|
-
padding: 20px 40px;
|
|
422
|
-
font-size: 18px;
|
|
423
|
-
cursor: pointer;
|
|
424
|
-
background-color: #2196F3;
|
|
425
|
-
color: white;
|
|
426
|
-
border: none;
|
|
427
|
-
border-radius: 5px;
|
|
428
|
-
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
|
429
|
-
">Click here when logged in to capture session</button>
|
|
430
|
-
</body>
|
|
431
|
-
</html>
|
|
432
|
-
""")
|
|
433
|
-
|
|
434
|
-
# Wait for button click using Playwright's wait_for_event
|
|
435
|
-
control_page.wait_for_selector('#capture-btn')
|
|
436
|
-
control_page.evaluate("""
|
|
437
|
-
() => {
|
|
438
|
-
return new Promise((resolve) => {
|
|
439
|
-
document.getElementById('capture-btn').onclick = () => {
|
|
440
|
-
resolve(true);
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
""")
|
|
445
|
-
|
|
446
|
-
storage = browser.storage_state()
|
|
447
|
-
if save_directory:
|
|
448
|
-
filename = os.path.join(save_directory, get_website_name(url) + "_session_data.json")
|
|
449
|
-
else:
|
|
450
|
-
filename = get_website_name(url) + "_session_data.json"
|
|
451
|
-
|
|
452
|
-
with open(filename, 'w') as f:
|
|
453
|
-
json.dump(storage, f, indent=2)
|
|
454
|
-
|
|
455
|
-
print(f"Session data saved to '{filename}'")
|
|
456
|
-
|
|
457
|
-
browser.close()
|
|
458
|
-
|
|
459
|
-
return filename
|
|
332
|
+
def create_login_session(self, url: str, proxies: Optional[bool] = True):
|
|
333
|
+
response = requests.post(
|
|
334
|
+
f"{BASE_URL}/create_login_session",
|
|
335
|
+
headers={
|
|
336
|
+
'x-api-key': self.api_key
|
|
337
|
+
},
|
|
338
|
+
data={'url': url, 'proxies': proxies}
|
|
339
|
+
)
|
|
340
|
+
if 'succeeded' not in response.json():
|
|
341
|
+
raise ValueError(f"It looks like the create_login_session action failed to return a response. Did you set your api_key when creating the Simplex class?")
|
|
342
|
+
if response.json()["succeeded"]:
|
|
343
|
+
return response.json()["login_session_url"]
|
|
344
|
+
else:
|
|
345
|
+
raise ValueError(f"Failed to create login session: {response.json()['error']}")
|
|
460
346
|
|
|
461
347
|
def restore_login_session(self, session_data: str, cdp_url: str = None):
|
|
462
348
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: simplex
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.36
|
|
4
4
|
Summary: Official Python SDK for Simplex API
|
|
5
5
|
Home-page: https://simplex.sh
|
|
6
6
|
Author: Simplex Labs, Inc.
|
|
@@ -17,6 +17,16 @@ Requires-Dist: colorama
|
|
|
17
17
|
Requires-Dist: requests
|
|
18
18
|
Requires-Dist: python-dotenv
|
|
19
19
|
Requires-Dist: click
|
|
20
|
+
Requires-Dist: playwright
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: author-email
|
|
23
|
+
Dynamic: classifier
|
|
24
|
+
Dynamic: description
|
|
25
|
+
Dynamic: description-content-type
|
|
26
|
+
Dynamic: home-page
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
20
30
|
|
|
21
31
|
# Simplex AI Python SDK
|
|
22
32
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
simplex/__init__.py,sha256=L_5i__xt_ZDkr6e-Wx9cr84t9sXpioOT7j01NJYJCTE,75
|
|
2
|
+
simplex/cli.py,sha256=FlZPWx014wpIy3TWYxhv8pANoPG9UWoq-ipkEIaiJAU,2389
|
|
3
|
+
simplex/simplex.py,sha256=dVFAW1Q83gSTpn20G6DOsKyvnILQsOIeJqOUYySgwjU,17707
|
|
4
|
+
simplex/deploy/__init__.py,sha256=_JQ81F_Nu7hSAfMA691gzs6a4-8oZ-buJ9h3Au12BKw,96
|
|
5
|
+
simplex/deploy/push.py,sha256=hRAbtFZaECKnBljaOLQ5nzJ6hk7tZgc1c7QdgxKQFoY,6123
|
|
6
|
+
simplex-1.2.36.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
|
|
7
|
+
simplex-1.2.36.dist-info/METADATA,sha256=th6kl09ViBxgKGYrIqgQej82XwrVnieyCgl5BJXtMiw,964
|
|
8
|
+
simplex-1.2.36.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
9
|
+
simplex-1.2.36.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
|
|
10
|
+
simplex-1.2.36.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
|
|
11
|
+
simplex-1.2.36.dist-info/RECORD,,
|
simplex-1.2.35.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
simplex/__init__.py,sha256=L_5i__xt_ZDkr6e-Wx9cr84t9sXpioOT7j01NJYJCTE,75
|
|
2
|
-
simplex/cli.py,sha256=DxZMiX-mqhy1cWJhf75YQs49GfZediueFuxyEhBFpLk,2324
|
|
3
|
-
simplex/simplex.py,sha256=ijEDiGkQhDMmeRXQVwyNa1m9e1SM-HPbDr3XSy0l_ZY,21782
|
|
4
|
-
simplex/deploy/__init__.py,sha256=_JQ81F_Nu7hSAfMA691gzs6a4-8oZ-buJ9h3Au12BKw,96
|
|
5
|
-
simplex/deploy/push.py,sha256=hRAbtFZaECKnBljaOLQ5nzJ6hk7tZgc1c7QdgxKQFoY,6123
|
|
6
|
-
simplex-1.2.35.dist-info/LICENSE,sha256=Xh0SJjYZfNI71pCNMB40aKlBLLuOB0blx5xkTtufFNQ,1075
|
|
7
|
-
simplex-1.2.35.dist-info/METADATA,sha256=LgkI9rOaiV9i6uPFEvHJXq4FJzZJkjBYHEbDeCb6flA,741
|
|
8
|
-
simplex-1.2.35.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
9
|
-
simplex-1.2.35.dist-info/entry_points.txt,sha256=3veL2w3c5vxb3dm8I_M8Fs-370n1ZnvD8uu1nSsL7z8,45
|
|
10
|
-
simplex-1.2.35.dist-info/top_level.txt,sha256=cbMH1bYpN0A3gP-ecibPRHasHoqB-01T_2BUFS8p0CE,8
|
|
11
|
-
simplex-1.2.35.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|