Enhance cursor_pro_keep_alive.py and update packaging

- Added logging functionality to cursor_pro_keep_alive.py for better error tracking.
- Improved configuration loading to handle frozen executables and updated success message.
- Introduced cleanup_temp_files function to remove temporary directories.
- Refactored browser options setup into a separate function for clarity.
- Updated .gitignore to include virtual environment directory.
- Enhanced CursorKeepAlive.spec to check for config.ini existence and updated app bundle details.
- Added new files for macOS app packaging, including Info.plist and application icon.
This commit is contained in:
cheng zhen
2024-12-28 20:05:29 +08:00
parent 61e93e08c9
commit a1002131a8
8 changed files with 254 additions and 34 deletions

4
.gitignore vendored
View File

@@ -1,4 +1,6 @@
.idea .idea
__pycache__ __pycache__
build build
venv

View File

@@ -18,6 +18,11 @@ a = Analysis(
excludes=[], excludes=[],
noarchive=False, noarchive=False,
) )
import os
if not os.path.exists('config.ini'):
raise FileNotFoundError('config.ini 文件不存在!请确保它在正确的位置。')
pyz = PYZ(a.pure) pyz = PYZ(a.pure)
exe = EXE( exe = EXE(
@@ -26,7 +31,7 @@ exe = EXE(
a.binaries, a.binaries,
a.datas, a.datas,
[], [],
name='cursorPro', name='CursorPro',
debug=False, debug=False,
bootloader_ignore_signals=False, bootloader_ignore_signals=False,
strip=False, strip=False,
@@ -39,4 +44,18 @@ exe = EXE(
target_arch=None, target_arch=None,
codesign_identity=None, codesign_identity=None,
entitlements_file=None, entitlements_file=None,
icon=None
)
app = BUNDLE(
exe,
name='CursorPro.app',
icon=None,
bundle_identifier='com.yourcompany.cursorpro',
info_plist={
'CFBundleShortVersionString': '1.0.0',
'CFBundleVersion': '1.0.0',
'NSHighResolutionCapable': True,
'LSBackgroundOnly': False,
},
) )

View File

@@ -1,3 +1,7 @@
import os
os.environ['PYTHONVERBOSE'] = '0'
os.environ['PYINSTALLER_VERBOSE'] = '0'
from DrissionPage import ChromiumOptions, Chromium from DrissionPage import ChromiumOptions, Chromium
from DrissionPage.common import Keys from DrissionPage.common import Keys
import re import re
@@ -7,19 +11,36 @@ from cursor_auth_manager import CursorAuthManager
from configparser import ConfigParser from configparser import ConfigParser
import os import os
import sys import sys
import logging
# 在文件开头设置日志
logging.basicConfig(
level=logging.WARNING,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('cursor_keep_alive.log', encoding='utf-8')
]
)
def load_config(): def load_config():
"""加载配置文件""" """加载配置文件"""
config = ConfigParser() config = ConfigParser()
# 获取程序运行的根目录 # 修改获取配置文件路径的方式
root_dir = os.getcwd() if getattr(sys, 'frozen', False):
# 如果是打包后的执行文件
root_dir = sys._MEIPASS
else:
# 如果是直接运行 Python 脚本
root_dir = os.getcwd()
config_path = os.path.join(root_dir, "config.ini") config_path = os.path.join(root_dir, "config.ini")
if os.path.exists(config_path): if os.path.exists(config_path):
config.read(config_path, encoding="utf-8") config.read(config_path, encoding="utf-8")
print("已加载配置文件") print(f"已加载配置文件: {config_path}")
return { return {
"account": config["Account"]["email"], "account": config["Account"]["email"],
"password": config["Account"]["password"], "password": config["Account"]["password"],
@@ -27,9 +48,7 @@ def load_config():
"last_name": config["Account"]["last_name"], "last_name": config["Account"]["last_name"],
} }
raise FileNotFoundError( raise FileNotFoundError(f"配置文件不存在: {config_path}")
f"配置文件不存在: {config_path}\n请确保配置文件在程序运行目录下"
)
def get_veri_code(tab): def get_veri_code(tab):
@@ -375,7 +394,46 @@ def get_extension_path():
return extension_path return extension_path
def get_browser_options():
co = ChromiumOptions()
try:
extension_path = get_extension_path()
co.add_extension(extension_path)
except FileNotFoundError as e:
print(f"警告: {e}")
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()
# Mac 系统特殊处理
if sys.platform == 'darwin':
co.set_argument('--no-sandbox')
co.set_argument('--disable-gpu')
return co
def cleanup_temp_files():
"""清理临时文件和缓存"""
try:
temp_dirs = [
os.path.join(os.getcwd(), '__pycache__'),
os.path.join(os.getcwd(), 'build'),
]
for dir_path in temp_dirs:
if os.path.exists(dir_path):
import shutil
shutil.rmtree(dir_path)
except Exception as e:
logging.warning(f"清理临时文件失败: {str(e)}")
if __name__ == "__main__": if __name__ == "__main__":
browser = None
try: try:
# 加载配置 # 加载配置
config = load_config() config = load_config()
@@ -395,24 +453,7 @@ if __name__ == "__main__":
auto_update_cursor_auth = True auto_update_cursor_auth = True
# 浏览器配置 # 浏览器配置
co = ChromiumOptions() co = get_browser_options()
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) browser = Chromium(co)
tab = browser.latest_tab tab = browser.latest_tab
@@ -440,14 +481,16 @@ if __name__ == "__main__":
print("账户删除失败") print("账户删除失败")
print("脚本执行完毕") print("脚本执行完毕")
browser.quit()
# 添加等待用户输入后再退出
input("\n按回车键退出...")
except FileNotFoundError as e:
print(f"错误: {e}")
print("请确保 config.ini 文件存在并包含正确的配置信息")
input("\n按回车键退出...")
except Exception as e: except Exception as e:
print(f"加载配置时出错: {e}") print(f"程序执行出错: {str(e)}")
import traceback
print(traceback.format_exc())
finally:
# 确保浏览器实例被正确关闭
if browser:
try:
browser.quit()
except:
pass
input("\n按回车键退出...") input("\n按回车键退出...")

BIN
dist/cursorPro.exe → dist/CursorPro vendored Normal file → Executable file

Binary file not shown.

28
dist/CursorPro.app/Contents/Info.plist vendored Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>CursorPro</string>
<key>CFBundleExecutable</key>
<string>CursorPro</string>
<key>CFBundleIconFile</key>
<string>icon-windowed.icns</string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.cursorpro</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>CursorPro</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>LSBackgroundOnly</key>
<false/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Resources/icon-windowed.icns</key>
<data>
eEHOuYpZLB0vKGVIWGZOh5rH8+o=
</data>
</dict>
<key>files2</key>
<dict>
<key>Resources/icon-windowed.icns</key>
<dict>
<key>hash2</key>
<data>
uQo7VuWRab4Phv4EEGmfQsyqFqDIXZgO8OtgaAMvCzY=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^Resources/</key>
<true/>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>