The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitignore
├── Cargo.toml
├── Domain Address.txt
├── LICENSE
├── README.md
├── example.py
├── mac.png
├── reset_machine.rs
└── win.png


/.gitignore:
--------------------------------------------------------------------------------
 1 | # Generated by Cargo
 2 | # will have compiled files and executables
 3 | debug/
 4 | target/
 5 | 
 6 | # These are backup files generated by rustfmt
 7 | **/*.rs.bk
 8 | 
 9 | # MSVC Windows builds of rustc generate these, which store debugging information
10 | *.pdb
11 | 
12 | # RustRover
13 | #  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
14 | #  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
15 | #  and can be added to the global gitignore or merged into this file.  For a more nuclear
16 | #  option (not recommended) you can uncomment the following to ignore the entire idea folder.
17 | #.idea/


--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
 1 | [package]
 2 | name = "cursor_reset_tool"
 3 | version = "0.1.0"
 4 | edition = "2021"
 5 | 
 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 7 | 
 8 | [dependencies]
 9 | serde = { version = "1.0", features = ["derive"] }
10 | serde_json = "1.0"
11 | uuid = { version = "1.6", features = ["v4", "serde"] }
12 | colored = "2.0"
13 | sysinfo = "0.30"
14 | rand = "0.8"
15 | chrono = "0.4"
16 | is_elevated = "0.1.2" # For checking admin privileges
17 | directories = "5.0" # For APPDATA, LOCALAPPDATA paths
18 | [target.'cfg(windows)'.dependencies]
19 | winreg = "0.52"


--------------------------------------------------------------------------------
/Domain Address.txt:
--------------------------------------------------------------------------------
1 | 如果有能力请支持官方cursor的正版Pro会员,它是一个很不错的编辑器,为了避免影响cursor官方正常权益,不再提供新的域名
2 | 
3 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2025 agentcodee
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # Cursor 免费助手
 2 | 
 3 | ## 简介
 4 | 
 5 | 完全免费的 Cursor 助手工具,提供以下功能:
 6 | - 一键获取新额度
 7 | - 自动满额度账号
 8 | 
 9 | ## 加入QQ群获取最新下载,交流学习
10 | <img src="https://github.com/user-attachments/assets/29496235-54c8-4f24-aa54-6cc1d1a77f6f" width="240" alt="QQ群二维码">
11 | 
12 | ### 支持 Windows、Mac系统
13 | 
14 | ## 声明
15 | 
16 | 本项目仅供学习交流使用,请勿用于商业用途。
17 | 
18 | 本项目不承担任何法律责任,使用本项目造成的任何后果,由使用者自行承担。
19 | 
20 | ## 特别鸣谢
21 | 
22 | 本项目的开发过程中得到了众多大佬和社区成员的支持与帮助,在此特别感谢。
23 | 


--------------------------------------------------------------------------------
/example.py:
--------------------------------------------------------------------------------
  1 | #!/usr/bin/env python3
  2 | # -*- coding: utf-8 -*-
  3 | 
  4 | import sys
  5 | import time
  6 | import requests
  7 | from urllib.parse import quote
  8 | 
  9 | def get_verification_code(server_url, email, retry_interval=3):
 10 |     """
 11 |     从网站获取指定邮箱的验证码
 12 |     
 13 |     参数:
 14 |         server_url: 网站URL,例如 "cjrom2ero@portaltrendsarena.com"
 15 |         email: 完整的邮箱地址
 16 |         retry_interval: 重试间隔(秒)
 17 |         
 18 |     返回:
 19 |         成功返回验证码字符串,失败返回None
 20 |     """
 21 |     # URL编码邮箱地址
 22 |     encoded_email = quote(email)
 23 |     api_url = f"{server_url}/get_code?email={encoded_email}"
 24 |     
 25 |     print(f"开始获取邮箱 {email} 的验证码...")
 26 |     
 27 |     max_retries = 3  # 增加重试次数
 28 |     for attempt in range(max_retries):
 29 |         try:
 30 |             print(f"尝试 {attempt+1}/{max_retries}: 请求验证码...")
 31 |             response = requests.get(api_url, timeout=30)
 32 |             
 33 |             if response.status_code == 200:
 34 |                 data = response.json()
 35 |                 if data.get("success") and data.get("code"):
 36 |                     print(f"成功获取验证码: {data['code']}")
 37 |                     return data["code"]
 38 |                 else:
 39 |                     print(f"未找到验证码,响应: {data}")
 40 |             else:
 41 |                 print(f"请求失败,状态码: {response.status_code}")
 42 |                 
 43 |             # 如果不是最后一次尝试,等待后重试
 44 |             if attempt < max_retries - 1:
 45 |                 retry_wait = retry_interval * (attempt + 1)  # 递增等待时间
 46 |                 print(f"等待 {retry_wait} 秒后重试...")
 47 |                 time.sleep(retry_wait)
 48 |                 
 49 |         except Exception as e:
 50 |             print(f"请求出错: {e}")
 51 |             if attempt < max_retries - 1:
 52 |                 retry_wait = retry_interval * (attempt + 1)
 53 |                 print(f"等待 {retry_wait} 秒后重试...")
 54 |                 time.sleep(retry_wait)
 55 |     
 56 |     print("达到最大重试次数,获取验证码失败")
 57 |     return None
 58 | 
 59 | def check_server_health(server_url):
 60 |     try:
 61 |         response = requests.get(f"{server_url}/health", timeout=5)
 62 |         if response.status_code == 200:
 63 |             data = response.json()
 64 |             return True
 65 |         else:
 66 |             print(f"失败,状态码: {response.status_code}")
 67 |             return False
 68 |     except Exception as e:
 69 |         print(f"出错: {e}")
 70 |         return False
 71 | 
 72 | def main():
 73 |     """主函数"""
 74 |     # 设置默认值 这个不变
 75 |     server_url = "http://更换自己搭建的"
 76 |     # server_url = "http://127.0.0.1:5362"
 77 | 
 78 |     # 在项目中的txt提供了大量的域名,从里面随便选一个
 79 |     # 前缀可以使用一个10位数的随机数 数字小大写字母混合,@后缀不能随机
 80 |     email = "lordsem89@storetaikhoan.com" #这个要修改,硬编码了一个测试邮箱
 81 |     
 82 |     # 如果提供了命令行参数则使用命令行参数
 83 |     if len(sys.argv) >= 3:
 84 |         server_url = sys.argv[1].rstrip('/')
 85 |         email = sys.argv[2]
 86 |     else:
 87 |         print("未提供命令行参数,使用默认值:")
 88 |         print(f"网站URL: {server_url}")
 89 |         print(f"邮箱地址: {email}")
 90 |     
 91 |     # 检查网站健康状态
 92 |     if not check_server_health(server_url):
 93 |         print("网站健康检查失败,退出程序")
 94 |         return
 95 |     
 96 |     # 获取验证码
 97 |     code = get_verification_code(server_url, email)
 98 |     
 99 | 
100 | if __name__ == "__main__":
101 |     main() 
102 | 


--------------------------------------------------------------------------------
/mac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentcodee/cursor-free-everyday/88ae6bc0e24c6250d48ffe09f72727222e19ba7f/mac.png


--------------------------------------------------------------------------------
/reset_machine.rs:
--------------------------------------------------------------------------------
  1 | use colored::*;
  2 | use directories::{BaseDirs, UserDirs};
  3 | use is_elevated::is_elevated;
  4 | use serde::{Deserialize, Serialize};
  5 | use serde_json::Value;
  6 | use std::collections::HashMap;
  7 | use std::env;
  8 | use std::fs;
  9 | use std::io::{self, Write};
 10 | use std::path::{Path, PathBuf};
 11 | use std::process::{Command, Stdio};
 12 | use sysinfo::{System};
 13 | use uuid::Uuid;
 14 | use winreg::enums::*;
 15 | use winreg::RegKey;
 16 | use chrono::Local;
 17 | use rand::{thread_rng, Rng, distributions::Alphanumeric};
 18 | 
 19 | // Color definitions (approximated from PowerShell)
 20 | const RED: &str = "red";
 21 | const GREEN: &str = "green";
 22 | const YELLOW: &str = "yellow";
 23 | const BLUE: &str = "blue";
 24 | // const NC: &str = "clear"; // `colored` crate handles reset implicitly or via `.normal()`
 25 | 
 26 | // Max retries and wait time for process termination
 27 | const MAX_RETRIES: u32 = 5;
 28 | const WAIT_TIME_SECONDS: u64 = 1;
 29 | 
 30 | // Configuration file paths
 31 | fn get_storage_file_path() -> Option<PathBuf> {
 32 |     if let Some(base_dirs) = BaseDirs::new() {
 33 |         let app_data_dir = base_dirs.config_dir(); // Typically %APPDATA% or ~/.config
 34 |         Some(app_data_dir.join("Cursor").join("User").join("globalStorage").join("storage.json"))
 35 |     } else {
 36 |         None
 37 |     }
 38 | }
 39 | 
 40 | fn get_backup_dir_path() -> Option<PathBuf> {
 41 |     if let Some(base_dirs) = BaseDirs::new() {
 42 |         let app_data_dir = base_dirs.config_dir();
 43 |         Some(app_data_dir.join("Cursor").join("User").join("globalStorage").join("backups"))
 44 |     } else {
 45 |         None
 46 |     }
 47 | }
 48 | 
 49 | fn get_cursor_package_path() -> Option<PathBuf> {
 50 |     if let Some(user_dirs) = BaseDirs::new() {
 51 |         let local_app_data_dir = user_dirs.data_local_dir();
 52 |         let primary_path = local_app_data_dir.join("Programs").join("cursor").join("resources").join("app").join("package.json");
 53 |         if primary_path.exists() {
 54 |             return Some(primary_path);
 55 |         }
 56 |         let alt_path = local_app_data_dir.join("cursor").join("resources").join("app").join("package.json");
 57 |         if alt_path.exists() {
 58 |             return Some(alt_path);
 59 |         }
 60 |     }
 61 |     None
 62 | }
 63 | 
 64 | fn get_cursor_updater_path() -> Option<PathBuf> {
 65 |     if let Some(user_dirs) = BaseDirs::new() {
 66 |         let local_app_data_dir = user_dirs.data_local_dir();
 67 |         Some(local_app_data_dir.join("cursor-updater"))
 68 |     } else {
 69 |         None
 70 |     }
 71 | }
 72 | 
 73 | 
 74 | fn press_enter_to_exit(exit_code: i32) {
 75 |     print!("Press Enter to exit...");
 76 |     io::stdout().flush().unwrap();
 77 |     let mut buffer = String::new();
 78 |     io::stdin().read_line(&mut buffer).unwrap();
 79 |     std::process::exit(exit_code);
 80 | }
 81 | 
 82 | fn main() {
 83 |     // Set output encoding to UTF-8 (Rust strings are UTF-8 by default, console might need setup on Windows)
 84 |     // On Windows, `chcp 65001` might be needed in the terminal before running for full UTF-8 display.
 85 |     // The script itself cannot reliably change the parent console's encoding.
 86 | 
 87 |     // Check administrator privileges
 88 |     if !is_elevated() {
 89 |         println!("{}", "[ERROR] Please run this script as administrator".color(RED));
 90 |         println!("Right-click the executable and select 'Run as administrator'");
 91 |         press_enter_to_exit(1);
 92 |     }
 93 | 
 94 |     // Display Logo
 95 |     // Using simple print for now, can be enhanced
 96 |     Command::new("cmd").args(&["/c", "cls"]).status().unwrap(); // Clear screen on Windows
 97 | 
 98 |     println!("{}", r#"
 99 |     ██████╗██╗   ██╗██████╗ ███████╗ ██████╗ ██████╗ 
100 |    ██╔════╝██║   ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗
101 |    ██║     ██║   ██║██████╔╝███████╗██║   ██║██████╔╝
102 |    ██║     ██║   ██║██╔══██╗╚════██║██║   ██║██╔══██╗
103 |    ╚██████╗╚██████╔╝██║  ██║███████║╚██████╔╝██║  ██║
104 |     ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝  ╚═╝
105 | 
106 | "#.bright_cyan());
107 |     println!("{}", "================================".color(BLUE));
108 |     println!("   {}", "Cursor Device ID Modifier Tool".color(GREEN));
109 |     println!("  {}", "Cursor ID Reset Tool - Community Edition".color(YELLOW));
110 |     println!("  {}", "Free tool for Cursor device ID management".color(YELLOW));
111 |     println!("  {}", "[IMPORTANT] This is a free community tool".color(YELLOW));
112 |     println!("{}", "================================".color(BLUE));
113 |     println!("  {}", "QQ群: 951642519 (交流/下载纯免费自动账号切换工具)".color(YELLOW));
114 |     println!("");
115 | 
116 |     // Get and display Cursor version
117 |     let cursor_version = get_cursor_version();
118 |     match &cursor_version {
119 |         Some(version) => println!("{} Current Cursor version: v{}", "[INFO]".color(GREEN), version),
120 |         None => {
121 |             println!("{} Unable to detect Cursor version", "[WARNING]".color(YELLOW));
122 |             println!("{} Please ensure Cursor is properly installed", "[TIP]".color(YELLOW));
123 |         }
124 |     }
125 |     println!("");
126 | 
127 |     println!("{} Latest 0.45.x (supported)", "[IMPORTANT NOTE]".color(YELLOW));
128 |     println!("");
129 | 
130 |     // Check and close Cursor processes
131 |     println!("{} Checking Cursor processes...", "[INFO]".color(GREEN));
132 |     close_cursor_process("Cursor");
133 |     close_cursor_process("cursor");
134 |     println!("");
135 | 
136 |     let storage_file_path = match get_storage_file_path() {
137 |         Some(path) => path,
138 |         None => {
139 |             println!("{}", "[ERROR] Could not determine APPDATA path for storage file.".color(RED));
140 |             press_enter_to_exit(1);
141 |             unreachable!(); // press_enter_to_exit exits
142 |         }
143 |     };
144 |     // println!("Storage file path: {:?}", storage_file_path);
145 | 
146 |     let backup_dir_path = match get_backup_dir_path() {
147 |         Some(path) => path,
148 |         None => {
149 |             println!("{}", "[ERROR] Could not determine APPDATA path for backup directory.".color(RED));
150 |             press_enter_to_exit(1);
151 |             unreachable!();
152 |         }
153 |     };
154 |     // println!("Backup dir path: {:?}", backup_dir_path);
155 | 
156 |     // Create backup directory
157 |     if !backup_dir_path.exists() {
158 |         match fs::create_dir_all(&backup_dir_path) {
159 |             Ok(_) => println!("{} Created backup directory at {:?}", "[INFO]".color(GREEN), backup_dir_path),
160 |             Err(e) => {
161 |                 println!("{} Failed to create backup directory at {:?}: {}", "[ERROR]".color(RED), backup_dir_path, e);
162 |                 press_enter_to_exit(1);
163 |             }
164 |         }
165 |     }
166 | 
167 |     // Backup existing configuration
168 |     if storage_file_path.exists() {
169 |         println!("{} Backing up configuration file...", "[INFO]".color(GREEN));
170 |         let backup_name = format!("storage.json.backup_{}", Local::now().format("%Y%m%d_%H%M%S"));
171 |         let backup_file_path = backup_dir_path.join(backup_name);
172 |         match fs::copy(&storage_file_path, &backup_file_path) {
173 |             Ok(_) => println!("{} Configuration backed up to {:?}", "[INFO]".color(GREEN), backup_file_path),
174 |             Err(e) => {
175 |                 println!("{} Failed to backup configuration file to {:?}: {}", "[ERROR]".color(RED), backup_file_path, e);
176 |                 // Decide if this is a fatal error or a warning
177 |             }
178 |         }
179 |     } else {
180 |         println!("{} No existing configuration file found at {:?} to back up.", "[INFO]".color(GREEN), storage_file_path);
181 |     }
182 |     println!("");
183 | 
184 |     // Generate new IDs
185 |     println!("{} Generating new IDs...", "[INFO]".color(GREEN));
186 |     let mac_machine_id = new_standard_machine_id();
187 |     let uuid_str = Uuid::new_v4().to_string();
188 |     let prefix_hex = "auth0|user_".as_bytes().iter().map(|b| format!("{:02x}", b)).collect::<String>();
189 |     let random_part = get_random_hex(32);
190 |     let machine_id = format!("{}{}", prefix_hex, random_part);
191 |     let sqm_id = format!("{{{}}}", Uuid::new_v4().to_string().to_uppercase());
192 | 
193 |     // println!("Generated MAC_MACHINE_ID: {}", mac_machine_id);
194 |     // println!("Generated UUID_STR: {}", uuid_str);
195 |     // println!("Generated MACHINE_ID: {}", machine_id);
196 |     // println!("Generated SQM_ID: {}", sqm_id);
197 |     // println!("");
198 | 
199 |     // Update MachineGuid in registry
200 |     let mut machine_guid_updated = false;
201 |     if cfg!(target_os = "windows") { // Only run on Windows
202 |         machine_guid_updated = update_machine_guid(&backup_dir_path);
203 |     } else {
204 |         println!("{} Skipping MachineGuid update (not on Windows)", "[INFO]".color(YELLOW));
205 |     }
206 | 
207 |     // Create or update configuration file
208 |     println!("{} Updating configuration...", "[INFO]".color(GREEN));
209 |     let storage_update_successful = update_storage_file(
210 |         &storage_file_path,
211 |         &machine_id,
212 |         &mac_machine_id,
213 |         &uuid_str, // This was $UUID in PowerShell, which corresponds to devDeviceId
214 |         &sqm_id
215 |     );
216 | 
217 |     if storage_update_successful {
218 |         println!("{} Configuration updated successfully.", "[INFO]".color(GREEN));
219 |         // Display results
220 |         println!("");
221 |         println!("{} Configuration updated details:", "[INFO]".color(GREEN));
222 |         println!("{} machineId: {}", "[DEBUG]".color(BLUE), machine_id);
223 |         println!("{} macMachineId: {}", "[DEBUG]".color(BLUE), mac_machine_id);
224 |         println!("{} devDeviceId: {}", "[DEBUG]".color(BLUE), uuid_str);
225 |         println!("{} sqmId: {}", "[DEBUG]".color(BLUE), sqm_id);
226 |     } else {
227 |         println!("{} Main operation failed to update storage file.", "[ERROR]".color(RED));
228 |         // The PS script has an alternative method here, which is complex.
229 |         // For now, we'll just indicate failure.
230 |         press_enter_to_exit(1);
231 |     }
232 |     println!("");
233 | 
234 |     // Display file tree structure
235 |     println!("{} File structure:", "[INFO]".color(GREEN));
236 |     if let Some(user_dirs) = UserDirs::new() {
237 |         // %APPDATA%\Cursor\User is not directly available via UserDirs or BaseDirs in a cross-platform way for this specific structure.
238 |         // We'll construct it based on APPDATA which UserDirs doesn't directly give, BaseDirs::config_dir() is the closest.
239 |         if let Some(base_dirs) = BaseDirs::new() {
240 |              let app_data_dir_equivalent = base_dirs.config_dir(); // This is platform specific, e.g. %APPDATA% on Windows
241 |              println!("{}", app_data_dir_equivalent.join("Cursor").join("User").display().to_string().color(BLUE));
242 |         }
243 |     } else {
244 |         println!("{} Could not determine APPDATA path for display.", "[WARNING]".color(YELLOW));
245 |     }
246 |     println!("├── globalStorage");
247 |     println!("│   ├── storage.json (modified)");
248 |     println!("│   └── backups");
249 | 
250 |     // List backup files
251 |     match fs::read_dir(&backup_dir_path) {
252 |         Ok(entries) => {
253 |             let mut backup_files_found = false;
254 |             for entry in entries {
255 |                 if let Ok(entry) = entry {
256 |                     if entry.path().is_file() {
257 |                         println!("│       └── {}", entry.file_name().to_string_lossy());
258 |                         backup_files_found = true;
259 |                     }
260 |                 }
261 |             }
262 |             if !backup_files_found {
263 |                 println!("│       └── (empty)");
264 |             }
265 |         }
266 |         Err(e) => {
267 |             println!("│       └── (Error reading backups: {})", e);
268 |         }
269 |     }
270 |     println!("");
271 | 
272 |     // Display completion message
273 |     println!("{}", "================================".color(GREEN));
274 |     println!("  {}", "Cursor ID Reset Tool - Community Edition".color(YELLOW));
275 |     println!("{}", "================================".color(GREEN));
276 |     println!("");
277 |     println!("{} Please restart Cursor to apply new configuration", "[INFO]".color(GREEN));
278 |     println!("");
279 | 
280 |     press_enter_to_exit(0);
281 | }
282 | 
283 | fn get_random_hex(length: usize) -> String {
284 |     thread_rng()
285 |         .sample_iter(&Alphanumeric)
286 |         .take(length)
287 |         .map(char::from)
288 |         .collect::<String>()
289 |         .to_lowercase() // PowerShell version produces lowercase hex
290 | }
291 | 
292 | fn new_standard_machine_id() -> String {
293 |     // Template: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
294 |     // y is one of 8, 9, a, b
295 |     let mut rng = thread_rng();
296 |     let mut id = String::with_capacity(36);
297 |     for (i, char_template) in "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".chars().enumerate() {
298 |         if char_template == '-' || char_template == '4' {
299 |             id.push(char_template);
300 |         } else if char_template == 'x' {
301 |             id.push_str(&format!("{:x}", rng.gen_range(0..16)));
302 |         } else if char_template == 'y' {
303 |             id.push_str(&format!("{:x}", rng.gen_range(8..12))); // 8, 9, a, b
304 |         }
305 |     }
306 |     id
307 | }
308 | 
309 | #[derive(Deserialize)]
310 | struct PackageJson {
311 |     version: String,
312 | }
313 | 
314 | fn get_cursor_version() -> Option<String> {
315 |     if let Some(package_path) = get_cursor_package_path() {
316 |         if package_path.exists() {
317 |             match fs::read_to_string(&package_path) {
318 |                 Ok(contents) => match serde_json::from_str::<PackageJson>(&contents) {
319 |                     Ok(json) => Some(json.version),
320 |                     Err(e) => {
321 |                         println!("{} Failed to parse package.json: {}", "[ERROR]".color(RED), e);
322 |                         None
323 |                     }
324 |                 },
325 |                 Err(e) => {
326 |                     println!("{} Failed to read package.json at {:?}: {}", "[ERROR]".color(RED), package_path, e);
327 |                     None
328 |                 }
329 |             }
330 |         } else {
331 |             println!("{} package.json not found at {:?}", "[WARNING]".color(YELLOW), package_path);
332 |             None
333 |         }
334 |     } else {
335 |         println!("{} Could not determine path to Cursor's package.json", "[WARNING]".color(YELLOW));
336 |         None
337 |     }
338 | }
339 | 
340 | fn close_cursor_process(process_name: &str) {
341 |     let mut sys = System::new_all();
342 |     sys.refresh_processes();
343 | 
344 |     let processes_to_kill: Vec<_> = sys
345 |         .processes()
346 |         .values()
347 |         .filter(|p| p.name().eq_ignore_ascii_case(process_name))
348 |         .collect();
349 | 
350 |     if !processes_to_kill.is_empty() {
351 |         println!("{} Found {} running", "[WARNING]".color(YELLOW), process_name);
352 |         for p in &processes_to_kill {
353 |             println!("  PID: {}, Name: {}, Path: {:?}", p.pid(), p.name(), p.exe());
354 |         }
355 | 
356 |         println!("{} Attempting to close {}...", "[WARNING]".color(YELLOW), process_name);
357 |         for p in processes_to_kill {
358 |             if !p.kill() { // kill() sends SIGKILL by default on Unix, TerminateProcess on Windows
359 |                 println!("{} Failed to send termination signal to {} (PID: {}). Trying to wait...", "[ERROR]".color(RED), process_name, p.pid());
360 |             }
361 |         }
362 | 
363 |         let mut retry_count = 0;
364 |         loop {
365 |             sys.refresh_processes();
366 |             let still_running: Vec<_> = sys
367 |                 .processes()
368 |                 .values()
369 |                 .filter(|p| p.name().eq_ignore_ascii_case(process_name))
370 |                 .collect();
371 | 
372 |             if still_running.is_empty() {
373 |                 break;
374 |             }
375 | 
376 |             retry_count += 1;
377 |             if retry_count >= MAX_RETRIES {
378 |                 println!("{} Unable to close {} after {} attempts", "[ERROR]".color(RED), process_name, MAX_RETRIES);
379 |                 for p in still_running {
380 |                      println!("  Still running - PID: {}, Name: {}, Path: {:?}", p.pid(), p.name(), p.exe());
381 |                 }
382 |                 println!("{} Please close the process manually and try again", "[ERROR]".color(RED));
383 |                 press_enter_to_exit(1);
384 |             }
385 | 
386 |             println!("{} Waiting for process to close, attempt {}/{}...", "[WARNING]".color(YELLOW), retry_count, MAX_RETRIES);
387 |             std::thread::sleep(std::time::Duration::from_secs(WAIT_TIME_SECONDS));
388 |         }
389 |         println!("{} {} successfully closed", "[INFO]".color(GREEN), process_name);
390 |     }
391 | }
392 | 
393 | #[cfg(target_os = "windows")]
394 | fn update_machine_guid(backup_dir: &Path) -> bool {
395 |     println!("{} Updating MachineGuid in registry...", "[INFO]".color(GREEN));
396 |     let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
397 |     let reg_path = "SOFTWARE\\Microsoft\\Cryptography";
398 |     let reg_key_name = "MachineGuid";
399 |     let full_reg_key_path_for_export = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography";
400 | 
401 |     let crypto_key = match hklm.open_subkey_with_flags(reg_path, KEY_READ | KEY_WRITE) {
402 |         Ok(key) => key,
403 |         Err(e) => {
404 |             println!("{} Failed to open registry key '{}': {}. Ensure you have admin rights.", "[ERROR]".color(RED), reg_path, e);
405 |             return false;
406 |         }
407 |     };
408 | 
409 |     let current_guid_val: Result<String, _> = crypto_key.get_value(reg_key_name);
410 |     let original_guid = match current_guid_val {
411 |         Ok(guid) => {
412 |             println!("{} Current registry value:", "[INFO]".color(GREEN));
413 |             println!("  {}", full_reg_key_path_for_export);
414 |             println!("    {}    REG_SZ    {}", reg_key_name, guid);
415 |             guid
416 |         }
417 |         Err(e) => {
418 |             println!("{} Unable to get current {}: {}. This might indicate a problem or the value might not exist.", "[ERROR]".color(RED), reg_key_name, e);
419 |             // Proceeding to set a new one if it doesn't exist, or fail if it's a permission issue.
420 |             String::new() // Or handle as a more critical error if needed.
421 |         }
422 |     };
423 | 
424 |     if !backup_dir.exists() {
425 |         if let Err(e) = fs::create_dir_all(backup_dir) {
426 |             println!("{} Failed to create backup directory for registry backup: {}. Proceeding without registry backup.", "[WARNING]".color(YELLOW), e);
427 |         }
428 |     }
429 | 
430 |     let backup_file_name = format!("MachineGuid_{}.reg", Local::now().format("%Y%m%d_%H%M%S"));
431 |     let backup_file_path = backup_dir.join(&backup_file_name);
432 |     let backup_command_str = format!("reg.exe export \"{}\" \"{}\" /y", full_reg_key_path_for_export, backup_file_path.display());
433 |     
434 |     println!("{} Attempting to backup registry key to: {:?}", "[INFO]".color(GREEN), backup_file_path);
435 |     match Command::new("cmd").args(&["/C", &backup_command_str]).status() {
436 |         Ok(status) if status.success() => {
437 |             println!("{} Registry key backed up successfully.", "[INFO]".color(GREEN));
438 |         }
439 |         Ok(status) => {
440 |             println!("{} Registry backup command finished with status: {}. Check permissions or if reg.exe is available.", "[WARNING]".color(YELLOW), status);
441 |         }
442 |         Err(e) => {
443 |             println!("{} Failed to execute registry backup command: {}. Proceeding with caution.", "[WARNING]".color(YELLOW), e);
444 |         }
445 |     }
446 | 
447 |     let new_guid = Uuid::new_v4().to_string();
448 |     match crypto_key.set_value(reg_key_name, &new_guid) {
449 |         Ok(_) => {
450 |             println!("{} Registry value {} set to: {}", "[INFO]".color(GREEN), reg_key_name, new_guid);
451 |             // Verification
452 |             let verify_guid: Result<String, _> = crypto_key.get_value(reg_key_name);
453 |             match verify_guid {
454 |                 Ok(val) if val == new_guid => {
455 |                     println!("{} Registry update verified successfully.", "[INFO]".color(GREEN));
456 |                     println!("  {}", full_reg_key_path_for_export);
457 |                     println!("    {}    REG_SZ    {}", reg_key_name, new_guid);
458 |                     true
459 |                 }
460 |                 Ok(val) => {
461 |                     println!("{} Registry verification failed: Updated value ({}) does not match expected value ({}).", "[ERROR]".color(RED), val, new_guid);
462 |                     // Attempt restore
463 |                     false // Placeholder for restore logic
464 |                 }
465 |                 Err(e) => {
466 |                     println!("{} Failed to verify registry update: {}.", "[ERROR]".color(RED), e);
467 |                     false // Placeholder for restore logic
468 |                 }
469 |             }
470 |         }
471 |         Err(e) => {
472 |             println!("{} Failed to set registry value {}: {}.", "[ERROR]".color(RED), reg_key_name, e);
473 |             // Attempt restore if original_guid was present and backup_file_path exists
474 |             if !original_guid.is_empty() && backup_file_path.exists() {
475 |                 println!("{} Attempting to restore registry from backup: {:?}", "[YELLOW]".color(YELLOW), backup_file_path);
476 |                 let restore_command_str = format!("reg.exe import \"{}\"", backup_file_path.display());
477 |                 match Command::new("cmd").args(&["/C", &restore_command_str]).status() {
478 |                     Ok(status) if status.success() => println!("{} Registry restored successfully from backup.", "[INFO]".color(GREEN)),
479 |                     Ok(status) => println!("{} Registry restore command failed with status: {}. Manual restore may be needed from {:?}", "[ERROR]".color(RED), status, backup_file_path),
480 |                     Err(re) => println!("{} Failed to execute registry restore command: {}. Manual restore needed from {:?}", "[ERROR]".color(RED), re, backup_file_path),
481 |                 }
482 |             }
483 |             false
484 |         }
485 |     }
486 | }
487 | 
488 | fn update_storage_file(
489 |     storage_file_path: &Path,
490 |     machine_id: &str,
491 |     mac_machine_id: &str,
492 |     dev_device_id: &str,
493 |     sqm_id: &str,
494 | ) -> bool {
495 |     if !storage_file_path.exists() {
496 |         println!("{} Configuration file not found: {:?}", "[ERROR]".color(RED), storage_file_path);
497 |         println!("{} Please install and run Cursor once before using this script", "[TIP]".color(YELLOW));
498 |         return false;
499 |     }
500 | 
501 |     let original_content = match fs::read_to_string(storage_file_path) {
502 |         Ok(content) => content,
503 |         Err(e) => {
504 |             println!("{} Failed to read configuration file {:?}: {}", "[ERROR]".color(RED), storage_file_path, e);
505 |             return false;
506 |         }
507 |     };
508 | 
509 |     let mut config: Value = match serde_json::from_str(&original_content) {
510 |         Ok(json_value) => json_value,
511 |         Err(e) => {
512 |             println!("{} Failed to parse configuration file JSON: {}", "[ERROR]".color(RED), e);
513 |             // Attempt to restore original content is not applicable here as we haven't written yet
514 |             return false;
515 |         }
516 |     };
517 | 
518 |     // Ensure the path to telemetry values exists or create it
519 |     // serde_json::Value uses `pointer_mut` for this kind of access.
520 |     // Example: /telemetry/machineId
521 |     // We need to ensure `config["telemetry"]` is an object.
522 |     if !config.get("telemetry").map_or(false, |v| v.is_object()) {
523 |         if config.as_object_mut().is_some() { // Check if config itself is an object
524 |             config["telemetry"] = serde_json::json!({});
525 |         } else {
526 |             println!("{} Configuration root is not a JSON object. Cannot set telemetry.", "[ERROR]".color(RED));
527 |             return false;
528 |         }
529 |     }
530 |     
531 |     // Update specific values
532 |     // Using .get_mut("telemetry") and then working with the resulting Option<&mut Value>
533 |     if let Some(telemetry) = config.get_mut("telemetry") {
534 |         if let Some(telemetry_obj) = telemetry.as_object_mut() {
535 |             telemetry_obj.insert("machineId".to_string(), Value::String(machine_id.to_string()));
536 |             telemetry_obj.insert("macMachineId".to_string(), Value::String(mac_machine_id.to_string()));
537 |             telemetry_obj.insert("devDeviceId".to_string(), Value::String(dev_device_id.to_string()));
538 |             telemetry_obj.insert("sqmId".to_string(), Value::String(sqm_id.to_string()));
539 |         } else {
540 |             println!("{} 'telemetry' field is not an object.", "[ERROR]".color(RED));
541 |             return false; // Or attempt to restore original_content
542 |         }
543 |     } else {
544 |         // This case should ideally be covered by the creation logic above.
545 |         println!("{} Failed to access or create 'telemetry' object.", "[ERROR]".color(RED));
546 |         return false; // Or attempt to restore original_content
547 |     }
548 |     
549 |     match serde_json::to_string_pretty(&config) { // Using pretty for readability, PowerShell does compact
550 |         Ok(updated_json) => {
551 |             match fs::write(storage_file_path, updated_json.as_bytes()) { // .as_bytes() for UTF-8
552 |                 Ok(_) => {
553 |                     println!("{} Configuration file updated successfully at {:?}", "[INFO]".color(GREEN), storage_file_path);
554 |                     true
555 |                 }
556 |                 Err(e) => {
557 |                     println!("{} Failed to write updated configuration to {:?}: {}", "[ERROR]".color(RED), storage_file_path, e);
558 |                     // Attempt to restore original content
559 |                     if fs::write(storage_file_path, original_content.as_bytes()).is_err() {
560 |                         println!("{} CRITICAL: Failed to restore original content to {:?} after write error.", "[ERROR]".color(RED), storage_file_path);
561 |                     }
562 |                     false
563 |                 }
564 |             }
565 |         }
566 |         Err(e) => {
567 |             println!("{} Failed to serialize updated configuration to JSON: {}", "[ERROR]".color(RED), e);
568 |             // Attempt to restore original content if we had changed it in memory (not the case here with direct write path)
569 |             // No need to restore file if serialization failed before writing.
570 |             false
571 |         }
572 |     }
573 | }
574 | 


--------------------------------------------------------------------------------
/win.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentcodee/cursor-free-everyday/88ae6bc0e24c6250d48ffe09f72727222e19ba7f/win.png


--------------------------------------------------------------------------------