99from driver import get_driver
1010
1111# Configure logging for this script to provide clear, structured output.
12- # Logs will be directed to standard output, making them compatible with containerization
13- # and centralized log collection systems.
12+ # Using a simpler format for better readability by end users.
1413logging .basicConfig (
1514 level = logging .INFO ,
16- format = '{"timestamp": "%(asctime)s", "level": "%(levelname)s", "module": "%(name)s", "message": "%(message)s"}' ,
15+ format = '%(asctime)s - %(levelname)s - %(message)s' ,
16+ datefmt = '%Y-%m-%d %H:%M:%S'
1717)
1818logger = logging .getLogger (__name__ )
1919
@@ -57,26 +57,47 @@ def get_pocketoption_ssid():
5757 Automates the process of logging into PocketOption, navigating to a specific cabinet page,
5858 and then scraping WebSocket traffic to extract the session ID (SSID).
5959 The extracted SSID is then saved to the .env file.
60+
61+ Instructions:
62+ 1. Run this script
63+ 2. A Chrome browser will open and navigate to PocketOption login page
64+ 3. Log in manually with your credentials
65+ 4. Wait for the script to automatically extract your SSID
66+ 5. The SSID will be saved to .env file in the current directory
6067 """
6168 driver = None
6269 try :
70+ logger .info ("=" * 80 )
71+ logger .info ("PocketOption SSID Extractor Tool" )
72+ logger .info ("=" * 80 )
73+ logger .info ("INSTRUCTIONS:" )
74+ logger .info ("1. A Chrome browser will open shortly" )
75+ logger .info ("2. Please log in to PocketOption with your credentials" )
76+ logger .info ("3. Wait for automatic redirection to the trading cabinet" )
77+ logger .info ("4. The script will extract your SSID automatically" )
78+ logger .info ("=" * 80 )
79+
6380 # Initialize the Selenium WebDriver using the helper function from driver.py.
6481 # This ensures the browser profile is persistent for easier logins.
6582 driver = get_driver ("chrome" )
6683 login_url = "https://pocketoption.com/en/login"
6784 cabinet_base_url = "https://pocketoption.com/en/cabinet"
6885 target_cabinet_url = "https://pocketoption.com/en/cabinet/demo-quick-high-low/"
69- # Regex to capture the entire "42[\"auth\",{...}]" string.
70- # This pattern is designed to be robust and capture the full authentication message,
71- # regardless of the specific content of the 'session' field (e.g., simple string or serialized PHP array).
72- ssid_pattern = r'(42\["auth",\{"session":"[^"]+","isDemo":\d+,"uid":\d+,"platform":\d+,"isFastHistory":(?:true|false)\}\])'
86+
87+ # Flexible regex pattern to capture auth messages in various formats
88+ # This pattern handles:
89+ # - Optional isFastHistory field
90+ # - Any field order in the JSON object
91+ # - Various session string formats
92+ ssid_pattern = r'42\["auth",(\{(?:[^{}]|\{[^}]*\})*\})\]'
7393
7494 logger .info (f"Navigating to login page: { login_url } " )
7595 driver .get (login_url )
7696
7797 # Wait indefinitely for the user to manually log in and be redirected to the cabinet base page.
7898 # This uses an explicit wait condition to check if the current URL contains the cabinet_base_url.
7999 logger .info (f"Waiting for user to login and redirect to { cabinet_base_url } ..." )
100+ logger .info ("Please complete the login in the browser window..." )
80101 WebDriverWait (driver , 9999 ).until (EC .url_contains (cabinet_base_url ))
81102 logger .info ("Login successful. Redirected to cabinet base page." )
82103
@@ -89,9 +110,10 @@ def get_pocketoption_ssid():
89110 WebDriverWait (driver , 60 ).until (EC .url_contains (target_cabinet_url ))
90111 logger .info ("Successfully navigated to the target cabinet page." )
91112
92- # Give the page some time to load all WebSocket connections and messages after redirection.
93- # This delay helps ensure that the relevant WebSocket frames are captured in the logs.
94- time .sleep (5 )
113+ # Give the page more time to establish WebSocket connections and capture auth messages
114+ # Increased from 5 to 10 seconds to ensure auth messages are captured
115+ logger .info ("Waiting for WebSocket connections to establish..." )
116+ time .sleep (10 )
95117
96118 # Retrieve performance logs which include network requests and WebSocket frames.
97119 # These logs are crucial for capturing the raw WebSocket messages.
@@ -104,35 +126,80 @@ def get_pocketoption_ssid():
104126 logger .info (f"Collected { len (performance_logs )} performance log entries." )
105127
106128 found_full_ssid_string = None
129+ websocket_frames_found = 0
130+ auth_messages_found = 0
131+
107132 # Iterate through the performance logs to find WebSocket frames.
108133 for entry in performance_logs :
109- message = json .loads (entry ["message" ])
110- # Check if the log entry is a WebSocket frame (either sent or received)
111- # and contains the desired payload data.
112- if (
113- message ["message" ]["method" ] == "Network.webSocketFrameReceived"
114- or message ["message" ]["method" ] == "Network.webSocketFrameSent"
115- ):
116- payload_data = message ["message" ]["params" ]["response" ]["payloadData" ]
117- # Attempt to find the full SSID string using the defined regex pattern.
118- match = re .search (ssid_pattern , payload_data )
119- if match :
120- # Capture the entire matched group as the full SSID string.
121- found_full_ssid_string = match .group (1 )
122- logger .info (
123- f"Found full SSID string in WebSocket payload: { found_full_ssid_string } "
124- )
125- # Break after finding the first match as it's likely the correct one.
126- break
134+ try :
135+ message = json .loads (entry ["message" ])
136+ # Check if the log entry is a WebSocket frame (either sent or received)
137+ # and contains the desired payload data.
138+ if (
139+ message ["message" ]["method" ] == "Network.webSocketFrameReceived"
140+ or message ["message" ]["method" ] == "Network.webSocketFrameSent"
141+ ):
142+ websocket_frames_found += 1
143+ payload_data = message ["message" ]["params" ]["response" ]["payloadData" ]
144+
145+ # Check if this is an auth-related message
146+ if '"auth"' in payload_data :
147+ auth_messages_found += 1
148+ logger .debug (f"Found auth message: { payload_data [:200 ]} ..." )
149+
150+ # Attempt to find the full SSID string using the defined regex pattern.
151+ match = re .search (ssid_pattern , payload_data )
152+ if match :
153+ # Reconstruct the full SSID string
154+ json_part = match .group (1 )
155+ found_full_ssid_string = f'42["auth",{ json_part } ]'
156+
157+ # Validate that it contains required fields
158+ try :
159+ data = json .loads (json_part )
160+ if "session" in data and "uid" in data :
161+ logger .info (
162+ f"Found valid SSID string in WebSocket payload"
163+ )
164+ logger .info (f"SSID preview: 42[\" auth\" ,{{\" session\" :\" ***\" ,\" uid\" :{ data .get ('uid' )} ,\" isDemo\" :{ data .get ('isDemo' , 'N/A' )} ,...}}]" )
165+ # Break after finding the first valid match
166+ break
167+ else :
168+ logger .warning (f"Found auth message but missing required fields: { list (data .keys ())} " )
169+ found_full_ssid_string = None
170+ except json .JSONDecodeError as e :
171+ logger .warning (f"Found auth pattern but invalid JSON: { e } " )
172+ found_full_ssid_string = None
173+ except Exception as e :
174+ logger .debug (f"Error processing log entry: { e } " )
175+ continue
176+
177+ logger .info (f"Statistics: Found { websocket_frames_found } WebSocket frames, { auth_messages_found } auth messages" )
127178
128179 if found_full_ssid_string :
129180 # Save the extracted full SSID string to the .env file.
130181 save_to_env ("SSID" , found_full_ssid_string )
131- logger .info ("Full SSID string successfully extracted and saved to .env." )
182+ logger .info ("=" * 80 )
183+ logger .info ("SUCCESS! SSID successfully extracted and saved to .env file." )
184+ logger .info ("You can now use this SSID in your PocketOption API scripts." )
185+ logger .info ("=" * 80 )
132186 else :
187+ logger .warning ("=" * 80 )
133188 logger .warning (
134- "Full SSID string pattern not found in WebSocket logs after login."
189+ "SSID string pattern not found in WebSocket logs after login."
135190 )
191+ logger .warning ("Possible reasons:" )
192+ logger .warning ("1. WebSocket connection was not established yet (try running again)" )
193+ logger .warning ("2. You may need to navigate to a trading page manually" )
194+ logger .warning ("3. The auth message format has changed" )
195+ logger .warning ("" )
196+ logger .warning ("Alternative method to get SSID:" )
197+ logger .warning ("1. Open PocketOption in Chrome" )
198+ logger .warning ("2. Open Developer Tools (F12)" )
199+ logger .warning ("3. Go to Network tab and filter by 'WS' (WebSocket)" )
200+ logger .warning ("4. Look for messages containing '42[\" auth\" '" )
201+ logger .warning ("5. Copy the complete message including the 42[\" auth\" ,{...}] format" )
202+ logger .warning ("=" * 80 )
136203
137204 except Exception as e :
138205 logger .error (f"An error occurred: { e } " , exc_info = True )
0 commit comments