diff --git a/account_manager.py b/account_manager.py index 4463154..966573b 100644 --- a/account_manager.py +++ b/account_manager.py @@ -6,6 +6,7 @@ import requests from typing import Dict, Optional from config import Config from logger import logging +import patch_cursor_get_machine_id class AccountManager: def __init__(self, api_base_url: str = None): @@ -69,6 +70,25 @@ class AccountManager: "Authorization": f"Bearer {self.api_token}" } + # 确保machine_id不为空 + machine_id = account_info.get("machine_id") + if not machine_id: + logging.warning("machine_id为空,尝试重新获取") + try: + # 先执行patch操作 + patch_cursor_get_machine_id.patch_cursor_get_machine_id() + + # 然后获取machine_id + pkg_path, _ = patch_cursor_get_machine_id.get_cursor_paths() + with open(pkg_path, "r", encoding="utf-8") as f: + pkg_data = json.load(f) + machine_id = pkg_data.get("machineId", "") + if machine_id: + logging.info(f"成功获取machine_id: {machine_id}") + except Exception as e: + logging.error(f"获取machine_id失败: {str(e)}") + machine_id = "" + # 准备请求数据 data = { "email": account_info["email"], @@ -77,7 +97,7 @@ class AccountManager: "last_name": account_info["last_name"], "access_token": account_info["access_token"], "refresh_token": account_info["refresh_token"], - "machine_id": account_info.get("machine_id", ""), + "machine_id": machine_id, "user_agent": account_info.get("user_agent", ""), "registration_time": datetime.fromisoformat(account_info["registration_time"]).strftime("%Y-%m-%d %H:%M:%S") } @@ -91,7 +111,7 @@ class AccountManager: ) response_data = response.json() - if response_data["code"] == 0: + if response_data["code"] == 0 and "添加成功" in response_data.get("msg", ""): logging.info(f"账号信息已同步到服务器: {account_info['email']}") return True elif response_data["code"] == 400: diff --git a/accounts.json b/accounts.json index 17bb7ce..a08f02e 100644 --- a/accounts.json +++ b/accounts.json @@ -71,6 +71,66 @@ "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", "registration_time": "2025-02-11T12:43:36.366349", "created_at": "2025-02-11T12:43:36.367348" + }, + { + "email": "updxuihl249936@nosqli.com", + "password": "565zgKZbqe7i", + "first_name": "Pvnoyo", + "last_name": "Zwisgk", + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUDI0UkVIQ1M2RkI1NlJOQjQwVkNYIiwidGltZSI6IjE3MzkyNTAwNTkiLCJyYW5kb21uZXNzIjoiYWI4NWQ4ZGEtNWRjOC00OGFjIiwiZXhwIjo0MzMxMjUwMDU5LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.HgDqpySIEFX-GwWhP-oVOGbHlkK5pjweN-RrTg_Xlck", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUDI0UkVIQ1M2RkI1NlJOQjQwVkNYIiwidGltZSI6IjE3MzkyNTAwNTkiLCJyYW5kb21uZXNzIjoiYWI4NWQ4ZGEtNWRjOC00OGFjIiwiZXhwIjo0MzMxMjUwMDU5LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.HgDqpySIEFX-GwWhP-oVOGbHlkK5pjweN-RrTg_Xlck", + "machine_id": "", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", + "registration_time": "2025-02-11T13:01:36.672278", + "created_at": "2025-02-11T13:01:36.672278" + }, + { + "email": "jrxqnsoz250264@nosqli.com", + "password": "q5^3wK$7EDSI", + "first_name": "Izklau", + "last_name": "Buaxxr", + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUEJLQlIxOTNKMjY3RENSVDRTR1YyIiwidGltZSI6IjE3MzkyNTAzNDgiLCJyYW5kb21uZXNzIjoiYWIyNWVhYTYtNDQzZC00Y2Q0IiwiZXhwIjo0MzMxMjUwMzQ4LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.f3VIttCJLWqhkEZpPmWJlYw32FuV_gLWl9E0N-O9oIc", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUEJLQlIxOTNKMjY3RENSVDRTR1YyIiwidGltZSI6IjE3MzkyNTAzNDgiLCJyYW5kb21uZXNzIjoiYWIyNWVhYTYtNDQzZC00Y2Q0IiwiZXhwIjo0MzMxMjUwMzQ4LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.f3VIttCJLWqhkEZpPmWJlYw32FuV_gLWl9E0N-O9oIc", + "machine_id": "", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", + "registration_time": "2025-02-11T13:06:24.503645", + "created_at": "2025-02-11T13:06:24.504644" + }, + { + "email": "geagvufj250945@nosqli.com", + "password": "*iBcNX@@Lc5r", + "first_name": "Txnrko", + "last_name": "Glkaro", + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUTBCQjRNWjFUSDFCNDRUODhZRTkyIiwidGltZSI6IjE3MzkyNTEwNDMiLCJyYW5kb21uZXNzIjoiYThhMjlhY2YtMmFhMy00Zjk4IiwiZXhwIjo0MzMxMjUxMDQzLCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.xtigV1ORDxmYvM37Ejj_bTwoRNwT_UFaepiNQiBT0wc", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUTBCQjRNWjFUSDFCNDRUODhZRTkyIiwidGltZSI6IjE3MzkyNTEwNDMiLCJyYW5kb21uZXNzIjoiYThhMjlhY2YtMmFhMy00Zjk4IiwiZXhwIjo0MzMxMjUxMDQzLCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.xtigV1ORDxmYvM37Ejj_bTwoRNwT_UFaepiNQiBT0wc", + "machine_id": "", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", + "registration_time": "2025-02-11T13:19:48.702686", + "created_at": "2025-02-11T13:19:48.702686" + }, + { + "email": "vuipeqkn251224@586vip.cn", + "password": "yb08AB@nnFk%", + "first_name": "Zyepdz", + "last_name": "Oexxrl", + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUThWVDY4UURRR01GQjBTTlEwOTBNIiwidGltZSI6IjE3MzkyNTEzMjciLCJyYW5kb21uZXNzIjoiZmU0YzQxNWEtYTQ0NC00YjFhIiwiZXhwIjo0MzMxMjUxMzI3LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.zq0Gn8ujbdKv-LETdRIxYc8aw5i4bAfmP-eY-mkRS64", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUThWVDY4UURRR01GQjBTTlEwOTBNIiwidGltZSI6IjE3MzkyNTEzMjciLCJyYW5kb21uZXNzIjoiZmU0YzQxNWEtYTQ0NC00YjFhIiwiZXhwIjo0MzMxMjUxMzI3LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.zq0Gn8ujbdKv-LETdRIxYc8aw5i4bAfmP-eY-mkRS64", + "machine_id": "", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", + "registration_time": "2025-02-11T13:24:29.297014", + "created_at": "2025-02-11T13:24:29.297014" + }, + { + "email": "xxugkslr251488@586vip.cn", + "password": "yb08AB@nnFk%", + "first_name": "Ttdkpi", + "last_name": "Lqevwq", + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUUc5Q0NWUDNZU0REVDEwQzBLS1FLIiwidGltZSI6IjE3MzkyNTE1NjciLCJyYW5kb21uZXNzIjoiNWQwYjY4YTgtYWNkZi00ZDc4IiwiZXhwIjo0MzMxMjUxNTY3LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.ypgfQ0aQu268HHhdFPTnHp7IHcSr1WQarxlCpgeErTI", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxSktTUUc5Q0NWUDNZU0REVDEwQzBLS1FLIiwidGltZSI6IjE3MzkyNTE1NjciLCJyYW5kb21uZXNzIjoiNWQwYjY4YTgtYWNkZi00ZDc4IiwiZXhwIjo0MzMxMjUxNTY3LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20ifQ.ypgfQ0aQu268HHhdFPTnHp7IHcSr1WQarxlCpgeErTI", + "machine_id": "", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36", + "registration_time": "2025-02-11T13:26:42.615884", + "created_at": "2025-02-11T13:26:42.615884" } ] } \ No newline at end of file diff --git a/interactive/icon/th (1).jpg b/interactive/icon/th (1).jpg new file mode 100644 index 0000000..4e7ddf8 Binary files /dev/null and b/interactive/icon/th (1).jpg differ diff --git a/interactive/icon/th (2).jpg b/interactive/icon/th (2).jpg new file mode 100644 index 0000000..3d836bf Binary files /dev/null and b/interactive/icon/th (2).jpg differ diff --git a/interactive/icon/th.jpg b/interactive/icon/th.jpg new file mode 100644 index 0000000..4729e70 Binary files /dev/null and b/interactive/icon/th.jpg differ diff --git a/interactive/icon/two.ico b/interactive/icon/two.ico new file mode 100644 index 0000000..fcd403e Binary files /dev/null and b/interactive/icon/two.ico differ diff --git a/interactive/main.py b/interactive/main.py new file mode 100644 index 0000000..236612f --- /dev/null +++ b/interactive/main.py @@ -0,0 +1,37 @@ +import logging +from pathlib import Path +from gui.main_window import MainWindow + +def setup_logging(): + """设置日志""" + log_dir = Path.home() / ".cursor_switcher" / "logs" + log_dir.mkdir(parents=True, exist_ok=True) + + log_file = log_dir / "switcher.log" + + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(levelname)s - %(message)s", + handlers=[ + logging.FileHandler(log_file, encoding="utf-8"), + logging.StreamHandler() + ] + ) + logging.info("日志系统初始化完成") + +def main(): + """主函数""" + try: + setup_logging() + logging.info("启动GUI界面...") + window = MainWindow() + window.run() + except KeyboardInterrupt: + logging.info("程序被用户中断") + except Exception as e: + logging.error(f"程序运行出错: {str(e)}") + finally: + logging.info("程序退出") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/interactive/requirements.txt b/interactive/requirements.txt new file mode 100644 index 0000000..34d8ed1 --- /dev/null +++ b/interactive/requirements.txt @@ -0,0 +1,2 @@ +requests==2.31.0 +pyinstaller==6.3.0 \ No newline at end of file diff --git a/interactive/utils/config.py b/interactive/utils/config.py new file mode 100644 index 0000000..f896cde --- /dev/null +++ b/interactive/utils/config.py @@ -0,0 +1,67 @@ +import os +import json +import logging +from pathlib import Path + +class Config: + def __init__(self): + self.api_base_url = "https://cursorapi.nosqli.com/admin" + self.config_dir = Path(os.path.expanduser("~")) / ".cursor_switcher" + self.config_file = self.config_dir / "config.json" + self.member_file = self.config_dir / "member.json" + self.load_config() + + def load_config(self): + """加载配置""" + try: + self.config_dir.mkdir(parents=True, exist_ok=True) + + if not self.config_file.exists(): + self.save_default_config() + + with open(self.config_file, "r", encoding="utf-8") as f: + config = json.load(f) + self.api_token = config.get("api_token", "") + + except Exception as e: + logging.error(f"加载配置失败: {str(e)}") + self.api_token = "" + + def save_member_info(self, info: dict): + """保存会员信息""" + try: + with open(self.member_file, "w", encoding="utf-8") as f: + json.dump(info, f, indent=2, ensure_ascii=False) + except Exception as e: + logging.error(f"保存会员信息失败: {str(e)}") + + def load_member_info(self) -> dict: + """读取会员信息""" + try: + if self.member_file.exists(): + with open(self.member_file, "r", encoding="utf-8") as f: + return json.load(f) + except Exception as e: + logging.error(f"读取会员信息失败: {str(e)}") + return { + "expire_time": "", + "days": 0, + "new_days": 0 + } + + def save_default_config(self): + """保存默认配置""" + config = { + "api_token": "" + } + with open(self.config_file, "w", encoding="utf-8") as f: + json.dump(config, f, indent=2, ensure_ascii=False) + + def save_config(self, api_token: str): + """保存新的配置""" + config = { + "api_token": api_token + } + with open(self.config_file, "w", encoding="utf-8") as f: + json.dump(config, f, indent=2, ensure_ascii=False) + self.api_token = api_token \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a81fc6b..405d04b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,5 @@ colorama==0.4.6 python-dotenv==1.0.0 pyinstaller playwright==1.41.1 -requests==2.31.0 \ No newline at end of file +requests>=2.31.0 +pytz>=2024.1 \ No newline at end of file diff --git a/test_api_response.py b/test_api_response.py new file mode 100644 index 0000000..efc65ea --- /dev/null +++ b/test_api_response.py @@ -0,0 +1,48 @@ +import requests +import json +from datetime import datetime + +def test_member_status(machine_id: str): + """测试会员状态接口""" + print(f"\n=== 测试会员状态 ===") + print(f"设备码: {machine_id}") + + try: + # 构造状态检查请求 + endpoint = "https://cursorapi.nosqli.com/admin/api.member/status" + data = { + "machine_id": machine_id + } + headers = { + "Content-Type": "application/json" + } + + print("\n发送请求...") + response = requests.post(endpoint, json=data, headers=headers, timeout=10) + print(f"状态码: {response.status_code}") + + print("\n响应数据:") + response_data = response.json() + print(json.dumps(response_data, indent=2, ensure_ascii=False)) + + if response_data.get("code") == 200: + data = response_data.get("data", {}) + print("\n解析后的信息:") + print(f"状态: {data.get('status', 'unknown')}") + print(f"到期时间: {data.get('expire_time', '')}") + print(f"剩余天数: {data.get('days_left', 0)}") + print(f"总天数: {data.get('total_days', 0)}") + + print("\n激活记录:") + for record in data.get("activation_records", []): + print(f"- 激活码: {record.get('code', '')}") + print(f" 激活时间: {record.get('activation_time', '')}") + print(f" 天数: {record.get('days', 0)}") + print() + + except Exception as e: + print(f"\n请求失败: {str(e)}") + +if __name__ == "__main__": + machine_id = "b2c32bdeff8d3f0d33dc88f2aadea6bc" + test_member_status(machine_id) \ No newline at end of file diff --git a/test_hardware_id.py b/test_hardware_id.py new file mode 100644 index 0000000..52e4a8c --- /dev/null +++ b/test_hardware_id.py @@ -0,0 +1,38 @@ +import subprocess +import hashlib +import logging + +def get_hardware_id() -> str: + """获取硬件唯一标识""" + try: + print("正在获取CPU信息...") + cpu_info = subprocess.check_output('wmic cpu get ProcessorId').decode() + cpu_id = cpu_info.split('\n')[1].strip() + print(f"CPU ID: {cpu_id}") + + print("\n正在获取主板序列号...") + board_info = subprocess.check_output('wmic baseboard get SerialNumber').decode() + board_id = board_info.split('\n')[1].strip() + print(f"主板序列号: {board_id}") + + print("\n正在获取BIOS序列号...") + bios_info = subprocess.check_output('wmic bios get SerialNumber').decode() + bios_id = bios_info.split('\n')[1].strip() + print(f"BIOS序列号: {bios_id}") + + # 组合信息并生成哈希 + combined = f"{cpu_id}:{board_id}:{bios_id}" + print(f"\n组合信息: {combined}") + + hardware_id = hashlib.md5(combined.encode()).hexdigest() + print(f"\n生成的硬件ID: {hardware_id}") + return hardware_id + except Exception as e: + print(f"获取硬件ID失败: {str(e)}") + return "" + +if __name__ == "__main__": + print("=== 硬件ID测试 ===\n") + hardware_id = get_hardware_id() + if hardware_id: + print("\n测试完成!") \ No newline at end of file