880 lines
33 KiB
Python
880 lines
33 KiB
Python
import sys
|
||
import os
|
||
import json
|
||
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
|
||
QLabel, QLineEdit, QPushButton, QTextEdit, QMessageBox,
|
||
QHBoxLayout, QDialog)
|
||
from PyQt6.QtCore import Qt, QTimer, QPropertyAnimation
|
||
from PyQt6.QtGui import QIcon, QPixmap
|
||
import traceback
|
||
import tempfile
|
||
|
||
# 创建临时日志文件
|
||
temp_log_file = os.path.join(tempfile.gettempdir(), 'cursor_helper_error.log')
|
||
|
||
def log_error(error_msg):
|
||
with open(temp_log_file, 'a', encoding='utf-8') as f:
|
||
f.write(f"{error_msg}\n")
|
||
|
||
try:
|
||
from logger import logging
|
||
import cursor_account_manager as backend
|
||
except Exception as e:
|
||
log_error(f"导入模块错误: {str(e)}\n{traceback.format_exc()}")
|
||
raise
|
||
|
||
# 添加密码管理类
|
||
class PasswordManager:
|
||
def __init__(self):
|
||
# 获取应用程序的实际运行路径
|
||
if getattr(sys, 'frozen', False):
|
||
# 如果是打包后的应用
|
||
if sys.platform == 'darwin':
|
||
# macOS下使用应用程序包内的Resources目录
|
||
bundle_dir = os.path.dirname(sys.executable)
|
||
app_root = os.path.abspath(os.path.join(bundle_dir, '..', 'Resources'))
|
||
self.app_support_dir = os.path.join(app_root, 'config')
|
||
else:
|
||
# 其他系统使用可执行文件所在目录
|
||
app_root = os.path.dirname(sys.executable)
|
||
self.app_support_dir = os.path.join(app_root, 'config')
|
||
else:
|
||
# 开发环境下使用用户目录
|
||
if sys.platform == 'darwin':
|
||
self.app_support_dir = os.path.expanduser('~/Library/Application Support/听泉Cursor助手')
|
||
else:
|
||
self.app_support_dir = os.path.expanduser('~/.听泉Cursor助手')
|
||
|
||
self.config_file = os.path.join(self.app_support_dir, 'config.json')
|
||
os.makedirs(self.app_support_dir, exist_ok=True)
|
||
logging.debug(f"密码管理器初始化,配置文件路径: {self.config_file}")
|
||
|
||
def save_password(self, password):
|
||
"""保存密码(这里可以添加简单加密)"""
|
||
try:
|
||
config = {'password': password}
|
||
with open(self.config_file, 'w', encoding='utf-8') as f:
|
||
json.dump(config, f)
|
||
logging.debug(f"密码保存{'成功' if password else '已清除'}")
|
||
return True
|
||
except Exception as e:
|
||
logging.error(f"保存密码失败: {str(e)}")
|
||
return False
|
||
|
||
def get_password(self):
|
||
"""获取保存的密码"""
|
||
try:
|
||
if os.path.exists(self.config_file):
|
||
with open(self.config_file, 'r', encoding='utf-8') as f:
|
||
config = json.load(f)
|
||
password = config.get('password')
|
||
logging.debug(f"读取到保存的密码: {'有' if password else '无'}")
|
||
return password
|
||
except Exception as e:
|
||
logging.error(f"读取密码失败: {str(e)}")
|
||
return None
|
||
|
||
class SuccessDialog(QDialog):
|
||
def __init__(self, message, parent=None):
|
||
super().__init__(parent)
|
||
self.setWindowTitle("激活成功")
|
||
self.setFixedSize(400, 300)
|
||
# 移除可能导致问题的窗口标志
|
||
self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
|
||
|
||
# 设置样式
|
||
self.setStyleSheet("""
|
||
QDialog {
|
||
background-color: #ffffff;
|
||
border: 1px solid #cccccc;
|
||
border-radius: 10px;
|
||
}
|
||
QLabel {
|
||
color: #333333;
|
||
font-size: 14px;
|
||
padding: 10px;
|
||
}
|
||
QLabel#titleLabel {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
color: #0078d4;
|
||
}
|
||
QLabel#messageLabel {
|
||
font-size: 16px;
|
||
padding: 20px;
|
||
background-color: #f8f8f8;
|
||
border-radius: 8px;
|
||
}
|
||
QPushButton {
|
||
background-color: #0078d4;
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 24px;
|
||
border-radius: 6px;
|
||
font-size: 16px;
|
||
min-width: 120px;
|
||
}
|
||
QPushButton:hover {
|
||
background-color: #006cbd;
|
||
}
|
||
QPushButton:pressed {
|
||
background-color: #005ba1;
|
||
}
|
||
""")
|
||
|
||
layout = QVBoxLayout()
|
||
layout.setSpacing(20)
|
||
layout.setContentsMargins(30, 30, 30, 30)
|
||
|
||
# 标题
|
||
title_label = QLabel("🎉 激活成功")
|
||
title_label.setObjectName("titleLabel")
|
||
title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
layout.addWidget(title_label)
|
||
|
||
# 消息内容
|
||
message_label = QLabel(message)
|
||
message_label.setObjectName("messageLabel")
|
||
message_label.setAlignment(Qt.AlignmentFlag.AlignLeft)
|
||
message_label.setWordWrap(True)
|
||
layout.addWidget(message_label)
|
||
|
||
# 确定按钮
|
||
ok_button = QPushButton("确定")
|
||
ok_button.clicked.connect(self.accept)
|
||
ok_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||
|
||
# 按钮容器
|
||
button_container = QWidget()
|
||
button_layout = QHBoxLayout()
|
||
button_layout.addStretch()
|
||
button_layout.addWidget(ok_button)
|
||
button_layout.addStretch()
|
||
button_container.setLayout(button_layout)
|
||
layout.addWidget(button_container)
|
||
|
||
self.setLayout(layout)
|
||
|
||
# 5秒后自动关闭
|
||
QTimer.singleShot(5000, self.accept)
|
||
|
||
# 设置窗口位置为父窗口中心
|
||
if parent:
|
||
self.move(
|
||
parent.x() + (parent.width() - self.width()) // 2,
|
||
parent.y() + (parent.height() - self.height()) // 2
|
||
)
|
||
|
||
def showEvent(self, event):
|
||
"""窗口显示时的动画效果"""
|
||
self.setWindowOpacity(0.0)
|
||
self.animation = QPropertyAnimation(self, b"windowOpacity")
|
||
self.animation.setDuration(300) # 300ms
|
||
self.animation.setStartValue(0.0)
|
||
self.animation.setEndValue(1.0)
|
||
self.animation.start()
|
||
super().showEvent(event)
|
||
|
||
def closeEvent(self, event):
|
||
"""窗口关闭时的动画效果"""
|
||
self.animation = QPropertyAnimation(self, b"windowOpacity")
|
||
self.animation.setDuration(200) # 200ms
|
||
self.animation.setStartValue(1.0)
|
||
self.animation.setEndValue(0.0)
|
||
self.animation.finished.connect(self.close)
|
||
self.animation.start()
|
||
event.ignore()
|
||
|
||
class PasswordDialog(QDialog):
|
||
def __init__(self, parent=None):
|
||
super().__init__(parent)
|
||
self.setWindowTitle("输入系统密码")
|
||
self.setFixedSize(450, 250) # 增加高度以容纳新控件
|
||
|
||
# 设置样式
|
||
self.setStyleSheet("""
|
||
QDialog {
|
||
background-color: #ffffff;
|
||
border: 1px solid #cccccc;
|
||
border-radius: 10px;
|
||
}
|
||
QLabel {
|
||
color: #333333;
|
||
font-size: 14px;
|
||
padding: 5px;
|
||
}
|
||
QLabel#tipLabel {
|
||
color: #666666;
|
||
font-size: 13px;
|
||
padding: 12px 15px;
|
||
background-color: #f8f8f8;
|
||
border-radius: 6px;
|
||
line-height: 20px;
|
||
min-height: 45px;
|
||
}
|
||
QLineEdit {
|
||
padding: 8px 12px;
|
||
border: 2px solid #cccccc;
|
||
border-radius: 6px;
|
||
background-color: white;
|
||
font-size: 14px;
|
||
min-height: 20px;
|
||
}
|
||
QLineEdit:focus {
|
||
border-color: #0078d4;
|
||
}
|
||
QPushButton {
|
||
background-color: #0078d4;
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 20px;
|
||
border-radius: 6px;
|
||
font-size: 14px;
|
||
min-width: 80px;
|
||
}
|
||
QPushButton:hover {
|
||
background-color: #006cbd;
|
||
}
|
||
QPushButton:pressed {
|
||
background-color: #005ba1;
|
||
}
|
||
QPushButton#cancelButton {
|
||
background-color: #f0f0f0;
|
||
color: #333333;
|
||
}
|
||
QPushButton#cancelButton:hover {
|
||
background-color: #e0e0e0;
|
||
}
|
||
QPushButton#cancelButton:pressed {
|
||
background-color: #d0d0d0;
|
||
}
|
||
QCheckBox {
|
||
color: #333333;
|
||
font-size: 13px;
|
||
}
|
||
QCheckBox::indicator {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
QCheckBox::indicator:unchecked {
|
||
border: 2px solid #cccccc;
|
||
background: white;
|
||
border-radius: 4px;
|
||
}
|
||
QCheckBox::indicator:checked {
|
||
border: 2px solid #0078d4;
|
||
background: #0078d4;
|
||
border-radius: 4px;
|
||
}
|
||
""")
|
||
|
||
layout = QVBoxLayout()
|
||
layout.setSpacing(8)
|
||
layout.setContentsMargins(20, 20, 20, 20)
|
||
|
||
# 提示文字
|
||
tip_label = QLabel("提示:这里需要输入您的Mac电脑开机密码(系统管理员密码),\n用于执行需要管理员权限的操作。")
|
||
tip_label.setObjectName("tipLabel")
|
||
tip_label.setWordWrap(True)
|
||
layout.addWidget(tip_label)
|
||
|
||
# 密码输入框
|
||
self.password_input = QLineEdit()
|
||
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
|
||
self.password_input.setPlaceholderText("请输入Mac系统管理员密码")
|
||
layout.addWidget(self.password_input)
|
||
|
||
# 记住密码选项
|
||
from PyQt6.QtWidgets import QCheckBox
|
||
self.remember_checkbox = QCheckBox("记住密码")
|
||
self.remember_checkbox.setChecked(True) # 默认勾选
|
||
layout.addWidget(self.remember_checkbox)
|
||
|
||
# 按钮区域
|
||
button_layout = QHBoxLayout()
|
||
button_layout.setSpacing(8)
|
||
|
||
cancel_button = QPushButton("取消")
|
||
cancel_button.setObjectName("cancelButton")
|
||
cancel_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||
cancel_button.clicked.connect(self.reject)
|
||
cancel_button.setFixedWidth(80)
|
||
|
||
ok_button = QPushButton("确定")
|
||
ok_button.setCursor(Qt.CursorShape.PointingHandCursor)
|
||
ok_button.clicked.connect(self.accept)
|
||
ok_button.setFixedWidth(80)
|
||
|
||
button_layout.addStretch()
|
||
button_layout.addWidget(cancel_button)
|
||
button_layout.addWidget(ok_button)
|
||
|
||
layout.addSpacing(5)
|
||
layout.addLayout(button_layout)
|
||
|
||
self.setLayout(layout)
|
||
|
||
# 设置窗口位置为父窗口中心
|
||
if parent:
|
||
self.move(
|
||
parent.x() + (parent.width() - self.width()) // 2,
|
||
parent.y() + (parent.height() - self.height()) // 2
|
||
)
|
||
|
||
# 尝试加载保存的密码
|
||
self.password_manager = PasswordManager()
|
||
saved_password = self.password_manager.get_password()
|
||
if saved_password:
|
||
self.password_input.setText(saved_password)
|
||
|
||
def get_password(self):
|
||
password = self.password_input.text()
|
||
# 如果选择记住密码,则保存
|
||
if self.remember_checkbox.isChecked():
|
||
self.password_manager.save_password(password)
|
||
return password
|
||
|
||
class CursorGUI(QMainWindow):
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.setWindowTitle("听泉Cursor助手 v3.0.2")
|
||
self.setFixedSize(600, 600)
|
||
|
||
# 添加全局会员状态
|
||
self.is_member_active = False
|
||
|
||
# 设置定时器,每3分钟检查一次会员状态
|
||
self.status_timer = QTimer(self)
|
||
self.status_timer.timeout.connect(self.check_member_status)
|
||
self.status_timer.start(180000) # 180000毫秒 = 3分钟
|
||
|
||
# 设置整体样式
|
||
self.setStyleSheet("""
|
||
QMainWindow {
|
||
background-color: #f5f5f5;
|
||
}
|
||
QWidget {
|
||
background-color: #f5f5f5;
|
||
color: #333333;
|
||
}
|
||
QLabel {
|
||
color: #333333;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
}
|
||
QLineEdit {
|
||
padding: 8px;
|
||
border: 1px solid #cccccc;
|
||
border-radius: 4px;
|
||
background-color: white;
|
||
selection-background-color: #0078d4;
|
||
}
|
||
QTextEdit {
|
||
padding: 8px;
|
||
border: 1px solid #cccccc;
|
||
border-radius: 4px;
|
||
background-color: white;
|
||
selection-background-color: #0078d4;
|
||
}
|
||
QScrollBar:vertical {
|
||
border: none;
|
||
background: #f0f0f0;
|
||
width: 10px;
|
||
margin: 0px;
|
||
}
|
||
QScrollBar::handle:vertical {
|
||
background: #c0c0c0;
|
||
min-height: 30px;
|
||
border-radius: 5px;
|
||
}
|
||
QScrollBar::handle:vertical:hover {
|
||
background: #a0a0a0;
|
||
}
|
||
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
||
height: 0px;
|
||
}
|
||
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
|
||
background: none;
|
||
}
|
||
QPushButton {
|
||
background-color: #0078d4;
|
||
color: white;
|
||
padding: 8px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
}
|
||
QPushButton:hover {
|
||
background-color: #006cbd;
|
||
}
|
||
QPushButton:pressed {
|
||
background-color: #005ba1;
|
||
}
|
||
""")
|
||
|
||
# 创建主窗口部件
|
||
main_widget = QWidget()
|
||
self.setCentralWidget(main_widget)
|
||
layout = QVBoxLayout()
|
||
layout.setSpacing(15) # 增加垂直间距
|
||
layout.setContentsMargins(20, 20, 20, 20) # 设置边距
|
||
main_widget.setLayout(layout)
|
||
|
||
# 设备ID显示区域
|
||
id_label = QLabel("设备识别码(勿动):")
|
||
id_layout = QHBoxLayout()
|
||
id_layout.setSpacing(10) # 设置水平间距
|
||
self.id_text = QLineEdit()
|
||
self.id_text.setReadOnly(True)
|
||
id_copy_btn = QPushButton("复制ID")
|
||
id_copy_btn.setFixedWidth(100)
|
||
id_copy_btn.clicked.connect(self.copy_device_id)
|
||
id_layout.addWidget(self.id_text)
|
||
id_layout.addWidget(id_copy_btn)
|
||
layout.addWidget(id_label)
|
||
layout.addLayout(id_layout)
|
||
|
||
# 会员状态显示区域
|
||
status_label = QLabel("会员状态")
|
||
self.status_text = QTextEdit()
|
||
self.status_text.setReadOnly(True)
|
||
self.status_text.setFixedHeight(150)
|
||
layout.addWidget(status_label)
|
||
layout.addWidget(self.status_text)
|
||
|
||
# 激活区域
|
||
activate_label = QLabel("激活会员,多个激活码叠加整体时长")
|
||
activate_layout = QHBoxLayout()
|
||
activate_layout.setSpacing(10) # 设置水平间距
|
||
self.activate_input = QLineEdit()
|
||
self.activate_input.setPlaceholderText("请输入激活码")
|
||
self.activate_btn = QPushButton("激活")
|
||
self.activate_btn.setFixedWidth(100)
|
||
self.activate_btn.clicked.connect(self.activate_account)
|
||
activate_layout.addWidget(self.activate_input)
|
||
activate_layout.addWidget(self.activate_btn)
|
||
layout.addWidget(activate_label)
|
||
layout.addLayout(activate_layout)
|
||
|
||
# 添加一些间距
|
||
layout.addSpacing(20)
|
||
|
||
# 功能按钮区域
|
||
button_style = """
|
||
QPushButton {
|
||
background-color: #0078d4;
|
||
color: white;
|
||
padding: 12px;
|
||
border: none;
|
||
border-radius: 6px;
|
||
font-size: 15px;
|
||
font-weight: bold;
|
||
margin: 5px 0;
|
||
}
|
||
QPushButton:hover {
|
||
background-color: #006cbd;
|
||
}
|
||
QPushButton:pressed {
|
||
background-color: #005ba1;
|
||
}
|
||
QPushButton:disabled {
|
||
background-color: #cccccc;
|
||
color: #666666;
|
||
}
|
||
"""
|
||
|
||
# 一键重置按钮
|
||
self.refresh_btn = QPushButton("刷新Cursor授权 (对话次数用完了提示limit时点一次)")
|
||
self.refresh_btn.setStyleSheet(button_style)
|
||
self.refresh_btn.setCursor(Qt.CursorShape.PointingHandCursor)
|
||
self.refresh_btn.clicked.connect(self.refresh_auth)
|
||
layout.addWidget(self.refresh_btn)
|
||
|
||
# 代用2按钮
|
||
self.patch_btn = QPushButton("突破0.45.x限制 (Too many free trials问题点这里)")
|
||
self.patch_btn.setStyleSheet(button_style)
|
||
self.patch_btn.setCursor(Qt.CursorShape.PointingHandCursor)
|
||
self.patch_btn.clicked.connect(self.install_patch)
|
||
layout.addWidget(self.patch_btn)
|
||
|
||
# 代用3按钮
|
||
self.update_btn = QPushButton("代用 3")
|
||
self.update_btn.setStyleSheet(button_style)
|
||
self.update_btn.setCursor(Qt.CursorShape.PointingHandCursor)
|
||
self.update_btn.clicked.connect(self.update_cursor)
|
||
layout.addWidget(self.update_btn)
|
||
|
||
# 初始化设备ID和状态
|
||
self.update_device_id()
|
||
self.update_status()
|
||
|
||
def update_device_id(self):
|
||
"""更新设备ID显示"""
|
||
try:
|
||
device_id = backend.get_mac_unique_id()
|
||
self.id_text.setText(device_id)
|
||
except Exception as e:
|
||
QMessageBox.warning(self, "错误", f"获取设备ID失败: {str(e)}")
|
||
|
||
def update_status(self):
|
||
"""更新会员状态显示"""
|
||
try:
|
||
account_manager = backend.CursorAccountManager()
|
||
success, status_data = account_manager.check_member_status()
|
||
|
||
# 获取设备信息
|
||
device_info = status_data.get("device_info", {}) if success else {}
|
||
|
||
# 设置状态文本和更新全局状态
|
||
if success and status_data.get("is_active"):
|
||
status_emoji = "✅"
|
||
status_text = "正常"
|
||
self.is_member_active = True
|
||
else:
|
||
status_emoji = "❌"
|
||
status_text = "未激活"
|
||
self.is_member_active = False
|
||
|
||
# 格式化显示文本
|
||
display_text = f"会员状态:{status_text} {status_emoji}\n"
|
||
display_text += f"到期时间:{status_data.get('expire_time', '--') if success else '--'}\n"
|
||
display_text += f"总天数:{status_data.get('total_days', 0) if success else 0}天\n"
|
||
display_text += f"剩余天数:{status_data.get('days_left', 0) if success else 0}天\n\n"
|
||
|
||
# 设备信息部分
|
||
display_text += "设备信息:\n"
|
||
display_text += f"系统:{device_info.get('system', sys.platform)}\n"
|
||
display_text += f"设备名:{device_info.get('device_name', '未知')}\n"
|
||
display_text += f"IP地址:{device_info.get('ip', '--')}\n"
|
||
display_text += f"地理位置:{device_info.get('location', '--')}"
|
||
|
||
self.status_text.setText(display_text)
|
||
|
||
except Exception as e:
|
||
error_text = "会员状态:未激活 ❌\n"
|
||
error_text += "到期时间:--\n"
|
||
error_text += "总天数:0天\n"
|
||
error_text += "剩余天数:0天\n\n"
|
||
error_text += "设备信息:\n"
|
||
error_text += f"系统:{sys.platform}\n"
|
||
error_text += f"设备名:{backend.platform.node()}\n"
|
||
error_text += "IP地址:--\n"
|
||
error_text += "地理位置:--"
|
||
self.status_text.setText(error_text)
|
||
|
||
def copy_device_id(self):
|
||
"""复制设备ID到剪贴板"""
|
||
clipboard = QApplication.clipboard()
|
||
clipboard.setText(self.id_text.text())
|
||
QMessageBox.information(self, "提示", "设备ID已复制到剪贴板")
|
||
|
||
def show_success_message(self, message):
|
||
"""显示统一的成功提示弹窗"""
|
||
msg = QMessageBox(self)
|
||
msg.setIcon(QMessageBox.Icon.Information)
|
||
msg.setWindowTitle("提示")
|
||
msg.setText(message)
|
||
msg.setStyleSheet("""
|
||
QMessageBox {
|
||
background-color: white;
|
||
}
|
||
QPushButton {
|
||
background-color: #0078d4;
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 16px;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
min-width: 80px;
|
||
}
|
||
QPushButton:hover {
|
||
background-color: #006cbd;
|
||
}
|
||
""")
|
||
msg.exec()
|
||
|
||
def activate_account(self):
|
||
"""激活账号"""
|
||
code = self.activate_input.text().strip()
|
||
if not code:
|
||
logging.debug("激活码为空,显示警告")
|
||
QMessageBox.warning(self, "警告", "请输入激活码")
|
||
return
|
||
|
||
# 禁用激活按钮,显示加载状态
|
||
self.activate_btn.setEnabled(False)
|
||
self.activate_btn.setText("激活中...")
|
||
QApplication.processEvents()
|
||
|
||
try:
|
||
logging.debug(f"开始检查激活码: {code}")
|
||
account_manager = backend.CursorAccountManager()
|
||
success, message, account_info = account_manager.check_activation_code(code)
|
||
logging.debug(f"激活码检查结果: success={success}, message={message}, account_info={account_info}")
|
||
|
||
if success:
|
||
logging.debug("激活成功,开始更新状态")
|
||
# 更新状态显示和全局状态
|
||
self.update_status()
|
||
self.is_member_active = True
|
||
|
||
# 构建成功消息
|
||
success_message = (
|
||
f"🎉 激活成功!\n\n"
|
||
f"激活码:{code}\n"
|
||
f"到期时间:{account_info.get('expire_time', '--')}\n"
|
||
f"总天数:{account_info.get('total_days', 0)}天\n"
|
||
f"剩余天数:{account_info.get('days_left', 0)}天"
|
||
)
|
||
logging.debug(f"准备显示成功弹窗,消息内容: {success_message}")
|
||
|
||
# 使用统一的成功提示弹窗
|
||
self.show_success_message(success_message)
|
||
logging.debug("成功弹窗显示完成")
|
||
|
||
# 清空输入框
|
||
self.activate_input.clear()
|
||
logging.debug("激活流程完成")
|
||
else:
|
||
logging.debug(f"激活失败,显示错误消息: {message}")
|
||
QMessageBox.warning(self, "错误", message)
|
||
except Exception as e:
|
||
error_msg = f"激活过程出错: {str(e)}\n{traceback.format_exc()}"
|
||
logging.error(error_msg)
|
||
QMessageBox.warning(self, "错误", f"激活过程出错: {str(e)}")
|
||
finally:
|
||
# 恢复激活按钮状态
|
||
logging.debug("恢复激活按钮状态")
|
||
self.activate_btn.setEnabled(True)
|
||
self.activate_btn.setText("激活")
|
||
|
||
def show_activation_dialog(self):
|
||
"""显示统一的激活提示弹窗"""
|
||
msg = QMessageBox(self)
|
||
msg.setIcon(QMessageBox.Icon.Warning)
|
||
msg.setWindowTitle("提示")
|
||
msg.setText("请输入激活码")
|
||
|
||
# 设置详细信息
|
||
msg.setInformativeText("获取会员激活码,请通过以下方式:\n\n" +
|
||
"• 官方自助网站:cursor.nosqli.com\n" +
|
||
"• 微信客服号:behikcigxr\n" +
|
||
"• 闲鱼店铺:xxx\n\n" +
|
||
"诚招代理商,欢迎加盟合作!")
|
||
|
||
# 添加按钮
|
||
visit_btn = msg.addButton("复制网站", QMessageBox.ButtonRole.ActionRole)
|
||
copy_wx_btn = msg.addButton("复制微信", QMessageBox.ButtonRole.ActionRole)
|
||
ok_btn = msg.addButton("确定", QMessageBox.ButtonRole.AcceptRole)
|
||
|
||
msg.setDefaultButton(ok_btn)
|
||
|
||
# 设置样式
|
||
msg.setStyleSheet("""
|
||
QMessageBox {
|
||
background-color: white;
|
||
}
|
||
QPushButton {
|
||
padding: 8px 16px;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
min-width: 80px;
|
||
}
|
||
QPushButton[text="确定"] {
|
||
background-color: #0078d4;
|
||
color: white;
|
||
border: none;
|
||
}
|
||
QPushButton[text="确定"]:hover {
|
||
background-color: #006cbd;
|
||
}
|
||
QPushButton[text="复制网站"], QPushButton[text="复制微信"] {
|
||
background-color: white;
|
||
border: 1px solid #0078d4;
|
||
color: #0078d4;
|
||
}
|
||
QPushButton[text="复制网站"]:hover, QPushButton[text="复制微信"]:hover {
|
||
background-color: #f0f9ff;
|
||
}
|
||
""")
|
||
|
||
# 显示对话框
|
||
clicked = msg.exec()
|
||
|
||
# 处理按钮点击
|
||
if msg.clickedButton() == visit_btn:
|
||
clipboard = QApplication.clipboard()
|
||
clipboard.setText("cursor.nosqli.com")
|
||
QMessageBox.information(self, "提示", "网址已复制到剪贴板")
|
||
elif msg.clickedButton() == copy_wx_btn:
|
||
clipboard = QApplication.clipboard()
|
||
clipboard.setText("behikcigxr")
|
||
QMessageBox.information(self, "提示", "微信号已复制到剪贴板")
|
||
|
||
return False
|
||
|
||
def check_member_status(self):
|
||
"""检查会员状态"""
|
||
try:
|
||
account_manager = backend.CursorAccountManager()
|
||
success, status_data = account_manager.check_member_status()
|
||
|
||
if success and status_data.get("is_active"):
|
||
self.is_member_active = True
|
||
return True
|
||
self.is_member_active = False
|
||
return False
|
||
except Exception as e:
|
||
logging.error(f"检查会员状态失败: {str(e)}")
|
||
self.is_member_active = False
|
||
return False
|
||
|
||
def refresh_auth(self):
|
||
"""刷新授权"""
|
||
# 检查会员状态,未激活则显示激活提示
|
||
if not self.is_member_active:
|
||
self.show_activation_dialog()
|
||
return
|
||
|
||
# 会员已激活,继续执行原有逻辑
|
||
while True:
|
||
# 先尝试获取保存的密码
|
||
password_manager = PasswordManager()
|
||
saved_password = password_manager.get_password()
|
||
|
||
if saved_password:
|
||
# 如果有保存的密码,直接使用
|
||
password = saved_password
|
||
else:
|
||
# 如果没有保存的密码,显示密码输入对话框
|
||
dialog = PasswordDialog(self)
|
||
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||
password = dialog.get_password()
|
||
else:
|
||
QMessageBox.warning(self, "取消", "重置操作已取消")
|
||
return
|
||
|
||
# 显示加载状态
|
||
self.refresh_btn.setEnabled(False)
|
||
self.refresh_btn.setText("重置中...")
|
||
QApplication.processEvents()
|
||
|
||
try:
|
||
success, message = backend.reset_auth_with_password(password)
|
||
if success:
|
||
self.show_success_message("重置成功")
|
||
self.update_status()
|
||
break # 成功后退出循环
|
||
else:
|
||
# 密码错误,清除保存的密码
|
||
password_manager.save_password("")
|
||
QMessageBox.warning(self, "错误", message)
|
||
# 继续循环,重新输入密码
|
||
except Exception as e:
|
||
QMessageBox.warning(self, "错误", f"重置失败: {str(e)}")
|
||
break # 遇到其他错误时退出循环
|
||
finally:
|
||
# 恢复按钮状态
|
||
self.refresh_btn.setEnabled(True)
|
||
self.refresh_btn.setText("刷新Cursor授权 (对话次数用完了提示limit时点一次)")
|
||
|
||
def install_patch(self):
|
||
"""安装补丁"""
|
||
# 检查会员状态,未激活则显示激活提示
|
||
if not self.is_member_active:
|
||
self.show_activation_dialog()
|
||
return
|
||
|
||
# 会员已激活,继续执行原有逻辑
|
||
try:
|
||
# 检查版本
|
||
greater_than_0_45 = backend.check_cursor_version()
|
||
logging.debug(f"Cursor版本检查结果: {'> 0.45' if greater_than_0_45 else '<= 0.45'}")
|
||
|
||
while True: # 添加循环以支持重试
|
||
# 先尝试获取保存的密码
|
||
password_manager = PasswordManager()
|
||
saved_password = password_manager.get_password()
|
||
|
||
if saved_password:
|
||
logging.debug("使用保存的密码进行验证")
|
||
password = saved_password
|
||
else:
|
||
logging.debug("没有保存的密码,显示密码输入对话框")
|
||
dialog = PasswordDialog(self)
|
||
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||
password = dialog.get_password()
|
||
logging.debug("用户输入了新密码")
|
||
else:
|
||
logging.debug("用户取消了密码输入")
|
||
QMessageBox.warning(self, "取消", "操作已取消")
|
||
return
|
||
|
||
# 显示加载状态
|
||
self.patch_btn.setEnabled(False)
|
||
self.patch_btn.setText("突破中...")
|
||
QApplication.processEvents()
|
||
|
||
try:
|
||
# 设置环境变量
|
||
os.environ['SUDO_PASSWORD'] = password
|
||
logging.debug("开始执行补丁安装...")
|
||
|
||
# 执行重置
|
||
backend.reset_machine_id(greater_than_0_45)
|
||
|
||
# 直接显示成功消息
|
||
logging.debug("补丁安装完成")
|
||
self.show_success_message("补丁安装成功")
|
||
self.update_status()
|
||
break # 成功后退出循环
|
||
|
||
except Exception as e:
|
||
logging.error(f"补丁安装过程发生错误: {str(e)}")
|
||
# 密码错误,清除保存的密码
|
||
password_manager.save_password("")
|
||
QMessageBox.warning(self, "错误", "密码验证失败,请重新输入")
|
||
continue # 继续循环,重新输入密码
|
||
finally:
|
||
# 恢复按钮状态
|
||
self.patch_btn.setEnabled(True)
|
||
self.patch_btn.setText("突破0.45.x限制 (Too many free trials问题点这里)")
|
||
except Exception as e:
|
||
logging.error(f"安装补丁失败: {str(e)}")
|
||
QMessageBox.warning(self, "错误", f"安装补丁失败: {str(e)}")
|
||
|
||
def update_cursor(self):
|
||
"""更新Cursor版本"""
|
||
# 检查会员状态,未激活则显示激活提示
|
||
if not self.is_member_active:
|
||
self.show_activation_dialog()
|
||
return
|
||
|
||
# 会员已激活,继续执行原有逻辑
|
||
QMessageBox.information(self, "提示", "更新功能开发中")
|
||
|
||
if __name__ == "__main__":
|
||
try:
|
||
# 记录启动信息
|
||
logging.info("=== 应用程序启动 ===")
|
||
logging.info(f"Python 版本: {sys.version}")
|
||
logging.info(f"操作系统: {sys.platform}")
|
||
|
||
app = QApplication(sys.argv)
|
||
window = CursorGUI()
|
||
window.show()
|
||
|
||
# 捕获未处理的异常
|
||
def handle_exception(exc_type, exc_value, exc_traceback):
|
||
error_msg = f"未捕获的异常:\n{traceback.format_exception(exc_type, exc_value, exc_traceback)}"
|
||
log_error(error_msg)
|
||
logging.error("未捕获的异常:", exc_info=(exc_type, exc_value, exc_traceback))
|
||
|
||
sys.excepthook = handle_exception
|
||
|
||
sys.exit(app.exec())
|
||
except Exception as e:
|
||
error_msg = f"程序启动失败: {str(e)}\n{traceback.format_exc()}"
|
||
log_error(error_msg)
|
||
logging.error(error_msg)
|
||
raise |