i have script like this
def on_message(ws, message):
if str(message).split()[0] == '<open':
print('Opening Game')
print(message)
elif str(message).split()[0] == '<start':
print('Game Started')
print(message)
elif str(message).split()[0] == '<catch':
print(message)
if str(message).split()[2] == '1':
#send catch value 1
else:
pass
elif str(message).split()[0] == '<result':
print(message)
#result value of catch is '2'
else:
pass
and server send broadcast message like this
sending opening game
send start game
send random 'catch' value to client on range(1 - 100)
How can I set an condition for the next message that comes through on_message on a WebSocket stream without causing it to run on the current message?
Related
doji = False
def on_message(ws, message):
message = json.loads(message)
print("MESSAGE", message[0]['o'], message[0]['c'])
if abs(message[0]['c'] - message[0]['o']) <= 0.15:
print("DOJI, waiting for next trade bar")
print(api.submit_order(symbol=f"{message[0]['S']}", side="buy", notional="1", type="market", time_in_force="day"))
doji = True
if doji == True:
#Do x
Adding time.sleep doesn't help, just delays it, is there a way to use a thread that would exit after? Or maybe using async?
I've been working on creating a connect 4 game for my discord bot, the game itself works fine,
but if someone removes the message that contains the Board and the reactions which are used by users to play the game, the game will start to break and won't work as it should until someone restarts the bot:
turn = 0 #switches between 0 and 1 during the game
game_over = False
while not game_over:
try:
reaction, user = await client.wait_for("reaction_add", check = check)
if turn == 0:
#do stuff depending on what the emoji reaction is
if winning move():
game_over = True
else:
#do stuff depending on what the emoji reaction is
if winning_move():
game_over = True
#more things that aren't necessary to show
Is there a way for me to change the game_over to True after someone removes the message and/or check if the message has been deleted and change the variable to True through that?
for e.g:
#If the board's not in the channel:
await message.channel.send("Board was not found")
game_over = True
any help would be highly appreciated!
You can use asyncio.wait() function.
See an example below where I have implemented simple mini-game logic.
#client.command()
async def mini_game(ctx):
message = await ctx.send("test message") # send first message
done, pending = await asyncio.wait(
[
asyncio.create_task(client.wait_for("reaction_add", check=your_check)), # specify `your_check` function
asyncio.create_task(client.wait_for("message_delete", check=lambda m: m == message))
],
return_when=asyncio.FIRST_COMPLETED,
timeout=30 # you can specify timeout here
)
if done == set():
pass # if time limit exceeded
else:
coro = done.pop().result()
try:
reaction, member = coro # if user `member` has added `reaction`
except TypeError:
pass # if message has been deleted
You can adapt this code to suit your needs.
You can check if a message has been deleted by simple trying to fetch the message with the id it had before being deleted. If this returns a NotFound error, the message has been deleted:
def is_message_deleted(ctx, message_id):
try:
await ctx.fetch_message(message_id) #try to fetch the message
return False
except discord.error.NotFound: #if a NotFound error appears, the message is either not in this channel or deleted
return True
You can then include this function in your code:
if is_message_deleted(ctx, board_message.id):
await message.channel.send("Board was not found")
game_over = True
References:
context.fetch_message()
I made a discord bot that sends every 120 sec transactions from one ethereum addrs but i dont want to send same stuff over and over so if it send USDT token and Again in 120 sec try USDT to just skip it until it got new thing is that possble or not?
code:
import requests
import sys
import json
import discord
import time
btoken = "mytoken"
result=requests.get('https://api.ethplorer.io/getAddressHistory/0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be?apiKey=freekey&type=transfer')
result.status_code
result.text
result.json()
results = "soon:tm:"
def price_of_gas(inp):
def recursive_function(inp):
if type(inp) is list:
for i in inp:
ans = recursive_function(i)
if ans!=None: return ans
elif type(inp) is dict:
if 'name' in inp: return inp['name']
for i in inp:
ans = recursive_function(inp[i])
if ans!=None: return ans
else: return None
ans = recursive_function(inp)
return ans if ans else "Could NOT find the new token tx"
print (price_of_gas(result.json()))
class MyClient(discord.Client):
async def on_ready(self):
print('Logged on as', self.user)
async def on_message(self, message):
# don't respond to ourselves
if message.author == self.user:
return
if message.content == '.get':
await message.channel.send('Alert! Alert! Buy')
await message.channel.send(result.json()['operations'][0]['tokenInfo']['symbol'])
await message.channel.send(result.json()['operations'][0]['tokenInfo']['address'])
print ('get command was tryed')
else:
print ('comand not found')
if message.content == '.help':
await message.channel.send("try .get")
print ('help command was tryed')
if message.content == '.stop':
await message.channel.send('Bye...')
print('bye')
sys.exit()
if message.content == '.start':
while True:
# Code executed here
print ('done')
price_of_gas(result.json())
print (price_of_gas(result.json()))
await message.channel.send(price_of_gas(result.json()))
time.sleep(120)
#print(result.json()['operations'][0]['tokenInfo']['name'])
#print(result.json()['operations'][0]['tokenInfo']['symbol'])
#print(result.json()['operations'][0]['tokenInfo']['address'])
#print (result.json()['tokenSymbol'])
#print (result.text)
print ('done no errors')
print ('done no errors with check data')
client = MyClient()
client.run(btoken)
print ('done no errors 2')
so if user type .start bot will start while loop that sends newest tx from selected addrs but problem is it will send same stuff i just need some if statment in while loop or something.
You shoudn't use the requests module (it's blocking), you should use aiohttp instead
You also shoudn't use time.sleep as it also blocks the whole thread. You should use asyncio.sleep. (If you still stay with time.sleep you're not going to be able to use the bot when it's "sleeping")
Answering your question, you can simply have a variable with the value of the previous price/value and check if the new message is the same, if it's not - send it
while True:
price = price_of_gas(result.json())
# Checking if the `previous_price` var exists
if hasattr(self, "previous_price"):
# If yes, comparing the values
if self.previous_price != price:
# If they're not the same, send the message
await message.channel.send(f"Current price: {price}")
self.previous_price = price # Updating the variable
else:
# If the `previous_price` var doesn't exists, creating it
self.previous_price = price
await asyncio.sleep(120) # Remember to import asyncio
Making HTTP requests with aiohttp
import aiohttp
async def main():
async with aiohttp.ClientSession() as session:
async with session.get("URL") as resp:
data = await resp.json()
# Note: you should create ONE session per application
EDIT:
If you want to use blocking functions (like the price_of_gas) you can use the next method
await self.loop.run_in_executor(None, price_of_gas, result.json())
More info here
I have created 2 ports as input, to capture data from a keyboard and a midi surface controller (which has a bunch of sliders and knobs). Although I am not sure how to get data from both
for msg1 in input_hw:
if not msg1.type == "clock":
print(msg1)
# Play the note if the note has been triggered
if msg1.type == 'note_on' or msg1.type == 'note_off' and msg1.velocity > 0:
out.send(msg1)
for msg in input_hw2:
#avoid to print the clock message
if not msg.type == "clock":
print(msg)
The first For loop works, I get the midi note on and off when playing the keyboard, which is tied to the input_hw port, but the second loop never goes through.
Found a solution; you need to wrap the for loops in a while loop, adn use the iter_pending() function, which does allow mido to continue and not getting stuck waiting on the first loop.
Probably there is a more elegant solution, but this is what I was able to find
while True:
for msg1 in input_hw.iter_pending():
if not msg1.type == "clock":
print(msg1)
# Play the note if the note has been triggered
if msg1.type == 'note_on' or msg1.type == 'note_off' and msg1.velocity > 0:
out.send(msg1)
for msg in input_hw2.iter_pending():
#avoid to print the clock message
if not msg.type == "clock":
print(msg)
I'm just start learning about python and I have problem with my project to blink LED. when I get new message and start new thread. The old thread is still running.
I want to kill old thread and start new thread. How to solve my problem?
(Sorry if I'm not good in english but I'm trying)
def led_action(topic,message):
print topic+" "+message
if message == 'OFF':
#state = False
print ("Stoping...")
while message == 'OFF':
GPIO.output(8,GPIO.LOW)
elif message == 'ON':
#state = True
print ("Opening...")
while message == 'ON':
GPIO.output(8,GPIO.HIGH) #Set LED pin 8 to HIGH
time.sleep(1) #Delay 1 second
GPIO.output(8,GPIO.LOW) #Set LED pin 8 to LOW
time.sleep(1)
# Get message form NETPIE and Do something
def subscription(topic,message):
set = thread.start_new_thread(led_action, (topic,message))
def connection():
print "Now I am connected with netpie"
def disconnect():
print "disconnect is work"
microgear.setalias("test")
microgear.on_connect = connection
microgear.on_message = subscription
microgear.on_disconnect = disconnect
microgear.subscribe("/mails")
microgear.connect(True)
To terminate a python thread you need to exit your function. You can do this by removing your while message == 'ON'/'OFF' checks. As message doesn't change anyways (it is passed to the function led_action) those checks are unnecessary.