JSON requests get specific value from dict Python - python

I'm trying to use this code from YouTube to detect a specific username in a Discord chat. If the username is, say "123" then print that as "Found: 123". Tried different ways to no avail.
Here's my full code:
import websocket
import json
import threading
import time
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)
def heartbeat(interval, ws):
print("Heartbeat begin")
while True:
time.sleep(interval)
heartbeatJSON = {
"op": 1,
"d": "null"
}
send_json_request(ws, heartbeatJSON)
print("Heartbeat sent")
ws = websocket.WebSocket()
ws.connect('wss://gateway.discord.gg/?v=6&encording=json')
event = receive_json_response(ws)
heartbeat_interval = event['d']['heartbeat_interval'] / 1000
threading._start_new_thread(heartbeat, (heartbeat_interval, ws))
token = "tokenhere"
payload = {
'op': 2,
"d": {
"token": token,
"properties": {
"$os": "windows",
"$browser": "chrome",
"$device": "pc"
}
}
}
send_json_request(ws, payload)
while True:
event = receive_json_response(ws)
try:
print(f"{event['d']['author']['username']}: {event['d']['content']}")
print(event)
op_code = event('op')
for specific in event:
if specific['d']['author']['username'] == "123":
print(f'Found: {specific}')
else:
print("Not found")
if op_code == 11:
print("Heartbeat received")
except:
pass
Code that doesn't work (but no errors):
for specific in event:
if specific['d']['author']['username'] == "123":
print(f'Found: {specific}')
else:
print("Not found")
What seems to be wrong? Thank you.

I shouldn't have been using for loop. I tried the below code, and it worked. It was such a simple mistake:
specific = event['d']['author']['username']
if specific == "123":
print(f"Found")
else:
print("Not found")

Related

Editing an ephemeral message posted by a slack bot

I've been working on creating a slack bot. I have been working on a command that can set the status of all users in a channel by recording some data into a database. For larger channels, this can take a while. My goal is to post a message that says "Processing" and then every second, replacing it with a variation of the word with various amounts of periods to indicate to users that the command indeed went through but was just computing. However, I have been encountering 2 issues.
Here is what my code currently looks like:
#app.route('/set', methods=['POST'])
def set():
data = request.form
user_id = data.get('user_id')
response_url = data.get("response_url")
start_time = time.time()
try:
x = threading.Thread(target=set_main, args=(data,))
x.start()
except Exception:
exception = traceback.format_exc()
dealWithUnknownErrors(user_id=user_id, exception=exception)
requests.post(response_url, json={})
return ""
def set_main(data):
user_id = data.get('user_id')
text = data.get('text')
channel_id = data.get('channel_id')
response_url = data.get("response_url")
text_list = text.split()
memberData = getMemberData()
x = None
if not memberData.get(user_id).get("leadership").get("isLeadership"):
whisperAndCatchErrors(text=ACCESS_DENIED_TEXT, user_id=user_id, channel_id=channel_id)
elif len(text_list) == 0:
whisperAndCatchErrors(text=SET_UNKNOWN_COMMAND_TEXT, user_id=user_id, channel_id=channel_id)
elif len(text_list) == 1 and text_list[0].lower() == "help":
whisperAndCatchErrors(text=SET_HELP_TEXT, user_id=user_id, channel_id=channel_id)
elif text_list[0].lower() == "leadershipstatus":
x = threading.Thread(target=set_leadershipStatus_main, args=(user_id, channel_id, text_list,))
elif text_list[0].lower() == "position":
x = threading.Thread(target=set_position_main, args=(user_id, channel_id, text_list,))
elif text_list[0].lower() == "instrument":
x = threading.Thread(target=set_instrument_main, args=(user_id, channel_id, text_list,))
else:
whisperAndCatchErrors(text=SET_UNKNOWN_COMMAND_TEXT, user_id=user_id, channel_id=channel_id)
x.start() if x else None
if x:
while x.is_alive():
message = {
"replace_original": True,
"text": "Processing"
}
requests.post(response_url, json=message)
time.sleep(1)
message = {
"replace_original": True,
"text": "Processing."
}
requests.post(response_url, json=message)
time.sleep(1)
message = {
"replace_original": True,
"text": "Processing.."
}
requests.post(response_url, json=message)
time.sleep(1)
message = {
"replace_original": True,
"text": "Processing..."
}
requests.post(response_url, json=message)
time.sleep(1)
message = {
"delete_original": True
}
requests.post(response_url, json=message)
The first issue that I have been running into is that the messages are not replacing the previous messages. They instead just post the messages into the channel, one after the other. I am unsure why they do not edit the preceding message.
The second issue is that I cannot use requests.post(response_url, json=message) more than 5 times before it stops allowing responses to be posted to the server (source), but ephemeral messages cannot be edited using the slack API (source).
Is there a way to add this "animation"? Also, is there a reason that my responses are not editing the previous messages? If I can fix that, then I could at least ditch the "animation" stuff and instead just post a single message to not go over the response limit.
Thanks for the help!

How to send predefined messages to specified discord channels at fixed intervals?

from http.client import HTTPSConnection
from sys import stderr
from json import dumps
from time import sleep
header_data = {
"content-type": "application/json",
"user-agent": "discordapp.com",
"authorization": "IPlaceTokenHere",
"host": "discordapp.com",
"referer": "TheChannelUrlhere"
}
def get_connection():
return HTTPSConnection("discordapp.com", 443)
def send_message(conn, channel_id, message_data):
try:
conn.request("POST", f"/api/v6/channels/{channel_id}/messages", message_data, header_data)
resp = conn.getresponse()
if 199 < resp.status < 300:
print("Message sent...")
pass
else:
stderr.write(f"Received HTTP {resp.status}: {resp.reason}\n")
pass
except:
stderr.write("Failed to send_message\n")
def main():
message_data = {
"content": "Hello, world!",
"tts": "false",
}
send_message(get_connection(), "ChannelIDhere", dumps(message_data))
if __name__ == '__main__':
while True: # Infinite loop
main() # Send the message
sleep(3600) # Wait an hour to repeat
I am doing this to send messages like 'Good morning' etc (hosted on my webserver). The thing is I want to add many channels(Since I own a lot of servers) with different messages. I am unable to figure out how.
You can simply pass multiple channel IDs to the send_message function, loop through them and send a message
def send_message(conn, message_data, *channel_ids):
for channel_id in channel_ids:
try:
conn.request("POST", f"/api/v6/channels/{channel_id}/messages", message_data, header_data)
resp = conn.getresponse()
if 199 < resp.status < 300:
print("Message sent...")
else:
stderr.write(f"Received HTTP {resp.status}: {resp.reason}\n")
except:
stderr.write("Failed to send_message\n")
def main():
message_data = {
"content": "Hello, world!",
"tts": "false",
}
send_message(
get_connection(),
dumps(message_data),
"CHANNEL ID 1",
"CHANNEL ID 2",
"CHANNEL ID 3"
)
Note that now the channel ID's must be entered as the last arguments. Also I removed the unnecessary pass keyword in the if and else part as they're useless there. If you'd like to send the messages in different timestamps you should look at asyncio to functions things concurrently.
EDIT:
If you also want to send different messages per channel you can simply map the channel ID to a message in a dict
def send_message(conn, channels): # You can also use kwargs
for channel_id, message_data in channels.items():
try:
conn.request("POST", f"/api/v6/channels/{channel_id}/messages", message_data, header_data)
resp = conn.getresponse()
if 199 < resp.status < 300:
print("Message sent...")
else:
stderr.write(f"Received HTTP {resp.status}: {resp.reason}\n")
except:
stderr.write("Failed to send_message\n")
def main():
data = {
"CHANNEL ID 1": json.dumps({"content": "message for channel 1", "tts": "false"}),
"CHANNEL ID 2": json.dumps({"content": "message for channel 2", "tts": "false"}),
"CHANNEL ID 3": json.dumps({"content": "message for channel 3", "tts": "false"})
}
send_message(get_connection(), data)
This can be improved a lot, I'll leave that to you.

Using an 'If' statement to check JSON data webhook response

I am using the requests library and made a request to the twitch api. I have filtered the data into variables but I would like to know if there was a way I could use an 'If' statement on the variables. The data is stored as JSON.
Edit: I don't get any errors but the code just doesn't run.
My code is below:
client = discord.Client()
token = open("token.txt", "r").read()
myclient = pymongo.MongoClient("mongodb url")
mydb = myclient["Cluster0"]
mycol = mydb["live"]
cursor = mycol.find({ "type": "user" }, {'_id': 0, 'twitch': 1, 'channelID': 1})
for item in cursor:
x = item.get('twitch')
channelid = item.get('channelID')
print(x)
print(channelid)
headers = {
'client-id': 'twitch client id',
'Authorization': 'twitch ouath token',
}
params = (
('query', x),
)
response = requests.get('https://api.twitch.tv/helix/search/channels', headers=headers, params=params)
final = response.json()
finali = final['data'][0]['is_live']
finale = final['data'][0]['thumbnail_url']
finaly = final['data'][0]['title']
finalo = final['data'][0]['started_at']
print(final)
# I would like the If here, Eg. If finali == "True":
async def my_background_task():
await client.wait_until_ready()
counter = 0
print("someone live")
channel = client.get_channel(channelid)
while not client.is_closed():
counter += 1
embedVar2 = discord.Embed(title="" + x + " is now live on Twitch!", description="" + finaly + "", url="https://twitch.tv/" + x + "", color=0x0C8BC2)
embedVar2.set_image(url="" + finale + "")
await channel.send("#everyone")
await channel.send(embed=embedVar2)
await asyncio.sleep(60) # task runs every 60 seconds
client.loop.create_task(my_background_task())
client.run('token')
Finali should return a bool from that json so rather than testing if finali == "True" you'd just check: if finali: which is if finali == True but shorter.
So the answer is yes you can use an if statement with those variables.

Why is my websocket request "unauthorized" only when written in OOP, when the same works perfectly when written with just functions?

I'm writing a Python program that does some trading automation. The API I work with is from Deribit, whose preferred transport mechanism is Websocket. I'm a complete newbie to Python's websockets and asyncio modules.
Here's the code I first wrote for authenticating my client and then sending a separate private message to get an order position from the account, written only with functions and no classes:
import asyncio
import websockets
import json
CL_ID = 'qxv0EeAu'
CL_SECRET = 't24F49ocH1_qFawiKnEyqlWF5D-haABb31O8xCQhySg'
REQ_URL = 'wss://test.deribit.com/ws/api/v2'
acc_token = ''
msg = {
"jsonrpc": "2.0",
"id": 1,
"params": {}
}
async def auth_api():
global msg
global acc_token
msg["method"] = "public/auth"
msg["params"] = {
"grant_type": "client_credentials",
"client_id": CL_ID,
"client_secret": CL_SECRET,
"scope": "session:test"
}
async with websockets.connect(REQ_URL) as websocket:
await websocket.send(json.dumps(msg))
while websocket.open:
response = await websocket.recv()
response_json = json.loads(response)
acc_token = response_json["result"]["access_token"]
return
async def get_position(websocket, instrument):
global msg
global acc_token
msg["id"] += 1
msg["method"] = "private/get_position"
msg["params"] = {
"access_token": acc_token,
"instrument_name": instrument
}
await websocket.send(json.dumps(msg))
while websocket.open:
response = await websocket.recv()
return response
async def main():
global msg
await auth_api()
async with websockets.connect(REQ_URL) as websocket:
response = await get_position(websocket, "BTC-PERPETUAL")
print(response)
asyncio.get_event_loop().run_until_complete(main())
It works perfectly fine. Here's my result:
{"jsonrpc":"2.0","id":2,"result":{"total_profit_loss":0.000209124,"size_currency":-0.017402402,"size":-150.0,"settlement_price":8649.9,"realized_profit_loss":2.67e-7,"open_orders_margin":0.0,"mark_price":8619.5,"maintenance_margin":0.000100079,"leverage":100,"kind":"future","instrument_name":"BTC-PERPETUAL","initial_margin":0.000174039,"index_price":8619.45,"floating_profit_loss":0.000061161,"estimated_liquidation_price":-14.95,"direction":"sell","delta":-0.017402402,"average_price":8724.34},"usIn":1573756522511975,"usOut":1573756522512240,"usDiff":265,"testnet":true}
I decided to rewrite it the OOP way, and here's the class I created (the file is named "Call_Deribit"):
import asyncio, websockets, json
class WSClient():
def __init__(self, key=None, secret=None, url=None):
self.api_key = key
self.api_secret = secret
self.msg = {
"jsonrpc": "2.0",
"id": 0
}
if url:
self.host = url
else:
self.host = 'wss://test.deribit.com/ws/api/v2'
async def call_api(self, msg):
async with websockets.connect(self.host) as websocket:
print("Connected to URL:", self.host)
try:
await websocket.send(msg)
while websocket.open:
response = await websocket.recv()
response_json = json.loads(response)
return response_json
except Exception as e:
return e
def request(self, method, params, session=None):
msg = self.msg
msg["id"] += 1
msg["method"] = method
msg["params"] = params
if session != None:
msg["params"]["scope": "session:{}".format(session)]
return asyncio.get_event_loop().run_until_complete(self.call_api(json.dumps(msg)))
def get_order_book(self, instrument):
method = "public/get_order_book"
params = {
"instrument_name": instrument
}
return self.request(method, params)
And here's the main file I'm accessing the class from and where I make all the requests:
import json, asyncio, websockets
from Call_Deribit import WSClient
CL_ID = 'qxv0EeAu'
CL_SECRET = 't24F49ocH1_qFawiKnEyqlWF5D-haABb31O8xCQhySg'
REQ_URL = 'wss://test.deribit.com/ws/api/v2'
method_auth = "public/auth"
params_auth = {
"grant_type": "client_credentials",
"client_id": CL_ID,
"client_secret": CL_SECRET
}
main_client = WSClient(key=CL_ID, secret=CL_SECRET, url=REQ_URL)
auth_response = main_client.request(method_auth, params_auth)
acc_token = auth_response["result"]["access_token"]
method_pos = "private/get_position"
params_pos = {
"access_token": acc_token,
"instrument_name": "BTC-PERPETUAL"
}
position = main_client.request(method_pos, params_pos)
print(position)
The first request for authentication is working this time, and I'm able to extract the access token as well, but the second private/get_position message is, for whatever reason, returning an unauthorized error.
{'jsonrpc': '2.0', 'id': 1, 'error': {'message': 'unauthorized', 'code': 13009}, 'testnet': True, 'usIn': 1573756936534405, 'usOut': 1573756936534629, 'usDiff': 224}
I've spent hours on it, and I seem to be doing exactly the same thing in the OOP version as I did on the original one. My familiarity with OOP and its concepts (such as inheritance) is limited, so I'd like to know what I'm missing here, and why my code isn't working in the OOP version, despite following the same exact workflow as in the original version.
Here's the documentation for the Deribit API: https://docs.deribit.com/v2/?python#json-rpc
Any help would be greatly appreciated.
Adding the scope under params_auth in the main file works:
params_auth = {
"grant_type": "client_credentials",
"client_id": CL_ID,
"client_secret": CL_SECRET,
"scope": "session:test"
}

Ambiguity in understanding the Websocket Python

I am trying this :
import websocket
import json
def on_open(ws):
json_data = json.dumps({'ticks':'R_100'})
ws.send(json_data)
def on_message(ws, message):
print('ticks update: %s' % message)
if __name__ == "__main__":
apiUrl = "wss://ws.binaryws.com/websockets/v3?app_id=1089"
ws = websocket.WebSocketApp(apiUrl, on_message = on_message, on_open = on_open)
ws.run_forever()
This is working fine. But the issue is when I want to have a history using the payload:
{
"ticks_history": "R_50",
"end": "latest",
"start": 1,
"style": "ticks",
"adjust_start_time": 1,
"count": 10
}
I am not understanding what exactly I needed to do to get the information as the app is running and it won't serve the request to me.
Please help me get through this.

Categories