Closed vladdd183 closed 2 months ago
Yes, same here, I am getting the error of 41, I am going to try using webdriver, probably it's beeing blocked, so I will try that, but I am not giving up on this api that for sure :)
I'll tell you what happened, and if I recomend it.
Okay, thank you very much. I'll keep trying and I'll tell you too if I find a solution :)
@theshadow76 I've made progress. It was the backslashes before the inverted commas. Now we're getting binary data However, after the first data is received, the disconnect occurs.
data = r'42["auth",{"session":"a:4:{s:10:\"session_id\";s:32:\"c53eec05c6f8a8be2d134d4fd55266f8\";s:10:\"ip_address\";s:14:\"46.138.176.190\";s:10:\"user_agent\";s:101:\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\";s:13:\"last_activity\";i:1707850603;}9f383935faff5a86bc1658bbde8c61e7","isDemo":1,"uid":72038016,"platform":3}]'
This is what the data should look like
Also you need "origin" header with website url, in my case: https://pocket-link19.co
async with websockets.connect(
"wss://api-eu.po.market/socket.io/?EIO=4&transport=websocket",
extra_headers={
"Origin": "https://pocket-link19.co",
},
) as websocket:
i am using "websockets" python library
so, to all you need:
i made a little mistake with reconnection, now it works good. Also you need only Backslashes and Origin Header
Thank you very much!
I'll adjust the code
@vladdd183 Hello! Sorry to bother you again, but here:
import urllib
import websocket
from pocketoptionapi.constants import REGION
import threading
import logging
import ssl
class WebSocketClient:
def __init__(self, url, pocket_api_instance=None):
self.url = url
self.pocket_api_instance = pocket_api_instance
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
# Create file handler and add it to the logger
file_handler = logging.FileHandler('pocket.log')
file_handler.setFormatter(formatter)
self.logger.addHandler(file_handler)
self.header = "Origin: https://google.com"
self.ws = websocket.WebSocketApp(self.url,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
header=[self.header])
self.logger.info("Starting websocket client...")
def on_message(self, ws, message):
print(f"Message: {message}")
self.logger.info(f"Recieved a message!: {message}")
if str(message).startswith('0{"sid":'):
ws.send("40")
if str(message).startswith('40{"sid"'):
data = r'42["auth",{"session":"a:4:{s:10:\"session_id\";s:32:\"da7a5a82c8f6c35a87b2ee31d4f5b3b4\";s:10:\"ip_address\";s:10:\"90.36.9.15\";s:10:\"user_agent\";s:120:\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 OP\";s:13:\"last_activity\";i:1707667599;}3a0058a58a6df5e7b49f652f8e4f8249","isDemo":0,"uid":27658142,"platform":1}]'
print(f"Sent the auth messaage!: {data}")
ws.send(data)
def on_error(self, ws, error):
print(error)
self.logger.error(f"Got a error: {error}")
def on_close(self, ws, close_status_code, close_msg):
print("### closed ###")
self.logger.warning(f"Connection closed, conections status_code: {close_status_code} and the message is: {close_msg}")
def on_open(self, ws):
print("Opened connection")
self.logger.info("Opened!")
def run(self):
self.ws.run_forever() # Use dispatcher for automatic reconnection
ws = WebSocketClient(url="wss://api-l.po.market/socket.io/?EIO=4&transport=websocket")
ws.run()
I am getting this output:
Opened connection
Message: 0{"sid":"s-DtcnSjnIgXZFuoNKB7","upgrades":[],"pingInterval":25000,"pingTimeout":20000,"maxPayload":1000000}
Message: 40{"sid":"aSAnWTMPfgSv-DKNNKCG"}
Sent the auth messaage!: 42["auth",{"session":"a:4:{s:10:\"session_id\";s:32:\"da7a5a82c8f6c35a87b2ee31d4f5b3b4\";s:10:\"ip_address\";s:10:\"90.36.9.15\";s:10:\"user_agent\";s:120:\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 OP\";s:13:\"last_activity\";i:1707667599;}3a0058a58a6df5e7b49f652f8e4f8249","isDemo":0,"uid":27658142,"platform":1}]
Message: 41
### closed ###
looks like I am still getting that issue even tho I've added the hedears, but can you check if the data variable is the way it should be? Maybe it had to be formated in a diferent way.
Let me know what you think!
or if you would like to share your code, that would help alot to. thx
self.header = "Origin: https://google.com"
you shoud to set origin with site you using, not google try: https://po.trade/ (official link) or https://pocket-link19.co (mirror link) official is prefered, use mirror only if official link banned in your country
Okey, let me check and I'll let you know
I use "websockets" library and "anyio" for async, also "rich" for better print formating
pip3 install websockets anyio rich
this is the code (try to use second origin, that commented):
import websockets
import anyio
from rich.pretty import pprint as print
import json
SESSION = r'session_string'
async def websocket_client(url, pro):
while True:
try:
async with websockets.connect(
url,
extra_headers={
"Origin": "https://pocket-link19.co",
# "Origin": "https://po.trade/"
},
) as websocket:
async for message in websocket:
await pro(message, websocket, url)
except KeyboardInterrupt:
exit()
except Exception as e:
print(e)
print("Connection lost... reconnecting")
await anyio.sleep(5)
return True
async def pro(message, websocket, url):
# if byte data
if type(message) == type(b""):
# cut 100 first symbols of byte date to prevent spam
print(str(message)[:100])
return
else:
print(message)
# Code to make order
# data = r'42["openOrder",{"asset":"#AXP_otc","amount":1,"action":"call","isDemo":1,"requestId":14680035,"optionType":100,"time":20}]'
# await websocket.send(data)
if message.startswith('0{"sid":"'):
print(f"{url.split('/')[2]} got 0 sid send 40 ")
await websocket.send("40")
elif message == "2":
# ping-pong thing
print(f"{url.split('/')[2]} got 2 send 3")
await websocket.send("3")
if message.startswith('40{"sid":"'):
print(f"{url.split('/')[2]} got 40 sid send session")
await websocket.send(SESSION)
async def main():
url = "wss://api-l.po.market/socket.io/?EIO=4&transport=websocket"
await websocket_client(url, pro)
if __name__ == "__main__":
anyio.run(main)
Thank you alot, I'll finish implementing it soon! Thanks for your help!!!
i tried to found error in your code, it's looks pretty similar to my. Headers has set, should work with the origin, but not working. I think it error with library, try to use "websockets" and async
now i am working on login-password auth system
write me after testing my version
Ok
also write code for selenium to get session string by login+password
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import urllib.parse
def test_d():
driver = webdriver.Firefox()
driver.get("https://pocket-link19.co/ru/login") # https://po.trade/login
driver.set_window_size(550, 691)
driver.find_element(By.NAME, "email").click()
driver.find_element(By.NAME, "email").send_keys("email@mail.com") # email@mail.com
driver.find_element(By.NAME, "password").click()
driver.find_element(By.NAME, "password").send_keys("password") # password
driver.find_element(By.CSS_SELECTOR, ".waves").click()
WebDriverWait(driver, 30).until(
expected_conditions.presence_of_element_located((By.CSS_SELECTOR, ".layer"))
)
# For demo:
driver.get(
"https://pocket-link19.co/ru/cabinet/demo-quick-high-low/"
) # https://po.trade/cabinet/demo-quick-high-low/
WebDriverWait(driver, 30).until(
expected_conditions.presence_of_element_located((By.CSS_SELECTOR, ".layer"))
)
cookies = driver.get_cookies()
session_token = [x["value"] for x in cookies if x["name"] == "ci_session"][0]
decoded_string = urllib.parse.unquote(session_token)
print(decoded_string)
driver.quit()
test_d()
tried to do it with requests, but have no successful
this code might help to get session string easily, but don't forget to add backslashes
also to make order you need requestId, that make from current time + random number
def generate_request_id():
now = int(time.time()) + random.randint(1, 100)
return now
a = generate_request_id()
data = '42["openOrder",{"asset":"BTCUSD","amount":10,"action":"call","isDemo":1,"requestId":{a},"optionType":100,"time":60}]'.replace('{a}', str(a))
Thank you so much. As of right now I am with bad internet, so I don't think I'll be able to keep coding today, maybe tomorrow I will, not sure.
But thx.
you are welcome
Hello! Sorry to bother you again I am getting this error from cloudflare:
InvalidStatusCode(200, Headers([('Date', 'Thu, 11 Apr 2024 00:16:11 GMT'), ('Content-Type', 'text/html; charset=UTF-8'), ('Transfer-Encoding', 'chunked'), ('Connection', 'keep-alive'), ('X-Powered-By', 'PHP/8.3.4'), ('CF-Cache-Status', 'DYNAMIC'), ('Report-To', '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=yJUynuTPCFrZNgmZpVgaDvlopmmCvS%2B59bldFgohoZ%2FijFTGdv2VL3R46Y5A02lCxhofJXp1b2UWx7Ov8mQEeq%2FTBOk2HGgdctK1H0Z13hOVzlxJALZkBOZ0bTZHD56d4rz9pQ7Ez%2FyVClrg84A%3D"}],"group":"cf-nel","max_age":604800}'), ('NEL', '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'), ('Server', 'cloudflare'), ('CF-RAY', '8726c950ef9fd772-SCL'), ('alt-svc', 'h3=":443"; ma=86400')]))
'Connection lost... reconnecting'
in this code
@vladdd183 do you know what could be the issue?
@theshadow76 Hi! you dont use "i" for url. You need change url to i
async def websocket_client(url, pro):
for i in REGION.get_regions(REGION):
print(f"Trying {i}...")
try:
async with websockets.connect(
>>>>> i, #url,
extra_headers={
#"Origin": "https://pocket-link33.co",
"Origin": "https://po.trade/"
},
That error means that you cannot connect to websocket for this region, so you need find region able to connect, if you change "url" to "i" it will find correct region websocket
Oh yeah thanks. Let me try...
@theshadow76 it helps?
@vladdd183 right now I can't test, I'll let you know soon.
ok)
@theshadow76 Thank you very much for giving a start in this code, thanks to this I have been able to develop almost all the important functions of the API such as logging in, purchasing, obtaining candle data, checking operation among other functions, I would only need to refine and optimize the code, I would be happy to collaborate on this project.
@chema2411 hello! Yes if you want you can do a pull request, so I can check it!
That would be so nice! Thank you alot!
@chema2411 hi! How you made login? Is it api or selenium?
@vladdd183 Hello, I did it through websockets, with asyncio and I run the websoket connection in a separate thread.
import asyncio from datetime import datetime, timedelta, timezone
import websocket import websockets import json import logging import ssl
import pocketoptionapi.constants as OP_code import pocketoptionapi.global_value as global_value from pocketoptionapi.constants import REGION from pocketoptionapi.ws.objects.timesync import TimeSync
logger = logging.getLogger(name)
timesync = TimeSync()
async def on_open(): # pylint: disable=unused-argument """Method to process websocket open.""" print("CONECTADO CON EXITO") logger = logging.getLogger(name) logger.debug("Websocket client connected.") global_value.websocket_is_connected = True
async def send_pin(ws): while global_value.websocket_is_connected is False: await asyncio.sleep(0.1) pass while True: await asyncio.sleep(20) await ws.send('42["ps"]')
class WebsocketClient(object): def init(self, api) -> None: """ Inicializa el cliente WebSocket.
:param ssid: El ID de sesión para la autenticación.
:param url: La URL del WebSocket a la que conectarse.
"""
self.updateHistoryNew = None
self.updateStream = None
self.history_data_ready = None
self.successcloseOrder = False
self.api = api
self.message = None
self.url = None
self.ssid = global_value.SSID
self.websocket = None
self.region = REGION()
self.loop = asyncio.get_event_loop()
self.esperar_segundo_mensaje = False
self.recibido_updateClosedDeals = False
async def websocket_listener(self, ws):
async for message in ws:
await self.on_message(message)
async def connect(self):
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
while global_value.websocket_is_connected is False:
for url in self.region.get_regions(True):
print(url)
try:
async with websockets.connect(url, extra_headers={"Origin": "https://m.pocketoption.com"}) as ws:
print("Conectado a: ", url)
self.websocket = ws
self.url = url
on_message_task = asyncio.create_task(self.websocket_listener(ws))
sender_task = asyncio.create_task(send_pin(ws))
message_task = asyncio.create_task(self.send_message(self.message))
await asyncio.gather(on_message_task, sender_task, message_task)
except websockets.ConnectionClosed as e:
await self.on_close(e)
except Exception as e:
await self.on_error(e)
return True
async def send_message(self, message):
while global_value.websocket_is_connected is False:
await asyncio.sleep(0.1)
pass
self.message = message
if global_value.websocket_is_connected:
if message is not None:
await self.websocket.send(message)
else:
logging.warning("WebSocked not connected")
@staticmethod
def dict_queue_add(self, dict, maxdict, key1, key2, key3, value):
if key3 in dict[key1][key2]:
dict[key1][key2][key3] = value
else:
while True:
try:
dic_size = len(dict[key1][key2])
except:
dic_size = 0
if dic_size < maxdict:
dict[key1][key2][key3] = value
break
else:
# del mini key
del dict[key1][key2][sorted(dict[key1][key2].keys(), reverse=False)[0]]
async def on_message(self, message): # pylint: disable=unused-argument
"""Method to process websocket messages."""
# global_value.ssl_Mutual_exclusion = True
logger = logging.getLogger(__name__)
logger.debug(message)
# message = json.loads(str(message))
if type(message) is bytes:
# Paso 1: Decodificar los bytes a una cadena de texto (string)
message = message.decode('utf-8')
message = json.loads(message)
# print(message, type(message)) # [:1000000])
if "balance" in message:
global_value.balance_id = message["uid"]
global_value.balance = message["balance"]
global_value.balance_type = message["isDemo"]
elif "requestId" in message and message["requestId"] == 'buy':
global_value.order_data = message
# Supongamos que este es el segundo mensaje de interés basado en tu lógica
elif self.esperar_segundo_mensaje and isinstance(message, list):
self.esperar_segundo_mensaje = False # Restablecer para futuros mensajes
self.recibido_updateClosedDeals = False # Restablecer el estado
elif self.esperar_segundo_mensaje and isinstance(message, dict) and self.successcloseOrder:
self.api.order_async = message
self.successcloseOrder = False # Restablecer para futuros mensajes
self.esperar_segundo_mensaje = False # Restablecer el estado
elif self.history_data_ready and isinstance(message, dict):
self.history_data_ready = False
self.api.history_data = message["data"]
elif self.updateStream and isinstance(message, list):
self.updateStream = False
self.api.timesync.server_timestamp = message[0][1]
# print("server_timestamp asignado:", timesync.server_timestamp)
elif self.updateHistoryNew and isinstance(message, dict):
self.updateHistoryNew = False
self.api.historyNew = message
return
else:
pass
# print(message)
if message.startswith('0{"sid":"'):
# print(f"{self.url.split('/')[2]} got 0 sid send 40")
await self.websocket.send("40")
elif message == "2":
# print(f"{self.url.split('/')[2]} got 2 send 3")
await self.websocket.send("3")
elif message.startswith('40{"sid":"'):
# print(f"{self.url.split('/')[2]} got 40 sid send session")
await self.websocket.send(self.ssid)
elif message.startswith('451-['):
# Eliminar el prefijo numérico y el guion para obtener el JSON válido
json_part = message.split("-", 1)[1]
# Convertir la parte JSON a un objeto Python
message = json.loads(json_part)
if message[0] == "successauth":
await on_open()
elif message[0] == "successupdateBalance":
global_value.balance_updated = True
elif message[0] == "successopenOrder":
global_value.result = True
# Si es el primer mensaje de interés
elif message[0] == "updateClosedDeals":
# Establecemos que hemos recibido el primer mensaje de interés
self.recibido_updateClosedDeals = True
self.esperar_segundo_mensaje = True # Establecemos que esperamos el segundo mensaje de interés
await self.websocket.send('42["changeSymbol",{"asset":"AUDNZD_otc","period":60}]')
elif message[0] == "successcloseOrder":
self.successcloseOrder = True
self.esperar_segundo_mensaje = True # Establecemos que esperamos el segundo mensaje de interés
elif message[0] == "loadHistoryPeriod":
self.history_data_ready = True
elif message[0] == "updateStream":
self.updateStream = True
elif message[0] == "updateHistoryNew":
self.updateHistoryNew = True
async def on_error(self, error): # pylint: disable=unused-argument
"""Method to process websocket errors."""
logger = logging.getLogger(__name__)
logger.error(error)
global_value.websocket_error_reason = str(error)
global_value.check_websocket_if_error = True
async def on_close(self, error): # pylint: disable=unused-argument
"""Method to process websocket close."""
logger = logging.getLogger(__name__)
logger.debug("Websocket connection closed.")
global_value.websocket_is_connected = False
@chema2411 you mean login with auth token. I think about email/password login. I tried to make login by email and password by api, but stuck on captcha (resolve captcha by 2captcha but pocket option always say, that its incorrect)
@vladdd183 Yes, I am referring to ssid login, which is easier than with selenium. It would be ideal in the future to be able to do this with a username and password.
To keep the connection active you must send a 42[`ps'] message every about 20 seconds or else the server closes the connection with a 41 message.
just wanted to ask about that, you beat me to it!) i saw it, but didn't understand what the message was for, i had it working without it just with ping pong ("2" -- "3" messages)
@vladdd183 Yeah. With just ping pong it works but in a short period of time the server kicks you out and you have to connect to another one.
I didn't know that, thank you very much!
Hello! I'm doing web socket reverse engineering too, ran into a problem, I'm doing the same as you:
- I connect to the web socket
- I get "0 sid..."
- Send "40" in response
- Receive message "40 sid..."
- I reply with "42 auth session"
- I get "41" in reply
async def process_message(message, websocket): print(message) if message.startswith('0{"sid":"'): message = message.lstrip("0") data = json.loads(message) print("got 0 sid send 40 ") await websocket.send("40") elif message == "2": print("got 2 send 3") await websocket.send("3") elif message.startswith('40{"sid":"'): print("got 40 sid send session") data = r"""42["auth",{"session":"a:4:{s:10:"session_id";s:32:"c53eec05c6f8a8be2d134d4fd55266f8";s:10:"ip_address";s:14:"46.138.176.190";s:10:"user_agent";s:101:"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";s:13:"last_activity";i:1707850603;}9f383935faff5a86bc1658bbde8c61e7","isDemo":1,"uid":72038016,"platform":3}]""" await websocket.send(data)
I don't understand what this is about, could you please advise me?
You should check the ssid that it is not expired since it expires in a period of time, I think one or two days, I'm not sure.
@theshadow76 Did you try the code I had?
Hello! I'm doing web socket reverse engineering too, ran into a problem, I'm doing the same as you:
- I connect to the web socket
- I get "0 sid..."
- Send "40" in response
- Receive message "40 sid..."
- I reply with "42 auth session"
- I get "41" in reply
async def process_message(message, websocket): print(message) if message.startswith('0{"sid":"'): message = message.lstrip("0") data = json.loads(message) print("got 0 sid send 40 ") await websocket.send("40") elif message == "2": print("got 2 send 3") await websocket.send("3") elif message.startswith('40{"sid":"'): print("got 40 sid send session") data = r"""42["auth",{"session":"a:4:{s:10:"session_id";s:32:"c53eec05c6f8a8be2d134d4fd55266f8";s:10:"ip_address";s:14:"46.138.176.190";s:10:"user_agent";s:101:"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";s:13:"last_activity";i:1707850603;}9f383935faff5a86bc1658bbde8c61e7","isDemo":1,"uid":72038016,"platform":3}]""" await websocket.send(data)
I don't understand what this is about, could you please advise me?
You should check the ssid that it is not expired since it expires in a period of time, I think one or two days, I'm not sure.
it old, i had resolve it
error was in backslahsen on qoutes
I will test the code in like 1 hour
Ok, please let me know, I know that together we can refine it more and have a good code.
Yes, this is awesome, once tested, I will work on other parts, maybe if you want to help more, we should talk, so that I don't code the same features that you work in.
Ok, perfect, that sounds good to me, I was thinking about starting to work on obtaining candle streams because I can reuse some functions that I created to obtain candle data, but if you want, you can take care of that.
Great, I'll do other extra stuff
looks like it is not connecting here:
wss://api-us-north.po.market/socket.io/?EIO=4&transport=websocket
Conectado a: wss://api-us-north.po.market/socket.io/?EIO=4&transport=websocket
False check connect
Get balance: None
here is my code:
import random
import time
from pocketoptionapi.stable_api import PocketOption
ssid = (r'42["auth",{"session":"a:4:{s:10:\"session_id\";s:32:\"a1dc009a7f1f0c8267d940d0a036156f\";s:10:\"ip_address\";s:12:\"190.162.4.33\";s:10:\"user_agent\";s:120:\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OP\";s:13:\"last_activity\";i:1709914958;}793884e7bccc89ec798c06ef1279fcf2","isDemo":0,"uid":27658142,"platform":1}]')
api = PocketOption(ssid)
def direction():
# Selecciona aleatoriamente entre 'call' y 'put'
return random.choice(['call', 'put'])
if __name__ == "__main__":
api.connect()
time.sleep(2)
print(api.check_connect(), "check connect")
#data_candles = api.get_candles("AUDNZD_otc", 60, time.time(), count_request=1)
print(f"Get balance: {api.get_balance()}")
while api.check_connect():
print(api.get_server_timestamp(), "server datetime")
time.sleep(1)
# Cierra la conexión con la API
@chema2411 do you know this issue?
Hello! I'm doing web socket reverse engineering too, ran into a problem, I'm doing the same as you:
I don't understand what this is about, could you please advise me?