create_sessions_browser.py 6.9 KB

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