Add initial implementation of Cursor Pro Keep Alive tool

- Created .gitignore to exclude unnecessary files.
- Added config.ini for account configuration.
- Implemented cursor_auth_manager.py for managing authentication.
- Developed cursor_pro_keep_alive.py for automated account management.
- Included CursorKeepAlive.spec for packaging.
- Added gpt-accesstoken.py for obtaining ChatGPT access tokens.
- Created README.md with usage instructions.
- Updated requirements.txt with necessary dependencies.
- Added run_cursor.bat for script execution.
- Implemented update_cursor_auth.py for updating authentication details.
- Included turnstilePatch for handling CAPTCHA challenges.
- Added logging functionality in log.txt for tracking script execution.
- Created dist folder with packaged executable and necessary files.
This commit is contained in:
chengchongzhen
2024-12-28 15:14:40 +08:00
commit d48b1a9d6d
18 changed files with 1045 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.idea
__pycache__
build

42
CursorKeepAlive.spec Normal file
View File

@@ -0,0 +1,42 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['cursor_pro_keep_alive.py'],
pathex=[],
binaries=[],
datas=[
('config.ini', '.'),
('turnstilePatch', 'turnstilePatch'),
('cursor_auth_manager.py', '.'),
],
hiddenimports=[
'cursor_auth_manager'
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='cursor_pro_keep_alive',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)

5
README.md Normal file
View File

@@ -0,0 +1,5 @@
# gpt-cursor-auto
Python脚本 一键获取 ChatGpt 的 Access Token -- gpt-accesstoken.py
***********************************************************************************************
Python脚本 一键获取 Cursor Pro 自动保活 -- cursor_pro_keep_alive.py
2024.12.14日 新增自动获取token无需再手动登录账号关联Cursor需要 依赖 cursor_auth_manager.py

5
config.ini Normal file
View File

@@ -0,0 +1,5 @@
[Account]
email = apxeme@mailto.plus
password = ccz14321@
first_name = cheng
last_name = zhen

60
cursor_auth_manager.py Normal file
View File

@@ -0,0 +1,60 @@
import sqlite3
import os
class CursorAuthManager:
"""Cursor认证信息管理器"""
def __init__(self):
# 判断操作系统
if os.name == 'nt': # Windows
self.db_path = os.path.join(os.getenv('APPDATA'), 'Cursor', 'User', 'globalStorage', 'state.vscdb')
else: # macOS
self.db_path = os.path.expanduser('~/Library/Application Support/Cursor/User/globalStorage/state.vscdb')
def update_auth(self, email=None, access_token=None, refresh_token=None):
"""
更新Cursor的认证信息
:param email: 新的邮箱地址
:param access_token: 新的访问令牌
:param refresh_token: 新的刷新令牌
:return: bool 是否成功更新
"""
updates = []
if email is not None:
updates.append(('cursorAuth/cachedEmail', email))
if access_token is not None:
updates.append(('cursorAuth/accessToken', access_token))
if refresh_token is not None:
updates.append(('cursorAuth/refreshToken', refresh_token))
if not updates:
print("没有提供任何要更新的值")
return False
conn = None
try:
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
for key, value in updates:
query = "UPDATE itemTable SET value = ? WHERE key = ?"
cursor.execute(query, (value, key))
if cursor.rowcount > 0:
print(f"成功更新 {key.split('/')[-1]}")
else:
print(f"未找到 {key.split('/')[-1]} 或值未变化")
conn.commit()
return True
except sqlite3.Error as e:
print("数据库错误:", str(e))
return False
except Exception as e:
print("发生错误:", str(e))
return False
finally:
if conn:
conn.close()

453
cursor_pro_keep_alive.py Normal file
View File

@@ -0,0 +1,453 @@
from DrissionPage import ChromiumOptions, Chromium
from DrissionPage.common import Keys
import re
import time
import random
from cursor_auth_manager import CursorAuthManager
from configparser import ConfigParser
import os
import sys
def load_config():
"""加载配置文件"""
config = ConfigParser()
# 获取程序运行的根目录
root_dir = os.getcwd()
config_path = os.path.join(root_dir, "config.ini")
if os.path.exists(config_path):
config.read(config_path, encoding="utf-8")
print(f"已加载配置文件: {config_path}")
return {
"account": config["Account"]["email"],
"password": config["Account"]["password"],
"first_name": config["Account"]["first_name"],
"last_name": config["Account"]["last_name"],
}
raise FileNotFoundError(
f"配置文件不存在: {config_path}\n请确保配置文件在程序运行目录下"
)
def get_veri_code(tab):
"""获取验证码"""
username = account.split("@")[0]
try:
while True:
if tab.ele("@id=pre_button"):
tab.actions.click("@id=pre_button").type(Keys.CTRL_A).key_down(
Keys.BACKSPACE
).key_up(Keys.BACKSPACE).input(username).key_down(Keys.ENTER).key_up(
Keys.ENTER
)
break
time.sleep(1)
while True:
new_mail = tab.ele("@class=mail")
if new_mail:
if new_mail.text:
print("最新的邮件:", new_mail.text)
tab.actions.click("@class=mail")
break
else:
print(new_mail)
break
time.sleep(1)
if tab.ele("@class=overflow-auto mb-20"):
email_content = tab.ele("@class=overflow-auto mb-20").text
verification_code = re.search(
r"verification code is (\d{6})", email_content
)
if verification_code:
code = verification_code.group(1)
print("验证码:", code)
else:
print("未找到验证码")
if tab.ele("@id=delete_mail"):
tab.actions.click("@id=delete_mail")
time.sleep(1)
if tab.ele("@id=confirm_mail"):
tab.actions.click("@id=confirm_mail")
print("删除邮件")
tab.close()
except Exception as e:
print(e)
return code
def handle_turnstile(tab):
"""处理 Turnstile 验证"""
print("准备处理验证")
try:
while True:
try:
challengeCheck = (
tab.ele("@id=cf-turnstile", timeout=2)
.child()
.shadow_root.ele("tag:iframe")
.ele("tag:body")
.sr("tag:input")
)
if challengeCheck:
print("验证框加载完成")
time.sleep(random.uniform(1, 3))
challengeCheck.click()
print("验证按钮已点击,等待验证完成...")
time.sleep(2)
return True
except:
pass
if tab.ele("@name=password"):
print("无需验证")
break
if tab.ele("@data-index=0"):
print("无需验证")
break
if tab.ele("Account Settings"):
print("无需验证")
break
time.sleep(random.uniform(1, 2))
except Exception as e:
print(e)
print("跳过验证")
return False
def delete_account(browser, tab):
"""删除账户流程"""
print("\n开始删除账户...")
try:
if tab.ele("@name=email"):
tab.ele("@name=email").input(account)
print("输入账号")
time.sleep(random.uniform(1, 3))
except Exception as e:
print(f"输入账号失败: {str(e)}")
try:
if tab.ele("Continue"):
tab.ele("Continue").click()
print("点击Continue")
except Exception as e:
print(f"点击Continue失败: {str(e)}")
handle_turnstile(tab)
time.sleep(5)
try:
if tab.ele("@name=password"):
tab.ele("@name=password").input(password)
print("输入密码")
time.sleep(random.uniform(1, 3))
except Exception as e:
print("输入密码失败")
sign_in_button = tab.ele(
"xpath:/html/body/div[1]/div/div/div[2]/div/form/div/button"
)
try:
if sign_in_button:
sign_in_button.click(by_js=True)
print("点击Sign in")
except Exception as e:
print(f"点击Sign in失败: {str(e)}")
handle_turnstile(tab)
# 处理验证码
while True:
try:
if tab.ele("Account Settings"):
break
if tab.ele("@data-index=0"):
tab_mail = browser.new_tab(mail_url)
browser.activate_tab(tab_mail)
print("打开邮箱页面")
code = get_veri_code(tab_mail)
if code:
print("获取验证码成功:", code)
browser.activate_tab(tab)
else:
print("获取验证码失败,程序退出")
return False
i = 0
for digit in code:
tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
i += 1
break
except Exception as e:
print(e)
handle_turnstile(tab)
time.sleep(random.uniform(1, 3))
# tab.get_screenshot('sign-in_success.png')
# print("登录账户截图")
tab.get(settings_url)
print("进入设置页面")
try:
if tab.ele("@class=mt-1"):
tab.ele("@class=mt-1").click()
print("点击Adavance")
time.sleep(random.uniform(1, 2))
except Exception as e:
print(f"点击Adavance失败: {str(e)}")
try:
if tab.ele("Delete Account"):
tab.ele("Delete Account").click()
print("点击Delete Account")
time.sleep(random.uniform(1, 2))
except Exception as e:
print(f"点击Delete Account失败: {str(e)}")
try:
if tab.ele("tag:input"):
tab.actions.click("tag:input").type("delete")
print("输入delete")
time.sleep(random.uniform(1, 2))
except Exception as e:
print(f"输入delete失败: {str(e)}")
delete_button = tab.ele(
"xpath:/html/body/main/div/div/div/div/div/div[1]/div[2]/div[3]/div[2]/div/div/div[2]/button[2]"
)
try:
if delete_button:
print("点击Delete")
delete_button.click()
time.sleep(5)
# tab.get_screenshot('delete_account.png')
# print("删除账户截图")
return True
except Exception as e:
print(f"点击Delete失败: {str(e)}")
return False
def get_cursor_session_token(tab):
"""获取cursor session token"""
cookies = tab.cookies()
cursor_session_token = None
for cookie in cookies:
if cookie["name"] == "WorkosCursorSessionToken":
cursor_session_token = cookie["value"].split("%3A%3A")[1]
break
return cursor_session_token
def update_cursor_auth(email=None, access_token=None, refresh_token=None):
"""
更新Cursor的认证信息的便捷函数
"""
auth_manager = CursorAuthManager()
return auth_manager.update_auth(email, access_token, refresh_token)
def sign_up_account(browser, tab):
"""注册账户流程"""
print("\n开始注册新账户...")
tab.get(sign_up_url)
try:
if tab.ele("@name=first_name"):
print("已打开注册页面")
tab.actions.click("@name=first_name").input(first_name)
time.sleep(random.uniform(1, 3))
tab.actions.click("@name=last_name").input(last_name)
time.sleep(random.uniform(1, 3))
tab.actions.click("@name=email").input(account)
print("输入邮箱")
time.sleep(random.uniform(1, 3))
tab.actions.click("@type=submit")
print("点击注册按钮")
except Exception as e:
print("打开注册页面失败")
return False
handle_turnstile(tab)
try:
if tab.ele("@name=password"):
tab.ele("@name=password").input(password)
print("输入密码")
time.sleep(random.uniform(1, 3))
tab.ele("@type=submit").click()
print("点击Continue按钮")
except Exception as e:
print("输入密码失败")
return False
time.sleep(random.uniform(1, 3))
if tab.ele("This email is not available."):
print("This email is not available.")
return False
handle_turnstile(tab)
while True:
try:
if tab.ele("Account Settings"):
break
if tab.ele("@data-index=0"):
tab_mail = browser.new_tab(mail_url)
browser.activate_tab(tab_mail)
print("打开邮箱页面")
code = get_veri_code(tab_mail)
if code:
print("获取验证码成功:", code)
browser.activate_tab(tab)
else:
print("获取验证码失败,程序退出")
return False
i = 0
for digit in code:
tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
i += 1
break
except Exception as e:
print(e)
handle_turnstile(tab)
time.sleep(random.uniform(1, 3))
print("进入设置页面")
tab.get(settings_url)
try:
usage_ele = tab.ele(
"xpath:/html/body/main/div/div/div/div/div/div[2]/div/div/div/div[1]/div[1]/span[2]"
)
if usage_ele:
usage_info = usage_ele.text
total_usage = usage_info.split("/")[-1].strip()
print("可用上限: " + total_usage)
except Exception as e:
print("获取可用上限失败")
# tab.get_screenshot("sign_up_success.png")
# print("注册账户截图")
print("注册完成")
print("Cursor 账号: " + account)
print(" 密码: " + password)
return True
def get_extension_path():
"""获取插件路径"""
root_dir = os.getcwd()
extension_path = os.path.join(root_dir, "turnstilePatch")
if hasattr(sys, "_MEIPASS"):
print("运行在打包环境中")
extension_path = os.path.join(sys._MEIPASS, "turnstilePatch")
print(f"尝试加载插件路径: {extension_path}")
if not os.path.exists(extension_path):
raise FileNotFoundError(
f"插件不存在: {extension_path}\n请确保 turnstilePatch 文件夹在正确位置"
)
return extension_path
if __name__ == "__main__":
try:
# 加载配置
config = load_config()
# 固定的 URL 配置
login_url = "https://authenticator.cursor.sh"
sign_up_url = "https://authenticator.cursor.sh/sign-up"
settings_url = "https://www.cursor.com/settings"
mail_url = "https://tempmail.plus"
# 账号信息
account = config["account"]
password = config["password"]
first_name = config["first_name"]
last_name = config["last_name"]
auto_update_cursor_auth = True
# 浏览器配置
co = ChromiumOptions()
try:
extension_path = get_extension_path()
co.add_extension(extension_path)
except FileNotFoundError as e:
print(f"警告: {e}")
print("将尝试继续执行...")
co.headless() # 无头模式
co.set_user_agent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36"
)
co.set_pref("credentials_enable_service", False)
co.set_argument("--hide-crash-restore-bubble")
co.auto_port()
# co.set_argument('--no-sandbox') # 无沙盒模式 用于linux
# co.set_argument('--headless=new') #无界面系统启动参数 用于linux
# co.set_proxy('127.0.0.1:10809') #设置代理
browser = Chromium(co)
tab = browser.latest_tab
tab.run_js("try { turnstile.reset() } catch(e) { }")
print("开始执行删除和注册流程")
print("***请确认已经用https://tempmail.plus/zh邮箱成功申请过cursor账号***")
tab.get(login_url)
# 执行删除和注册流程
if delete_account(browser, tab):
print("账户删除成功")
time.sleep(3)
if sign_up_account(browser, tab):
token = get_cursor_session_token(tab)
print(f"CursorSessionToken: {token}")
print("账户注册成功")
if auto_update_cursor_auth:
update_cursor_auth(
email=account, access_token=token, refresh_token=token
)
else:
print("账户注册失败")
else:
print("账户删除失败")
print("脚本执行完毕")
browser.quit()
# 添加等待用户输入后再退出
input("\n按回车键退出...")
except FileNotFoundError as e:
print(f"<EFBFBD><EFBFBD><EFBFBD>误: {e}")
print("请确保 config.ini 文件存在并包含正确的配置信息")
input("\n按回车键退出...")
except Exception as e:
print(f"加载配置时出错: {e}")
input("\n按回车键退出...")

5
dist/config - 副本.ini vendored Normal file
View File

@@ -0,0 +1,5 @@
[Account]
email = xxxx
password = xxx
first_name = xxxx
last_name = xxxx

5
dist/config.ini vendored Normal file
View File

@@ -0,0 +1,5 @@
[Account]
email = apxeme@mailto.plus
password = ccz14321@
first_name = cheng
last_name = zhen

BIN
dist/cursor_pro_keep_alive.exe vendored Normal file

Binary file not shown.

95
dist/readme.md vendored Normal file
View File

@@ -0,0 +1,95 @@
# Cursor Pro Keep Alive 使用说明文档
## 1. 软件介绍
Cursor Pro Keep Alive 是一个自动化工具,用于管理 Cursor 账号的注册和更新。该工具可以自动执行账号删除和重新注册流程,以保持账号活跃。
## 2. 安装和准备
### 2.1 必要文件
确保您有以下文件:
- `cursor_pro_keep_alive.exe` - 主程序
- `config.ini` - 配置文件
- `turnstilePatch` - 插件文件夹
### 2.2 文件结构
```
your_folder/
├── cursor_pro_keep_alive.exe
├── config.ini
└── turnstilePatch/
└── (插件文件)
```
## 3. 配置文件设置
在运行程序前,需要正确配置 `config.ini` 文件:
```ini
[Account]
email = your_username@mailto.plus # 邮箱地址(必须使用 mailto.plus 域名)
password = your_password # 账号密码
first_name = your_firstname # 名字
last_name = your_lastname # 姓氏
```
注意事项:
- 邮箱必须使用 `mailto.plus` 域名
- 请确保配置文件使用 UTF-8 编码保存
## 4. 运行程序
### 4.1 运行步骤
1. 确保所有必要文件都在同一目录下
2. 双击运行 `cursor_pro_keep_alive.exe`
3. 程序会自动执行以下操作:
- 删除现有账号
- 注册新账号
- 更新认证信息
### 4.2 运行提示
- 程序运行过程中会显示各个步骤的执行状态
- 如果出现验证码,程序会自动处理
- 运行完成后会显示操作结果
## 5. 常见问题解决
### 5.1 配置文件错误
错误提示:`配置文件不存在`
- 解决方法:确保 `config.ini` 文件在程序同目录下
### 5.2 插件加载失败
错误提示:`插件不存在`
- 解决方法:确保 `turnstilePatch` 文件夹在程序同目录下
- 注意:即使插件加载失败,程序仍会继续执行
### 5.3 账号注册失败
- 检查邮箱格式是否正确(必须是 mailto.plus
- 确保密码符合要求
- 检查网络连接是否正常
## 6. 注意事项
1. 运行环境要求:
- Windows 操作系统
- 稳定的网络连接
2. 安全提示:
- 请妥善保管配置文件,避免泄露账号信息
- 建议定期更改密码
3. 使用建议:
- 建议在非高峰时段运行程序
- 保持配置文件的定期备份
## 7. 技术支持
如遇到问题,请检查:
1. 配置文件格式是否正确
2. 必要文件是否完整
3. 网络连接是否正常
## 8. 免责声明
本程序仅供学习和研究使用,请遵守相关服务条款和法律法规。使用本程序产生的任何后果由用户自行承担。

166
gpt-accesstoken.py Normal file
View File

@@ -0,0 +1,166 @@
from DrissionPage import ChromiumOptions, Chromium
import random
import time
def handle_turnstile(tab):
"""处理 Turnstile 验证"""
print("准备处理验证")
try:
while True:
if tab.ele('@id=email-input', timeout=2):
print("无需验证 - 邮箱输入框已加载")
return True
if tab.ele('@id=password', timeout=2):
print("无需验证 - 密码输入框已加载")
return True
try:
challenge_element = (tab.ele("@name=cf-turnstile-response", timeout=2)
.parent()
.shadow_root
.ele("tag:iframe")
.ele("tag:body")
.sr("tag:input"))
if challenge_element:
print("验证框加载完成")
time.sleep(random.uniform(1, 3))
challenge_element.click()
print("验证按钮已点击,等待验证完成...")
time.sleep(2)
return True
except:
pass
time.sleep(2)
except Exception as e:
print(f"验证处理出错: {str(e)}")
print('跳过验证')
return False
account = 'your_chatgpt_account'
password = 'your_chatgpt_password'
co = ChromiumOptions()
co.add_extension("turnstilePatch")
# co.headless()
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36')
co.set_pref('credentials_enable_service', False)
co.set_argument('--hide-crash-restore-bubble')
co.auto_port()
browser = Chromium(co)
tab = browser.latest_tab
tab.run_js("try { turnstile.reset() } catch(e) { }")
print("\n步骤1: 开始访问网站...")
tab.get('https://chatgpt.com')
print('等待页面加载...')
print("\n步骤2: 开始登录...")
for _ in range(5):
try:
if tab.ele('xpath:/html/body/div[1]/div[1]/main/div[1]/div[1]/div/div[1]/div/div[3]/div/button[1]'):
signin_btn = tab.ele('xpath:/html/body/div[1]/div[1]/main/div[1]/div[1]/div/div[1]/div/div[3]/div/button[1]')
print("找到黑色登录按钮:", signin_btn.text)
break
if tab.ele('@data-testid=login-button'):
signin_btn = tab.ele('@data-testid=login-button')
print("找到蓝色登录按钮:", signin_btn.text)
break
if tab.ele("@name=cf-turnstile-response"):
print('加载页面时出现CF验证, IP 质量太差, 请更换 IP 重新尝试!')
browser.quit()
exit()
time.sleep(3)
except Exception as e:
print(f"处理登录按钮时出错: {str(e)}")
for _ in range(5):
try:
if signin_btn:
signin_btn.click()
print("点击登录按钮")
break
except Exception as e:
print(f"处理登录按钮时出错: {str(e)}")
time.sleep(3)
else:
print("尝试点击登录按钮失败,程序退出")
exit()
handle_turnstile(tab)
print("\n步骤3: 输入邮箱...")
for _ in range(5):
try:
if tab.ele('@id=email-input'):
tab.actions.click('@id=email-input').type(account)
time.sleep(0.5)
tab.ele('@class=continue-btn').click()
print("输入邮箱并点击继续")
break
except Exception as e:
print(f"加载邮箱输入框时出错: {str(e)}")
time.sleep(3)
else:
print("尝试加载邮箱输入框失败,程序退出")
browser.quit()
exit()
handle_turnstile(tab)
print("\n步骤4: 输入密码...")
for _ in range(5):
try:
if tab.ele('@id=password'):
print("密码输入框加载完成")
tab.actions.click('@id=password').input(password)
time.sleep(2)
tab.ele('@type=submit').click('js')
# tab.actions.click('@type=submit')
print("输入密码并JS点击登录")
break
except Exception as e:
print(f"输入密码时出错: {str(e)}")
time.sleep(3)
else:
print("尝试加载密码输入框失败,程序退出")
browser.quit()
exit()
for _ in range(5):
try:
if tab.ele('有什么可以帮忙的?'):
print('登录成功!')
break
if tab.ele('重新发送电子邮件'):
print('提示需要邮箱验证码,脚本终止,请手动获取')
exit()
except Exception as e:
print(f"登录可能遇到问题: {str(e)}")
time.sleep(3)
else:
print("登录失败,程序退出")
browser.quit()
exit()
time.sleep(random.uniform(1,2))
print('\n',"步骤5: 获取access_token...")
browser.new_tab('https://chatgpt.com/api/auth/session')
tab = browser.latest_tab
time.sleep(1)
response_json = tab.json
if response_json and 'accessToken' in response_json:
access_token = response_json['accessToken']
print('\n',"请复制保存你的access_token:",'\n')
print(access_token)
else:
print("错误:未找到access token")
# input("\n按Enter键关闭浏览器...")
browser.quit()

90
log.txt Normal file
View File

@@ -0,0 +1,90 @@
[2024/12/26 <20><><EFBFBD><EFBFBD> 13:11:03.37] 开始执行脚<E8A18C><E8849A>?
[2024/12/26 <20><><EFBFBD><EFBFBD> 13:17:58.13] 开始执行脚<E8A18C><E8849A>?
<EFBFBD><EFBFBD>ʼִ<EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
***<2A><>ȷ<EFBFBD><C8B7><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>https://tempmail.plus/zh<7A><68><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>cursor<6F>˺ţ<CBBA>***
<EFBFBD><EFBFBD>ʼɾ<EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˺<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Continue
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Sign in
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Adavance
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Delete Account
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>delete
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Delete
<EFBFBD>˻<EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
<EFBFBD><EFBFBD>ʼע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD>...
<EFBFBD>Ѵ<EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>ᰴť
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Continue<EFBFBD><EFBFBD>ť
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD> Cursor <no-reply@cursor.sh>
07:19
Verify your email address
<EFBFBD><EFBFBD>֤<EFBFBD>룺 227917
ɾ<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>
<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD> 227917
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Cursor <20>˺ţ<CBBA> apxeme@mailto.plus
<20><><EFBFBD>룺 ccz14321@
CursorSessionToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSkcwUEZXQUNHSEQ5SDVNU1RWWlFHUDZOIiwidGltZSI6IjE3MzUxOTA0MDEiLCJyYW5kb21uZXNzIjoiYTM4NDBhYzEtZGYwNi00NDhkIiwiZXhwIjo0MzI3MTkwNDAxLCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.YYQ_C4BjbkHlShTFElkOvXFDqA8kYA-aWMqHKLa5RsU
<EFBFBD>˻<EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> cachedEmail
<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> accessToken
<EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> refreshToken
<EFBFBD>ű<EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
[2024/12/26 <20><><EFBFBD><EFBFBD> 13:20:14.57] 脚本执行完成
Traceback (most recent call last):
File "cursor_pro_keep_alive.py", line 370, in <module>
if delete_account(browser, tab):
~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "cursor_pro_keep_alive.py", line 146, in delete_account
if tab.ele("Account Settings"):
~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "DrissionPage\_pages\mix_tab.py", line 109, in ele
File "DrissionPage\_pages\chromium_base.py", line 424, in ele
File "DrissionPage\_base\base.py", line 356, in _ele
File "DrissionPage\_pages\mix_tab.py", line 192, in _find_elements
File "DrissionPage\_pages\chromium_base.py", line 492, in _find_elements
File "DrissionPage\_base\driver.py", line 176, in run
File "DrissionPage\_base\driver.py", line 84, in _send
File "queue.py", line 213, in get
File "threading.py", line 363, in wait
KeyboardInterrupt
[PYI-35588:ERROR] Failed to execute script 'cursor_pro_keep_alive' due to unhandled exception!
<EFBFBD><EFBFBD>ʼִ<EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
***<2A><>ȷ<EFBFBD><C8B7><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>https://tempmail.plus/zh<7A><68><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>cursor<6F>˺ţ<CBBA>***
<EFBFBD><EFBFBD>ʼɾ<EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˺<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Continue
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Sign in
׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ť<EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...

27
requirements.txt Normal file
View File

@@ -0,0 +1,27 @@
altgraph==0.17.4
certifi==2024.12.14
charset-normalizer==3.4.1
click==8.1.8
colorama==0.4.6
cssselect==1.2.0
DataRecorder==3.6.2
DownloadKit==2.0.7
DrissionPage==4.1.0.9
et_xmlfile==2.0.0
filelock==3.16.1
idna==3.10
lxml==5.3.0
openpyxl==3.1.5
packaging==24.2
pefile==2023.2.7
psutil==6.1.1
pyinstaller==6.11.1
pyinstaller-hooks-contrib==2024.11
PyVirtualDisplay==3.0
pywin32-ctypes==0.2.3
requests==2.32.3
requests-file==2.1.0
setuptools==75.6.0
tldextract==5.1.3
urllib3==2.3.0
websocket-client==1.8.0

11
run_cursor.bat Normal file
View File

@@ -0,0 +1,11 @@
@echo off
:: 设置控制台代码页为 UTF-8
chcp 65001
:: 设置 Python 环境变量为 UTF-8
set PYTHONIOENCODING=utf-8
echo [%date% %time%] 开始执行脚本 >> log.txt
cd /d "%~dp0"
python cursor_pro_keep_alive.py >> log.txt 2>&1
echo [%date% %time%] 脚本执行完成 >> log.txt
pause

View File

@@ -0,0 +1,18 @@
{
"manifest_version": 3,
"name": "Turnstile Patcher",
"version": "2.1",
"content_scripts": [
{
"js": [
"./script.js"
],
"matches": [
"<all_urls>"
],
"run_at": "document_start",
"all_frames": true,
"world": "MAIN"
}
]
}

View File

@@ -0,0 +1 @@

12
turnstilePatch/script.js Normal file
View File

@@ -0,0 +1,12 @@
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// old method wouldn't work on 4k screens
let screenX = getRandomInt(800, 1200);
let screenY = getRandomInt(400, 600);
Object.defineProperty(MouseEvent.prototype, 'screenX', { value: screenX });
Object.defineProperty(MouseEvent.prototype, 'screenY', { value: screenY });

46
update_cursor_auth.py Normal file
View File

@@ -0,0 +1,46 @@
from cursor_auth_manager import CursorAuthManager
def update_cursor_auth(email=None, access_token=None, refresh_token=None):
"""
更新Cursor的认证信息的便捷函数
"""
auth_manager = CursorAuthManager()
return auth_manager.update_auth(email, access_token, refresh_token)
def main():
# 示例用法
print("请选择要更新的项目:")
print("1. 更新邮箱")
print("2. 更新访问令牌")
print("3. 更新刷新令牌")
print("4. 更新多个值")
print("0. 退出")
choice = input("\n请输入选项数字: ")
if choice == "1":
email = input("请输入新的邮箱: ")
update_cursor_auth(email=email)
elif choice == "2":
token = input("请输入新的访问令牌: ")
update_cursor_auth(access_token=token)
elif choice == "3":
token = input("请输入新的刷新令牌: ")
update_cursor_auth(refresh_token=token)
elif choice == "4":
email = input("请输入新的邮箱 (直接回车跳过): ")
access_token = input("请输入新的访问令牌 (直接回车跳过): ")
refresh_token = input("请输入新的刷新令牌 (直接回车跳过): ")
update_cursor_auth(
email=email if email else None,
access_token=access_token if access_token else None,
refresh_token=refresh_token if refresh_token else None
)
elif choice == "0":
print("退出程序")
else:
print("无效的选项")
if __name__ == "__main__":
main()