create_session_browser.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #!/usr/bin/env python3
  2. """
  3. Requirements:
  4. pip install -r tools/requirements.txt
  5. Usage:
  6. python3 tools/create_session_browser.py <username> <password> [totp_seed] [--append sessions.jsonl] [--headless]
  7. Examples:
  8. # Output to terminal
  9. python3 tools/create_session_browser.py myusername mypassword TOTP_SECRET
  10. # Append to sessions.jsonl
  11. python3 tools/create_session_browser.py myusername mypassword TOTP_SECRET --append sessions.jsonl
  12. # Headless mode (may increase detection risk)
  13. python3 tools/create_session_browser.py myusername mypassword TOTP_SECRET --headless
  14. Output:
  15. {"kind": "cookie", "username": "...", "id": "...", "auth_token": "...", "ct0": "..."}
  16. """
  17. import asyncio
  18. import json
  19. import os
  20. import sys
  21. import nodriver as uc
  22. import pyotp
  23. async def login_and_get_cookies(username, password, totp_seed=None, headless=False):
  24. """Authenticate with X.com and extract session cookies"""
  25. # Note: headless mode may increase detection risk from bot-detection systems
  26. browser = await uc.start(headless=headless)
  27. tab = await browser.get("https://x.com/i/flow/login")
  28. try:
  29. # Enter username
  30. print(f"[*] Entering username {username}...", file=sys.stderr)
  31. retry = 0
  32. while retry < 5:
  33. username_input = await tab.find(
  34. 'input[autocomplete="username"]', timeout=10
  35. )
  36. pos = await username_input.get_position()
  37. await tab.mouse_move(pos.x, pos.y, steps=50, flash=True)
  38. await asyncio.sleep(0.1)
  39. await username_input.click()
  40. await asyncio.sleep(0.5)
  41. await username_input.send_keys(username)
  42. await asyncio.sleep(0.2)
  43. await username_input.send_keys("\n")
  44. await asyncio.sleep(2)
  45. page_content = await tab.get_content()
  46. if "Could not log you in" in page_content:
  47. retry += 1
  48. wait = retry * 10
  49. print(f"Retrying in {wait} seconds...")
  50. await asyncio.sleep(wait)
  51. else:
  52. break
  53. # Enter password
  54. print("[*] Entering password...", file=sys.stderr)
  55. pretry = 0
  56. while pretry < 5:
  57. password_input = await tab.find(
  58. 'input[autocomplete="current-password"]', timeout=15
  59. )
  60. await password_input.click()
  61. await asyncio.sleep(0.5)
  62. await password_input.send_keys(password)
  63. await asyncio.sleep(0.2)
  64. await password_input.send_keys("\n")
  65. await asyncio.sleep(2)
  66. page_content = await tab.get_content()
  67. if "Could not log you in" in page_content:
  68. pretry += 1
  69. wait = pretry * 10
  70. print(f"Retrying in {wait} seconds...")
  71. await asyncio.sleep(wait)
  72. else:
  73. break
  74. # Handle 2FA if needed
  75. page_content = await tab.get_content()
  76. if "verification code" in page_content or "Enter code" in page_content:
  77. if not totp_seed:
  78. raise Exception("2FA required but no TOTP seed provided")
  79. print("[*] 2FA detected, entering code...", file=sys.stderr)
  80. totp_code = pyotp.TOTP(totp_seed).now()
  81. code_input = await tab.select('input[type="text"]')
  82. await code_input.send_keys(totp_code + "\n")
  83. await asyncio.sleep(3)
  84. # Get cookies
  85. print("[*] Retrieving cookies...", file=sys.stderr)
  86. for _ in range(20): # 20 second timeout
  87. cookies = await browser.cookies.get_all()
  88. cookies_dict = {cookie.name: cookie.value for cookie in cookies}
  89. if "auth_token" in cookies_dict and "ct0" in cookies_dict:
  90. # Extract ID from twid cookie (may be URL-encoded)
  91. user_id = None
  92. if "twid" in cookies_dict:
  93. twid = cookies_dict["twid"]
  94. # Try to extract the ID from twid (format: u%3D<id> or u=<id>)
  95. if "u%3D" in twid:
  96. user_id = twid.split("u%3D")[1].split("&")[0].strip('"')
  97. elif "u=" in twid:
  98. user_id = twid.split("u=")[1].split("&")[0].strip('"')
  99. cookies_dict["username"] = username
  100. if user_id:
  101. cookies_dict["id"] = user_id
  102. return cookies_dict
  103. await asyncio.sleep(1)
  104. raise Exception("Timeout waiting for cookies")
  105. finally:
  106. browser.stop()
  107. async def main():
  108. if len(sys.argv) < 3:
  109. print(
  110. "Usage: python3 create_session_browser.py username password [totp_seed] [--append file.jsonl] [--headless]"
  111. )
  112. sys.exit(1)
  113. username = sys.argv[1]
  114. password = sys.argv[2]
  115. totp_seed = None
  116. append_file = None
  117. headless = False
  118. # Parse optional arguments
  119. i = 3
  120. while i < len(sys.argv):
  121. arg = sys.argv[i]
  122. if arg == "--append":
  123. if i + 1 < len(sys.argv):
  124. append_file = sys.argv[i + 1]
  125. i += 2 # Skip '--append' and filename
  126. else:
  127. print("[!] Error: --append requires a filename", file=sys.stderr)
  128. sys.exit(1)
  129. elif arg == "--headless":
  130. headless = True
  131. i += 1
  132. elif not arg.startswith("--"):
  133. if totp_seed is None:
  134. totp_seed = arg
  135. i += 1
  136. else:
  137. # Unkown args
  138. print(f"[!] Warning: Unknown argument: {arg}", file=sys.stderr)
  139. i += 1
  140. try:
  141. cookies = await login_and_get_cookies(username, password, totp_seed, headless)
  142. session = {
  143. "kind": "cookie",
  144. "username": cookies["username"],
  145. "id": cookies.get("id"),
  146. "auth_token": cookies["auth_token"],
  147. "ct0": cookies["ct0"],
  148. }
  149. output = json.dumps(session)
  150. if append_file:
  151. with open(append_file, "a") as f:
  152. f.write(output + "\n")
  153. print(f"✓ Session appended to {append_file}", file=sys.stderr)
  154. else:
  155. print(output)
  156. os._exit(0)
  157. except Exception as error:
  158. print(f"[!] Error: {error}", file=sys.stderr)
  159. sys.exit(1)
  160. if __name__ == "__main__":
  161. asyncio.run(main())