From d81244c7e4d7c57a2ae1d20be6f04aca74291fdc Mon Sep 17 00:00:00 2001 From: huangzhenpc Date: Thu, 13 Feb 2025 15:16:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=201.=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=AD=A5=E9=AA=A4=E8=AF=B4=E6=98=8E=E7=9A=84?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F,=E8=B0=83=E6=95=B4=E8=A1=8C=E9=AB=98?= =?UTF-8?q?=E5=92=8C=E5=AD=97=E4=BD=93=E5=A4=A7=E5=B0=8F,=E6=8F=90?= =?UTF-8?q?=E5=8D=87=E5=8F=AF=E8=AF=BB=E6=80=A7=202.=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E6=88=AA=E5=9B=BE=203.=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E5=8C=85=E7=89=88=E6=9C=AC=204.=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=89=88=E6=9C=AC=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- banbenjietu.png | Bin 38117 -> 48451 bytes gui/main_window.py | 488 ++++++++++++++++++++++++++++++++------- requirements.txt | 3 +- test_version_manager.py | 63 +++++ utils/version_manager.py | 265 +++++++++++++++++++++ version.txt | 2 +- version_check.log | 127 ++++++++++ versioncheck.doc | 70 ++++++ 8 files changed, 936 insertions(+), 82 deletions(-) create mode 100644 test_version_manager.py create mode 100644 utils/version_manager.py create mode 100644 version_check.log create mode 100644 versioncheck.doc diff --git a/banbenjietu.png b/banbenjietu.png index bb45f02b4454cd2ff27afbbc04dd6fb463cf14a3..c090d6e9512dc7cab2be6aeb5e1663b69a0e2d61 100644 GIT binary patch literal 48451 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" - "

使用步骤说明:

" - "

" + "

" + "

使用步骤说明:

" + "

" "第一步: " "输入激活码点击【激活】按钮完成激活
" @@ -301,68 +381,117 @@ class MainWindow(QMainWindow): QLabel { color: #333333; font-size: 13px; - padding: 0px; - margin: 10px 0; + background: transparent; } """) usage_label.setTextFormat(Qt.RichText) usage_label.setWordWrap(True) - main_layout.addWidget(usage_label) + activation_layout.addWidget(usage_label) + + main_layout.addWidget(activation_frame) # 操作按钮区域 btn_frame = QFrame() btn_layout = QVBoxLayout(btn_frame) + btn_layout.setSpacing(15) # 增加按钮间距 + btn_layout.setContentsMargins(0, 10, 0, 10) - # 设置按钮样式 + # 按钮基础样式 button_style = """ QPushButton { - background-color: #0d6efd; color: white; border: none; - padding: 15px; border-radius: 6px; - font-size: 13px; - min-width: 300px; - margin: 5px; + font-size: 14px; + font-weight: 500; + min-width: 500px; + } + """ + + # 刷新授权按钮(主按钮) + refresh_btn = QPushButton("刷新 Cursor 编辑器授权") + refresh_btn.setStyleSheet(button_style + """ + QPushButton { + background-color: #0d6efd; + padding: 15px; } QPushButton:hover { background-color: #0b5ed7; } - QPushButton:pressed { - background-color: #0a58ca; - } - """ - - # 刷新授权按钮 - refresh_btn = QPushButton("刷新 Cursor 编辑器授权") - refresh_btn.setStyleSheet(button_style) + """) refresh_btn.clicked.connect(self.refresh_cursor_auth) - refresh_btn.setMinimumHeight(50) - btn_layout.addWidget(refresh_btn) + refresh_btn.setMinimumHeight(60) + refresh_btn.setMinimumWidth(500) + btn_layout.addWidget(refresh_btn, 0, Qt.AlignCenter) # 突破限制按钮 bypass_btn = QPushButton("突破 Cursor 0.45.x 限制") - bypass_btn.setStyleSheet(button_style.replace("#0d6efd", "#198754").replace("#0b5ed7", "#157347").replace("#0a58ca", "#146c43")) + bypass_btn.setStyleSheet(button_style + """ + QPushButton { + background-color: #198754; + padding: 12px; + } + QPushButton:hover { + background-color: #157347; + } + """) bypass_btn.clicked.connect(self.bypass_cursor_limit) bypass_btn.setMinimumHeight(50) - btn_layout.addWidget(bypass_btn) + bypass_btn.setMinimumWidth(500) + btn_layout.addWidget(bypass_btn, 0, Qt.AlignCenter) # 禁用更新按钮 disable_update_btn = QPushButton("禁用 Cursor 版本更新") - disable_update_btn.setStyleSheet(button_style.replace("#0d6efd", "#dc3545").replace("#0b5ed7", "#bb2d3b").replace("#0a58ca", "#b02a37")) + disable_update_btn.setStyleSheet(button_style + """ + QPushButton { + background-color: #dc3545; + padding: 12px; + } + QPushButton:hover { + background-color: #bb2d3b; + } + """) disable_update_btn.clicked.connect(self.disable_cursor_update) disable_update_btn.setMinimumHeight(50) - btn_layout.addWidget(disable_update_btn) - - # 设置按钮间距 - btn_layout.setSpacing(10) - btn_layout.setContentsMargins(20, 10, 20, 10) + disable_update_btn.setMinimumWidth(500) + btn_layout.addWidget(disable_update_btn, 0, Qt.AlignCenter) main_layout.addWidget(btn_frame) + # 检查更新按钮 + update_frame = QFrame() + update_frame.setStyleSheet(""" + QFrame { + background: transparent; + padding: 5px; + } + """) + update_layout = QHBoxLayout(update_frame) + update_layout.setContentsMargins(0, 0, 0, 0) + check_update_btn = QPushButton("检查更新") + check_update_btn.setStyleSheet(""" + QPushButton { + background-color: #6c757d; + color: white; + border: none; + padding: 8px 20px; + border-radius: 4px; + font-size: 13px; + } + QPushButton:hover { + background-color: #5a6268; + } + """) + check_update_btn.clicked.connect(self.check_for_updates) + update_layout.addWidget(check_update_btn) + main_layout.addWidget(update_frame) + # 启动时检查一次状态 QTimer.singleShot(0, self.check_status) + # 启动时自动检查更新 + QTimer.singleShot(1000, self.check_for_updates) + def create_tray_icon(self): """创建系统托盘图标""" try: @@ -1324,4 +1453,203 @@ class MainWindow(QMainWindow): def _request_complete(self): """请求完成,重置状态""" - self._is_requesting = False \ No newline at end of file + self._is_requesting = False + + def check_for_updates(self): + """检查更新""" + if self._is_requesting: + return + + self._is_requesting = True + self.show_loading_dialog("正在检查更新...") + + self.update_worker = UpdateWorker(self.version_manager) + self.update_worker.progress.connect(lambda msg: self.loading_dialog.message_label.setText(msg)) + self.update_worker.finished.connect(self.on_update_check_complete) + self.update_worker.start() + + def on_update_check_complete(self, result): + """更新检查完成的回调""" + self.hide_loading_dialog() + self._is_requesting = False + + has_update, is_force, version_info = result + + if isinstance(version_info, str): # 发生错误 + self.show_custom_error("检查更新失败", f"检查更新时发生错误: {version_info}") + return + + if not has_update: + self.show_custom_message( + "检查更新", + "已是最新版本", + "您当前使用的已经是最新版本。", + QStyle.SP_DialogApplyButton, + "#198754" + ) + return + + # 显示更新信息 + msg = QDialog(self) + msg.setWindowTitle("发现新版本") + msg.setFixedWidth(500) + msg.setWindowFlags(msg.windowFlags() & ~Qt.WindowContextHelpButtonHint) + + layout = QVBoxLayout() + + # 添加图标 + icon_label = QLabel() + icon_label.setPixmap(self.style().standardIcon(QStyle.SP_MessageBoxInformation).pixmap(32, 32)) + icon_label.setAlignment(Qt.AlignCenter) + layout.addWidget(icon_label) + + # 添加标题 + title_label = QLabel("发现新版本") + title_label.setAlignment(Qt.AlignCenter) + title_label.setStyleSheet(""" + font-size: 16px; + font-weight: bold; + color: #0d6efd; + padding: 10px; + """) + layout.addWidget(title_label) + + # 版本信息 + version_frame = QFrame() + version_frame.setStyleSheet(""" + QFrame { + background-color: #f8f9fa; + border-radius: 8px; + border: 1px solid #dee2e6; + margin: 10px; + padding: 15px; + } + QLabel { + color: #333333; + font-size: 14px; + padding: 5px; + } + """) + version_layout = QVBoxLayout(version_frame) + + # 当前版本 + current_version_label = QLabel(f"当前版本:v{self.version_manager.current_version}") + version_layout.addWidget(current_version_label) + + # 最新版本 + new_version_label = QLabel(f"最新版本:v{version_info.get('version_no', '未知')} ({version_info.get('version_name', '未知')})") + new_version_label.setStyleSheet("font-weight: bold; color: #0d6efd;") + version_layout.addWidget(new_version_label) + + # 分割线 + line = QFrame() + line.setFrameShape(QFrame.HLine) + line.setStyleSheet("background-color: #dee2e6;") + version_layout.addWidget(line) + + # 更新说明 + desc_label = QLabel("更新说明:") + desc_label.setStyleSheet("font-weight: bold; padding-top: 10px;") + version_layout.addWidget(desc_label) + + desc_text = version_info.get('description', '无') + desc_content = QLabel(desc_text if desc_text else "无更新说明") + desc_content.setWordWrap(True) + desc_content.setStyleSheet("padding: 5px 10px;") + version_layout.addWidget(desc_content) + + # 强制更新提示 + if is_force: + force_label = QLabel("* 此更新为强制更新,请立即更新!") + force_label.setStyleSheet("color: #dc3545; font-weight: bold; padding-top: 10px;") + version_layout.addWidget(force_label) + + layout.addWidget(version_frame) + + # 按钮区域 + btn_layout = QHBoxLayout() + + # 暂不更新按钮 + if not is_force: + later_btn = QPushButton("暂不更新") + later_btn.setStyleSheet(""" + QPushButton { + background-color: #6c757d; + color: white; + border: none; + padding: 8px 20px; + border-radius: 4px; + font-size: 13px; + min-width: 100px; + } + QPushButton:hover { + background-color: #5a6268; + } + """) + later_btn.clicked.connect(msg.reject) + btn_layout.addWidget(later_btn) + + # 立即更新按钮 + update_btn = QPushButton("立即更新") + update_btn.setStyleSheet(""" + QPushButton { + background-color: #0d6efd; + color: white; + border: none; + padding: 8px 20px; + border-radius: 4px; + font-size: 13px; + min-width: 100px; + font-weight: bold; + } + QPushButton:hover { + background-color: #0b5ed7; + } + """) + update_btn.clicked.connect(msg.accept) + btn_layout.addWidget(update_btn) + + layout.addLayout(btn_layout) + msg.setLayout(layout) + + # 显示对话框 + if msg.exec_() == QDialog.Accepted: + self.download_update(version_info.get('download_url')) + + def download_update(self, download_url): + """下载更新""" + if not download_url: + self.show_custom_error("更新失败", "无法获取下载地址,请联系管理员") + return + + try: + # 创建下载目录 + download_dir = Path.home() / "Downloads" / "CursorHelper" + download_dir.mkdir(parents=True, exist_ok=True) + + # 下载文件名 + file_name = download_url.split('/')[-1] + save_path = download_dir / file_name + + self.show_loading_dialog("正在下载更新...") + + # 开始下载 + success, message = self.version_manager.download_update(download_url, str(save_path)) + self.hide_loading_dialog() + + if success: + self.show_custom_message( + "下载完成", + "更新包下载成功", + f"更新包已下载到:\n{save_path}\n\n请关闭程序后运行更新包完成更新。", + QStyle.SP_DialogApplyButton, + "#198754" + ) + # 退出程序 + self.quit_application() + else: + self.show_custom_error("下载失败", message) + + except Exception as e: + self.hide_loading_dialog() + self.show_custom_error("下载失败", f"下载更新时发生错误: {str(e)}") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 742fcca..672808c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ altgraph>=0.17.4 pyinstaller==6.3.0 pillow==10.2.0 PyQt5==5.15.10 -pywin32==306 \ No newline at end of file +pywin32==306 +packaging>=23.2 \ No newline at end of file diff --git a/test_version_manager.py b/test_version_manager.py new file mode 100644 index 0000000..e0006f6 --- /dev/null +++ b/test_version_manager.py @@ -0,0 +1,63 @@ +import logging +import sys +from pathlib import Path +from utils.version_manager import VersionManager + +# 配置日志 +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.StreamHandler(sys.stdout), + logging.FileHandler('version_check.log') + ] +) + +def test_version_manager(): + """测试版本管理器功能""" + try: + vm = VersionManager() + logging.info(f"当前版本: {vm.current_version}") + logging.info(f"当前平台: {vm.platform}") + + # 测试获取最新版本 + logging.info("\n=== 测试获取最新版本 ===") + latest = vm.get_latest_version() + logging.info(f"最新版本信息: {latest}") + + # 测试检查更新 + logging.info("\n=== 测试检查更新 ===") + update_info = vm.check_update() + logging.info(f"更新检查结果: {update_info}") + + # 测试是否需要更新 + logging.info("\n=== 测试是否需要更新 ===") + has_update, is_force, version_info = vm.needs_update() + logging.info(f"是否有更新: {has_update}") + logging.info(f"是否强制更新: {is_force}") + logging.info(f"版本信息: {version_info}") + + # 如果有更新,测试下载功能 + if has_update and version_info: + logging.info("\n=== 测试下载更新 ===") + download_url = version_info.get('download_url') + if download_url: + save_path = Path.home() / "Downloads" / "CursorHelper" / "test_update.exe" + save_path.parent.mkdir(parents=True, exist_ok=True) + + logging.info(f"下载地址: {download_url}") + logging.info(f"保存路径: {save_path}") + + success = vm.download_update(download_url, str(save_path)) + logging.info(f"下载结果: {'成功' if success else '失败'}") + + if success: + logging.info(f"文件大小: {save_path.stat().st_size} 字节") + else: + logging.warning("未找到下载地址") + + except Exception as e: + logging.error(f"测试过程中发生错误: {str(e)}", exc_info=True) + +if __name__ == "__main__": + test_version_manager() \ No newline at end of file diff --git a/utils/version_manager.py b/utils/version_manager.py new file mode 100644 index 0000000..4c732c7 --- /dev/null +++ b/utils/version_manager.py @@ -0,0 +1,265 @@ +import os +import sys +import requests +from packaging import version +from typing import Optional, Dict, Any +import json +import logging +from urllib.parse import quote, unquote + +class VersionManager: + """版本管理器 + + 错误码说明: + - 0: 成功 + - 1: 一般性错误 + - 401: 未授权或授权失败 + - 404: 请求的资源不存在 + - 500: 服务器内部错误 + """ + + def __init__(self): + self.base_url = "https://cursorapi.nosqli.com" + self.current_version = self._get_current_version() + self.platform = "windows" if sys.platform.startswith("win") else "mac" if sys.platform.startswith("darwin") else "linux" + + def _get_current_version(self) -> str: + """获取当前版本号""" + try: + with open("version.txt", "r") as f: + return f.read().strip() + except FileNotFoundError: + return "0.0.0" + + def _handle_response(self, response: requests.Response) -> Dict[str, Any]: + """处理API响应 + + Args: + response: API响应对象 + + Returns: + Dict[str, Any]: 处理后的响应数据 + + Raises: + Exception: API调用失败时抛出异常 + """ + try: + data = response.json() + code = data.get("code") + msg = data.get("msg") or data.get("info", "未知错误") # 兼容 info 字段 + + if code == 0 or code == 1: # 兼容 code=1 的情况 + # 处理空数据情况 + if not data.get("data"): + logging.warning("API返回空数据") + return { + "code": 0, + "msg": msg, + "data": { + "has_update": False, + "is_force": False, + "version_info": None + } + } + return { + "code": 0, # 统一返回 code=0 + "msg": msg, + "data": data.get("data") + } + elif code == 401: + raise Exception("未授权或授权失败") + elif code == 404: + raise Exception("请求的资源不存在") + elif code == 500: + raise Exception("服务器内部错误") + else: + raise Exception(msg) + + except requests.exceptions.JSONDecodeError: + raise Exception("服务器响应格式错误") + + def check_update(self) -> Dict[str, Any]: + """检查是否有更新""" + try: + url = f"{self.base_url}/admin/api.version/check" + params = { + "version": self.current_version, + "platform": self.platform + } + logging.info(f"正在请求: {url}") + logging.info(f"参数: {params}") + + response = requests.get( + url, + params=params, + timeout=10 + ) + + logging.info(f"状态码: {response.status_code}") + logging.info(f"响应头: {dict(response.headers)}") + logging.info(f"响应内容: {response.text}") + + return self._handle_response(response) + except requests.exceptions.Timeout: + logging.error("检查更新超时") + return {"code": -1, "msg": "请求超时,请检查网络连接", "data": None} + except requests.exceptions.ConnectionError as e: + logging.error(f"检查更新连接失败: {str(e)}") + return {"code": -1, "msg": "连接服务器失败,请检查网络连接", "data": None} + except Exception as e: + logging.error(f"检查更新失败: {str(e)}") + return {"code": -1, "msg": str(e), "data": None} + + def get_latest_version(self) -> Dict[str, Any]: + """获取最新版本信息""" + try: + url = f"{self.base_url}/admin/api.version/latest" + params = {"platform": self.platform} + logging.info(f"正在请求: {url}") + logging.info(f"参数: {params}") + + response = requests.get( + url, + params=params, + timeout=10 + ) + + logging.info(f"状态码: {response.status_code}") + logging.info(f"响应头: {dict(response.headers)}") + logging.info(f"响应内容: {response.text}") + + return self._handle_response(response) + except requests.exceptions.Timeout: + logging.error("获取最新版本超时") + return {"code": -1, "msg": "请求超时,请检查网络连接", "data": None} + except requests.exceptions.ConnectionError as e: + logging.error(f"获取最新版本连接失败: {str(e)}") + return {"code": -1, "msg": "连接服务器失败,请检查网络连接", "data": None} + except Exception as e: + logging.error(f"获取最新版本失败: {str(e)}") + return {"code": -1, "msg": str(e), "data": None} + + def needs_update(self) -> tuple[bool, bool, Optional[Dict[str, Any]]]: + """检查是否需要更新 + + Returns: + tuple: (是否有更新, 是否强制更新, 版本信息) + """ + result = self.check_update() + if result["code"] == 0 and result["data"]: + data = result["data"] + return ( + data["has_update"], + bool(data.get("is_force")), + data.get("version_info") + ) + return False, False, None + + def download_update(self, download_url: str, save_path: str) -> tuple[bool, str]: + """下载更新文件 + + Args: + download_url: 下载地址 + save_path: 保存路径 + + Returns: + tuple[bool, str]: (是否下载成功, 错误信息) + """ + try: + if not download_url: + error_msg = "下载地址为空,请联系管理员" + logging.error(error_msg) + return False, error_msg + + # 处理下载地址中的中文字符 + url_parts = download_url.split('/') + # 只对最后一部分(文件名)进行编码 + url_parts[-1] = quote(url_parts[-1]) + encoded_url = '/'.join(url_parts) + + logging.info(f"原始下载地址: {download_url}") + logging.info(f"编码后的地址: {encoded_url}") + + # 设置请求头,模拟浏览器行为 + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', + 'Accept': '*/*', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + } + + response = requests.get( + encoded_url, + stream=True, + headers=headers, + timeout=30 # 增加下载超时时间 + ) + + # 检查响应状态 + if response.status_code == 404: + error_msg = "下载地址无效,请联系管理员更新下载地址" + logging.error(error_msg) + return False, error_msg + + response.raise_for_status() + + total_size = int(response.headers.get('content-length', 0)) + if total_size == 0: + error_msg = "无法获取文件大小,下载地址可能无效,请联系管理员" + logging.error(error_msg) + return False, error_msg + + block_size = 8192 + downloaded_size = 0 + + logging.info(f"开始下载文件,总大小: {total_size} 字节") + + with open(save_path, 'wb') as f: + for chunk in response.iter_content(chunk_size=block_size): + if chunk: + f.write(chunk) + downloaded_size += len(chunk) + # 打印下载进度 + if total_size > 0: + progress = (downloaded_size / total_size) * 100 + logging.info(f"下载进度: {progress:.2f}%") + + # 验证文件大小 + actual_size = os.path.getsize(save_path) + if actual_size != total_size: + error_msg = f"文件下载不完整: 预期{total_size}字节,实际{actual_size}字节,请重试或联系管理员" + logging.error(error_msg) + # 删除不完整文件 + try: + os.remove(save_path) + logging.info(f"已删除不完整的下载文件: {save_path}") + except Exception as clean_e: + logging.error(f"清理不完整文件失败: {str(clean_e)}") + return False, error_msg + + logging.info(f"文件下载完成: {save_path}") + return True, "下载成功" + + except requests.exceptions.Timeout: + error_msg = "下载超时,请检查网络连接后重试" + logging.error(error_msg) + return False, error_msg + except requests.exceptions.ConnectionError as e: + error_msg = "下载连接失败,请检查网络连接后重试" + logging.error(f"{error_msg}: {str(e)}") + return False, error_msg + except requests.exceptions.HTTPError as e: + error_msg = f"下载地址无效或服务器错误,请联系管理员 (HTTP {e.response.status_code})" + logging.error(error_msg) + return False, error_msg + except Exception as e: + error_msg = f"下载失败,请联系管理员: {str(e)}" + logging.error(error_msg) + # 如果下载失败,删除可能存在的不完整文件 + try: + if os.path.exists(save_path): + os.remove(save_path) + logging.info(f"已删除不完整的下载文件: {save_path}") + except Exception as clean_e: + logging.error(f"清理不完整文件失败: {str(clean_e)}") + return False, error_msg \ No newline at end of file diff --git a/version.txt b/version.txt index fbcbf73..a423d42 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.4.0 \ No newline at end of file +3.4.2 \ No newline at end of file diff --git a/version_check.log b/version_check.log new file mode 100644 index 0000000..774d54a --- /dev/null +++ b/version_check.log @@ -0,0 +1,127 @@ +2025-02-13 13:30:48,255 - INFO - ǰ汾: 3.4.1 +2025-02-13 13:30:48,255 - INFO - ǰƽ̨: windows +2025-02-13 13:30:48,255 - INFO - +=== Իȡ°汾 === +2025-02-13 13:30:49,989 - INFO - °汾Ϣ: {'code': 0, 'info': 'ް汾Ϣ', 'data': {}} +2025-02-13 13:30:49,989 - INFO - +=== Լ === +2025-02-13 13:30:51,712 - ERROR - ʧ: δ֪ +2025-02-13 13:30:51,713 - INFO - ¼: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:30:51,713 - INFO - +=== ǷҪ === +2025-02-13 13:30:53,394 - ERROR - ʧ: δ֪ +2025-02-13 13:30:53,395 - INFO - Ƿи: False +2025-02-13 13:30:53,395 - INFO - ǷǿƸ: False +2025-02-13 13:30:53,395 - INFO - 汾Ϣ: None +2025-02-13 13:49:13,952 - INFO - ǰ汾: 3.4.1 +2025-02-13 13:49:13,952 - INFO - ǰƽ̨: windows +2025-02-13 13:49:13,952 - INFO - +=== Իȡ°汾 === +2025-02-13 13:49:15,718 - ERROR - ȡ°汾ʧ: δ֪ +2025-02-13 13:49:15,720 - INFO - °汾Ϣ: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:49:15,720 - INFO - +=== Լ === +2025-02-13 13:49:17,452 - ERROR - ʧ: δ֪ +2025-02-13 13:49:17,454 - INFO - ¼: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:49:17,454 - INFO - +=== ǷҪ === +2025-02-13 13:49:19,277 - ERROR - ʧ: δ֪ +2025-02-13 13:49:19,278 - INFO - Ƿи: False +2025-02-13 13:49:19,278 - INFO - ǷǿƸ: False +2025-02-13 13:49:19,278 - INFO - 汾Ϣ: None +2025-02-13 13:53:02,577 - INFO - ǰ汾: 3.4.1 +2025-02-13 13:53:02,577 - INFO - ǰƽ̨: windows +2025-02-13 13:53:02,577 - INFO - +=== Իȡ°汾 === +2025-02-13 13:53:02,578 - INFO - : https://cursorapi.nosqli.com/admin/api.version/latest +2025-02-13 13:53:02,578 - INFO - : {'platform': 'windows'} +2025-02-13 13:53:04,292 - INFO - ״̬: 200 +2025-02-13 13:53:04,292 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:53:02 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=c6053c5e6170796bf1c5dde92415b981; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:53:04,292 - INFO - Ӧ: {"code":1,"info":"ȡɹ","data":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}} +2025-02-13 13:53:04,292 - ERROR - ȡ°汾ʧ: δ֪ +2025-02-13 13:53:04,294 - INFO - °汾Ϣ: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:53:04,294 - INFO - +=== Լ === +2025-02-13 13:53:04,294 - INFO - : https://cursorapi.nosqli.com/admin/api.version/check +2025-02-13 13:53:04,294 - INFO - : {'version': '3.4.1', 'platform': 'windows'} +2025-02-13 13:53:06,028 - INFO - ״̬: 200 +2025-02-13 13:53:06,028 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:53:04 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=cbb7943860ca50662d842719c53e7c73; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:53:06,028 - INFO - Ӧ: {"code":1,"info":"","data":{"has_update":true,"is_force":0,"version_info":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}}} +2025-02-13 13:53:06,028 - ERROR - ʧ: δ֪ +2025-02-13 13:53:06,029 - INFO - ¼: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:53:06,029 - INFO - +=== ǷҪ === +2025-02-13 13:53:06,029 - INFO - : https://cursorapi.nosqli.com/admin/api.version/check +2025-02-13 13:53:06,029 - INFO - : {'version': '3.4.1', 'platform': 'windows'} +2025-02-13 13:53:07,770 - INFO - ״̬: 200 +2025-02-13 13:53:07,770 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:53:05 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=c8004bac4b2d4c5054b69dca0311d6f7; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:53:07,770 - INFO - Ӧ: {"code":1,"info":"","data":{"has_update":true,"is_force":0,"version_info":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}}} +2025-02-13 13:53:07,771 - ERROR - ʧ: δ֪ +2025-02-13 13:53:07,774 - INFO - Ƿи: False +2025-02-13 13:53:07,774 - INFO - ǷǿƸ: False +2025-02-13 13:53:07,774 - INFO - 汾Ϣ: None +2025-02-13 13:53:33,800 - INFO - ǰ汾: 3.4.1 +2025-02-13 13:53:33,801 - INFO - ǰƽ̨: windows +2025-02-13 13:53:33,801 - INFO - +=== Իȡ°汾 === +2025-02-13 13:53:33,801 - INFO - : https://cursorapi.nosqli.com/admin/api.version/latest +2025-02-13 13:53:33,801 - INFO - : {'platform': 'windows'} +2025-02-13 13:53:35,509 - INFO - ״̬: 200 +2025-02-13 13:53:35,510 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:53:33 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=16d07427624c6aaf6c89254d173fe273; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:53:35,510 - INFO - Ӧ: {"code":1,"info":"ȡɹ","data":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}} +2025-02-13 13:53:35,510 - ERROR - ȡ°汾ʧ: δ֪ +2025-02-13 13:53:35,513 - INFO - °汾Ϣ: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:53:35,513 - INFO - +=== Լ === +2025-02-13 13:53:35,513 - INFO - : https://cursorapi.nosqli.com/admin/api.version/check +2025-02-13 13:53:35,513 - INFO - : {'version': '3.4.1', 'platform': 'windows'} +2025-02-13 13:53:37,280 - INFO - ״̬: 200 +2025-02-13 13:53:37,281 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:53:35 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=489a85b5766d7a30c4ba9dccda6f4967; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:53:37,281 - INFO - Ӧ: {"code":1,"info":"","data":{"has_update":true,"is_force":0,"version_info":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}}} +2025-02-13 13:53:37,281 - ERROR - ʧ: δ֪ +2025-02-13 13:53:37,283 - INFO - ¼: {'code': -1, 'msg': 'δ֪', 'data': None} +2025-02-13 13:53:37,283 - INFO - +=== ǷҪ === +2025-02-13 13:53:37,283 - INFO - : https://cursorapi.nosqli.com/admin/api.version/check +2025-02-13 13:53:37,284 - INFO - : {'version': '3.4.1', 'platform': 'windows'} +2025-02-13 13:53:39,003 - INFO - ״̬: 200 +2025-02-13 13:53:39,003 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:53:37 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=b3619976145458f7ffd03d0438958a73; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:53:39,004 - INFO - Ӧ: {"code":1,"info":"","data":{"has_update":true,"is_force":0,"version_info":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}}} +2025-02-13 13:53:39,004 - ERROR - ʧ: δ֪ +2025-02-13 13:53:39,005 - INFO - Ƿи: False +2025-02-13 13:53:39,005 - INFO - ǷǿƸ: False +2025-02-13 13:53:39,005 - INFO - 汾Ϣ: None +2025-02-13 13:54:24,914 - INFO - ǰ汾: 3.4.1 +2025-02-13 13:54:24,915 - INFO - ǰƽ̨: windows +2025-02-13 13:54:24,915 - INFO - +=== Իȡ°汾 === +2025-02-13 13:54:24,915 - INFO - : https://cursorapi.nosqli.com/admin/api.version/latest +2025-02-13 13:54:24,915 - INFO - : {'platform': 'windows'} +2025-02-13 13:54:26,652 - INFO - ״̬: 200 +2025-02-13 13:54:26,652 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:54:24 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=fc779e7ca81172e81a4d03cab86876a1; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:54:26,652 - INFO - Ӧ: {"code":1,"info":"ȡɹ","data":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}} +2025-02-13 13:54:26,654 - INFO - °汾Ϣ: {'code': 0, 'msg': 'ȡɹ', 'data': {'id': 1, 'version_no': '3.4.1.4', 'version_name': 'cursor', 'download_url': 'https://cursorapi.nosqli.com/upload/Ȫcursorv3.4.1.4.exe', 'is_force': 0, 'min_version': '', 'platform': 'all', 'status': 1, 'description': '', 'create_time': '2025-02-13 13:32:35', 'update_time': '2025-02-13 13:32:35'}} +2025-02-13 13:54:26,654 - INFO - +=== Լ === +2025-02-13 13:54:26,654 - INFO - : https://cursorapi.nosqli.com/admin/api.version/check +2025-02-13 13:54:26,654 - INFO - : {'version': '3.4.1', 'platform': 'windows'} +2025-02-13 13:54:28,445 - INFO - ״̬: 200 +2025-02-13 13:54:28,445 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:54:26 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=f8a3f46919c8aaa4d8f34d361ea3386a; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:54:28,445 - INFO - Ӧ: {"code":1,"info":"","data":{"has_update":true,"is_force":0,"version_info":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}}} +2025-02-13 13:54:28,447 - INFO - ¼: {'code': 0, 'msg': '', 'data': {'has_update': True, 'is_force': 0, 'version_info': {'id': 1, 'version_no': '3.4.1.4', 'version_name': 'cursor', 'download_url': 'https://cursorapi.nosqli.com/upload/Ȫcursorv3.4.1.4.exe', 'is_force': 0, 'min_version': '', 'platform': 'all', 'status': 1, 'description': '', 'create_time': '2025-02-13 13:32:35', 'update_time': '2025-02-13 13:32:35'}}} +2025-02-13 13:54:28,447 - INFO - +=== ǷҪ === +2025-02-13 13:54:28,447 - INFO - : https://cursorapi.nosqli.com/admin/api.version/check +2025-02-13 13:54:28,447 - INFO - : {'version': '3.4.1', 'platform': 'windows'} +2025-02-13 13:54:30,144 - INFO - ״̬: 200 +2025-02-13 13:54:30,145 - INFO - Ӧͷ: {'Server': 'nginx', 'Date': 'Thu, 13 Feb 2025 05:54:28 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'X-Frame-Options': 'sameorigin', 'Set-Cookie': 'ssid=169a8bdefde9a16f0e9f3e32da4d8ba5; path=/; secure; HttpOnly, lang=zh-cn; path=/; secure; HttpOnly', 'Strict-Transport-Security': 'max-age=31536000', 'Alt-Svc': 'quic=":443"; h3=":443"; h3-29=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"', 'Content-Encoding': 'gzip'} +2025-02-13 13:54:30,145 - INFO - Ӧ: {"code":1,"info":"","data":{"has_update":true,"is_force":0,"version_info":{"id":1,"version_no":"3.4.1.4","version_name":"cursor","download_url":"https:\/\/cursorapi.nosqli.com\/upload\/Ȫcursorv3.4.1.4.exe","is_force":0,"min_version":"","platform":"all","status":1,"description":"","create_time":"2025-02-13 13:32:35","update_time":"2025-02-13 13:32:35"}}} +2025-02-13 13:54:30,146 - INFO - Ƿи: True +2025-02-13 13:54:30,146 - INFO - ǷǿƸ: False +2025-02-13 13:54:30,146 - INFO - 汾Ϣ: {'id': 1, 'version_no': '3.4.1.4', 'version_name': 'cursor', 'download_url': 'https://cursorapi.nosqli.com/upload/Ȫcursorv3.4.1.4.exe', 'is_force': 0, 'min_version': '', 'platform': 'all', 'status': 1, 'description': '', 'create_time': '2025-02-13 13:32:35', 'update_time': '2025-02-13 13:32:35'} +2025-02-13 13:54:30,146 - INFO - +=== ظ === +2025-02-13 13:54:30,148 - INFO - صַ: https://cursorapi.nosqli.com/upload/Ȫcursorv3.4.1.4.exe +2025-02-13 13:54:30,148 - INFO - ·: C:\Users\huangzhen\Downloads\CursorHelper\test_update.exe +2025-02-13 13:54:31,822 - ERROR - ظʧ: 404 Client Error: Not Found for url: https://cursorapi.nosqli.com/upload/%E5%90%AC%E6%B3%89cursor%E5%8A%A9%E6%89%8Bv3.4.1.4.exe +2025-02-13 13:54:31,823 - INFO - ؽ: ʧ diff --git a/versioncheck.doc b/versioncheck.doc new file mode 100644 index 0000000..08d23ee --- /dev/null +++ b/versioncheck.doc @@ -0,0 +1,70 @@ +版本更新API文档 +域名 +base_url: https://cursorapi.nosqli.com +# 版本更新API文档 + +# + * 公共返回参数: + * - code: 错误码,0表示成功,非0表示失败 + * - msg: 提示信息 + * - data: 返回的数据,请求失败时可能为空 + * + * 错误码说明: + * - 0: 成功 + * - 1: 一般性错误(具体错误信息见msg) + * - 401: 未授权或授权失败 + * - 404: 请求的资源不存在 + * - 500: 服务器内部错误 + * + * 版本号格式:x.x.x (例如: 3.4.1) + * 平台类型: + * - all: 全平台 + * - windows: Windows平台 + * - mac: Mac平台 + * - linux: Linux平台 + * ==================================================== + * + * 1. 获取最新版本 [GET] /admin/api.version/latest + * 请求参数: + * - platform: 平台类型(all|windows|mac|linux), 默认为all + * 返回数据: + * { + * "code": 0, + * "msg": "获取成功", + * "data": { + * "id": "1", + * "version_no": "3.4.1.4", + * "version_name": "听泉cursor助手", + * "download_url": "http://domain/upload/xxx.exe", + * "is_force": 1, // 是否强制更新(1是,0否) + * "min_version": "3.4.0.0", // 最低要求版本 + * "platform": "all", // 平台类型 + * "description": "版本描述", // 版本描述 + * "status": 1, // 状态(1启用,0禁用) + * "create_time": "2024-03-20 10:00:00" + * } + * } + * + * 2. 检查版本更新 [GET] /admin/api.version/check + * 请求参数: + * - version: 当前版本号(必填) + * - platform: 平台类型(all|windows|mac|linux), 默认为all + * 返回数据: + * { + * "code": 0, + * "msg": "检查完成", + * "data": { + * "has_update": true, // 是否有更新 + * "is_force": 1, // 是否强制更新 + * "version_info": { // 新版本信息(has_update为true时返回) + * // 同上面的版本信息 + * } + * } + * } + * + * 错误返回示例: + * { + * "code": 1, + * "msg": "请提供当前版本号", + * "data": null + * } \ No newline at end of file