cursor_pro_keep_alive.py 8.0 KB

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