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:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.idea
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
build
|
||||||
42
CursorKeepAlive.spec
Normal file
42
CursorKeepAlive.spec
Normal 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
5
README.md
Normal 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
5
config.ini
Normal 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
60
cursor_auth_manager.py
Normal 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
453
cursor_pro_keep_alive.py
Normal 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
5
dist/config - 副本.ini
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Account]
|
||||||
|
email = xxxx
|
||||||
|
password = xxx
|
||||||
|
first_name = xxxx
|
||||||
|
last_name = xxxx
|
||||||
5
dist/config.ini
vendored
Normal file
5
dist/config.ini
vendored
Normal 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
BIN
dist/cursor_pro_keep_alive.exe
vendored
Normal file
Binary file not shown.
95
dist/readme.md
vendored
Normal file
95
dist/readme.md
vendored
Normal 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
166
gpt-accesstoken.py
Normal 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
90
log.txt
Normal 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
27
requirements.txt
Normal 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
11
run_cursor.bat
Normal 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
|
||||||
18
turnstilePatch/manifest.json
Normal file
18
turnstilePatch/manifest.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1
turnstilePatch/readme.txt
Normal file
1
turnstilePatch/readme.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
12
turnstilePatch/script.js
Normal file
12
turnstilePatch/script.js
Normal 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
46
update_cursor_auth.py
Normal 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()
|
||||||
Reference in New Issue
Block a user