How to Index Websocket Data Stream - python

I've successfully connected to the Bitstamp websocket and I am now attempting to index the data stream that I receive. Specifically, I want to save bids[0][0] into a best_price variable:
{'data': {'timestamp': '1615553987', 'microtimestamp': '1615553987492634', 'bids': [['56355.57', '0.09439734'], ['56347.20', '0.03743896'], ['56346.03', '0.47172493']....etc
The problem is that I get a "subscription succeeded" message when I first connect:
{'event': 'bts:subscription_succeeded', 'channel': 'order_book_btcusd', 'data': {}}
This means I get the following error, because I cannot index the None returned from the empty data steam:
IndexError: too many indices for array: array is 0-dimensional, but 1 were indexed
Here is my code
import asyncio
import websockets
import json
import numpy as np
def error_handler(err):
pass
def handler(msg):
pass
async def bitstamp_connect(callback):
uri = "wss://ws.bitstamp.net/"
subscription = {
"event": "bts:subscribe",
"data": {
"channel": "order_book_btcusd"
}
}
async with websockets.connect(uri) as websocket:
await websocket.send(json.dumps(subscription))
while True:
msg = json.loads(await websocket.recv())
bids = np.array(msg['data'].get('bids'))
#print(bids)
print(bids[0][0])
asyncio.get_event_loop().run_until_complete(bitstamp_connect(handler))

The problem can be easily solved by simply adding an if statement checking if the message received was a 'subscription successful' message or a 'data' message. Change your while loop to the following:
while True:
msg = json.loads(await websocket.recv())
# Check what type of message we received
if msg['event'] == 'data':
bids = np.array(msg['data'].get('bids'))
print(bids[0][0])
elif msg['event'] == 'bts:subscription_succeeded':
# You can put code here if you want to do something when first subscribing
pass

Related

Warning discord.getaway "discord.gateway: Shard ID None heartbeat blocked for more than 10 seconds."

I tried to write a Discord bot that forwards messages from one server to another. But I get a warning that disconnects my connection to the discord gateway. I read that it is possible because of tyme.slep(), but without it, the connection is always interrupted. As I understand it, DDOS protection is activated due to a large number of requests.
import asyncio
import websocket
import json
from threading import Thread
import discord
import requests
from io import BytesIO
import time
from discord.ext import tasks
# Bot
bot_token = "anything"
user_token = "anything"
client = discord.Client(intents=discord.Intents.default())
# Channels list
f = open('channels.txt', 'r')
channels_file = f.read()
channels_array = channels_file.strip().split('\n')
# Connect func
def send_json_request(ws, request):
ws.send(json.dumps(request))
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
#WebSoket
def on_closed(ws):
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
ws = websocket.WebSocket(on_close=on_closed)
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
def get_attachment_media(media):
media_array = []
for i in media:
response = requests.get(i['url'])
im = BytesIO(response.content)
print(im)
media_array.append(discord.File(im))
return media_array
def get_channel(id):
for i in channels_array:
if i == id:
return True
return False
#Heartbeat
def heartbeat(interval):
print("Heartbeat begin")
while True:
time.sleep(interval)
heartbeatJSON = {
"op": 1,
"d": "null"
}
send_json_request(ws, heartbeatJSON)
print("Heartbeat sent")
#tasks.loop(seconds=0.5)
async def main():
channel = client.get_channel(anything)
event = receive_json_response(ws)
try:
if event['d']['author']['id'] == 'anything':
return
id_channel = event['d']['channel_id']
id_guild = event['d']['guild_id']
if get_channel(id_channel):
content = event['d']['content']
attachment_media = get_attachment_media(event['d']['attachments'])
await channel.send(content, files=attachment_media)
op_code = event('op')
if op_code == 11:
print('Heartbeat recieved')
except:
pass
#client.event
async def on_ready():
event = receive_json_response(ws)
heartbeat_interval = event['d']['heartbeat_interval'] / 1000
send_json_request(ws, {
"op": 2,
"d": {
"token": user_token,
"properties": {
"$os": 'linux',
"$browser": 'chrome',
"$device": 'pc'
}
}
})
main.start()
asyncio.run(heartbeat(heartbeat_interval))
client.run(bot_token)
I recommend you to check this answer and adjust it to your code.
However, if you are just trying to make your bot copy the contenet of the messages sent in one server and sending to another one, you can do it in a easier way using the on_message() event. This is the entire code, which should also prevent any warning (unless the bot tries to send too many messages in a short period of time):
import discord
intents = discord.Intents.default()
intents.message_content = True # You are missing the message_content intent! (needed to read the content of the guild's messages)
client = discord.Client(intents=intents)
TOKEN = "Your Token"
guild_id = 123456789 # The guild you want your bot to send the messages to
channel_id = 987654321 # The channel of the guild you want your bot to send the messages to
guild = None
channel = None
#client.event
async def on_ready():
global guild, channel, guild_id, channel_id
await client.wait_until_ready()
guild = client.get_guild(guild_id)
channel = guild.get_channel(channel_id)
print("Logged")
#client.event
async def on_message(message : discord.Message):
if message.author == client.user: # You don't want to send the own bot messages
return
if message.guild.id == guild_id: # You don't want to send the messages from the own guild your bot is sending the messages to
return
await channel.send(f"{message.author}: {message.content}") # Add attachments if you want
client.run(TOKEN)

How can I access dict key while using asyncio?

This is a simple program to retrieve candlestick data from Binance exchange for several pairs. I found out that it could be done with asyncio package.
import websockets
import asyncio
import json
import pprint
async def candle_stick_data():
url = "wss://stream.binance.com:9443/ws/" #steam address
first_pair = 'xlmbusd#kline_1m' #first pair
async with websockets.connect(url+first_pair) as sock:
pairs = '{"method": "SUBSCRIBE", "params": ["xlmbnb#kline_1m","bnbbusd#kline_1m" ], "id": 1}' #other pairs
await sock.send(pairs)
print(f"> {pairs}")
while True:
resp = await sock.recv()
resp=json.loads(resp)
pprint.pprint(resp)
candle = resp['k']
asyncio.get_event_loop().run_until_complete(candle_stick_data())
I am getting messages and changing type to dict with json.loads(resp). My question is how can I access dict values because candle = resp['k'] causes "Key error 'k'". I am new to asyncio maybe I don't need it at all to retrieve data for several pairs.
updated message screenshot
Your first incoming message really does not have 'k' key in dictionary.
I just added if else block to your code and it works well:
import websockets
import asyncio
import json
import pprint
async def candle_stick_data():
url = "wss://stream.binance.com:9443/ws/" #steam address
first_pair = 'xlmbusd#kline_1m' #first pair
async with websockets.connect(url+first_pair) as sock:
pairs = '{"method": "SUBSCRIBE", "params": ["xlmbnb#kline_1m","bnbbusd#kline_1m" ], "id": 1}' #other pairs
await sock.send(pairs)
print(f"> {pairs}")
while True:
resp = await sock.recv()
resp = json.loads(resp)
# get 'k' key value if it exits, otherwise None
k_key_val = resp.get('k', None)
# easy if else block
if not k_key_val:
print(f"No k key found: {resp}")
else:
pprint.pprint(k_key_val)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(candle_stick_data())

iot edge direct method handler in python

I have created a module for a Bacnet scan and it will respond with a list of devices and its address as a result. But I'm having trouble implementing a direct method handler in python. When i first tried implementing it myself i got this error. Which could mean I didn't successfully register the direct method callback. I have some references but it was from C# and azure docs is not helping me figure out the right method to register the callback. for IoTHubModuleClient there's a on_method_request_received and a receive_method_request. appreciate any help!
def iothub_client_scan_run():
try:
iot_client = iothub_client_init()
bacnet_scan_listener_thread = threading.Thread(target=device_method_listener, args=(iot_client,))
bacnet_scan_listener_thread.daemon = True
bacnet_scan_listener_thread.start()
while True:
time.sleep(1000)
def device_method_listener(iot_client):
while True:
# Receive the direct method request
method_request = iot_client.receive_method_request()
print (
"\nMethod callback called with:\nmethodName = {method_name}\npayload = {payload}".format(
method_name=method_request.name,
payload=method_request.payload
)
)
if method_request.name == "runBacnetScan":
response = bacnet_scan_device(method_request)
else:
response_payload = {"Response": "Direct method {} not defined".format(method_request.name)}
response_status = 404
# Send a method response indicating the method request was resolved
print('Sending method response')
iot_client.send_method_response(response)
print('Message sent!')
Edit:
Here is my route config
I was able to resolve my issue or at least find the root cause and it was my network configuration under the createOptions. It seems like there's an issue when I'm trying to do NetworkMode: host and connects to the IotModuleClient.connect_from_edge_environment via connect with connection string. I'm still trying to tweak the connection configuration but at least i know its not on the code.
async def method_request_handler(module_client):
while True:
method_request = await module_client.receive_method_request()
print (
"\nMethod callback called with:\nmethodName = {method_name}\npayload = {payload}".format(
method_name=method_request.name,
payload=method_request.payload
)
)
if method_request.name == "method1":
payload = {"result": True, "data": "some data"} # set response payload
status = 200 # set return status code
print("executed method1")
elif method_request.name == "method2":
payload = {"result": True, "data": 1234} # set response payload
status = 200 # set return status code
print("executed method2")
else:
payload = {"result": False, "data": "unknown method"} # set response payload
status = 400 # set return status code
print("executed unknown method: " + method_request.name)
# Send the response
method_response = MethodResponse.create_from_method_request(method_request, status, payload)
await module_client.send_method_response(method_response)
print('Message sent!')
def stdin_listener():
while True:
try:
selection = input("Press Q to quit\n")
if selection == "Q" or selection == "q":
print("Quitting...")
break
except:
time.sleep(10)
# Schedule task for C2D Listener
listeners = asyncio.gather(input1_listener(module_client), twin_patch_listener(module_client), method_request_handler(module_client))

Check if a .json dictionary contains a user's id discord.py

I'm Creating a bot with reCAPTCHA and leveling system.
The data is being stored in a .JSON file (temporarily, I'm trying to learn how to use MySQL and transfer the data to a proper db to prevent corruption of the data)
The .JSON file looks a bit like this
{
"user": [
{
"u": "224906648890638337",
"m": 89,
"lvl": 0,
"score": 28,
"captcha": false,
"captchacode": 123456
},
{
"u": "635042028643811357",
"m": 0,
"lvl": 0,
"score": 0,
"captcha": false,
"captchacode": 12345
]
}
The Captcha code is the code that was sent to a user when they joined the server in the form of an Image.
What I want to do is have a verify command, that looks into the .JSON file and returns the captcacode of the user that sent the verify command.
And then it checks if the captchacode they were sent matches with the one they sent in the verify command.
My code for that:
#commands.command()
async def verification(self, ctx, code):
with open("JSON_files/testdb.json", "r") as f:
db = json.load(f)
if captchacode == code:
await ctx.send("Captcha successfully completed ✅")
remove_unverified = discord.utils.get(ctx.message.guild.roles, name="unverified")
await ctx.author.remove_roles(remove_unverified)
else:
await ctx.send("⛔| Invalid captcha! Make sure to type: `!verification (code that was sent to you)` but without the brackets")
If anyone could help me with that, that would be great.
Comment or just ask if anything needs clarification.
Thanks!
First, you are missing a } in your json file
"captcha": false,
"captchacode": 12345
} <- here
]
}
In your verification function, you can iterate through every user and then check, if the captchacode matches.
Your verification function could be looking like this
#commands.command()
async def verification(self, ctx, code):
with open("JSON_files/testdb.json", "r") as f:
db = json.load(f)
captchacode_matched = False
# iterate through every user
for user in db["user"]:
# get the captchacode
user_captchacode = user["captchacode"]
# check if the code matches
if user_captchacode == code:
captchacode_matched = True
await ctx.send("Captcha successfully completed ✅")
remove_unverified = discord.utils.get(ctx.message.guild.roles, name="unverified")
await ctx.author.remove_roles(remove_unverified)
# break the loop
break
# if no captchacode matched, send invalid captcha
if captchacode_matched == False:
await ctx.send("⛔| Invalid captcha! Make sure to type: `!verification (code that was sent to you)` but without the brackets")
I hope this will work for you

Can't load JSON-type message in client

I can't load JSON-type message with dictionary inside when client receives it from server
Dictionary contains: message, sender address, time of sending
When i dump dictionary to JSON and send it to client, client tries to load this dict, so he can't use data from dictionary from server and print it to user
Also, when client sending message he can write "/r" to receive data from server, that means client can receive big data at one time.
This is only parts of code with sending and receiving data from server and in client
SERVER
def serialize_data(self, sending_time, message, address,):
message_dict = {
'sending_time': sending_time,
'message': message,
'sender_address': address
}
serialized_dict = dumps(message_dict)
return serialized_dict
def send_messages(self, data_dict, address):
if enable_log:
message = f'{self.get_time()}, {data_dict["message"]}, {address}'
self.save_log(message, 'a')
message = self.serialize_data(self.get_time(), data_dict['message'], address)
for client in self.connections_list:
message = dumps(message)
client.sendall(bytes(message, encoding='utf-8'))
CLIENT
def receive_data(self,):
while True:
try:
data = self.sock.recv(2048).decode('utf-8')
print(data)
data_dict = loads(data)
for d in data_dict:
d = loads(d)
d = f"{d['sending_time']} {d['sender_address']} - {d['message']}"
print(d)
except timeout:
break
I getting this in client when i trying to receive data from server:
"{\"sending_time\": \"2019-05-17 | 21:16:32 \", \"message\": \"connected!\", \"sender_address\": \"127.0.0.1\"}""{\"sending_time\": \"2019-05-17 | 21:16:33 \", \"message\": \"abcd\", \"sender_address\": \"127.0.0.1\"}"
That is because you are calling json.dumps() twice.
def serialize_data(self, sending_time, message, address,):
message_dict = {
'sending_time': sending_time,
'message': message,
'sender_address': address
}
serialized_dict = dumps(message_dict) # -------------> first time
return serialized_dict
def send_messages(self, data_dict, address):
if enable_log:
message = f'{self.get_time()}, {data_dict["message"]}, {address}'
self.save_log(message, 'a')
message = self.serialize_data(self.get_time(), data_dict['message'], address)
for client in self.connections_list:
message = dumps(message) # ------------------> Second time
client.sendall(bytes(message, encoding='utf-8'))
Removing either one of them should fix it.

Categories