-
-
## 🌟 English
### 📝 Description
-A tool to resolve the following prompt issue during Cursor's free trial period:
+Resets Cursor's free trial limitation when you see:
-
-
-
-
+```
Too many free trial accounts used on this machine.
Please upgrade to pro. We have this limit in place
to prevent abuse. Please let us know if you believe
this is a mistake.
-
- |
-
-
-
-### ✨ Features
-
-- 🔄 Reset Cursor free trial limitations
-- 🔍 Automatic detection and closing of running instances
-- 🌐 Cross-platform support with architecture detection
-- 📦 Automated installation scripts
-- 🖥️ Both GUI and command-line interfaces
+```
### 💻 System Support
-| Platform | Status |
-| ----------------------------------------------------------------------------------------------- | ---------------------- |
-|  | ✅ x64 |
-|  | ✅ Intel/Apple Silicon |
-|  | ✅ x64/ARM64 |
-
-### 📥 Installation Methods
+**Windows** ✅ x64
+**macOS** ✅ Intel & M-series
+**Linux** ✅ x64 & ARM64
-
-1️⃣ Automated Installation (Recommended)
-
-#### Linux/macOS
+### 📥 Installation
+**Linux/macOS**
```bash
-curl -fsSL https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/install.sh | sudo bash
+curl -fsSL https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/install.sh | bash -s -- --auto-sudo && rm -f /tmp/cursor_id_modifier_*
```
-#### Windows PowerShell
-
+**Windows** (Run in PowerShell as Admin)
```powershell
-# Download and run with admin privileges
-$url = "https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/bin/cursor_id_modifier_v2.0.0_windows_amd64.exe"
-$output = "$env:TEMP\cursor-id-modifier.exe"
-Invoke-WebRequest -Uri $url -OutFile $output
-Start-Process -FilePath $output -Verb RunAs
+Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/bin/cursor_id_modifier_v2.0.0_windows_amd64.exe')); Remove-Item -Path "$env:TEMP\cursor-id-modifier.exe" -ErrorAction SilentlyContinue
```
-
-
-
-2️⃣ Manual Download
-
-Download from [Releases](https://github.com/yuaotian/go-cursor-help/releases/latest):
-
-| Platform | Architecture | File |
-| ----------------------------------------------------------------------------------------------- | ------------- | -------------------------- |
-|  | x64 | `cursor-id-modifier.exe` |
-|  | Intel (x64) | `cursor-id-modifier-amd64` |
-|  | Apple Silicon | `cursor-id-modifier-arm64` |
-|  | x64 | `cursor-id-modifier` |
-|  | ARM64 | `cursor-id-modifier-arm64` |
-
-
-
-### 📚 Usage Instructions
-
-
-Prerequisites
-
-- 👑 Administrator/root privileges required
-- 🚫 Cursor should be completely closed
-- 🌐 Internet connection for installation
-
-
-
-
-Running the Tool
-
-The tool will automatically:
-
-1. 🔑 Check for and request admin privileges
-2. 🔍 Detect and close Cursor instances
-3. 💾 Backup existing configuration
-4. 🔄 Generate new identifiers
-5. ✅ Apply changes
-
-Restart Cursor after completion.
-
-
-
-### 🔧 Troubleshooting
-
-
-Common Issues
-
-#### 🚫 Permission Denied
-
-- Windows: Right-click → "Run as Administrator"
-- Linux/macOS: Use \`sudo\` when running
-
-#### ⚠️ Cursor Still Running
-
-- Tool will attempt auto-close
-- Manual close via Task Manager if needed
-
-#### 🔒 macOS Security
-
-If you see "unidentified developer" warning:
-
-1. Right-click → Open
-2. Click "Open" in dialog
-
-
-
-### ⚠️ Cautions
-
-- 🛡️ Use at your own risk
-- 💾 Backup important data
-- 📚 Educational purposes only
+### 🔧 Technical Details
-### 🤝 Contributing
+The program modifies Cursor's `storage.json` config file:
+- Windows: `%APPDATA%\Cursor\User\globalStorage\`
+- macOS: `~/Library/Application Support/Cursor/User/globalStorage/`
+- Linux: `~/.config/Cursor/User/globalStorage/`
-We welcome contributions! Please ensure:
-
-- ✅ Cross-platform compatibility
-- 🚫 No breaking changes
-- 🔍 Proper error handling
-- 📝 Documentation updates
+Generates new unique identifiers for:
+- `telemetry.machineId`
+- `telemetry.macMachineId`
+- `telemetry.devDeviceId`
---
@@ -168,140 +65,44 @@ We welcome contributions! Please ensure:
### 📝 问题描述
-解决Cursor在免费订阅期间出现以下提示的问题:
+当看到以下提示时重置Cursor试用期:
-
-
-
-
+```
Too many free trial accounts used on this machine.
Please upgrade to pro. We have this limit in place
to prevent abuse. Please let us know if you believe
this is a mistake.
-
- |
-
-
-
-### ✨ 功能特性
-
-- 🔄 重置Cursor免费试用限制
-- 🔍 自动检测和关闭运行中的实例
-- 🌐 跨平台支持,自动检测系统架构
-- 📦 自动化安装脚本
-- 🖥️ 支持图形界面和命令行
+```
### 💻 系统支持
-| 平台 | 状态 |
-| ----------------------------------------------------------------------------------------------- | ---------------------- |
-|  | ✅ x64 |
-|  | ✅ Intel/Apple Silicon |
-|  | ✅ x64/ARM64 |
+**Windows** ✅ x64
+**macOS** ✅ Intel和M系列
+**Linux** ✅ x64和ARM64
### 📥 安装方法
-
-1️⃣ 自动安装(推荐)
-
-#### Linux/macOS
-
-
+**Linux/macOS**
```bash
-curl -fsSL https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/install.sh | sudo bash
+curl -fsSL https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/install.sh | bash -s -- --auto-sudo && rm -f /tmp/cursor_id_modifier_*
```
-#### Windows PowerShell
-
+**Windows** (以管理员身份运行PowerShell)
```powershell
-# 下载管理员运行
-$url = "https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/bin/cursor_id_modifier_v2.0.0_windows_amd64.exe"
-$output = "$env:TEMP\cursor-id-modifier.exe"
-Invoke-WebRequest -Uri $url -OutFile $output
-Start-Process -FilePath $output -Verb RunAs
+Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/yuaotian/go-cursor-help/refs/heads/master/bin/cursor_id_modifier_v2.0.0_windows_amd64.exe')); Remove-Item -Path "$env:TEMP\cursor-id-modifier.exe" -ErrorAction SilentlyContinue
```
-
-
-
-2️⃣ 手动下载
-
-从[发布页面](https://github.com/yuaotian/go-cursor-help/releases/latest)下载:
-
-| 平台 | 架构 | 文件 |
-| ----------------------------------------------------------------------------------------------- | ------------- | -------------------------- |
-|  | x64 | `cursor-id-modifier.exe` |
-|  | Intel (x64) | `cursor-id-modifier-amd64` |
-|  | Apple Silicon | `cursor-id-modifier-arm64` |
-|  | x64 | `cursor-id-modifier` |
-|  | ARM64 | `cursor-id-modifier-arm64` |
-
-
-
-### 📚 使用说明
-
-
-使用前提
-
-- 👑 需要管理员/root权限
-- 🚫 确保Cursor完全关闭
-- 🌐 需要网络连接进行安装
-
-
-
-
-运行工具
-
-工具将自动执行:
-
-1. 🔑 检查并请求管理员权限
-2. 🔍 检测并关闭Cursor进程
-3. 💾 备份现有配置
-4. 🔄 生成新的标识符
-5. ✅ 应用更改
-
-完成后重启Cursor即可。
-
-
-
-### 🔧 故障排除
-
-
-常见问题
-
-#### 🚫 权限被拒绝
-
-- Windows:右键 → "以管理员身份运行"
-- Linux/macOS:使用 \`sudo\` 运行
-
-#### ⚠️ Cursor仍在运行
-
-- 工具会尝试自动关闭
-- 如需要请通过任务管理器手动关闭
-
-#### 🔒 macOS安全性问题
-
-如果看到"未识别的开发者"提示:
-
-1. 右键点击 → 打开
-2. 点击确认对话框中的"打开"
-
-
-
-### ⚠️ 注意事项
-
-- 🛡️ 使用本工具需自行承担风险
-- 💾 使用前请备份重要数据
-- 📚 仅用于学习研究目的
-
-### 🤝 贡献
+### 🔧 技术细节
-欢迎提交问题和改进建议!请确保:
+程序修改Cursor的`storage.json`配置文件:
+- Windows: `%APPDATA%\Cursor\User\globalStorage\`
+- macOS: `~/Library/Application Support/Cursor/User/globalStorage/`
+- Linux: `~/.config/Cursor/User/globalStorage/`
-- ✅ 保持跨平台兼容性
-- 🚫 避免破坏性更改
-- 🔍 完善的错误处理
-- 📝 更新相关文档
+生成新的唯一标识符:
+- `telemetry.machineId`
+- `telemetry.macMachineId`
+- `telemetry.devDeviceId`
## 📄 License
diff --git a/install.sh b/install.sh
index 9a73305..4aaddb6 100644
--- a/install.sh
+++ b/install.sh
@@ -3,24 +3,50 @@
# Version / 版本号
VERSION="v2.0.0"
+# Configuration / 配置
+KEEP_BINARY=false
+DOWNLOAD_DIR="/tmp"
+INSTALL_DIR="/usr/local/bin"
+AUTO_SUDO=false
+
+# Colors / 颜色
+RED='\033[31m'
+GREEN='\033[32m'
+YELLOW='\033[33m'
+BLUE='\033[36m'
+BOLD='\033[1m'
+NC='\033[0m'
+
+# Separator / 分隔线
+SEPARATOR="${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
+
# Bilingual message functions / 双语消息函数
error() {
- echo "❌ Error: $1"
- echo "❌ 错误:$2"
+ echo -e "\n${SEPARATOR}"
+ echo -e "${RED}${BOLD}❌ Error:${NC} $1"
+ echo -e "${RED}${BOLD}❌ 错误:${NC}$2"
+ echo -e "${SEPARATOR}\n"
exit 1
}
info() {
- echo "ℹ️ $1"
- echo "ℹ️ $2"
+ echo -e "\n${BLUE}${BOLD}ℹ️ [EN]:${NC} $1"
+ echo -e "${BLUE}${BOLD}ℹ️ [中文]:${NC} $2\n"
}
success() {
- echo "✅ $1"
- echo "✅ $2"
+ echo -e "\n${SEPARATOR}"
+ echo -e "${GREEN}${BOLD}✅ [EN]:${NC} $1"
+ echo -e "${GREEN}${BOLD}✅ [中文]:${NC} $2"
+ echo -e "${SEPARATOR}\n"
}
-# Detect OS and architecture / 检测操作系统和架构
+warning() {
+ echo -e "\n${YELLOW}${BOLD}⚠️ [EN]:${NC} $1"
+ echo -e "${YELLOW}${BOLD}⚠️ [中文]:${NC} $2\n"
+}
+
+# System detection / 系统检测
detect_platform() {
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
@@ -51,38 +77,51 @@ detect_platform() {
esac
}
-# Check system requirements / 检查系统要求
+# System checks / 系统检查
check_requirements() {
info "Checking system requirements..." "正在检查系统要求..."
- # 添加网络连接检查
+ # Check network connectivity / 检查网络连接
if ! ping -c 1 github.com >/dev/null 2>&1; then
- error "No network connection to GitHub" \
- "无法连接到 GitHub"
+ error "No network connection to GitHub" "无法连接到 GitHub"
fi
- # Check curl
+ # Check curl / 检查curl
if ! command -v curl >/dev/null 2>&1; then
error "curl is required. Please install curl first." \
"需要安装 curl。请先安装 curl 后再运行此脚本。"
fi
-
- # Check write permissions / 检查写入权限
- if [ ! -w "$INSTALL_DIR" ]; then
- error "No write permission for $INSTALL_DIR. Please run with sudo." \
- "没有 $INSTALL_DIR 的写入权限。请使用 sudo 运行此脚本。"
+}
+
+# Privilege check / 权限检查
+check_privileges() {
+ if [ "$EUID" -ne 0 ]; then
+ if [ "$AUTO_SUDO" = "true" ]; then
+ if command -v sudo >/dev/null 2>&1; then
+ info "Re-running with sudo..." "使用 sudo 重新运行..."
+ exec sudo bash "$0" "$@"
+ else
+ error "This script must be run as root. Please use sudo." \
+ "此脚本必须以 root 身份运行。请使用 sudo。"
+ fi
+ else
+ error "This script must be run as root. Please use sudo." \
+ "此脚本必须以 root 身份运行。请使用 sudo。"
+ fi
fi
}
-# Verify binary / 验证二进制文件
+# Binary verification / 二进制验证
verify_binary() {
info "Verifying binary..." "正在验证二进制文件..."
+
+ # Check file existence / 检查文件是否存在
if [ ! -f "$DOWNLOAD_PATH" ]; then
error "Binary file download failed or does not exist" \
"二进制文件下载失败或不存在"
fi
- # 添加可执行文件格式检查
+ # Check executable format / 检查可执行格式
if ! file "$DOWNLOAD_PATH" | grep -q "executable"; then
error "Downloaded file is not an executable" \
"下载的文件不是可执行文件"
@@ -91,8 +130,8 @@ verify_binary() {
# Check file size / 检查文件大小
local size=$(wc -c < "$DOWNLOAD_PATH")
if [ "$size" -lt 1000000 ]; then # At least 1MB / 至少1MB
- error "Downloaded file size is abnormal, download might be incomplete" \
- "下载的文件大小异常,可能下载不完整"
+ error "Downloaded file size is abnormal" \
+ "下载的文件大小异常"
fi
# Set executable permissions / 设置可执行权限
@@ -102,14 +141,30 @@ verify_binary() {
fi
}
-# 在文件开头添加配置项
-KEEP_BINARY=true # 修改默认值为 true
-DOWNLOAD_DIR="." # 默认下载到当前目录
+# Cleanup functions / 清理函数
+cleanup_old_version() {
+ if [ -f "$INSTALL_DIR/cursor-id-modifier" ]; then
+ info "Removing old version..." "正在删除旧版..."
+ rm -f "$INSTALL_DIR/cursor-id-modifier" || \
+ error "Failed to remove old version" "删除旧版本失败"
+ fi
+}
+
+cleanup_temp_files() {
+ if [ "$KEEP_BINARY" = "false" ]; then
+ rm -f "$DOWNLOAD_PATH"
+ rm -f "$INSTALL_DIR/cursor-id-modifier-wrapper"
+ fi
+}
-# 在 main 函数之前添加参数解析
+# Parse arguments / 解析参数
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
+ --auto-sudo)
+ AUTO_SUDO=true
+ shift
+ ;;
--keep-binary)
KEEP_BINARY=true
shift
@@ -125,104 +180,76 @@ parse_args() {
done
}
+# Print banner / 打印横幅
+print_banner() {
+ echo -e "\n${BLUE}${BOLD}"
+ echo " ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗"
+ echo " ██╔════╝██║ ██║██╔══██╗██╔════╝█╔═══██╗██╔══██╗"
+ echo " ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝"
+ echo " ██║ ██║ ██║██╔══██╗╚════██ ██║ ██║██╔══██╗"
+ echo " ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║"
+ echo " ╚════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚════╝ ╚═╝ ╚═╝"
+ echo -e "${NC}"
+ echo -e "${YELLOW}${BOLD} >> Cursor ID Modifier ${VERSION} <<${NC}"
+ echo -e "${BLUE}${BOLD} [ By Pancake Fruit Rolled Shark Chili ]${NC}\n"
+}
+
# Main installation process / 主安装流程
main() {
+ check_privileges "$@"
+
+ print_banner
+
info "Starting installation of cursor-id-modifier ${VERSION}..." \
"开始安装 cursor-id-modifier ${VERSION}..."
- # Initialize installation / 初始化安装
detect_platform
- INSTALL_DIR="/usr/local/bin"
- if [ ! -d "$INSTALL_DIR" ]; then
- if ! mkdir -p "$INSTALL_DIR" 2>/dev/null; then
- error "Failed to create installation directory" \
- "无法创建安装目录"
- fi
- fi
-
- # Check requirements / 检查要求
check_requirements
- # Create temp directory / 创建临时目录
- info "Creating temporary directory..." \
- "正在创建临时目录..."
- TEMP_DIR=$(mktemp -d)
- info "Note: Temporary directory will be automatically cleaned up after installation" \
- "注意:临时目录将在安装完成后自动清理"
- trap 'rm -rf "$TEMP_DIR"' EXIT
-
- # 检查下载目录权限
- if [ ! -w "$DOWNLOAD_DIR" ]; then
- error "No write permission for download directory: $DOWNLOAD_DIR" \
- "下载目录无写入权限:$DOWNLOAD_DIR"
- fi
+ # Create installation directory / 创建安装目录
+ mkdir -p "$INSTALL_DIR" 2>/dev/null || \
+ error "Failed to create installation directory" "无法创建安装目录"
- # 下载二进制文件
+ # Download binary / 下载二进制文件
info "Downloading cursor-id-modifier ($OS-$ARCH)..." \
"正在下载 cursor-id-modifier ($OS-$ARCH)..."
- # 定义下载 URL
DOWNLOAD_URL="https://github.com/yuaotian/go-cursor-help/raw/refs/heads/master/bin/$BINARY_NAME"
DOWNLOAD_PATH="$DOWNLOAD_DIR/$BINARY_NAME"
- info "File will be downloaded to: $DOWNLOAD_PATH" \
- "文件将下载到:$DOWNLOAD_PATH"
if ! curl -L --progress-bar "$DOWNLOAD_URL" -o "$DOWNLOAD_PATH"; then
- error "Failed to download binary from: $DOWNLOAD_URL" \
- "从以下地址下载二进制文件失败:$DOWNLOAD_URL"
+ error "Failed to download binary" "下载二进制文件失败"
fi
- success "Download completed to: $DOWNLOAD_PATH" \
- "下载完成,文件位置:$DOWNLOAD_PATH"
-
- # 添加手动设置权限的提示
- info "To make the file executable, run:" \
- "要使文件可执行,请运行:"
- info "chmod +x $DOWNLOAD_PATH" \
- "chmod +x $DOWNLOAD_PATH"
- info "Then you can run it with:" \
- "然后可以通过以下命令运行:"
- info "./$BINARY_NAME" \
- "./$BINARY_NAME"
+ success "Download completed" "下载完成"
- # 验证和安装
verify_binary
+ cleanup_old_version
- # 安装到系统目录
+ # Install binary / 安装二进制文件
info "Installing binary..." "正在安装二进制文件..."
if ! cp "$DOWNLOAD_PATH" "$INSTALL_DIR/cursor-id-modifier"; then
error "Failed to install binary" "安装二进制文件失败"
fi
- # 根据设置决定是否保留下载的文件
- if [ "$KEEP_BINARY" = false ]; then
- info "Binary file will be cleaned up after installation" \
- "二进制文件将在安装后被清理"
- info "Use --keep-binary flag to keep the downloaded file" \
- "使用 --keep-binary 参数可以保留下载的文件"
- info "Cleaning up downloaded file..." "正在清理下载的文件..."
- rm -f "$DOWNLOAD_PATH"
- else
- info "Binary file is kept at: $DOWNLOAD_PATH" \
- "二进制文件保留在:$DOWNLOAD_PATH"
- fi
-
- success "Installation successful! You can now run 'cursor-id-modifier' from anywhere." \
- "安装成功!现在可以在任何位置运行 'cursor-id-modifier'。"
- success "For help, run 'cursor-id-modifier --help'" \
- "如需帮助,请运行 'cursor-id-modifier --help'"
-}
-
-cleanup_old_version() {
- if [ -f "$INSTALL_DIR/cursor-id-modifier" ]; then
- info "Removing old version..." "正在删除旧版..."
- rm -f "$INSTALL_DIR/cursor-id-modifier" || \
- error "Failed to remove old version" "删除旧版本失败"
- fi
+ # Create wrapper script / 创建包装脚本
+ cat > "$INSTALL_DIR/cursor-id-modifier-wrapper" << 'EOF'
+#!/bin/bash
+if [ "$(uname -s)" = "Darwin" ]; then
+ sudo /usr/local/bin/cursor-id-modifier "$@"
+else
+ sudo /usr/local/bin/cursor-id-modifier "$@"
+fi
+EOF
+ chmod +x "$INSTALL_DIR/cursor-id-modifier-wrapper"
+
+ # Cleanup / 清理
+ cleanup_temp_files
+
+ success "Installation successful! Run 'cursor-id-modifier-wrapper' from anywhere." \
+ "安装成功!现在可以在任何位置运行 'cursor-id-modifier-wrapper'。"
}
-# 在主程序开始前解析参数
-parse_args "$@"
-
# Start installation / 开始安装
-main
\ No newline at end of file
+parse_args "$@"
+main "$@"
\ No newline at end of file
diff --git a/main.go b/main.go
index f1abe7b..cc1d4dd 100644
--- a/main.go
+++ b/main.go
@@ -1,12 +1,14 @@
package main
-// 导入所需的包 / Import required packages
+// Core imports / 核心导入
import (
"bufio"
+ "context"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
+ "errors"
"fmt"
"log"
"os"
@@ -14,86 +16,106 @@ import (
"os/user"
"path/filepath"
"runtime"
+ "runtime/debug"
"strings"
"time"
+
"github.com/fatih/color"
- "context"
- "errors"
- "runtime/debug"
)
-// 语言类型和常量 / Language type and constants
+// Types and Constants / 类型和常量
type Language string
const (
+ // Language options / 语言选项
CN Language = "cn"
EN Language = "en"
- // Version constant
+ // Version / 版本号
Version = "1.0.1"
- // 定义错误类型常量
+ // Error types / 错误类型
ErrPermission = "permission_error"
ErrConfig = "config_error"
ErrProcess = "process_error"
ErrSystem = "system_error"
)
-// TextResource 存储多语言文本 / TextResource stores multilingual text
-type TextResource struct {
- SuccessMessage string
- RestartMessage string
- ReadingConfig string
- GeneratingIds string
- PressEnterToExit string
- ErrorPrefix string
- PrivilegeError string
- RunAsAdmin string
- RunWithSudo string
- SudoExample string
- ConfigLocation string
-}
+// Configuration Structures / 配置结构
+type (
+ // TextResource stores multilingual text / 存储多语言文本
+ TextResource struct {
+ SuccessMessage string
+ RestartMessage string
+ ReadingConfig string
+ GeneratingIds string
+ PressEnterToExit string
+ ErrorPrefix string
+ PrivilegeError string
+ RunAsAdmin string
+ RunWithSudo string
+ SudoExample string
+ ConfigLocation string
+ }
-// StorageConfig 优化的存储配置结构 / StorageConfig optimized storage configuration struct
-type StorageConfig struct {
- TelemetryMacMachineId string `json:"telemetry.macMachineId"`
- TelemetryMachineId string `json:"telemetry.machineId"`
- TelemetryDevDeviceId string `json:"telemetry.devDeviceId"`
- LastModified time.Time `json:"lastModified"`
- Version string `json:"version"`
-}
+ // StorageConfig optimized storage configuration / 优化的存储配置
+ StorageConfig struct {
+ TelemetryMacMachineId string `json:"telemetry.macMachineId"`
+ TelemetryMachineId string `json:"telemetry.machineId"`
+ TelemetryDevDeviceId string `json:"telemetry.devDeviceId"`
+ LastModified time.Time `json:"lastModified"`
+ Version string `json:"version"`
+ }
-// AppError 定义错误类型 / AppError defines error types
-type AppError struct {
- Type string
- Op string
- Path string
- Err error
- Context map[string]interface{}
-}
+ // AppError defines error types / 定义错误类型
+ AppError struct {
+ Type string
+ Op string
+ Path string
+ Err error
+ Context map[string]interface{}
+ }
-// ProgressSpinner 用于显示进度动画 / ProgressSpinner for showing progress animation
-type ProgressSpinner struct {
- frames []string
- current int
- message string
-}
+ // Config structures / 配置结构
+ Config struct {
+ Storage StorageConfig
+ UI UIConfig
+ System SystemConfig
+ }
-// SpinnerConfig 定义进度条配置
-type SpinnerConfig struct {
- Frames []string
- Delay time.Duration
-}
+ UIConfig struct {
+ Language Language
+ Theme string
+ Spinner SpinnerConfig
+ }
+
+ SystemConfig struct {
+ RetryAttempts int
+ RetryDelay time.Duration
+ Timeout time.Duration
+ }
+ // SpinnerConfig defines spinner configuration / 定义进度条配置
+ SpinnerConfig struct {
+ Frames []string
+ Delay time.Duration
+ }
+ // ProgressSpinner for showing progress animation / 用于显示进度动画
+ ProgressSpinner struct {
+ frames []string
+ current int
+ message string
+ }
+)
-// 全局变量 / Global variables
+// Global Variables / 全局变量
var (
- currentLanguage = CN // 默认为中文 / Default to Chinese
+ currentLanguage = CN // Default to Chinese / 默认为中文
texts = map[Language]TextResource{
CN: {
- SuccessMessage: "[√] 配置文件已成功更新!",
+ SuccessMessage: "[√] 配置文件已成功更新!",
RestartMessage: "[!] 请手动重启 Cursor 以使更新生效",
ReadingConfig: "正在读取配置文件...",
GeneratingIds: "正在生成新的标识符...",
@@ -121,7 +143,7 @@ var (
}
)
-// Error implementation for AppError
+// Error Implementation / 错误实现
func (e *AppError) Error() string {
if e.Context != nil {
return fmt.Sprintf("[%s] %s: %v (context: %v)", e.Type, e.Op, e.Err, e.Context)
@@ -129,7 +151,7 @@ func (e *AppError) Error() string {
return fmt.Sprintf("[%s] %s: %v", e.Type, e.Op, e.Err)
}
-// NewStorageConfig 创建新的实例 / Creates a new configuration instance
+// Configuration Functions / 配置函数
func NewStorageConfig() *StorageConfig {
return &StorageConfig{
TelemetryMacMachineId: generateMachineId(),
@@ -140,7 +162,28 @@ func NewStorageConfig() *StorageConfig {
}
}
-// 生成类似原始machineId的字符串(64位小十六进制) / Generate a string similar to the original machineId (64-bit lowercase hex)
+func initConfig() *Config {
+ return &Config{
+ Storage: StorageConfig{
+ Version: Version,
+ },
+ UI: UIConfig{
+ Language: detectLanguage(),
+ Theme: "default",
+ Spinner: SpinnerConfig{
+ Frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
+ Delay: 100 * time.Millisecond,
+ },
+ },
+ System: SystemConfig{
+ RetryAttempts: 3,
+ RetryDelay: time.Second,
+ Timeout: 30 * time.Second,
+ },
+ }
+}
+
+// ID Generation Functions / ID生成函数
func generateMachineId() string {
data := make([]byte, 32)
if _, err := rand.Read(data); err != nil {
@@ -150,51 +193,18 @@ func generateMachineId() string {
return hex.EncodeToString(hash[:])
}
-// 生成类似原始devDeviceId的字符串(标准UUID格式) / Generate a string similar to the original devDeviceId (standard UUID format)
func generateDevDeviceId() string {
uuid := make([]byte, 16)
if _, err := rand.Read(uuid); err != nil {
panic(fmt.Errorf("failed to generate UUID: %v", err))
}
-
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
-
return fmt.Sprintf("%x-%x-%x-%x-%x",
- uuid[0:4],
- uuid[4:6],
- uuid[6:8],
- uuid[8:10],
- uuid[10:16])
-}
-
-// NewProgressSpinner creates a new progress spinner
-func NewProgressSpinner(message string) *ProgressSpinner {
- return &ProgressSpinner{
- frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
- message: message,
- }
-}
-
-// Spin advances the spinner animation
-func (s *ProgressSpinner) Spin() {
- frame := s.frames[s.current%len(s.frames)]
- s.current++
- fmt.Printf("\r%s %s", color.CyanString(frame), s.message)
-}
-
-// Stop ends the spinner animation
-func (s *ProgressSpinner) Stop() {
- fmt.Println()
-}
-
-// Start starts the spinner animation
-func (s *ProgressSpinner) Start() {
- s.current = 0
+ uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:16])
}
-// File and system operations
-
+// File Operations / 文件操作
func getConfigPath() (string, error) {
var configDir string
switch runtime.GOOS {
@@ -218,8 +228,24 @@ func getConfigPath() (string, error) {
return filepath.Join(configDir, "storage.json"), nil
}
-func safeWriteFile(path string, data []byte, perm os.FileMode) error {
- dir := filepath.Dir(path)
+func saveConfig(config *StorageConfig) error {
+ configPath, err := getConfigPath()
+ if err != nil {
+ return err
+ }
+
+ content, err := json.MarshalIndent(config, "", " ")
+ if err != nil {
+ return &AppError{
+ Type: ErrSystem,
+ Op: "generate JSON",
+ Path: "",
+ Err: err,
+ }
+ }
+
+ // Create parent directories with proper permissions
+ dir := filepath.Dir(configPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return &AppError{
Type: ErrSystem,
@@ -229,8 +255,19 @@ func safeWriteFile(path string, data []byte, perm os.FileMode) error {
}
}
- tmpPath := path + ".tmp"
- if err := os.WriteFile(tmpPath, data, perm); err != nil {
+ // First ensure we can write to the file
+ if err := os.Chmod(configPath, 0666); err != nil && !os.IsNotExist(err) {
+ return &AppError{
+ Type: ErrSystem,
+ Op: "modify file permissions",
+ Path: configPath,
+ Err: err,
+ }
+ }
+
+ // Write to temporary file first
+ tmpPath := configPath + ".tmp"
+ if err := os.WriteFile(tmpPath, content, 0666); err != nil {
return &AppError{
Type: ErrSystem,
Op: "write temporary file",
@@ -239,25 +276,60 @@ func safeWriteFile(path string, data []byte, perm os.FileMode) error {
}
}
- if err := os.Rename(tmpPath, path); err != nil {
+ // Ensure proper permissions on temporary file
+ if err := os.Chmod(tmpPath, 0444); err != nil {
+ os.Remove(tmpPath)
+ return &AppError{
+ Type: ErrSystem,
+ Op: "set temporary file permissions",
+ Path: tmpPath,
+ Err: err,
+ }
+ }
+
+ // Atomic rename
+ if err := os.Rename(tmpPath, configPath); err != nil {
os.Remove(tmpPath)
return &AppError{
Type: ErrSystem,
Op: "rename file",
- Path: path,
+ Path: configPath,
Err: err,
}
}
+ // Sync the directory to ensure changes are written to disk
+ if dir, err := os.Open(filepath.Dir(configPath)); err == nil {
+ dir.Sync()
+ dir.Close()
+ }
+
return nil
}
-func setFilePermissions(filePath string) error {
- return os.Chmod(filePath, 0444)
-}
+func readExistingConfig() (*StorageConfig, error) {
+ configPath, err := getConfigPath()
+ if err != nil {
+ return nil, err
+ }
-// Process management functions
+ data, err := os.ReadFile(configPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil, nil
+ }
+ return nil, err
+ }
+
+ var config StorageConfig
+ if err := json.Unmarshal(data, &config); err != nil {
+ return nil, err
+ }
+ return &config, nil
+}
+
+// Process Management / 进程管理
type ProcessManager struct {
config *SystemConfig
}
@@ -288,6 +360,36 @@ func (pm *ProcessManager) killProcess(ctx context.Context) error {
return pm.killUnixProcess(ctx)
}
+func (pm *ProcessManager) killWindowsProcess(ctx context.Context) error {
+ exec.CommandContext(ctx, "taskkill", "/IM", "Cursor.exe").Run()
+ time.Sleep(pm.config.RetryDelay)
+ exec.CommandContext(ctx, "taskkill", "/F", "/IM", "Cursor.exe").Run()
+ return nil
+}
+
+func (pm *ProcessManager) killUnixProcess(ctx context.Context) error {
+ // First try graceful termination
+ if err := exec.CommandContext(ctx, "pkill", "-TERM", "-f", "Cursor").Run(); err == nil {
+ // Wait for processes to terminate gracefully
+ time.Sleep(2 * time.Second)
+ }
+
+ // Force kill if still running
+ if err := exec.CommandContext(ctx, "pkill", "-KILL", "-f", "Cursor").Run(); err == nil {
+ time.Sleep(1 * time.Second)
+ }
+
+ // Also try lowercase variant
+ exec.CommandContext(ctx, "pkill", "-KILL", "-f", "cursor").Run()
+
+ // Verify no processes are left
+ if output, err := exec.CommandContext(ctx, "pgrep", "-f", "Cursor").Output(); err == nil && len(output) > 0 {
+ return errors.New("cursor processes still running after kill attempts")
+ }
+
+ return nil
+}
+
func checkCursorRunning() bool {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
@@ -300,67 +402,64 @@ func checkCursorRunning() bool {
return strings.Contains(string(output), "Cursor") || strings.Contains(string(output), "cursor")
}
-// UI and display functions
-
-func clearScreen() {
- var cmd *exec.Cmd
- if runtime.GOOS == "windows" {
- cmd = exec.Command("cmd", "/c", "cls")
- } else {
- cmd = exec.Command("clear")
- }
- cmd.Stdout = os.Stdout
- cmd.Run()
+// UI Components / UI组件
+type UI struct {
+ config *UIConfig
+ spinner *ProgressSpinner
}
-func showProgress(message string) {
- spinner := NewProgressSpinner(message)
- for i := 0; i < 15; i++ {
- spinner.Spin()
- time.Sleep(100 * time.Millisecond)
+func NewUI(config *UIConfig) *UI {
+ return &UI{
+ config: config,
+ spinner: NewProgressSpinner(""),
}
- spinner.Stop()
}
-func printCyberpunkBanner() {
- cyan := color.New(color.FgCyan, color.Bold)
- yellow := color.New(color.FgYellow, color.Bold)
- magenta := color.New(color.FgMagenta, color.Bold)
- green := color.New(color.FgGreen, color.Bold)
-
- banner := `
- ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗
- ██╔════╝██║ ██║██╔══██╗██╔════╝█╔═══██╗██╔══██╗
- ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝
- ██║ ██║ ██║██╔══██╗╚════██ ██║ ██║██╔══██╗
- ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║
- ╚════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚════╝ ╚═╝ ╚═╝
- `
- cyan.Println(banner)
- yellow.Println("\t\t>> Cursor ID Modifier v1.0 <<")
- magenta.Println("\t\t [ By Pancake Fruit Rolled Shark Chili ]")
-
- langText := "当前语言/Language: "
- if currentLanguage == CN {
- langText += "简体中文"
- } else {
- langText += "English"
+func (ui *UI) showProgress(message string) {
+ ui.spinner.message = message
+ ui.spinner.Start()
+ defer ui.spinner.Stop()
+
+ ticker := time.NewTicker(ui.config.Spinner.Delay)
+ defer ticker.Stop()
+
+ for i := 0; i < 15; i++ {
+ <-ticker.C
+ ui.spinner.Spin()
}
- green.Printf("\n\t\t %s\n\n", langText)
}
+// Display Functions / 显示函数
func showSuccess() {
text := texts[currentLanguage]
successColor := color.New(color.FgGreen, color.Bold)
warningColor := color.New(color.FgYellow, color.Bold)
pathColor := color.New(color.FgCyan)
- successColor.Printf("\n%s\n", text.SuccessMessage)
- warningColor.Printf("%s\n", text.RestartMessage)
+ // Clear any previous output
+ fmt.Println()
+
+ if currentLanguage == EN {
+ // English messages with extra spacing
+ successColor.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ successColor.Printf("%s\n", text.SuccessMessage)
+ fmt.Println()
+ warningColor.Printf("%s\n", text.RestartMessage)
+ successColor.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ } else {
+ // Chinese messages with extra spacing
+ successColor.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ successColor.Printf("%s\n", text.SuccessMessage)
+ fmt.Println()
+ warningColor.Printf("%s\n", text.RestartMessage)
+ successColor.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ }
- // 获取并输出配置文件路径
+ // Add spacing before config location
+ fmt.Println()
+
if configPath, err := getConfigPath(); err == nil {
- pathColor.Printf("\n配置文件位置/Config file location:\n%s\n", configPath)
+ pathColor.Printf("%s\n%s\n", text.ConfigLocation, configPath)
}
}
@@ -369,116 +468,24 @@ func showPrivilegeError() {
red := color.New(color.FgRed, color.Bold)
yellow := color.New(color.FgYellow)
- red.Println(text.PrivilegeError)
- if runtime.GOOS == "windows" {
- yellow.Println(text.RunAsAdmin)
- } else {
- yellow.Println(text.RunWithSudo)
- yellow.Printf(text.SudoExample, os.Args[0])
- }
-}
-
-func showIdComparison(oldConfig *StorageConfig, newConfig *StorageConfig) {
- cyan := color.New(color.FgCyan)
- yellow := color.New(color.FgYellow)
-
- fmt.Println("\n=== ID Modification Comparison / ID 修改对比 ===")
-
- if oldConfig != nil {
- cyan.Println("\n[Original IDs / 原始 ID]")
- yellow.Printf("Machine ID: %s\n", oldConfig.TelemetryMachineId)
- yellow.Printf("Mac Machine ID: %s\n", oldConfig.TelemetryMacMachineId)
- yellow.Printf("Dev Device ID: %s\n", oldConfig.TelemetryDevDeviceId)
- }
-
- cyan.Println("\n[Newly Generated IDs / 新生成 ID]")
- yellow.Printf("Machine ID: %s\n", newConfig.TelemetryMachineId)
- yellow.Printf("Mac Machine ID: %s\n", newConfig.TelemetryMacMachineId)
- yellow.Printf("Dev Device ID: %s\n", newConfig.TelemetryDevDeviceId)
- fmt.Println()
-}
-
-// Configuration operations
-
-func saveConfig(config *StorageConfig) error {
- configPath, err := getConfigPath()
- if err != nil {
- return err
- }
-
- content, err := json.MarshalIndent(config, "", " ")
- if err != nil {
- return &AppError{
- Type: ErrSystem,
- Op: "generate JSON",
- Path: "",
- Err: err,
+ if currentLanguage == EN {
+ red.Println(text.PrivilegeError)
+ if runtime.GOOS == "windows" {
+ yellow.Println(text.RunAsAdmin)
+ } else {
+ yellow.Printf("%s\n%s\n", text.RunWithSudo, fmt.Sprintf(text.SudoExample, os.Args[0]))
}
- }
-
- if err := os.Chmod(configPath, 0666); err != nil && !os.IsNotExist(err) {
- return &AppError{
- Type: ErrSystem,
- Op: "modify file permissions",
- Path: configPath,
- Err: err,
- }
- }
-
- if err := safeWriteFile(configPath, content, 0666); err != nil {
- return err
- }
-
- return setFilePermissions(configPath)
-}
-
-func readExistingConfig() (*StorageConfig, error) {
- configPath, err := getConfigPath()
- if err != nil {
- return nil, err
- }
-
- data, err := os.ReadFile(configPath)
- if err != nil {
- if os.IsNotExist(err) {
- return nil, nil
- }
- return nil, err
- }
-
- var config StorageConfig
- if err := json.Unmarshal(data, &config); err != nil {
- return nil, err
- }
-
- return &config, nil
-}
-
-func loadAndUpdateConfig(ui *UI) (*StorageConfig, error) {
- configPath, err := getConfigPath()
- if err != nil {
- return nil, err
- }
-
- text := texts[currentLanguage]
- ui.showProgress(text.ReadingConfig)
-
- _, err = os.ReadFile(configPath)
- if err != nil && !os.IsNotExist(err) {
- return nil, &AppError{
- Type: ErrSystem,
- Op: "read config file",
- Path: configPath,
- Err: err,
+ } else {
+ red.Printf("\n%s\n", text.PrivilegeError)
+ if runtime.GOOS == "windows" {
+ yellow.Printf("%s\n", text.RunAsAdmin)
+ } else {
+ yellow.Printf("%s\n%s\n", text.RunWithSudo, fmt.Sprintf(text.SudoExample, os.Args[0]))
}
}
-
- showProgress(text.GeneratingIds)
- return NewStorageConfig(), nil
}
-// System privilege functions
-
+// System Functions / 系统函数
func checkAdminPrivileges() (bool, error) {
switch runtime.GOOS {
case "windows":
@@ -502,10 +509,8 @@ func checkAdminPrivileges() (bool, error) {
}
}
-// Utility functions
-
func detectLanguage() Language {
- // 1. 首先检查常用的语言环境变量
+ // Check common environment variables
for _, envVar := range []string{"LANG", "LANGUAGE", "LC_ALL"} {
if lang := os.Getenv(envVar); lang != "" {
if strings.Contains(strings.ToLower(lang), "zh") {
@@ -514,9 +519,8 @@ func detectLanguage() Language {
}
}
- // 2. Windows 特定的语言检查
+ // Windows-specific language check
if runtime.GOOS == "windows" {
- // 检查 Windows 用户默认语言设置
cmd := exec.Command("powershell", "-Command",
"[System.Globalization.CultureInfo]::CurrentUICulture.Name")
output, err := cmd.Output()
@@ -527,18 +531,15 @@ func detectLanguage() Language {
}
}
- // 检查 Windows 系统区域设置
+ // Check Windows locale
cmd = exec.Command("wmic", "os", "get", "locale")
output, err = cmd.Output()
- if err == nil {
- // Windows 语言代码 2052 表示简体中文
- if strings.Contains(string(output), "2052") {
- return CN
- }
+ if err == nil && strings.Contains(string(output), "2052") {
+ return CN
}
}
- // 3. 检查 Unix 系统的其他语言配置
+ // Check Unix locale
if runtime.GOOS != "windows" {
cmd := exec.Command("locale")
output, err := cmd.Output()
@@ -547,17 +548,45 @@ func detectLanguage() Language {
}
}
- // 默认返回英文
return EN
}
-func waitExit() {
- fmt.Println("\nPress Enter to exit... / 按回车键退出程序...")
- os.Stdout.Sync()
- bufio.NewReader(os.Stdin).ReadString('\n')
+func selfElevate() error {
+ switch runtime.GOOS {
+ case "windows":
+ // Set automated mode for the elevated process
+ os.Setenv("AUTOMATED_MODE", "1")
+
+ verb := "runas"
+ exe, _ := os.Executable()
+ cwd, _ := os.Getwd()
+ args := strings.Join(os.Args[1:], " ")
+
+ cmd := exec.Command("cmd", "/C", "start", verb, exe, args)
+ cmd.Dir = cwd
+ return cmd.Run()
+
+ case "darwin", "linux":
+ // Set automated mode for the elevated process
+ os.Setenv("AUTOMATED_MODE", "1")
+
+ exe, err := os.Executable()
+ if err != nil {
+ return err
+ }
+
+ cmd := exec.Command("sudo", append([]string{exe}, os.Args[1:]...)...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+
+ default:
+ return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
+ }
}
-// 错误处理函数
+// Utility Functions / 实用函数
func handleError(err error) {
if err == nil {
return
@@ -576,10 +605,24 @@ func handleError(err error) {
}
}
-// Main program entry
+func waitExit() {
+ // Skip waiting in automated mode
+ if os.Getenv("AUTOMATED_MODE") == "1" {
+ return
+ }
+
+ if currentLanguage == EN {
+ fmt.Println("\nPress Enter to exit...")
+ } else {
+ fmt.Println("\n按回车键退出程序...")
+ }
+ os.Stdout.Sync()
+ bufio.NewReader(os.Stdin).ReadString('\n')
+}
+// Main Function / 主函数
func main() {
- // 初始化错误恢复
+ // Initialize error recovery
defer func() {
if r := recover(); r != nil {
log.Printf("Panic recovered: %v\n", r)
@@ -588,14 +631,11 @@ func main() {
}
}()
- // 始化配置
+ // Initialize configuration
config := initConfig()
-
- // 初始化组件
ui := NewUI(&config.UI)
-
- // 权限检查
+ // Check privileges
os.Stdout.Sync()
currentLanguage = detectLanguage()
log.Println("Current language: ", currentLanguage)
@@ -607,7 +647,11 @@ func main() {
}
if !isAdmin && runtime.GOOS == "windows" {
- fmt.Println("Requesting administrator privileges... / 请求管理员权限...")
+ if currentLanguage == EN {
+ fmt.Println("\nRequesting administrator privileges...")
+ } else {
+ fmt.Println("\n请求管理员权限...")
+ }
if err := selfElevate(); err != nil {
handleError(err)
showPrivilegeError()
@@ -621,7 +665,7 @@ func main() {
return
}
- // 进程管理
+ // Process management
pm := &ProcessManager{
config: &SystemConfig{
RetryAttempts: 3,
@@ -630,34 +674,44 @@ func main() {
},
}
if checkCursorRunning() {
- fmt.Println("\nDetected running Cursor instance(s). Closing... / 检测到正在运行的 Cursor 实例,正在关闭...")
+ if currentLanguage == EN {
+ fmt.Println("\nDetected running Cursor instance(s). Closing...")
+ } else {
+ fmt.Println("\n检测到正在运行的 Cursor 实例,正在关闭...")
+ }
+
if err := pm.killCursorProcesses(); err != nil {
- fmt.Println("Warning: Could not close all Cursor instances. Please close them manually. / 警告:无法关闭所有 Cursor 实例,请手动关闭。")
+ if currentLanguage == EN {
+ fmt.Println("Warning: Could not close all Cursor instances. Please close them manually.")
+ } else {
+ fmt.Println("警告:无法关闭所有 Cursor 实例,请手动关闭。")
+ }
waitExit()
return
}
time.Sleep(2 * time.Second)
if checkCursorRunning() {
- fmt.Println("\nWarning: Cursor is still running. Please close it manually. / 警告:Cursor 仍在运行,请手动关闭。")
+ if currentLanguage == EN {
+ fmt.Println("\nWarning: Cursor is still running. Please close it manually.")
+ } else {
+ fmt.Println("\n警告:Cursor 仍在运行,请手动关闭。")
+ }
waitExit()
return
}
}
- // 清屏并打印标题
+ // Clear screen and show banner
clearScreen()
-
- // 打印标题
printCyberpunkBanner()
- // 读取现有配置
+ // Read and update configuration
oldConfig, err := readExistingConfig()
if err != nil {
oldConfig = nil
}
- // 加载并更新配置
storageConfig, err := loadAndUpdateConfig(ui)
if err != nil {
handleError(err)
@@ -665,132 +719,133 @@ func main() {
return
}
- // 显示ID修改对比
+ // Show changes and save
showIdComparison(oldConfig, storageConfig)
- // 保存配置
if err := saveConfig(storageConfig); err != nil {
handleError(err)
waitExit()
return
}
- // 显示成功信息
+ // Show success and exit
showSuccess()
- fmt.Println("\nOperation completed! / 操作完成!")
+ if currentLanguage == EN {
+ fmt.Println("\nOperation completed!")
+ } else {
+ fmt.Println("\n操作完成!")
+ }
+
+ // Check if running in automated mode
+ if os.Getenv("AUTOMATED_MODE") == "1" {
+ return
+ }
+
waitExit()
}
-// 优化配置结构
-type Config struct {
- Storage StorageConfig
- UI UIConfig
- System SystemConfig
+// Progress spinner functions / 进度条函数
+func NewProgressSpinner(message string) *ProgressSpinner {
+ return &ProgressSpinner{
+ frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
+ message: message,
+ }
}
-type UIConfig struct {
- Language Language
- Theme string
- Spinner SpinnerConfig
+func (s *ProgressSpinner) Spin() {
+ frame := s.frames[s.current%len(s.frames)]
+ s.current++
+ fmt.Printf("\r%s %s", color.CyanString(frame), s.message)
}
-type SystemConfig struct {
- RetryAttempts int
- RetryDelay time.Duration
- Timeout time.Duration
+func (s *ProgressSpinner) Stop() {
+ fmt.Println()
}
-// 配置初始化函数
-func initConfig() *Config {
- return &Config{
- Storage: StorageConfig{
- Version: Version,
- },
- UI: UIConfig{
- Language: detectLanguage(),
- Theme: "default",
- Spinner: SpinnerConfig{
- Frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
- Delay: 100 * time.Millisecond,
- },
- },
- System: SystemConfig{
- RetryAttempts: 3,
- RetryDelay: time.Second,
- Timeout: 30 * time.Second,
- },
- }
+func (s *ProgressSpinner) Start() {
+ s.current = 0
}
-// UI 组件
-type UI struct {
- config *UIConfig
- spinner *ProgressSpinner
+// Display utility functions / 显示工具函数
+func clearScreen() {
+ var cmd *exec.Cmd
+ if runtime.GOOS == "windows" {
+ cmd = exec.Command("cmd", "/c", "cls")
+ } else {
+ cmd = exec.Command("clear")
+ }
+ cmd.Stdout = os.Stdout
+ cmd.Run()
}
-func NewUI(config *UIConfig) *UI {
- return &UI{
- config: config,
- spinner: NewProgressSpinner(""),
+func printCyberpunkBanner() {
+ cyan := color.New(color.FgCyan, color.Bold)
+ yellow := color.New(color.FgYellow, color.Bold)
+ magenta := color.New(color.FgMagenta, color.Bold)
+ green := color.New(color.FgGreen, color.Bold)
+
+ banner := `
+ ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗
+ ██╔════╝██║ ██║██╔══██╗██╔════╝█╔═══██╗██╔══██╗
+ ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝
+ ██║ ██║ ██║██╔══██╗╚════██ ██║ ██║██╔══██╗
+ ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║
+ ╚════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚════╝ ╚═╝ ╚═╝
+ `
+ cyan.Println(banner)
+ yellow.Println("\t\t>> Cursor ID Modifier v1.0 <<")
+ magenta.Println("\t\t [ By Pancake Fruit Rolled Shark Chili ]")
+
+ langText := "当前语言/Language: "
+ if currentLanguage == CN {
+ langText += "简体中文"
+ } else {
+ langText += "English"
}
+ green.Printf("\n\t\t %s\n\n", langText)
}
-func (ui *UI) showProgress(message string) {
- ui.spinner.message = message
- ui.spinner.Start()
- defer ui.spinner.Stop()
-
- ticker := time.NewTicker(ui.config.Spinner.Delay)
- defer ticker.Stop()
-
- for i := 0; i < 15; i++ {
- <-ticker.C
- ui.spinner.Spin()
+func showIdComparison(oldConfig *StorageConfig, newConfig *StorageConfig) {
+ cyan := color.New(color.FgCyan)
+ yellow := color.New(color.FgYellow)
+
+ fmt.Println("\n=== ID Modification Comparison / ID 修改对比 ===")
+
+ if oldConfig != nil {
+ cyan.Println("\n[Original IDs / 原始 ID]")
+ yellow.Printf("Machine ID: %s\n", oldConfig.TelemetryMachineId)
+ yellow.Printf("Mac Machine ID: %s\n", oldConfig.TelemetryMacMachineId)
+ yellow.Printf("Dev Device ID: %s\n", oldConfig.TelemetryDevDeviceId)
}
-}
-func (pm *ProcessManager) killWindowsProcess(ctx context.Context) error {
- // 使用 taskkill 命令结束进程
- exec.CommandContext(ctx, "taskkill", "/IM", "Cursor.exe").Run()
- time.Sleep(pm.config.RetryDelay)
- exec.CommandContext(ctx, "taskkill", "/F", "/IM", "Cursor.exe").Run()
- return nil
+ cyan.Println("\n[Newly Generated IDs / 新生成 ID]")
+ yellow.Printf("Machine ID: %s\n", newConfig.TelemetryMachineId)
+ yellow.Printf("Mac Machine ID: %s\n", newConfig.TelemetryMacMachineId)
+ yellow.Printf("Dev Device ID: %s\n", newConfig.TelemetryDevDeviceId)
+ fmt.Println()
}
-func (pm *ProcessManager) killUnixProcess(ctx context.Context) error {
- exec.CommandContext(ctx, "pkill", "-f", "Cursor").Run()
- exec.CommandContext(ctx, "pkill", "-f", "cursor").Run()
- return nil
-}
+// Configuration functions / 配置函数
+func loadAndUpdateConfig(ui *UI) (*StorageConfig, error) {
+ configPath, err := getConfigPath()
+ if err != nil {
+ return nil, err
+ }
-func selfElevate() error {
- switch runtime.GOOS {
- case "windows":
- // 使用 cmd 实现 Windows 下的提权
- verb := "runas"
- exe, _ := os.Executable()
- cwd, _ := os.Getwd()
- args := strings.Join(os.Args[1:], " ")
-
- cmd := exec.Command("cmd", "/C", "start", verb, exe, args)
- cmd.Dir = cwd
- return cmd.Run()
-
- case "darwin", "linux":
- // Unix 系统使用 sudo
- exe, err := os.Executable()
- if err != nil {
- return err
+ text := texts[currentLanguage]
+ ui.showProgress(text.ReadingConfig)
+
+ _, err = os.ReadFile(configPath)
+ if err != nil && !os.IsNotExist(err) {
+ return nil, &AppError{
+ Type: ErrSystem,
+ Op: "read config file",
+ Path: configPath,
+ Err: err,
}
-
- cmd := exec.Command("sudo", append([]string{exe}, os.Args[1:]...)...)
- cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- return cmd.Run()
-
- default:
- return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
+
+ ui.showProgress(text.GeneratingIds)
+ return NewStorageConfig(), nil
}
|