cursor_pro_keep_alive.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. import os
  2. from license_manager import LicenseManager
  3. os.environ["PYTHONVERBOSE"] = "0"
  4. os.environ["PYINSTALLER_VERBOSE"] = "0"
  5. import re
  6. import time
  7. import random
  8. from cursor_auth_manager import CursorAuthManager
  9. import os
  10. import sys
  11. import logging
  12. from browser_utils import BrowserManager
  13. from get_veri_code import EmailVerificationHandler
  14. # 在文件开头设置日志
  15. logging.basicConfig(
  16. level=logging.INFO,
  17. format="%(asctime)s - %(levelname)s - %(message)s",
  18. handlers=[
  19. logging.StreamHandler(),
  20. logging.FileHandler("cursor_keep_alive.log", encoding="utf-8"),
  21. ],
  22. )
  23. def handle_turnstile(tab):
  24. print("准备处理验证")
  25. try:
  26. while True:
  27. try:
  28. challengeCheck = (
  29. tab.ele("@id=cf-turnstile", timeout=2)
  30. .child()
  31. .shadow_root.ele("tag:iframe")
  32. .ele("tag:body")
  33. .sr("tag:input")
  34. )
  35. if challengeCheck:
  36. print("验证框加载完成")
  37. time.sleep(random.uniform(1, 3))
  38. challengeCheck.click()
  39. print("验证按钮已点击,等待验证完成...")
  40. time.sleep(2)
  41. return True
  42. except:
  43. pass
  44. if tab.ele("@name=password"):
  45. print("无需验证")
  46. break
  47. if tab.ele("@data-index=0"):
  48. print("无需验证")
  49. break
  50. if tab.ele("Account Settings"):
  51. print("无需验证")
  52. break
  53. time.sleep(random.uniform(1, 2))
  54. except Exception as e:
  55. print(e)
  56. print("跳过验证")
  57. return False
  58. def get_cursor_session_token(tab, max_attempts=3, retry_interval=2):
  59. """
  60. 获取Cursor会话token,带有重试机制
  61. :param tab: 浏览器标签页
  62. :param max_attempts: 最大尝试次数
  63. :param retry_interval: 重试间隔(秒)
  64. :return: session token 或 None
  65. """
  66. print("开始获取cookie")
  67. attempts = 0
  68. while attempts < max_attempts:
  69. try:
  70. cookies = tab.cookies()
  71. for cookie in cookies:
  72. if cookie.get("name") == "WorkosCursorSessionToken":
  73. return cookie["value"].split("%3A%3A")[1]
  74. attempts += 1
  75. if attempts < max_attempts:
  76. print(
  77. f"第 {attempts} 次尝试未获取到CursorSessionToken,{retry_interval}秒后重试..."
  78. )
  79. time.sleep(retry_interval)
  80. else:
  81. print(f"已达到最大尝试次数({max_attempts}),获取CursorSessionToken失败")
  82. except Exception as e:
  83. print(f"获取cookie失败: {str(e)}")
  84. attempts += 1
  85. if attempts < max_attempts:
  86. print(f"将在 {retry_interval} 秒后重试...")
  87. time.sleep(retry_interval)
  88. return None
  89. def update_cursor_auth(email=None, access_token=None, refresh_token=None):
  90. """
  91. 更新Cursor的认证信息的便捷函数
  92. """
  93. auth_manager = CursorAuthManager()
  94. return auth_manager.update_auth(email, access_token, refresh_token)
  95. def sign_up_account(browser, tab):
  96. print("\n开始注册新账户...")
  97. tab.get(sign_up_url)
  98. try:
  99. if tab.ele("@name=first_name"):
  100. tab.actions.click("@name=first_name").input(first_name)
  101. time.sleep(random.uniform(1, 3))
  102. tab.actions.click("@name=last_name").input(last_name)
  103. time.sleep(random.uniform(1, 3))
  104. tab.actions.click("@name=email").input(account)
  105. time.sleep(random.uniform(1, 3))
  106. tab.actions.click("@type=submit")
  107. except Exception as e:
  108. print("打开注册页面失败")
  109. return False
  110. handle_turnstile(tab)
  111. try:
  112. if tab.ele("@name=password"):
  113. tab.ele("@name=password").input(password)
  114. time.sleep(random.uniform(1, 3))
  115. tab.ele("@type=submit").click()
  116. print("点击Continue按钮")
  117. except Exception as e:
  118. print("输入密码失败")
  119. return False
  120. time.sleep(random.uniform(1, 3))
  121. if tab.ele("This email is not available."):
  122. print("This email is not available.")
  123. return False
  124. handle_turnstile(tab)
  125. while True:
  126. try:
  127. if tab.ele("Account Settings"):
  128. break
  129. if tab.ele("@data-index=0"):
  130. code = email_handler.get_verification_code(account)
  131. if not code:
  132. return False
  133. i = 0
  134. for digit in code:
  135. tab.ele(f"@data-index={i}").input(digit)
  136. time.sleep(random.uniform(0.1, 0.3))
  137. i += 1
  138. break
  139. except Exception as e:
  140. print(e)
  141. handle_turnstile(tab)
  142. wait_time = random.randint(3, 6)
  143. for i in range(wait_time):
  144. print(f"等待中... {wait_time-i}秒")
  145. time.sleep(1)
  146. tab.get(settings_url)
  147. try:
  148. usage_selector = (
  149. "css:div.col-span-2 > div > div > div > div > "
  150. "div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
  151. "span.font-mono.text-sm\\/\\[0\\.875rem\\]"
  152. )
  153. usage_ele = tab.ele(usage_selector)
  154. if usage_ele:
  155. usage_info = usage_ele.text
  156. total_usage = usage_info.split("/")[-1].strip()
  157. print("可用上限: " + total_usage)
  158. except Exception as e:
  159. print("获取可用上限失败")
  160. print("注册完成")
  161. account_info = f"\nCursor 账号: {account} 密码: {password}"
  162. logging.info(account_info)
  163. time.sleep(5)
  164. return True
  165. class EmailGenerator:
  166. def __init__(
  167. self,
  168. domain="mailto.plus",
  169. password="".join(
  170. random.choices(
  171. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*",
  172. k=12,
  173. )
  174. ),
  175. first_name="yuyan",
  176. last_name="peng",
  177. ):
  178. self.domain = domain
  179. self.default_password = password
  180. self.default_first_name = first_name
  181. self.default_last_name = last_name
  182. def generate_email(self, length=8):
  183. """生成随机邮箱地址"""
  184. random_str = "".join(random.choices("abcdefghijklmnopqrstuvwxyz", k=length))
  185. timestamp = str(int(time.time()))[-6:] # 使用时间戳后6位
  186. return f"{random_str}{timestamp}@{self.domain}"
  187. def get_account_info(self):
  188. """获取完整的账号信息"""
  189. return {
  190. "email": self.generate_email(),
  191. "password": self.default_password,
  192. "first_name": self.default_first_name,
  193. "last_name": self.default_last_name,
  194. }
  195. if __name__ == "__main__":
  196. browser_manager = None
  197. try:
  198. license_manager = LicenseManager()
  199. # 验证许可证
  200. is_valid, message = license_manager.verify_license()
  201. if not is_valid:
  202. print(f"许可证验证失败: {message}")
  203. # 提示用户激活
  204. license_key = input("请输入激活码: ")
  205. success, activate_message = license_manager.activate_license(license_key)
  206. if not success:
  207. print(f"激活失败: {activate_message}")
  208. sys.exit(1)
  209. print("激活成功!")
  210. # 初始化浏览器
  211. browser_manager = BrowserManager()
  212. browser = browser_manager.init_browser()
  213. # 初始化邮箱验证处理器
  214. email_handler = EmailVerificationHandler(browser)
  215. # 固定的 URL 配置
  216. login_url = "https://authenticator.cursor.sh"
  217. sign_up_url = "https://authenticator.cursor.sh/sign-up"
  218. settings_url = "https://www.cursor.com/settings"
  219. mail_url = "https://tempmail.plus"
  220. # 生成随机邮箱
  221. email_generator = EmailGenerator()
  222. account = email_generator.generate_email()
  223. password = email_generator.default_password
  224. first_name = email_generator.default_first_name
  225. last_name = email_generator.default_last_name
  226. auto_update_cursor_auth = True
  227. tab = browser.latest_tab
  228. tab.run_js("try { turnstile.reset() } catch(e) { }")
  229. tab.get(login_url)
  230. if sign_up_account(browser, tab):
  231. token = get_cursor_session_token(tab)
  232. if token:
  233. update_cursor_auth(
  234. email=account, access_token=token, refresh_token=token
  235. )
  236. else:
  237. print("账户注册失败")
  238. print("脚本执行完毕")
  239. except Exception as e:
  240. logging.error(f"程序执行出错: {str(e)}")
  241. import traceback
  242. logging.error(traceback.format_exc())
  243. finally:
  244. if browser_manager:
  245. browser_manager.quit()
  246. input("\n按回车键退出...")